Annotation of sys/arch/sparc/dev/be.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: be.c,v 1.40 2006/05/27 23:59:07 jason Exp $ */
2:
3: /*
4: * Copyright (c) 1998 Theo de Raadt and Jason L. Wright.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: #include <sys/param.h>
29: #include <sys/systm.h>
30: #include <sys/kernel.h>
31: #include <sys/errno.h>
32: #include <sys/ioctl.h>
33: #include <sys/mbuf.h>
34: #include <sys/socket.h>
35: #include <sys/syslog.h>
36: #include <sys/device.h>
37: #include <sys/malloc.h>
38: #include <sys/timeout.h>
39:
40: #include <net/if.h>
41: #include <net/if_dl.h>
42: #include <net/if_types.h>
43: #include <net/netisr.h>
44: #include <net/if_media.h>
45:
46: #ifdef INET
47: #include <netinet/in.h>
48: #include <netinet/in_systm.h>
49: #include <netinet/in_var.h>
50: #include <netinet/ip.h>
51: #include <netinet/if_ether.h>
52: #endif
53:
54: #include "bpfilter.h"
55: #if NBPFILTER > 0
56: #include <net/bpf.h>
57: #include <net/bpfdesc.h>
58: #endif
59:
60: #include <machine/autoconf.h>
61: #include <machine/cpu.h>
62:
63: #include <sparc/dev/sbusvar.h>
64: #include <sparc/dev/dmareg.h>
65: #include <sparc/dev/dmavar.h>
66:
67: #include <sparc/dev/qecvar.h>
68: #include <sparc/dev/qecreg.h>
69: #include <sparc/dev/bereg.h>
70: #include <sparc/dev/bevar.h>
71:
72: int bematch(struct device *, void *, void *);
73: void beattach(struct device *, struct device *, void *);
74:
75: void beinit(struct besoftc *);
76: void bestart(struct ifnet *);
77: void bestop(struct besoftc *);
78: void bewatchdog(struct ifnet *);
79: int beioctl(struct ifnet *, u_long, caddr_t);
80: void bereset(struct besoftc *);
81:
82: int beintr(void *);
83: int berint(struct besoftc *);
84: int betint(struct besoftc *);
85: int beqint(struct besoftc *, u_int32_t);
86: int beeint(struct besoftc *, u_int32_t);
87: void be_read(struct besoftc *, int, int);
88:
89: void be_tcvr_idle(struct besoftc *);
90: void be_tcvr_init(struct besoftc *);
91: void be_tcvr_write(struct besoftc *, u_int8_t, u_int16_t);
92: void be_tcvr_write_bit(struct besoftc *, int);
93: int be_tcvr_read_bit1(struct besoftc *);
94: int be_tcvr_read_bit2(struct besoftc *);
95: int be_tcvr_read(struct besoftc *, u_int8_t);
96: void be_ifmedia_sts(struct ifnet *, struct ifmediareq *);
97: int be_ifmedia_upd(struct ifnet *);
98: void be_mcreset(struct besoftc *);
99: void betick(void *);
100: void be_tx_harvest(struct besoftc *);
101:
102: struct cfdriver be_cd = {
103: NULL, "be", DV_IFNET
104: };
105:
106: struct cfattach be_ca = {
107: sizeof(struct besoftc), bematch, beattach
108: };
109:
110: int
111: bematch(parent, vcf, aux)
112: struct device *parent;
113: void *vcf, *aux;
114: {
115: struct cfdata *cf = vcf;
116: struct confargs *ca = aux;
117: register struct romaux *ra = &ca->ca_ra;
118:
119: if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
120: return (0);
121: return (1);
122: }
123:
124: void
125: beattach(parent, self, aux)
126: struct device *parent, *self;
127: void *aux;
128: {
129: struct qec_softc *qec = (struct qec_softc *)parent;
130: struct besoftc *sc = (struct besoftc *)self;
131: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
132: struct confargs *ca = aux;
133: struct bootpath *bp;
134: extern void myetheraddr(u_char *);
135: int pri, bmsr;
136:
137: if (ca->ca_ra.ra_nintr != 1) {
138: printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr);
139: return;
140: }
141: pri = ca->ca_ra.ra_intr[0].int_pri;
142: sc->sc_rev = getpropint(ca->ca_ra.ra_node, "board-version", -1);
143:
144: timeout_set(&sc->sc_tick, betick, sc);
145:
146: sc->sc_cr = mapiodev(&ca->ca_ra.ra_reg[0], 0, sizeof(struct be_cregs));
147: sc->sc_br = mapiodev(&ca->ca_ra.ra_reg[1], 0, sizeof(struct be_bregs));
148: sc->sc_tr = mapiodev(&ca->ca_ra.ra_reg[2], 0, sizeof(struct be_tregs));
149: sc->sc_qec = qec;
150: sc->sc_qr = qec->sc_regs;
151: bestop(sc);
152:
153: sc->sc_channel = getpropint(ca->ca_ra.ra_node, "channel#", -1);
154: if (sc->sc_channel == -1)
155: sc->sc_channel = 0;
156:
157: sc->sc_burst = getpropint(ca->ca_ra.ra_node, "burst-sizes", -1);
158: if (sc->sc_burst == -1)
159: sc->sc_burst = qec->sc_burst;
160:
161: /* Clamp at parent's burst sizes */
162: sc->sc_burst &= qec->sc_burst;
163:
164: sc->sc_ih.ih_fun = beintr;
165: sc->sc_ih.ih_arg = sc;
166: intr_establish(pri, &sc->sc_ih, IPL_NET, sc->sc_dev.dv_xname);
167:
168: myetheraddr(sc->sc_arpcom.ac_enaddr);
169:
170: be_tcvr_init(sc);
171:
172: ifmedia_init(&sc->sc_ifmedia, 0, be_ifmedia_upd, be_ifmedia_sts);
173: bmsr = be_tcvr_read(sc, PHY_BMSR);
174: if (bmsr == BE_TCVR_READ_INVALID)
175: return;
176:
177: if (bmsr & PHY_BMSR_10BASET_HALF) {
178: ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL);
179: ifmedia_add(&sc->sc_ifmedia,
180: IFM_ETHER | IFM_10_T | IFM_HDX, 0, NULL);
181: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX;
182: }
183:
184: if (bmsr & PHY_BMSR_10BASET_FULL) {
185: ifmedia_add(&sc->sc_ifmedia,
186: IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL);
187: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_FDX;
188: }
189:
190: if (bmsr & PHY_BMSR_100BASETX_HALF) {
191: ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_100_TX, 0, NULL);
192: ifmedia_add(&sc->sc_ifmedia,
193: IFM_ETHER | IFM_100_TX | IFM_HDX, 0, NULL);
194: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_HDX;
195: }
196:
197: if (bmsr & PHY_BMSR_100BASETX_FULL) {
198: ifmedia_add(&sc->sc_ifmedia,
199: IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL);
200: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_FDX;
201: }
202:
203: if (bmsr & PHY_BMSR_100BASET4) {
204: ifmedia_add(&sc->sc_ifmedia,
205: IFM_ETHER | IFM_100_T4, 0, NULL);
206: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_T4;
207: }
208:
209: if (bmsr & PHY_BMSR_ANC) {
210: ifmedia_add(&sc->sc_ifmedia,
211: IFM_ETHER | IFM_AUTO, 0, NULL);
212: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_AUTO;
213: }
214:
215: ifmedia_set(&sc->sc_ifmedia, sc->sc_ifmedia.ifm_media);
216:
217: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
218: ifp->if_softc = sc;
219: ifp->if_start = bestart;
220: ifp->if_ioctl = beioctl;
221: ifp->if_watchdog = bewatchdog;
222: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
223: IFF_MULTICAST;
224:
225: IFQ_SET_MAXLEN(&ifp->if_snd, BE_TX_RING_SIZE);
226: IFQ_SET_READY(&ifp->if_snd);
227:
228: /* Attach the interface. */
229: if_attach(ifp);
230: ether_ifattach(ifp);
231:
232: printf(" pri %d: rev %x address %s\n", pri, sc->sc_rev,
233: ether_sprintf(sc->sc_arpcom.ac_enaddr));
234:
235: bp = ca->ca_ra.ra_bp;
236: if (bp != NULL && strcmp(bp->name, "be") == 0 &&
237: sc->sc_dev.dv_unit == bp->val[1])
238: bp->dev = &sc->sc_dev;
239: }
240:
241: /*
242: * Start output on interface.
243: * We make two assumptions here:
244: * 1) that the current priority is set to splnet _before_ this code
245: * is called *and* is returned to the appropriate priority after
246: * return
247: * 2) that the IFF_OACTIVE flag is checked before this code is called
248: * (i.e. that the output part of the interface is idle)
249: */
250: void
251: bestart(ifp)
252: struct ifnet *ifp;
253: {
254: struct besoftc *sc = (struct besoftc *)ifp->if_softc;
255: struct mbuf *m;
256: int bix, len, cnt;
257:
258: if (sc->sc_no_td > 0) {
259: /* Try to free previous stuff */
260: be_tx_harvest(sc);
261: }
262:
263: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
264: return;
265:
266: bix = sc->sc_last_td;
267: cnt = sc->sc_no_td;
268:
269: for (;;) {
270: IFQ_POLL(&ifp->if_snd, m);
271: if (m == NULL)
272: break;
273:
274: IFQ_DEQUEUE(&ifp->if_snd, m);
275:
276: #if NBPFILTER > 0
277: /*
278: * If BPF is listening on this interface, let it see the
279: * packet before we commit it to the wire.
280: */
281: if (ifp->if_bpf)
282: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
283: #endif
284:
285: /*
286: * Copy the mbuf chain into the transmit buffer.
287: */
288: len = qec_put(sc->sc_bufs->tx_buf[bix & BE_TX_RING_MASK], m);
289:
290: /*
291: * Initialize transmit registers and start transmission
292: */
293: sc->sc_desc->be_txd[bix].tx_flags =
294: BE_TXD_OWN | BE_TXD_SOP | BE_TXD_EOP |
295: (len & BE_TXD_LENGTH);
296: sc->sc_cr->ctrl = BE_CR_CTRL_TWAKEUP;
297:
298: if (++bix == BE_TX_RING_MAXSIZE)
299: bix = 0;
300:
301: if (++cnt == BE_TX_RING_SIZE) {
302: ifp->if_flags |= IFF_OACTIVE;
303: break;
304: }
305: }
306:
307: if (cnt > BE_TX_HIGH_WATER) {
308: /* turn on interrupt */
309: sc->sc_tx_intr = 1;
310: sc->sc_cr->timask = 0;
311: }
312:
313: if (cnt != sc->sc_no_td) {
314: ifp->if_timer = 5;
315: sc->sc_last_td = bix;
316: sc->sc_no_td = cnt;
317: }
318: }
319:
320: void
321: bestop(sc)
322: struct besoftc *sc;
323: {
324: int tries;
325:
326: sc->sc_arpcom.ac_if.if_timer = 0;
327: if (timeout_pending(&sc->sc_tick))
328: timeout_del(&sc->sc_tick);
329:
330: tries = 32;
331: sc->sc_br->tx_cfg = 0;
332: while (sc->sc_br->tx_cfg != 0 && --tries)
333: DELAY(20);
334:
335: tries = 32;
336: sc->sc_br->rx_cfg = 0;
337: while (sc->sc_br->rx_cfg != 0 && --tries)
338: DELAY(20);
339: }
340:
341: /*
342: * Reset interface.
343: */
344: void
345: bereset(sc)
346: struct besoftc *sc;
347: {
348: int s;
349:
350: s = splnet();
351: bestop(sc);
352: beinit(sc);
353: splx(s);
354: }
355:
356: void
357: bewatchdog(ifp)
358: struct ifnet *ifp;
359: {
360: struct besoftc *sc = ifp->if_softc;
361:
362: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
363: ++sc->sc_arpcom.ac_if.if_oerrors;
364:
365: bereset(sc);
366: }
367:
368: int
369: beintr(v)
370: void *v;
371: {
372: struct besoftc *sc = (struct besoftc *)v;
373: u_int32_t whyq, whyb, whyc;
374: int r = 0;
375:
376: whyq = sc->sc_qr->stat; /* qec status */
377: whyc = sc->sc_cr->stat; /* be channel status */
378: whyb = sc->sc_br->stat; /* be status */
379:
380: if (whyq & QEC_STAT_BM)
381: r |= beeint(sc, whyb);
382:
383: if (whyq & QEC_STAT_ER)
384: r |= beqint(sc, whyc);
385:
386: if (sc->sc_tx_intr && (whyq & QEC_STAT_TX) && (whyc & BE_CR_STAT_TXIRQ))
387: r |= betint(sc);
388:
389: if (whyq & QEC_STAT_RX && whyc & BE_CR_STAT_RXIRQ)
390: r |= berint(sc);
391:
392: return (r);
393: }
394:
395: /*
396: * QEC Interrupt.
397: */
398: int
399: beqint(sc, why)
400: struct besoftc *sc;
401: u_int32_t why;
402: {
403: int r = 0, rst = 0;
404:
405: if (why & BE_CR_STAT_TXIRQ)
406: r |= 1;
407: if (why & BE_CR_STAT_RXIRQ)
408: r |= 1;
409:
410: if (why & BE_CR_STAT_ERRORS) {
411: r |= 1;
412: rst = 1;
413: }
414:
415: if (rst || r == 0) {
416: printf("%s:%s qstat=%b\n", sc->sc_dev.dv_xname,
417: (r) ? "" : " unexpected",
418: why, BE_CR_STAT_BITS);
419: printf("%s: resetting\n", sc->sc_dev.dv_xname);
420: bereset(sc);
421: }
422:
423: return r;
424: }
425:
426: /*
427: * Error interrupt.
428: */
429: int
430: beeint(sc, why)
431: struct besoftc *sc;
432: u_int32_t why;
433: {
434: int r = 0;
435:
436: if (why & (BE_BR_STAT_RFIFOVF | BE_BR_STAT_TFIFO_UND |
437: BE_BR_STAT_MAXPKTERR)) {
438: r |= 1;
439: }
440:
441: printf("%s:%s stat=%b\n", sc->sc_dev.dv_xname,
442: (r) ? "" : " unexpected", why, BE_BR_STAT_BITS);
443:
444: printf("%s: resetting\n", sc->sc_dev.dv_xname);
445: bereset(sc);
446:
447: return r;
448: }
449:
450: void
451: be_tx_harvest(sc)
452: struct besoftc *sc;
453: {
454: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
455: int bix, cnt;
456: struct be_txd txd;
457:
458: bix = sc->sc_first_td;
459: cnt = sc->sc_no_td;
460:
461: for (;;) {
462: if (cnt <= 0)
463: break;
464:
465: txd.tx_flags = sc->sc_desc->be_txd[bix].tx_flags;
466:
467: if (txd.tx_flags & BE_TXD_OWN)
468: break;
469:
470: ifp->if_opackets++;
471:
472: if (++bix == BE_TX_RING_MAXSIZE)
473: bix = 0;
474:
475: --cnt;
476: }
477:
478: if (cnt <= 0)
479: ifp->if_timer = 0;
480:
481: if (sc->sc_no_td != cnt) {
482: sc->sc_first_td = bix;
483: sc->sc_no_td = cnt;
484: ifp->if_flags &= ~IFF_OACTIVE;
485: }
486:
487: if (sc->sc_no_td < BE_TX_LOW_WATER) {
488: /* turn off interrupt */
489: sc->sc_tx_intr = 0;
490: sc->sc_cr->timask = 0xffffffff;
491: }
492: }
493:
494: /*
495: * Transmit interrupt.
496: */
497: int
498: betint(sc)
499: struct besoftc *sc;
500: {
501: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
502:
503: bestart(ifp);
504: return (1);
505: }
506:
507: /*
508: * Receive interrupt.
509: */
510: int
511: berint(sc)
512: struct besoftc *sc;
513: {
514: int bix, len;
515:
516: bix = sc->sc_last_rd;
517:
518: /*
519: * Process all buffers with valid data.
520: */
521: for (;;) {
522: if (sc->sc_desc->be_rxd[bix].rx_flags & BE_RXD_OWN)
523: break;
524:
525: len = sc->sc_desc->be_rxd[bix].rx_flags & BE_RXD_LENGTH;
526: be_read(sc, bix, len);
527:
528: sc->sc_desc->be_rxd[(bix + BE_RX_RING_SIZE) & BE_RX_RING_MAXMASK].rx_flags =
529: BE_RXD_OWN | (BE_PKT_BUF_SZ & BE_RXD_LENGTH);
530:
531: if (++bix == BE_RX_RING_MAXSIZE)
532: bix = 0;
533: }
534:
535: sc->sc_last_rd = bix;
536:
537: return 1;
538: }
539:
540: void
541: betick(vsc)
542: void *vsc;
543: {
544: struct besoftc *sc = vsc;
545: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
546: struct be_bregs *br = sc->sc_br;
547: int s;
548:
549: s = splnet();
550: /*
551: * Get collision counters
552: */
553: ifp->if_collisions += br->nc_ctr + br->fc_ctr + br->ex_ctr + br->lt_ctr;
554: br->nc_ctr = 0;
555: br->fc_ctr = 0;
556: br->ex_ctr = 0;
557: br->lt_ctr = 0;
558: bestart(ifp);
559: splx(s);
560: timeout_add(&sc->sc_tick, hz);
561: }
562:
563: int
564: beioctl(ifp, cmd, data)
565: struct ifnet *ifp;
566: u_long cmd;
567: caddr_t data;
568: {
569: struct besoftc *sc = ifp->if_softc;
570: struct ifaddr *ifa = (struct ifaddr *)data;
571: struct ifreq *ifr = (struct ifreq *)data;
572: int s, error = 0;
573:
574: s = splnet();
575:
576: switch (cmd) {
577: case SIOCSIFADDR:
578: ifp->if_flags |= IFF_UP;
579: switch (ifa->ifa_addr->sa_family) {
580: #ifdef INET
581: case AF_INET:
582: beinit(sc);
583: arp_ifinit(&sc->sc_arpcom, ifa);
584: break;
585: #endif /* INET */
586: default:
587: beinit(sc);
588: break;
589: }
590: break;
591:
592: case SIOCSIFFLAGS:
593: if ((ifp->if_flags & IFF_UP) == 0 &&
594: (ifp->if_flags & IFF_RUNNING) != 0) {
595: /*
596: * If interface is marked down and it is running, then
597: * stop it.
598: */
599: bestop(sc);
600: ifp->if_flags &= ~IFF_RUNNING;
601: } else if ((ifp->if_flags & IFF_UP) != 0 &&
602: (ifp->if_flags & IFF_RUNNING) == 0) {
603: /*
604: * If interface is marked up and it is stopped, then
605: * start it.
606: */
607: beinit(sc);
608: } else {
609: /*
610: * Reset the interface to pick up changes in any other
611: * flags that affect hardware registers.
612: */
613: bestop(sc);
614: beinit(sc);
615: }
616: break;
617:
618: case SIOCADDMULTI:
619: case SIOCDELMULTI:
620: error = (cmd == SIOCADDMULTI) ?
621: ether_addmulti(ifr, &sc->sc_arpcom):
622: ether_delmulti(ifr, &sc->sc_arpcom);
623:
624: if (error == ENETRESET) {
625: /*
626: * Multicast list has changed; set the hardware filter
627: * accordingly.
628: */
629: if (ifp->if_flags & IFF_RUNNING)
630: be_mcreset(sc);
631: error = 0;
632: }
633: break;
634: case SIOCGIFMEDIA:
635: case SIOCSIFMEDIA:
636: error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
637: break;
638: default:
639: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
640: splx(s);
641: return error;
642: }
643: error = ENOTTY;
644: break;
645: }
646: splx(s);
647: return error;
648: }
649:
650: void
651: beinit(sc)
652: struct besoftc *sc;
653: {
654: struct be_bregs *br = sc->sc_br;
655: struct be_cregs *cr = sc->sc_cr;
656: struct qec_softc *qec = sc->sc_qec;
657: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
658: int s = splnet();
659: int i;
660:
661: /*
662: * Allocate descriptor ring and buffers, if not already done
663: */
664: if (sc->sc_desc == NULL)
665: sc->sc_desc_dva = (struct be_desc *) dvma_malloc(
666: sizeof(struct be_desc), &sc->sc_desc, M_NOWAIT);
667: if (sc->sc_bufs == NULL)
668: sc->sc_bufs_dva = (struct be_bufs *) dvma_malloc(
669: sizeof(struct be_bufs), &sc->sc_bufs, M_NOWAIT);
670:
671: for (i = 0; i < BE_TX_RING_MAXSIZE; i++) {
672: sc->sc_desc->be_txd[i].tx_addr =
673: (u_int32_t)sc->sc_bufs_dva->tx_buf[i & BE_TX_RING_MASK];
674: sc->sc_desc->be_txd[i].tx_flags = 0;
675: }
676: for (i = 0; i < BE_RX_RING_MAXSIZE; i++) {
677: sc->sc_desc->be_rxd[i].rx_addr =
678: (u_int32_t)sc->sc_bufs_dva->rx_buf[i & BE_RX_RING_MASK];
679: if (i < BE_RX_RING_SIZE)
680: sc->sc_desc->be_rxd[i].rx_flags =
681: BE_RXD_OWN | (BE_PKT_BUF_SZ & BE_RXD_LENGTH);
682: else
683: sc->sc_desc->be_rxd[i].rx_flags = 0;
684: }
685:
686: sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
687: sc->sc_last_rd = 0;
688:
689: be_tcvr_init(sc);
690:
691: be_ifmedia_upd(ifp);
692:
693: bestop(sc);
694:
695: br->mac_addr2 = (sc->sc_arpcom.ac_enaddr[4] << 8) |
696: sc->sc_arpcom.ac_enaddr[5];
697: br->mac_addr1 = (sc->sc_arpcom.ac_enaddr[2] << 8) |
698: sc->sc_arpcom.ac_enaddr[3];
699: br->mac_addr0 = (sc->sc_arpcom.ac_enaddr[0] << 8) |
700: sc->sc_arpcom.ac_enaddr[1];
701:
702: br->rx_cfg = BE_BR_RXCFG_HENABLE | BE_BR_RXCFG_FIFO;
703:
704: be_mcreset(sc);
705:
706: DELAY(20);
707:
708: br->tx_cfg = BE_BR_TXCFG_FIFO;
709: br->rand_seed = 0xbd;
710:
711: br->xif_cfg = BE_BR_XCFG_ODENABLE | BE_BR_XCFG_RESV;
712:
713: cr->rxds = (u_int32_t)sc->sc_desc_dva->be_rxd;
714: cr->txds = (u_int32_t)sc->sc_desc_dva->be_txd;
715:
716: cr->rxwbufptr = cr->rxrbufptr = sc->sc_channel * qec->sc_msize;
717: cr->txwbufptr = cr->txrbufptr = cr->rxrbufptr + qec->sc_rsize;
718:
719: /*
720: * Turn off counter expiration interrupts as well as
721: * 'gotframe' and 'sentframe'
722: */
723: br->imask = BE_BR_IMASK_GOTFRAME |
724: BE_BR_IMASK_RCNTEXP |
725: BE_BR_IMASK_ACNTEXP |
726: BE_BR_IMASK_CCNTEXP |
727: BE_BR_IMASK_LCNTEXP |
728: BE_BR_IMASK_CVCNTEXP |
729: BE_BR_IMASK_SENTFRAME |
730: BE_BR_IMASK_NCNTEXP |
731: BE_BR_IMASK_ECNTEXP |
732: BE_BR_IMASK_LCCNTEXP |
733: BE_BR_IMASK_FCNTEXP |
734: BE_BR_IMASK_DTIMEXP;
735:
736: cr->rimask = 0;
737:
738: /* disable tx interrupts initially */
739: cr->timask = 0xffffffff;
740: sc->sc_tx_intr = 0;
741:
742: cr->qmask = 0;
743: cr->bmask = 0;
744:
745: br->jsize = 4;
746:
747: cr->ccnt = 0;
748:
749: br->tx_cfg |= BE_BR_TXCFG_ENABLE;
750: br->rx_cfg |= BE_BR_RXCFG_ENABLE;
751:
752: ifp->if_flags |= IFF_RUNNING;
753: ifp->if_flags &= ~IFF_OACTIVE;
754: splx(s);
755:
756: timeout_add(&sc->sc_tick, hz);
757: bestart(ifp);
758: }
759:
760: /*
761: * Set the tcvr to an idle state
762: */
763: void
764: be_tcvr_idle(sc)
765: struct besoftc *sc;
766: {
767: struct be_tregs *tr = sc->sc_tr;
768: volatile u_int32_t x;
769: int i = 20;
770:
771: while (i--) {
772: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO |
773: MGMT_PAL_OENAB;
774: x = tr->mgmt_pal;
775: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO |
776: MGMT_PAL_OENAB | MGMT_PAL_DCLOCK;
777: x = tr->mgmt_pal;
778: }
779: }
780:
781: /*
782: * Initialize the transceiver and figure out whether we're using the
783: * external or internal one.
784: */
785: void
786: be_tcvr_init(sc)
787: struct besoftc *sc;
788: {
789: volatile u_int32_t x;
790: struct be_tregs *tr = sc->sc_tr;
791:
792: be_tcvr_idle(sc);
793:
794: if (sc->sc_rev != 1) {
795: printf("%s: rev %d PAL not supported.\n",
796: sc->sc_dev.dv_xname,
797: sc->sc_rev);
798: return;
799: }
800:
801: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
802: x = tr->mgmt_pal;
803:
804: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO;
805: x = tr->mgmt_pal;
806: DELAY(200);
807:
808: if (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) {
809: sc->sc_tcvr_type = BE_TCVR_EXTERNAL;
810: tr->tcvr_pal = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE |
811: TCVR_PAL_LTENABLE);
812: x = tr->tcvr_pal;
813: }
814: else if (tr->mgmt_pal & MGMT_PAL_INT_MDIO) {
815: sc->sc_tcvr_type = BE_TCVR_INTERNAL;
816: tr->tcvr_pal = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE |
817: TCVR_PAL_LTENABLE | TCVR_PAL_SERIAL);
818: x = tr->tcvr_pal;
819: }
820: else {
821: printf("%s: no internal or external transceiver found.\n",
822: sc->sc_dev.dv_xname);
823: }
824: }
825:
826: int
827: be_tcvr_read(sc, reg)
828: struct besoftc *sc;
829: u_int8_t reg;
830: {
831: int phy, i;
832: u_int32_t ret = 0;
833:
834: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL)
835: phy = BE_PHY_INTERNAL;
836: else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL)
837: phy = BE_PHY_EXTERNAL;
838: else {
839: printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
840: return BE_TCVR_READ_INVALID;
841: }
842:
843: be_tcvr_idle(sc);
844:
845: be_tcvr_write_bit(sc, 0);
846: be_tcvr_write_bit(sc, 1);
847: be_tcvr_write_bit(sc, 1);
848: be_tcvr_write_bit(sc, 0);
849:
850: for (i = 4; i >= 0; i--)
851: be_tcvr_write_bit(sc, (phy >> i) & 1);
852:
853: for (i = 4; i >= 0; i--)
854: be_tcvr_write_bit(sc, (reg >> i) & 1);
855:
856: if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
857: (void) be_tcvr_read_bit2(sc);
858: (void) be_tcvr_read_bit2(sc);
859:
860: for (i = 15; i >= 0; i--) {
861: int b;
862:
863: b = be_tcvr_read_bit2(sc);
864: ret |= (b & 1) << i;
865: }
866:
867: (void) be_tcvr_read_bit2(sc);
868: (void) be_tcvr_read_bit2(sc);
869: (void) be_tcvr_read_bit2(sc);
870: }
871: else {
872: (void) be_tcvr_read_bit1(sc);
873: (void) be_tcvr_read_bit1(sc);
874:
875: for (i = 15; i >= 0; i--) {
876: int b;
877:
878: b = be_tcvr_read_bit1(sc);
879: ret |= (b & 1) << i;
880: }
881:
882: (void) be_tcvr_read_bit1(sc);
883: (void) be_tcvr_read_bit1(sc);
884: (void) be_tcvr_read_bit1(sc);
885: }
886: return ret;
887: }
888:
889: int
890: be_tcvr_read_bit1(sc)
891: struct besoftc *sc;
892: {
893: volatile u_int32_t x;
894: struct be_tregs *tr = sc->sc_tr;
895: int ret = 0;
896:
897: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
898: tr->mgmt_pal = MGMT_PAL_EXT_MDIO;
899: x = tr->mgmt_pal;
900: tr->mgmt_pal = MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
901: x = tr->mgmt_pal;
902: DELAY(20);
903: ret = (tr->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3;
904: } else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
905: tr->mgmt_pal = MGMT_PAL_INT_MDIO;
906: x = tr->mgmt_pal;
907: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK;
908: x = tr->mgmt_pal;
909: DELAY(20);
910: ret = (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2;
911: } else {
912: printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
913: }
914: return (ret & 1);
915: }
916:
917: int
918: be_tcvr_read_bit2(sc)
919: struct besoftc *sc;
920: {
921: volatile u_int32_t x;
922: struct be_tregs *tr = sc->sc_tr;
923: int ret = 0;
924:
925: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
926: tr->mgmt_pal = MGMT_PAL_EXT_MDIO;
927: x = tr->mgmt_pal;
928: DELAY(20);
929: ret = (tr->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3;
930: tr->mgmt_pal = MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
931: x = tr->mgmt_pal;
932: } else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
933: tr->mgmt_pal = MGMT_PAL_INT_MDIO;
934: x = tr->mgmt_pal;
935: DELAY(20);
936: ret = (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2;
937: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK;
938: x = tr->mgmt_pal;
939: } else {
940: printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
941: }
942: return ret;
943: }
944:
945: void
946: be_tcvr_write(sc, reg, val)
947: struct besoftc *sc;
948: u_int8_t reg;
949: u_int16_t val;
950: {
951: int phy, i;
952:
953: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL)
954: phy = BE_PHY_INTERNAL;
955: else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL)
956: phy = BE_PHY_EXTERNAL;
957: else {
958: printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
959: return;
960: }
961:
962: be_tcvr_idle(sc);
963:
964: be_tcvr_write_bit(sc, 0);
965: be_tcvr_write_bit(sc, 1);
966: be_tcvr_write_bit(sc, 0);
967: be_tcvr_write_bit(sc, 1);
968:
969: for (i = 4; i >= 0; i--)
970: be_tcvr_write_bit(sc, (phy >> i) & 1);
971:
972: for (i = 4; i >= 0; i--)
973: be_tcvr_write_bit(sc, (reg >> i) & 1);
974:
975: be_tcvr_write_bit(sc, 1);
976: be_tcvr_write_bit(sc, 0);
977:
978: for (i = 15; i >= 0; i--)
979: be_tcvr_write_bit(sc, (val >> i) & 1);
980: }
981:
982: void
983: be_tcvr_write_bit(sc, bit)
984: struct besoftc *sc;
985: int bit;
986: {
987: volatile u_int32_t x;
988:
989: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
990: bit = ((bit & 1) << 3) | MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO;
991: sc->sc_tr->mgmt_pal = bit;
992: x = sc->sc_tr->mgmt_pal;
993: sc->sc_tr->mgmt_pal = bit | MGMT_PAL_DCLOCK;
994: x = sc->sc_tr->mgmt_pal;
995: } else {
996: bit = ((bit & 1) << 2) | MGMT_PAL_OENAB | MGMT_PAL_INT_MDIO;
997: sc->sc_tr->mgmt_pal = bit;
998: x = sc->sc_tr->mgmt_pal;
999: sc->sc_tr->mgmt_pal = bit | MGMT_PAL_DCLOCK;
1000: x = sc->sc_tr->mgmt_pal;
1001: }
1002: }
1003:
1004: /*
1005: * Pass a packet to the higher levels.
1006: */
1007: void
1008: be_read(sc, idx, len)
1009: struct besoftc *sc;
1010: int idx, len;
1011: {
1012: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1013: struct mbuf *m;
1014:
1015: if (len <= sizeof(struct ether_header) ||
1016: len > ETHERMTU + sizeof(struct ether_header)) {
1017:
1018: printf("%s: invalid packet size %d; dropping\n",
1019: ifp->if_xname, len);
1020:
1021: ifp->if_ierrors++;
1022: return;
1023: }
1024:
1025: /*
1026: * Pull packet off interface.
1027: */
1028: m = qec_get(ifp, sc->sc_bufs->rx_buf[idx & BE_RX_RING_MASK], len);
1029: if (m == NULL) {
1030: ifp->if_ierrors++;
1031: return;
1032: }
1033: ifp->if_ipackets++;
1034:
1035:
1036: #if NBPFILTER > 0
1037: /*
1038: * Check if there's a BPF listener on this interface.
1039: * If so, hand off the raw packet to BPF.
1040: */
1041: if (ifp->if_bpf)
1042: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1043: #endif
1044: /* Pass the packet up. */
1045: ether_input_mbuf(ifp, m);
1046: }
1047:
1048: /*
1049: * Get current media settings.
1050: */
1051: void
1052: be_ifmedia_sts(ifp, ifmr)
1053: struct ifnet *ifp;
1054: struct ifmediareq *ifmr;
1055: {
1056: struct besoftc *sc = ifp->if_softc;
1057: int bmcr, bmsr;
1058:
1059: bmcr = be_tcvr_read(sc, PHY_BMCR);
1060:
1061: switch (bmcr & (PHY_BMCR_SPEED | PHY_BMCR_DUPLEX)) {
1062: case (PHY_BMCR_SPEED | PHY_BMCR_DUPLEX):
1063: ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_FDX;
1064: break;
1065: case PHY_BMCR_SPEED:
1066: ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_HDX;
1067: break;
1068: case PHY_BMCR_DUPLEX:
1069: ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_FDX;
1070: break;
1071: case 0:
1072: ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_HDX;
1073: break;
1074: }
1075:
1076: bmsr = be_tcvr_read(sc, PHY_BMSR);
1077: if (bmsr & PHY_BMSR_LINKSTATUS)
1078: ifmr->ifm_status |= IFM_AVALID | IFM_ACTIVE;
1079: else {
1080: ifmr->ifm_status |= IFM_AVALID;
1081: ifmr->ifm_status &= ~IFM_ACTIVE;
1082: }
1083: }
1084:
1085: /*
1086: * Set media options.
1087: */
1088: int
1089: be_ifmedia_upd(ifp)
1090: struct ifnet *ifp;
1091: {
1092: struct besoftc *sc = ifp->if_softc;
1093: struct ifmedia *ifm = &sc->sc_ifmedia;
1094: int bmcr, tries;
1095:
1096: if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1097: return (EINVAL);
1098:
1099: be_tcvr_write(sc, PHY_BMCR,
1100: PHY_BMCR_LOOPBACK | PHY_BMCR_PDOWN | PHY_BMCR_ISOLATE);
1101: be_tcvr_write(sc, PHY_BMCR, PHY_BMCR_RESET);
1102:
1103: for (tries = 16; tries >= 0; tries--) {
1104: bmcr = be_tcvr_read(sc, PHY_BMCR);
1105: if ((bmcr & PHY_BMCR_RESET) == 0)
1106: break;
1107: DELAY(20);
1108: }
1109: if (tries == 0) {
1110: printf("%s: bmcr reset failed\n", sc->sc_dev.dv_xname);
1111: return (EIO);
1112: }
1113:
1114: bmcr = be_tcvr_read(sc, PHY_BMCR);
1115:
1116: if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_T4) {
1117: bmcr |= PHY_BMCR_SPEED;
1118: bmcr &= ~PHY_BMCR_DUPLEX;
1119: }
1120:
1121: if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) {
1122: bmcr |= PHY_BMCR_SPEED;
1123: }
1124:
1125: if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) {
1126: bmcr &= ~PHY_BMCR_SPEED;
1127: }
1128:
1129: if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
1130: bmcr |= PHY_BMCR_DUPLEX;
1131: sc->sc_br->tx_cfg |= BE_BR_TXCFG_FULLDPLX;
1132: }
1133: else {
1134: bmcr &= ~PHY_BMCR_DUPLEX;
1135: sc->sc_br->tx_cfg &= ~BE_BR_TXCFG_FULLDPLX;
1136: }
1137:
1138: be_tcvr_write(sc, PHY_BMCR, bmcr & (~PHY_BMCR_ISOLATE));
1139:
1140: for (tries = 32; tries >= 0; tries--) {
1141: bmcr = be_tcvr_read(sc, PHY_BMCR);
1142: if ((bmcr & PHY_BMCR_ISOLATE) == 0)
1143: break;
1144: DELAY(20);
1145: }
1146: if (tries == 0) {
1147: printf("%s: bmcr unisolate failed\n", sc->sc_dev.dv_xname);
1148: return (EIO);
1149: }
1150:
1151: return (0);
1152: }
1153:
1154: void
1155: be_mcreset(sc)
1156: struct besoftc *sc;
1157: {
1158: struct arpcom *ac = &sc->sc_arpcom;
1159: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1160: struct be_bregs *br = sc->sc_br;
1161: u_int32_t crc;
1162: u_int16_t hash[4];
1163: u_int8_t octet;
1164: int i, j;
1165: struct ether_multi *enm;
1166: struct ether_multistep step;
1167:
1168: if (ifp->if_flags & IFF_PROMISC) {
1169: br->rx_cfg |= BE_BR_RXCFG_PMISC;
1170: return;
1171: }
1172: else
1173: br->rx_cfg &= ~BE_BR_RXCFG_PMISC;
1174:
1175: if (ifp->if_flags & IFF_ALLMULTI) {
1176: br->htable3 = 0xffff;
1177: br->htable2 = 0xffff;
1178: br->htable1 = 0xffff;
1179: br->htable0 = 0xffff;
1180: return;
1181: }
1182:
1183: hash[3] = hash[2] = hash[1] = hash[0] = 0;
1184:
1185: ETHER_FIRST_MULTI(step, ac, enm);
1186: while (enm != NULL) {
1187: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1188: /*
1189: * We must listen to a range of multicast
1190: * addresses. For now, just accept all
1191: * multicasts, rather than trying to set only
1192: * those filter bits needed to match the range.
1193: * (At this time, the only use of address
1194: * ranges is for IP multicast routing, for
1195: * which the range is big enough to require
1196: * all bits set.)
1197: */
1198: br->htable3 = 0xffff;
1199: br->htable2 = 0xffff;
1200: br->htable1 = 0xffff;
1201: br->htable0 = 0xffff;
1202: ifp->if_flags |= IFF_ALLMULTI;
1203: return;
1204: }
1205:
1206: crc = 0xffffffff;
1207:
1208: for (i = 0; i < ETHER_ADDR_LEN; i++) {
1209: octet = enm->enm_addrlo[i];
1210:
1211: for (j = 0; j < 8; j++) {
1212: if ((crc & 1) ^ (octet & 1)) {
1213: crc >>= 1;
1214: crc ^= MC_POLY_LE;
1215: }
1216: else
1217: crc >>= 1;
1218: octet >>= 1;
1219: }
1220: }
1221:
1222: crc >>= 26;
1223: hash[crc >> 4] |= 1 << (crc & 0xf);
1224: ETHER_NEXT_MULTI(step, enm);
1225: }
1226:
1227: br->htable3 = hash[3];
1228: br->htable2 = hash[2];
1229: br->htable1 = hash[1];
1230: br->htable0 = hash[0];
1231: ifp->if_flags &= ~IFF_ALLMULTI;
1232: }
CVSweb