This source file includes following definitions.
- bematch
- beattach
- be_put
- be_get
- be_read
- bestart
- bestop
- bereset
- bewatchdog
- beintr
- beqint
- beeint
- betint
- berint
- beioctl
- beinit
- be_mcreset
- be_mii_sync
- be_pal_gate
- be_tcvr_read_bit
- be_tcvr_write_bit
- be_mii_sendbits
- be_mii_readreg
- be_mii_writereg
- be_mii_reset
- be_tick
- be_mii_statchg
- be_ifmedia_sts
- be_ifmedia_upd
- be_intphy_service
- be_intphy_status
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 #include "bpfilter.h"
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/timeout.h>
70 #include <sys/kernel.h>
71 #include <sys/errno.h>
72 #include <sys/ioctl.h>
73 #include <sys/mbuf.h>
74 #include <sys/socket.h>
75 #include <sys/syslog.h>
76 #include <sys/device.h>
77 #include <sys/malloc.h>
78
79 #include <net/if.h>
80 #include <net/if_dl.h>
81 #include <net/if_types.h>
82 #include <net/netisr.h>
83 #include <net/if_media.h>
84
85 #ifdef INET
86 #include <netinet/in.h>
87 #include <netinet/in_systm.h>
88 #include <netinet/in_var.h>
89 #include <netinet/ip.h>
90 #include <netinet/if_ether.h>
91 #endif
92
93 #if NBPFILTER > 0
94 #include <net/bpf.h>
95 #endif
96
97 #include <machine/bus.h>
98 #include <machine/intr.h>
99 #include <machine/autoconf.h>
100
101 #include <dev/sbus/sbusvar.h>
102
103 #include <dev/mii/mii.h>
104 #include <dev/mii/miivar.h>
105
106 #include <dev/sbus/qecreg.h>
107 #include <dev/sbus/qecvar.h>
108 #include <dev/sbus/bereg.h>
109
110 struct be_softc {
111 struct device sc_dev;
112 bus_space_tag_t sc_bustag;
113 bus_dma_tag_t sc_dmatag;
114 bus_dmamap_t sc_dmamap;
115 struct arpcom sc_arpcom;
116
117 struct mii_data sc_mii;
118 #define sc_media sc_mii.mii_media
119 int sc_phys[2];
120
121 struct timeout sc_tick_ch;
122
123
124
125
126
127 int sc_mii_inst;
128 int sc_mii_active;
129 int sc_mii_ticks;
130 int sc_mii_flags;
131 #define MIIF_HAVELINK 0x04000000
132 int sc_intphy_curspeed;
133
134 struct qec_softc *sc_qec;
135
136 bus_space_handle_t sc_qr;
137 bus_space_handle_t sc_br;
138 bus_space_handle_t sc_cr;
139 bus_space_handle_t sc_tr;
140
141 u_int sc_rev;
142
143 int sc_channel;
144 int sc_burst;
145
146 struct qec_ring sc_rb;
147 };
148
149 int bematch(struct device *, void *, void *);
150 void beattach(struct device *, struct device *, void *);
151
152 void beinit(struct be_softc *);
153 void bestart(struct ifnet *);
154 void bestop(struct be_softc *);
155 void bewatchdog(struct ifnet *);
156 int beioctl(struct ifnet *, u_long, caddr_t);
157 void bereset(struct be_softc *);
158
159 int beintr(void *);
160 int berint(struct be_softc *);
161 int betint(struct be_softc *);
162 int beqint(struct be_softc *, u_int32_t);
163 int beeint(struct be_softc *, u_int32_t);
164
165 static void be_read(struct be_softc *, int, int);
166 static int be_put(struct be_softc *, int, struct mbuf *);
167 static struct mbuf *be_get(struct be_softc *, int, int);
168
169 void be_pal_gate(struct be_softc *, int);
170
171
172 void be_ifmedia_sts(struct ifnet *, struct ifmediareq *);
173 int be_ifmedia_upd(struct ifnet *);
174
175 void be_mcreset(struct be_softc *);
176
177
178 static int be_mii_readreg(struct device *, int, int);
179 static void be_mii_writereg(struct device *, int, int, int);
180 static void be_mii_statchg(struct device *);
181
182
183 static void be_mii_sync(struct be_softc *);
184 static void be_mii_sendbits(struct be_softc *, int, u_int32_t, int);
185 static int be_mii_reset(struct be_softc *, int);
186 static int be_tcvr_read_bit(struct be_softc *, int);
187 static void be_tcvr_write_bit(struct be_softc *, int, int);
188
189 void be_tick(void *);
190 void be_intphy_auto(struct be_softc *);
191 void be_intphy_status(struct be_softc *);
192 int be_intphy_service(struct be_softc *, struct mii_data *, int);
193
194
195 struct cfattach be_ca = {
196 sizeof(struct be_softc), bematch, beattach
197 };
198
199 struct cfdriver be_cd = {
200 NULL, "be", DV_IFNET
201 };
202
203 int
204 bematch(struct device *parent, void *vcf, void *aux)
205 {
206 struct cfdata *cf = vcf;
207 struct sbus_attach_args *sa = aux;
208
209 return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0);
210 }
211
212 void
213 beattach(struct device *parent, struct device *self, void *aux)
214 {
215 struct sbus_attach_args *sa = aux;
216 struct qec_softc *qec = (struct qec_softc *)parent;
217 struct be_softc *sc = (struct be_softc *)self;
218 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
219 struct mii_data *mii = &sc->sc_mii;
220 struct mii_softc *child;
221 int node = sa->sa_node;
222 bus_dma_tag_t dmatag = sa->sa_dmatag;
223 bus_dma_segment_t seg;
224 bus_size_t size;
225 int instance;
226 int rseg, error;
227 u_int32_t v;
228 extern void myetheraddr(u_char *);
229
230
231 sc->sc_bustag = sa->sa_bustag;
232 sc->sc_dmatag = sa->sa_dmatag;
233
234 if (sa->sa_nreg < 3) {
235 printf("%s: only %d register sets\n",
236 self->dv_xname, sa->sa_nreg);
237 return;
238 }
239
240 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
241 (bus_addr_t)sa->sa_reg[0].sbr_offset,
242 (bus_size_t)sa->sa_reg[0].sbr_size, 0, 0, &sc->sc_cr) != 0) {
243 printf("beattach: cannot map registers\n");
244 return;
245 }
246
247 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
248 (bus_addr_t)sa->sa_reg[1].sbr_offset,
249 (bus_size_t)sa->sa_reg[1].sbr_size, 0, 0, &sc->sc_br) != 0) {
250 printf("beattach: cannot map registers\n");
251 return;
252 }
253
254 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[2].sbr_slot,
255 (bus_addr_t)sa->sa_reg[2].sbr_offset,
256 (bus_size_t)sa->sa_reg[2].sbr_size, 0, 0, &sc->sc_tr) != 0) {
257 printf("beattach: cannot map registers\n");
258 return;
259 }
260
261 sc->sc_qec = qec;
262 sc->sc_qr = qec->sc_regs;
263
264 sc->sc_rev = getpropint(node, "board-version", -1);
265 printf(" rev %x", sc->sc_rev);
266
267 bestop(sc);
268
269 sc->sc_channel = getpropint(node, "channel#", -1);
270 if (sc->sc_channel == -1)
271 sc->sc_channel = 0;
272
273 sc->sc_burst = getpropint(node, "burst-sizes", -1);
274 if (sc->sc_burst == -1)
275 sc->sc_burst = qec->sc_burst;
276
277
278 sc->sc_burst &= qec->sc_burst;
279
280
281 if (sa->sa_nintr == 0 || bus_intr_establish(sa->sa_bustag, sa->sa_pri,
282 IPL_NET, 0, beintr, sc, self->dv_xname) == NULL) {
283 printf(": no interrupt established\n");
284 return;
285 }
286
287 myetheraddr(sc->sc_arpcom.ac_enaddr);
288 printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
289
290
291
292
293
294
295 sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE;
296 sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE;
297
298 size = QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) +
299 QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) +
300 sc->sc_rb.rb_ntbuf * BE_PKT_BUF_SZ +
301 sc->sc_rb.rb_nrbuf * BE_PKT_BUF_SZ;
302
303
304 if ((error = bus_dmamap_create(dmatag, size, 1, size, 0,
305 BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
306 printf("%s: DMA map create error %d\n", self->dv_xname, error);
307 return;
308 }
309
310
311 if ((error = bus_dmamem_alloc(sa->sa_dmatag, size, 0, 0,
312 &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
313 printf("%s: DMA buffer alloc error %d\n",
314 self->dv_xname, error);
315 return;
316 }
317
318
319 if ((error = bus_dmamem_map(sa->sa_dmatag, &seg, rseg, size,
320 &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
321 printf("%s: DMA buffer map error %d\n",
322 self->dv_xname, error);
323 bus_dmamem_free(sa->sa_dmatag, &seg, rseg);
324 return;
325 }
326
327
328 if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap,
329 sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) {
330 printf("%s: DMA buffer map load error %d\n",
331 self->dv_xname, error);
332 bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size);
333 bus_dmamem_free(dmatag, &seg, rseg);
334 return;
335 }
336 sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr;
337
338
339
340
341 mii->mii_ifp = ifp;
342 mii->mii_readreg = be_mii_readreg;
343 mii->mii_writereg = be_mii_writereg;
344 mii->mii_statchg = be_mii_statchg;
345
346 ifmedia_init(&mii->mii_media, 0, be_ifmedia_upd, be_ifmedia_sts);
347
348 timeout_set(&sc->sc_tick_ch, be_tick, sc);
349
350
351
352
353 be_mii_sync(sc);
354 v = bus_space_read_4(sc->sc_bustag, sc->sc_tr, BE_TRI_MGMTPAL);
355
356 instance = 0;
357
358 if ((v & MGMT_PAL_EXT_MDIO) != 0) {
359
360 mii_attach(&sc->sc_dev, mii, 0xffffffff, BE_PHY_EXTERNAL,
361 MII_OFFSET_ANY, 0);
362
363 child = LIST_FIRST(&mii->mii_phys);
364 if (child == NULL) {
365
366 ifmedia_add(&sc->sc_media,
367 IFM_MAKEWORD(IFM_ETHER,IFM_NONE,0,instance),
368 0, NULL);
369 ifmedia_set(&sc->sc_media,
370 IFM_MAKEWORD(IFM_ETHER,IFM_NONE,0,instance));
371 } else {
372
373
374
375
376 #ifdef DIAGNOSTIC
377 if (LIST_NEXT(child, mii_list) != NULL) {
378 printf("%s: spurious MII device %s attached\n",
379 sc->sc_dev.dv_xname,
380 child->mii_dev.dv_xname);
381 }
382 #endif
383 if (child->mii_phy != BE_PHY_EXTERNAL ||
384 child->mii_inst > 0) {
385 printf("%s: cannot accommodate MII device %s"
386 " at phy %d, instance %d\n",
387 sc->sc_dev.dv_xname,
388 child->mii_dev.dv_xname,
389 child->mii_phy, child->mii_inst);
390 } else {
391 sc->sc_phys[instance] = child->mii_phy;
392 }
393
394
395
396
397
398 ifmedia_set(&sc->sc_media,
399 IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance));
400
401
402 be_pal_gate(sc, BE_PHY_EXTERNAL);
403 instance++;
404 }
405
406 }
407
408 if ((v & MGMT_PAL_INT_MDIO) != 0) {
409
410
411
412
413
414
415
416 sc->sc_mii_inst = instance;
417 sc->sc_phys[instance] = BE_PHY_INTERNAL;
418
419
420 ifmedia_add(&sc->sc_media,
421 IFM_MAKEWORD(IFM_ETHER,IFM_10_T,0,instance), 0, NULL);
422 ifmedia_add(&sc->sc_media,
423 IFM_MAKEWORD(IFM_ETHER,IFM_100_TX,0,instance),
424 BMCR_S100, NULL);
425 ifmedia_add(&sc->sc_media,
426 IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance), 0, NULL);
427
428 printf("on-board transceiver at %s: 10baseT, 100baseTX, auto\n",
429 self->dv_xname);
430
431 be_mii_reset(sc, BE_PHY_INTERNAL);
432
433 if (instance == 0) {
434 be_pal_gate(sc, BE_PHY_INTERNAL);
435 ifmedia_set(&sc->sc_media,
436 IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance));
437 } else
438 be_mii_writereg((void *)sc,
439 BE_PHY_INTERNAL, MII_BMCR, BMCR_ISO);
440 }
441
442 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
443 ifp->if_softc = sc;
444 ifp->if_start = bestart;
445 ifp->if_ioctl = beioctl;
446 ifp->if_watchdog = bewatchdog;
447 ifp->if_flags =
448 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
449 IFQ_SET_READY(&ifp->if_snd);
450
451
452 if_attach(ifp);
453 ether_ifattach(ifp);
454 }
455
456
457
458
459
460
461 static __inline__ int
462 be_put(struct be_softc *sc, int idx, struct mbuf *m)
463 {
464 struct mbuf *n;
465 int len, tlen = 0, boff = 0;
466 caddr_t bp;
467
468 bp = sc->sc_rb.rb_txbuf + (idx % sc->sc_rb.rb_ntbuf) * BE_PKT_BUF_SZ;
469
470 for (; m; m = n) {
471 len = m->m_len;
472 if (len == 0) {
473 MFREE(m, n);
474 continue;
475 }
476 bcopy(mtod(m, caddr_t), bp+boff, len);
477 boff += len;
478 tlen += len;
479 MFREE(m, n);
480 }
481 return (tlen);
482 }
483
484
485
486
487
488
489
490 static __inline__ struct mbuf *
491 be_get(struct be_softc *sc, int idx, int totlen)
492 {
493 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
494 struct mbuf *m;
495 struct mbuf *top, **mp;
496 int len, pad, boff = 0;
497 caddr_t bp;
498
499 bp = sc->sc_rb.rb_rxbuf + (idx % sc->sc_rb.rb_nrbuf) * BE_PKT_BUF_SZ;
500
501 MGETHDR(m, M_DONTWAIT, MT_DATA);
502 if (m == NULL)
503 return (NULL);
504 m->m_pkthdr.rcvif = ifp;
505 m->m_pkthdr.len = totlen;
506
507 pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
508 m->m_data += pad;
509 len = MHLEN - pad;
510 top = NULL;
511 mp = ⊤
512
513 while (totlen > 0) {
514 if (top) {
515 MGET(m, M_DONTWAIT, MT_DATA);
516 if (m == NULL) {
517 m_freem(top);
518 return (NULL);
519 }
520 len = MLEN;
521 }
522 if (top && totlen >= MINCLSIZE) {
523 MCLGET(m, M_DONTWAIT);
524 if (m->m_flags & M_EXT)
525 len = MCLBYTES;
526 }
527 m->m_len = len = min(totlen, len);
528 bcopy(bp + boff, mtod(m, caddr_t), len);
529 boff += len;
530 totlen -= len;
531 *mp = m;
532 mp = &m->m_next;
533 }
534
535 return (top);
536 }
537
538
539
540
541 static __inline__ void
542 be_read(struct be_softc *sc, int idx, int len)
543 {
544 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
545 struct mbuf *m;
546
547 if (len <= sizeof(struct ether_header) ||
548 len > ETHERMTU + sizeof(struct ether_header)) {
549
550 printf("%s: invalid packet size %d; dropping\n",
551 ifp->if_xname, len);
552
553 ifp->if_ierrors++;
554 return;
555 }
556
557
558
559
560 m = be_get(sc, idx, len);
561 if (m == NULL) {
562 ifp->if_ierrors++;
563 return;
564 }
565 ifp->if_ipackets++;
566
567 #if NBPFILTER > 0
568
569
570
571
572 if (ifp->if_bpf)
573 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
574 #endif
575
576 ether_input_mbuf(ifp, m);
577 }
578
579
580
581
582
583
584
585
586
587
588 void
589 bestart(struct ifnet *ifp)
590 {
591 struct be_softc *sc = (struct be_softc *)ifp->if_softc;
592 struct qec_xd *txd = sc->sc_rb.rb_txd;
593 struct mbuf *m;
594 unsigned int bix, len;
595 unsigned int ntbuf = sc->sc_rb.rb_ntbuf;
596
597 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
598 return;
599
600 bix = sc->sc_rb.rb_tdhead;
601
602 for (;;) {
603 IFQ_DEQUEUE(&ifp->if_snd, m);
604 if (m == 0)
605 break;
606
607 #if NBPFILTER > 0
608
609
610
611
612 if (ifp->if_bpf)
613 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
614 #endif
615
616
617
618
619 len = be_put(sc, bix, m);
620
621
622
623
624 txd[bix].xd_flags = QEC_XD_OWN | QEC_XD_SOP | QEC_XD_EOP |
625 (len & QEC_XD_LENGTH);
626 bus_space_write_4(sc->sc_bustag, sc->sc_cr, BE_CRI_CTRL,
627 BE_CR_CTRL_TWAKEUP);
628
629 if (++bix == QEC_XD_RING_MAXSIZE)
630 bix = 0;
631
632 if (++sc->sc_rb.rb_td_nbusy == ntbuf) {
633 ifp->if_flags |= IFF_OACTIVE;
634 break;
635 }
636 }
637
638 sc->sc_rb.rb_tdhead = bix;
639 }
640
641 void
642 bestop(struct be_softc *sc)
643 {
644 int n;
645 bus_space_tag_t t = sc->sc_bustag;
646 bus_space_handle_t br = sc->sc_br;
647
648 timeout_del(&sc->sc_tick_ch);
649
650
651 mii_down(&sc->sc_mii);
652 (void)be_intphy_service(sc, &sc->sc_mii, MII_DOWN);
653
654
655 bus_space_write_4(t, br, BE_BRI_TXCFG, 0);
656 for (n = 32; n > 0; n--) {
657 if (bus_space_read_4(t, br, BE_BRI_TXCFG) == 0)
658 break;
659 DELAY(20);
660 }
661
662
663 bus_space_write_4(t, br, BE_BRI_RXCFG, 0);
664 for (n = 32; n > 0; n--) {
665 if (bus_space_read_4(t, br, BE_BRI_RXCFG) == 0)
666 break;
667 DELAY(20);
668 }
669 }
670
671
672
673
674 void
675 bereset(struct be_softc *sc)
676 {
677 int s;
678
679 s = splnet();
680 bestop(sc);
681 if ((sc->sc_arpcom.ac_if.if_flags & IFF_UP) != 0)
682 beinit(sc);
683 splx(s);
684 }
685
686 void
687 bewatchdog(struct ifnet *ifp)
688 {
689 struct be_softc *sc = ifp->if_softc;
690
691 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
692 ++sc->sc_arpcom.ac_if.if_oerrors;
693 bereset(sc);
694 }
695
696 int
697 beintr(void *v)
698 {
699 struct be_softc *sc = (struct be_softc *)v;
700 bus_space_tag_t t = sc->sc_bustag;
701 u_int32_t whyq, whyb, whyc;
702 int r = 0;
703
704
705 whyq = bus_space_read_4(t, sc->sc_qr, QEC_QRI_STAT);
706 whyc = bus_space_read_4(t, sc->sc_cr, BE_CRI_STAT);
707 whyb = bus_space_read_4(t, sc->sc_br, BE_BRI_STAT);
708
709 if (whyq & QEC_STAT_BM)
710 r |= beeint(sc, whyb);
711
712 if (whyq & QEC_STAT_ER)
713 r |= beqint(sc, whyc);
714
715 if (whyq & QEC_STAT_TX && whyc & BE_CR_STAT_TXIRQ)
716 r |= betint(sc);
717
718 if (whyq & QEC_STAT_RX && whyc & BE_CR_STAT_RXIRQ)
719 r |= berint(sc);
720
721 return (r);
722 }
723
724
725
726
727 int
728 beqint(struct be_softc *sc, u_int32_t why)
729 {
730 int r = 0, rst = 0;
731
732 if (why & BE_CR_STAT_TXIRQ)
733 r |= 1;
734 if (why & BE_CR_STAT_RXIRQ)
735 r |= 1;
736
737 if (why & BE_CR_STAT_BERROR) {
738 r |= 1;
739 rst = 1;
740 printf("%s: bigmac error\n", sc->sc_dev.dv_xname);
741 }
742
743 if (why & BE_CR_STAT_TXDERR) {
744 r |= 1;
745 rst = 1;
746 printf("%s: bogus tx descriptor\n", sc->sc_dev.dv_xname);
747 }
748
749 if (why & (BE_CR_STAT_TXLERR | BE_CR_STAT_TXPERR | BE_CR_STAT_TXSERR)) {
750 r |= 1;
751 rst = 1;
752 printf("%s: tx dma error ( ", sc->sc_dev.dv_xname);
753 if (why & BE_CR_STAT_TXLERR)
754 printf("Late ");
755 if (why & BE_CR_STAT_TXPERR)
756 printf("Parity ");
757 if (why & BE_CR_STAT_TXSERR)
758 printf("Generic ");
759 printf(")\n");
760 }
761
762 if (why & BE_CR_STAT_RXDROP) {
763 r |= 1;
764 rst = 1;
765 printf("%s: out of rx descriptors\n", sc->sc_dev.dv_xname);
766 }
767
768 if (why & BE_CR_STAT_RXSMALL) {
769 r |= 1;
770 rst = 1;
771 printf("%s: rx descriptor too small\n", sc->sc_dev.dv_xname);
772 }
773
774 if (why & (BE_CR_STAT_RXLERR | BE_CR_STAT_RXPERR | BE_CR_STAT_RXSERR)) {
775 r |= 1;
776 rst = 1;
777 printf("%s: rx dma error ( ", sc->sc_dev.dv_xname);
778 if (why & BE_CR_STAT_RXLERR)
779 printf("Late ");
780 if (why & BE_CR_STAT_RXPERR)
781 printf("Parity ");
782 if (why & BE_CR_STAT_RXSERR)
783 printf("Generic ");
784 printf(")\n");
785 }
786
787 if (!r) {
788 rst = 1;
789 printf("%s: unexpected error interrupt %08x\n",
790 sc->sc_dev.dv_xname, why);
791 }
792
793 if (rst) {
794 printf("%s: resetting\n", sc->sc_dev.dv_xname);
795 bereset(sc);
796 }
797
798 return (r);
799 }
800
801
802
803
804 int
805 beeint(struct be_softc *sc, u_int32_t why)
806 {
807 int r = 0, rst = 0;
808
809 if (why & BE_BR_STAT_RFIFOVF) {
810 r |= 1;
811 rst = 1;
812 printf("%s: receive fifo overrun\n", sc->sc_dev.dv_xname);
813 }
814 if (why & BE_BR_STAT_TFIFO_UND) {
815 r |= 1;
816 rst = 1;
817 printf("%s: transmit fifo underrun\n", sc->sc_dev.dv_xname);
818 }
819 if (why & BE_BR_STAT_MAXPKTERR) {
820 r |= 1;
821 rst = 1;
822 printf("%s: max packet size error\n", sc->sc_dev.dv_xname);
823 }
824
825 if (!r) {
826 rst = 1;
827 printf("%s: unexpected error interrupt %08x\n",
828 sc->sc_dev.dv_xname, why);
829 }
830
831 if (rst) {
832 printf("%s: resetting\n", sc->sc_dev.dv_xname);
833 bereset(sc);
834 }
835
836 return (r);
837 }
838
839
840
841
842 int
843 betint(struct be_softc *sc)
844 {
845 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
846 bus_space_tag_t t = sc->sc_bustag;
847 bus_space_handle_t br = sc->sc_br;
848 unsigned int bix, txflags;
849
850
851
852
853 ifp->if_collisions +=
854 bus_space_read_4(t, br, BE_BRI_NCCNT) +
855 bus_space_read_4(t, br, BE_BRI_FCCNT) +
856 bus_space_read_4(t, br, BE_BRI_EXCNT) +
857 bus_space_read_4(t, br, BE_BRI_LTCNT);
858
859
860
861
862 bus_space_write_4(t, br, BE_BRI_NCCNT, 0);
863 bus_space_write_4(t, br, BE_BRI_FCCNT, 0);
864 bus_space_write_4(t, br, BE_BRI_EXCNT, 0);
865 bus_space_write_4(t, br, BE_BRI_LTCNT, 0);
866
867 bix = sc->sc_rb.rb_tdtail;
868
869 for (;;) {
870 if (sc->sc_rb.rb_td_nbusy <= 0)
871 break;
872
873 txflags = sc->sc_rb.rb_txd[bix].xd_flags;
874
875 if (txflags & QEC_XD_OWN)
876 break;
877
878 ifp->if_flags &= ~IFF_OACTIVE;
879 ifp->if_opackets++;
880
881 if (++bix == QEC_XD_RING_MAXSIZE)
882 bix = 0;
883
884 --sc->sc_rb.rb_td_nbusy;
885 }
886
887 sc->sc_rb.rb_tdtail = bix;
888
889 bestart(ifp);
890
891 if (sc->sc_rb.rb_td_nbusy == 0)
892 ifp->if_timer = 0;
893
894 return (1);
895 }
896
897
898
899
900 int
901 berint(struct be_softc *sc)
902 {
903 struct qec_xd *xd = sc->sc_rb.rb_rxd;
904 unsigned int bix, len;
905 unsigned int nrbuf = sc->sc_rb.rb_nrbuf;
906
907 bix = sc->sc_rb.rb_rdtail;
908
909
910
911
912 for (;;) {
913 len = xd[bix].xd_flags;
914 if (len & QEC_XD_OWN)
915 break;
916
917 len &= QEC_XD_LENGTH;
918 be_read(sc, bix, len);
919
920
921 xd[(bix+nrbuf) % QEC_XD_RING_MAXSIZE].xd_flags =
922 QEC_XD_OWN | (BE_PKT_BUF_SZ & QEC_XD_LENGTH);
923
924 if (++bix == QEC_XD_RING_MAXSIZE)
925 bix = 0;
926 }
927
928 sc->sc_rb.rb_rdtail = bix;
929
930 return (1);
931 }
932
933 int
934 beioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
935 {
936 struct be_softc *sc = ifp->if_softc;
937 struct ifaddr *ifa = (struct ifaddr *)data;
938 struct ifreq *ifr = (struct ifreq *)data;
939 int s, error = 0;
940
941 s = splnet();
942
943 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
944 splx(s);
945 return (error);
946 }
947
948 switch (cmd) {
949 case SIOCSIFADDR:
950 ifp->if_flags |= IFF_UP;
951 switch (ifa->ifa_addr->sa_family) {
952 #ifdef INET
953 case AF_INET:
954 beinit(sc);
955 arp_ifinit(&sc->sc_arpcom, ifa);
956 break;
957 #endif
958 default:
959 beinit(sc);
960 break;
961 }
962 break;
963
964 case SIOCSIFFLAGS:
965 if ((ifp->if_flags & IFF_UP) == 0 &&
966 (ifp->if_flags & IFF_RUNNING) != 0) {
967
968
969
970
971 bestop(sc);
972 ifp->if_flags &= ~IFF_RUNNING;
973 } else if ((ifp->if_flags & IFF_UP) != 0 &&
974 (ifp->if_flags & IFF_RUNNING) == 0) {
975
976
977
978
979 beinit(sc);
980 } else {
981
982
983
984
985 bestop(sc);
986 beinit(sc);
987 }
988 #ifdef BEDEBUG
989 if (ifp->if_flags & IFF_DEBUG)
990 sc->sc_debug = 1;
991 else
992 sc->sc_debug = 0;
993 #endif
994 break;
995
996 case SIOCADDMULTI:
997 case SIOCDELMULTI:
998 error = (cmd == SIOCADDMULTI) ?
999 ether_addmulti(ifr, &sc->sc_arpcom):
1000 ether_delmulti(ifr, &sc->sc_arpcom);
1001
1002 if (error == ENETRESET) {
1003
1004
1005
1006
1007 if (ifp->if_flags & IFF_RUNNING)
1008 be_mcreset(sc);
1009 error = 0;
1010 }
1011 break;
1012 case SIOCGIFMEDIA:
1013 case SIOCSIFMEDIA:
1014 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1015 break;
1016 default:
1017 error = EINVAL;
1018 break;
1019 }
1020 splx(s);
1021 return (error);
1022 }
1023
1024
1025 void
1026 beinit(struct be_softc *sc)
1027 {
1028 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1029 bus_space_tag_t t = sc->sc_bustag;
1030 bus_space_handle_t br = sc->sc_br;
1031 bus_space_handle_t cr = sc->sc_cr;
1032 struct qec_softc *qec = sc->sc_qec;
1033 u_int32_t v;
1034 u_int32_t qecaddr;
1035 u_int8_t *ea;
1036 int s;
1037
1038 s = splnet();
1039
1040 qec_meminit(&sc->sc_rb, BE_PKT_BUF_SZ);
1041
1042 bestop(sc);
1043
1044 ea = sc->sc_arpcom.ac_enaddr;
1045 bus_space_write_4(t, br, BE_BRI_MACADDR0, (ea[0] << 8) | ea[1]);
1046 bus_space_write_4(t, br, BE_BRI_MACADDR1, (ea[2] << 8) | ea[3]);
1047 bus_space_write_4(t, br, BE_BRI_MACADDR2, (ea[4] << 8) | ea[5]);
1048
1049
1050 bus_space_write_4(t, br, BE_BRI_HASHTAB0, 0);
1051 bus_space_write_4(t, br, BE_BRI_HASHTAB1, 0);
1052 bus_space_write_4(t, br, BE_BRI_HASHTAB2, 0);
1053 bus_space_write_4(t, br, BE_BRI_HASHTAB3, 0);
1054
1055
1056 v = BE_BR_RXCFG_FIFO;
1057 bus_space_write_4(t, br, BE_BRI_RXCFG, v);
1058
1059 be_mcreset(sc);
1060
1061 bus_space_write_4(t, br, BE_BRI_RANDSEED, 0xbd);
1062
1063 bus_space_write_4(t, br, BE_BRI_XIFCFG,
1064 BE_BR_XCFG_ODENABLE | BE_BR_XCFG_RESV);
1065
1066 bus_space_write_4(t, br, BE_BRI_JSIZE, 4);
1067
1068
1069
1070
1071
1072 bus_space_write_4(t, br, BE_BRI_IMASK,
1073 BE_BR_IMASK_GOTFRAME |
1074 BE_BR_IMASK_RCNTEXP |
1075 BE_BR_IMASK_ACNTEXP |
1076 BE_BR_IMASK_CCNTEXP |
1077 BE_BR_IMASK_LCNTEXP |
1078 BE_BR_IMASK_CVCNTEXP |
1079 BE_BR_IMASK_SENTFRAME |
1080 BE_BR_IMASK_NCNTEXP |
1081 BE_BR_IMASK_ECNTEXP |
1082 BE_BR_IMASK_LCCNTEXP |
1083 BE_BR_IMASK_FCNTEXP |
1084 BE_BR_IMASK_DTIMEXP);
1085
1086
1087 bus_space_write_4(t, cr, BE_CRI_RXDS, (u_int32_t)sc->sc_rb.rb_rxddma);
1088 bus_space_write_4(t, cr, BE_CRI_TXDS, (u_int32_t)sc->sc_rb.rb_txddma);
1089
1090 qecaddr = sc->sc_channel * qec->sc_msize;
1091 bus_space_write_4(t, cr, BE_CRI_RXWBUF, qecaddr);
1092 bus_space_write_4(t, cr, BE_CRI_RXRBUF, qecaddr);
1093 bus_space_write_4(t, cr, BE_CRI_TXWBUF, qecaddr + qec->sc_rsize);
1094 bus_space_write_4(t, cr, BE_CRI_TXRBUF, qecaddr + qec->sc_rsize);
1095
1096 bus_space_write_4(t, cr, BE_CRI_RIMASK, 0);
1097 bus_space_write_4(t, cr, BE_CRI_TIMASK, 0);
1098 bus_space_write_4(t, cr, BE_CRI_QMASK, 0);
1099 bus_space_write_4(t, cr, BE_CRI_BMASK, 0);
1100 bus_space_write_4(t, cr, BE_CRI_CCNT, 0);
1101
1102
1103 bus_space_write_4(t, br, BE_BRI_TXCFG,
1104 BE_BR_TXCFG_FIFO | BE_BR_TXCFG_ENABLE);
1105
1106
1107 v = bus_space_read_4(t, br, BE_BRI_RXCFG);
1108 v |= BE_BR_RXCFG_FIFO | BE_BR_RXCFG_ENABLE;
1109 bus_space_write_4(t, br, BE_BRI_RXCFG, v);
1110
1111 ifp->if_flags |= IFF_RUNNING;
1112 ifp->if_flags &= ~IFF_OACTIVE;
1113
1114 be_ifmedia_upd(ifp);
1115 timeout_add(&sc->sc_tick_ch, hz);
1116 splx(s);
1117 }
1118
1119 void
1120 be_mcreset(struct be_softc *sc)
1121 {
1122 struct arpcom *ac = &sc->sc_arpcom;
1123 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1124 bus_space_tag_t t = sc->sc_bustag;
1125 bus_space_handle_t br = sc->sc_br;
1126 u_int32_t crc;
1127 u_int16_t hash[4];
1128 u_int8_t octet;
1129 u_int32_t v;
1130 int i, j;
1131 struct ether_multi *enm;
1132 struct ether_multistep step;
1133
1134 if (ifp->if_flags & IFF_PROMISC) {
1135 v = bus_space_read_4(t, br, BE_BRI_RXCFG);
1136 v |= BE_BR_RXCFG_PMISC;
1137 bus_space_write_4(t, br, BE_BRI_RXCFG, v);
1138 return;
1139 }
1140
1141 if (ifp->if_flags & IFF_ALLMULTI) {
1142 hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
1143 goto chipit;
1144 }
1145
1146 hash[3] = hash[2] = hash[1] = hash[0] = 0;
1147
1148 ETHER_FIRST_MULTI(step, ac, enm);
1149 while (enm != NULL) {
1150 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161 hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
1162 ifp->if_flags |= IFF_ALLMULTI;
1163 goto chipit;
1164 }
1165
1166 crc = 0xffffffff;
1167
1168 for (i = 0; i < ETHER_ADDR_LEN; i++) {
1169 octet = enm->enm_addrlo[i];
1170
1171 for (j = 0; j < 8; j++) {
1172 if ((crc & 1) ^ (octet & 1)) {
1173 crc >>= 1;
1174 crc ^= MC_POLY_LE;
1175 }
1176 else
1177 crc >>= 1;
1178 octet >>= 1;
1179 }
1180 }
1181
1182 crc >>= 26;
1183 hash[crc >> 4] |= 1 << (crc & 0xf);
1184 ETHER_NEXT_MULTI(step, enm);
1185 }
1186
1187 ifp->if_flags &= ~IFF_ALLMULTI;
1188
1189 chipit:
1190
1191 bus_space_write_4(t, br, BE_BRI_HASHTAB0, hash[0]);
1192 bus_space_write_4(t, br, BE_BRI_HASHTAB1, hash[1]);
1193 bus_space_write_4(t, br, BE_BRI_HASHTAB2, hash[2]);
1194 bus_space_write_4(t, br, BE_BRI_HASHTAB3, hash[3]);
1195
1196 v = bus_space_read_4(t, br, BE_BRI_RXCFG);
1197 v &= ~BE_BR_RXCFG_PMISC;
1198 v |= BE_BR_RXCFG_HENABLE;
1199 bus_space_write_4(t, br, BE_BRI_RXCFG, v);
1200 }
1201
1202
1203
1204
1205 void
1206 be_mii_sync(struct be_softc *sc)
1207 {
1208 bus_space_tag_t t = sc->sc_bustag;
1209 bus_space_handle_t tr = sc->sc_tr;
1210 int n = 32;
1211
1212 while (n--) {
1213 bus_space_write_4(t, tr, BE_TRI_MGMTPAL,
1214 MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO | MGMT_PAL_OENAB);
1215 (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
1216 bus_space_write_4(t, tr, BE_TRI_MGMTPAL,
1217 MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO |
1218 MGMT_PAL_OENAB | MGMT_PAL_DCLOCK);
1219 (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
1220 }
1221 }
1222
1223 void
1224 be_pal_gate(struct be_softc *sc, int phy)
1225 {
1226 bus_space_tag_t t = sc->sc_bustag;
1227 bus_space_handle_t tr = sc->sc_tr;
1228 u_int32_t v;
1229
1230 be_mii_sync(sc);
1231
1232 v = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE | TCVR_PAL_LTENABLE);
1233 if (phy == BE_PHY_INTERNAL)
1234 v &= ~TCVR_PAL_SERIAL;
1235
1236 bus_space_write_4(t, tr, BE_TRI_TCVRPAL, v);
1237 (void)bus_space_read_4(t, tr, BE_TRI_TCVRPAL);
1238 }
1239
1240 static int
1241 be_tcvr_read_bit(struct be_softc *sc, int phy)
1242 {
1243 bus_space_tag_t t = sc->sc_bustag;
1244 bus_space_handle_t tr = sc->sc_tr;
1245 int ret;
1246
1247 if (phy == BE_PHY_INTERNAL) {
1248 bus_space_write_4(t, tr, BE_TRI_MGMTPAL, MGMT_PAL_EXT_MDIO);
1249 (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
1250 bus_space_write_4(t, tr, BE_TRI_MGMTPAL,
1251 MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK);
1252 (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
1253 ret = (bus_space_read_4(t, tr, BE_TRI_MGMTPAL) &
1254 MGMT_PAL_INT_MDIO) >> MGMT_PAL_INT_MDIO_SHIFT;
1255 } else {
1256 bus_space_write_4(t, tr, BE_TRI_MGMTPAL, MGMT_PAL_INT_MDIO);
1257 (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
1258 ret = (bus_space_read_4(t, tr, BE_TRI_MGMTPAL) &
1259 MGMT_PAL_EXT_MDIO) >> MGMT_PAL_EXT_MDIO_SHIFT;
1260 bus_space_write_4(t, tr, BE_TRI_MGMTPAL,
1261 MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK);
1262 (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
1263 }
1264
1265 return (ret);
1266 }
1267
1268 static void
1269 be_tcvr_write_bit(struct be_softc *sc, int phy, int bit)
1270 {
1271 bus_space_tag_t t = sc->sc_bustag;
1272 bus_space_handle_t tr = sc->sc_tr;
1273 u_int32_t v;
1274
1275 if (phy == BE_PHY_INTERNAL) {
1276 v = ((bit & 1) << MGMT_PAL_INT_MDIO_SHIFT) |
1277 MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO;
1278 } else {
1279 v = ((bit & 1) << MGMT_PAL_EXT_MDIO_SHIFT)
1280 | MGMT_PAL_OENAB | MGMT_PAL_INT_MDIO;
1281 }
1282 bus_space_write_4(t, tr, BE_TRI_MGMTPAL, v);
1283 (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
1284 bus_space_write_4(t, tr, BE_TRI_MGMTPAL, v | MGMT_PAL_DCLOCK);
1285 (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
1286 }
1287
1288 static void
1289 be_mii_sendbits(struct be_softc *sc, int phy, u_int32_t data, int nbits)
1290 {
1291 int i;
1292
1293 for (i = 1 << (nbits - 1); i != 0; i >>= 1)
1294 be_tcvr_write_bit(sc, phy, (data & i) != 0);
1295 }
1296
1297 static int
1298 be_mii_readreg(struct device *self, int phy, int reg)
1299 {
1300 struct be_softc *sc = (struct be_softc *)self;
1301 int val = 0, i;
1302
1303
1304
1305
1306 be_mii_sync(sc);
1307 be_mii_sendbits(sc, phy, MII_COMMAND_START, 2);
1308 be_mii_sendbits(sc, phy, MII_COMMAND_READ, 2);
1309 be_mii_sendbits(sc, phy, phy, 5);
1310 be_mii_sendbits(sc, phy, reg, 5);
1311
1312 (void) be_tcvr_read_bit(sc, phy);
1313 (void) be_tcvr_read_bit(sc, phy);
1314
1315 for (i = 15; i >= 0; i--)
1316 val |= (be_tcvr_read_bit(sc, phy) << i);
1317
1318 (void) be_tcvr_read_bit(sc, phy);
1319 (void) be_tcvr_read_bit(sc, phy);
1320 (void) be_tcvr_read_bit(sc, phy);
1321
1322 return (val);
1323 }
1324
1325 void
1326 be_mii_writereg(struct device *self, int phy, int reg, int val)
1327 {
1328 struct be_softc *sc = (struct be_softc *)self;
1329 int i;
1330
1331
1332
1333
1334 be_mii_sync(sc);
1335 be_mii_sendbits(sc, phy, MII_COMMAND_START, 2);
1336 be_mii_sendbits(sc, phy, MII_COMMAND_WRITE, 2);
1337 be_mii_sendbits(sc, phy, phy, 5);
1338 be_mii_sendbits(sc, phy, reg, 5);
1339
1340 be_tcvr_write_bit(sc, phy, 1);
1341 be_tcvr_write_bit(sc, phy, 0);
1342
1343 for (i = 15; i >= 0; i--)
1344 be_tcvr_write_bit(sc, phy, (val >> i) & 1);
1345 }
1346
1347 int
1348 be_mii_reset(struct be_softc *sc, int phy)
1349 {
1350 int n;
1351
1352 be_mii_writereg((struct device *)sc, phy, MII_BMCR,
1353 BMCR_LOOP | BMCR_PDOWN | BMCR_ISO);
1354 be_mii_writereg((struct device *)sc, phy, MII_BMCR, BMCR_RESET);
1355
1356 for (n = 16; n >= 0; n--) {
1357 int bmcr = be_mii_readreg((struct device *)sc, phy, MII_BMCR);
1358 if ((bmcr & BMCR_RESET) == 0)
1359 break;
1360 DELAY(20);
1361 }
1362 if (n == 0) {
1363 printf("%s: bmcr reset failed\n", sc->sc_dev.dv_xname);
1364 return (EIO);
1365 }
1366
1367 return (0);
1368 }
1369
1370 void
1371 be_tick(void *arg)
1372 {
1373 struct be_softc *sc = arg;
1374 int s = splnet();
1375
1376 mii_tick(&sc->sc_mii);
1377 (void)be_intphy_service(sc, &sc->sc_mii, MII_TICK);
1378
1379 timeout_add(&sc->sc_tick_ch, hz);
1380 splx(s);
1381 }
1382
1383 void
1384 be_mii_statchg(struct device *self)
1385 {
1386 struct be_softc *sc = (struct be_softc *)self;
1387 bus_space_tag_t t = sc->sc_bustag;
1388 bus_space_handle_t br = sc->sc_br;
1389 u_int instance;
1390 u_int32_t v;
1391
1392 instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
1393 #ifdef DIAGNOSTIC
1394 if (instance > 1)
1395 panic("be_mii_statchg: instance %d out of range", instance);
1396 #endif
1397
1398
1399 v = bus_space_read_4(t, br, BE_BRI_TXCFG);
1400 if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
1401 v |= BE_BR_TXCFG_FULLDPLX;
1402 else
1403 v &= ~BE_BR_TXCFG_FULLDPLX;
1404 bus_space_write_4(t, br, BE_BRI_TXCFG, v);
1405
1406
1407 be_pal_gate(sc, sc->sc_phys[instance]);
1408 }
1409
1410
1411
1412
1413 void
1414 be_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1415 {
1416 struct be_softc *sc = ifp->if_softc;
1417
1418 mii_pollstat(&sc->sc_mii);
1419 (void)be_intphy_service(sc, &sc->sc_mii, MII_POLLSTAT);
1420
1421 ifmr->ifm_status = sc->sc_mii.mii_media_status;
1422 ifmr->ifm_active = sc->sc_mii.mii_media_active;
1423 return;
1424 }
1425
1426
1427
1428
1429 int
1430 be_ifmedia_upd(struct ifnet *ifp)
1431 {
1432 struct be_softc *sc = ifp->if_softc;
1433 int error;
1434
1435 if ((error = mii_mediachg(&sc->sc_mii)) != 0)
1436 return (error);
1437
1438 return (be_intphy_service(sc, &sc->sc_mii, MII_MEDIACHG));
1439 }
1440
1441
1442
1443
1444 int
1445 be_intphy_service(struct be_softc *sc, struct mii_data *mii, int cmd)
1446 {
1447 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
1448 int bmcr, bmsr;
1449 int error;
1450
1451 switch (cmd) {
1452 case MII_POLLSTAT:
1453
1454
1455
1456 if (IFM_INST(ife->ifm_media) != sc->sc_mii_inst)
1457 return (0);
1458
1459 break;
1460
1461 case MII_MEDIACHG:
1462
1463
1464
1465
1466
1467 if (IFM_INST(ife->ifm_media) != sc->sc_mii_inst) {
1468 bmcr = be_mii_readreg((void *)sc,
1469 BE_PHY_INTERNAL, MII_BMCR);
1470 be_mii_writereg((void *)sc,
1471 BE_PHY_INTERNAL, MII_BMCR, bmcr | BMCR_ISO);
1472 sc->sc_mii_flags &= ~MIIF_HAVELINK;
1473 sc->sc_intphy_curspeed = 0;
1474 return (0);
1475 }
1476
1477
1478 if ((error = be_mii_reset(sc, BE_PHY_INTERNAL)) != 0)
1479 return (error);
1480
1481 bmcr = be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMCR);
1482
1483
1484
1485
1486 if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_TX)
1487 bmcr |= BMCR_S100;
1488 else if (IFM_SUBTYPE(ife->ifm_media) == IFM_10_T)
1489 bmcr &= ~BMCR_S100;
1490 else if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
1491 if ((sc->sc_mii_flags & MIIF_HAVELINK) != 0) {
1492 bmcr &= ~BMCR_S100;
1493 bmcr |= sc->sc_intphy_curspeed;
1494 } else {
1495
1496 bmcr |= BMCR_ISO;
1497 sc->sc_mii_flags |= MIIF_DOINGAUTO;
1498 }
1499 }
1500
1501 if ((IFM_OPTIONS(ife->ifm_media) & IFM_FDX) != 0)
1502 bmcr |= BMCR_FDX;
1503 else
1504 bmcr &= ~BMCR_FDX;
1505
1506 be_mii_writereg((void *)sc, BE_PHY_INTERNAL, MII_BMCR, bmcr);
1507 break;
1508
1509 case MII_TICK:
1510
1511
1512
1513 if (IFM_INST(ife->ifm_media) != sc->sc_mii_inst)
1514 return (0);
1515
1516
1517 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
1518 return (0);
1519
1520
1521 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
1522 return (0);
1523
1524
1525
1526
1527
1528
1529
1530
1531 bmsr = be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMSR) |
1532 be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMSR);
1533
1534 if ((bmsr & BMSR_LINK) != 0) {
1535
1536 bmcr = be_mii_readreg((void *)sc,
1537 BE_PHY_INTERNAL, MII_BMCR);
1538
1539 if ((sc->sc_mii_flags & MIIF_DOINGAUTO) != 0) {
1540 bmcr = be_mii_readreg((void *)sc,
1541 BE_PHY_INTERNAL, MII_BMCR);
1542
1543 sc->sc_mii_flags |= MIIF_HAVELINK;
1544 sc->sc_intphy_curspeed = (bmcr & BMCR_S100);
1545 sc->sc_mii_flags &= ~MIIF_DOINGAUTO;
1546
1547 bmcr &= ~BMCR_ISO;
1548 be_mii_writereg((void *)sc,
1549 BE_PHY_INTERNAL, MII_BMCR, bmcr);
1550
1551 printf("%s: link up at %s Mbps\n",
1552 sc->sc_dev.dv_xname,
1553 (bmcr & BMCR_S100) ? "100" : "10");
1554 }
1555 return (0);
1556 }
1557
1558 if ((sc->sc_mii_flags & MIIF_DOINGAUTO) == 0) {
1559 sc->sc_mii_flags |= MIIF_DOINGAUTO;
1560 sc->sc_mii_flags &= ~MIIF_HAVELINK;
1561 sc->sc_intphy_curspeed = 0;
1562 printf("%s: link down\n", sc->sc_dev.dv_xname);
1563 }
1564
1565
1566 if (++sc->sc_mii_ticks < 5)
1567 return(0);
1568
1569 sc->sc_mii_ticks = 0;
1570 bmcr = be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMCR);
1571
1572 bmcr ^= BMCR_S100;
1573 be_mii_writereg((void *)sc, BE_PHY_INTERNAL, MII_BMCR, bmcr);
1574
1575 break;
1576
1577 case MII_DOWN:
1578
1579 bmcr = be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMCR);
1580 be_mii_writereg((void *)sc,
1581 BE_PHY_INTERNAL, MII_BMCR, bmcr | BMCR_ISO);
1582 return (0);
1583 }
1584
1585
1586 be_intphy_status(sc);
1587
1588
1589 if (sc->sc_mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
1590 (*mii->mii_statchg)((struct device *)sc);
1591 sc->sc_mii_active = mii->mii_media_active;
1592 }
1593 return (0);
1594 }
1595
1596
1597
1598
1599 void
1600 be_intphy_status(struct be_softc *sc)
1601 {
1602 struct mii_data *mii = &sc->sc_mii;
1603 int media_active, media_status;
1604 int bmcr, bmsr;
1605
1606 media_status = IFM_AVALID;
1607 media_active = 0;
1608
1609
1610
1611
1612 bmcr = be_mii_readreg((struct device *)sc, BE_PHY_INTERNAL, MII_BMCR);
1613
1614 switch (bmcr & (BMCR_S100 | BMCR_FDX)) {
1615 case (BMCR_S100 | BMCR_FDX):
1616 media_active = IFM_ETHER | IFM_100_TX | IFM_FDX;
1617 break;
1618 case BMCR_S100:
1619 media_active = IFM_ETHER | IFM_100_TX | IFM_HDX;
1620 break;
1621 case BMCR_FDX:
1622 media_active = IFM_ETHER | IFM_10_T | IFM_FDX;
1623 break;
1624 case 0:
1625 media_active = IFM_ETHER | IFM_10_T | IFM_HDX;
1626 break;
1627 }
1628
1629
1630 bmsr = be_mii_readreg((struct device *)sc, BE_PHY_INTERNAL, MII_BMSR)|
1631 be_mii_readreg((struct device *)sc, BE_PHY_INTERNAL, MII_BMSR);
1632 if (bmsr & BMSR_LINK)
1633 media_status |= IFM_ACTIVE;
1634
1635 mii->mii_media_status = media_status;
1636 mii->mii_media_active = media_active;
1637 }