Annotation of sys/dev/sbus/qe.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: qe.c,v 1.20 2006/06/21 18:08:47 jason Exp $ */
2: /* $NetBSD: qe.c,v 1.16 2001/03/30 17:30:18 christos Exp $ */
3:
4: /*-
5: * Copyright (c) 1999 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Paul Kranenburg.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: /*
41: * Copyright (c) 1998 Jason L. Wright.
42: * All rights reserved.
43: *
44: * Redistribution and use in source and binary forms, with or without
45: * modification, are permitted provided that the following conditions
46: * are met:
47: * 1. Redistributions of source code must retain the above copyright
48: * notice, this list of conditions and the following disclaimer.
49: * 2. Redistributions in binary form must reproduce the above copyright
50: * notice, this list of conditions and the following disclaimer in the
51: * documentation and/or other materials provided with the distribution.
52: *
53: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
54: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56: * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
57: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
62: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63: */
64:
65: /*
66: * Driver for the SBus qec+qe QuadEthernet board.
67: *
68: * This driver was written using the AMD MACE Am79C940 documentation, some
69: * ideas gleaned from the S/Linux driver for this card, Solaris header files,
70: * and a loan of a card from Paul Southworth of the Internet Engineering
71: * Group (www.ieng.com).
72: */
73:
74: #define QEDEBUG
75:
76: #include "bpfilter.h"
77:
78: #include <sys/param.h>
79: #include <sys/systm.h>
80: #include <sys/kernel.h>
81: #include <sys/errno.h>
82: #include <sys/ioctl.h>
83: #include <sys/mbuf.h>
84: #include <sys/socket.h>
85: #include <sys/syslog.h>
86: #include <sys/device.h>
87: #include <sys/malloc.h>
88:
89: #include <net/if.h>
90: #include <net/if_dl.h>
91: #include <net/if_types.h>
92: #include <net/netisr.h>
93: #include <net/if_media.h>
94:
95: #ifdef INET
96: #include <netinet/in.h>
97: #include <netinet/in_systm.h>
98: #include <netinet/in_var.h>
99: #include <netinet/ip.h>
100: #include <netinet/if_ether.h>
101: #endif
102:
103: #if NBPFILTER > 0
104: #include <net/bpf.h>
105: #endif
106:
107: #include <machine/bus.h>
108: #include <machine/intr.h>
109: #include <machine/autoconf.h>
110:
111: #include <dev/sbus/sbusvar.h>
112: #include <dev/sbus/qecreg.h>
113: #include <dev/sbus/qecvar.h>
114: #include <dev/sbus/qereg.h>
115:
116: struct qe_softc {
117: struct device sc_dev; /* base device */
118: bus_space_tag_t sc_bustag; /* bus & dma tags */
119: bus_dma_tag_t sc_dmatag;
120: bus_dmamap_t sc_dmamap;
121: struct arpcom sc_arpcom;
122: struct ifmedia sc_ifmedia; /* interface media */
123:
124: struct qec_softc *sc_qec; /* QEC parent */
125:
126: bus_space_handle_t sc_qr; /* QEC registers */
127: bus_space_handle_t sc_mr; /* MACE registers */
128: bus_space_handle_t sc_cr; /* channel registers */
129:
130: int sc_channel; /* channel number */
131: u_int sc_rev; /* board revision */
132:
133: int sc_burst;
134:
135: struct qec_ring sc_rb; /* Packet Ring Buffer */
136:
137: #ifdef QEDEBUG
138: int sc_debug;
139: #endif
140: };
141:
142: int qematch(struct device *, void *, void *);
143: void qeattach(struct device *, struct device *, void *);
144:
145: void qeinit(struct qe_softc *);
146: void qestart(struct ifnet *);
147: void qestop(struct qe_softc *);
148: void qewatchdog(struct ifnet *);
149: int qeioctl(struct ifnet *, u_long, caddr_t);
150: void qereset(struct qe_softc *);
151:
152: int qeintr(void *);
153: int qe_eint(struct qe_softc *, u_int32_t);
154: int qe_rint(struct qe_softc *);
155: int qe_tint(struct qe_softc *);
156: void qe_mcreset(struct qe_softc *);
157:
158: int qe_put(struct qe_softc *, int, struct mbuf *);
159: void qe_read(struct qe_softc *, int, int);
160: struct mbuf *qe_get(struct qe_softc *, int, int);
161:
162: /* ifmedia callbacks */
163: void qe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
164: int qe_ifmedia_upd(struct ifnet *);
165:
166: struct cfattach qe_ca = {
167: sizeof(struct qe_softc), qematch, qeattach
168: };
169:
170: struct cfdriver qe_cd = {
171: NULL, "qe", DV_IFNET
172: };
173:
174: int
175: qematch(parent, vcf, aux)
176: struct device *parent;
177: void *vcf;
178: void *aux;
179: {
180: struct cfdata *cf = vcf;
181: struct sbus_attach_args *sa = aux;
182:
183: return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0);
184: }
185:
186: void
187: qeattach(parent, self, aux)
188: struct device *parent, *self;
189: void *aux;
190: {
191: struct sbus_attach_args *sa = aux;
192: struct qec_softc *qec = (struct qec_softc *)parent;
193: struct qe_softc *sc = (struct qe_softc *)self;
194: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
195: int node = sa->sa_node;
196: bus_dma_tag_t dmatag = sa->sa_dmatag;
197: bus_dma_segment_t seg;
198: bus_size_t size;
199: int rseg, error;
200: extern void myetheraddr(u_char *);
201:
202: /* Pass on the bus tags */
203: sc->sc_bustag = sa->sa_bustag;
204: sc->sc_dmatag = sa->sa_dmatag;
205:
206: if (sa->sa_nreg < 2) {
207: printf("%s: only %d register sets\n",
208: self->dv_xname, sa->sa_nreg);
209: return;
210: }
211:
212: if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
213: (bus_addr_t)sa->sa_reg[0].sbr_offset,
214: (bus_size_t)sa->sa_reg[0].sbr_size, 0, 0, &sc->sc_cr) != 0) {
215: printf("%s: cannot map registers\n", self->dv_xname);
216: return;
217: }
218:
219: if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
220: (bus_addr_t)sa->sa_reg[1].sbr_offset,
221: (bus_size_t)sa->sa_reg[1].sbr_size, 0, 0, &sc->sc_mr) != 0) {
222: printf("%s: cannot map registers\n", self->dv_xname);
223: return;
224: }
225:
226: sc->sc_rev = getpropint(node, "mace-version", -1);
227: printf(" rev %x", sc->sc_rev);
228:
229: sc->sc_qec = qec;
230: sc->sc_qr = qec->sc_regs;
231:
232: sc->sc_channel = getpropint(node, "channel#", -1);
233: sc->sc_burst = qec->sc_burst;
234:
235: qestop(sc);
236:
237: /* Note: no interrupt level passed */
238: if (bus_intr_establish(sa->sa_bustag, 0, IPL_NET, 0, qeintr, sc,
239: self->dv_xname) == NULL) {
240: printf(": no interrupt established\n");
241: return;
242: }
243:
244: myetheraddr(sc->sc_arpcom.ac_enaddr);
245:
246: /*
247: * Allocate descriptor ring and buffers.
248: */
249:
250: /* for now, allocate as many bufs as there are ring descriptors */
251: sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE;
252: sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE;
253:
254: size =
255: QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) +
256: QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) +
257: sc->sc_rb.rb_ntbuf * QE_PKT_BUF_SZ +
258: sc->sc_rb.rb_nrbuf * QE_PKT_BUF_SZ;
259:
260: /* Get a DMA handle */
261: if ((error = bus_dmamap_create(dmatag, size, 1, size, 0,
262: BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
263: printf("%s: DMA map create error %d\n", self->dv_xname, error);
264: return;
265: }
266:
267: /* Allocate DMA buffer */
268: if ((error = bus_dmamem_alloc(dmatag, size, 0, 0,
269: &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
270: printf("%s: DMA buffer alloc error %d\n",
271: self->dv_xname, error);
272: return;
273: }
274:
275: /* Map DMA buffer in CPU addressable space */
276: if ((error = bus_dmamem_map(dmatag, &seg, rseg, size,
277: &sc->sc_rb.rb_membase,
278: BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
279: printf("%s: DMA buffer map error %d\n",
280: self->dv_xname, error);
281: bus_dmamem_free(dmatag, &seg, rseg);
282: return;
283: }
284:
285: /* Load the buffer */
286: if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap,
287: sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) {
288: printf("%s: DMA buffer map load error %d\n",
289: self->dv_xname, error);
290: bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size);
291: bus_dmamem_free(dmatag, &seg, rseg);
292: return;
293: }
294: sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr;
295:
296: /* Initialize media properties */
297: ifmedia_init(&sc->sc_ifmedia, 0, qe_ifmedia_upd, qe_ifmedia_sts);
298: ifmedia_add(&sc->sc_ifmedia,
299: IFM_MAKEWORD(IFM_ETHER,IFM_10_T,0,0), 0, NULL);
300: ifmedia_add(&sc->sc_ifmedia,
301: IFM_MAKEWORD(IFM_ETHER,IFM_10_5,0,0), 0, NULL);
302: ifmedia_add(&sc->sc_ifmedia,
303: IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,0), 0, NULL);
304: ifmedia_set(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO);
305:
306: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
307: ifp->if_softc = sc;
308: ifp->if_start = qestart;
309: ifp->if_ioctl = qeioctl;
310: ifp->if_watchdog = qewatchdog;
311: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
312: IFF_MULTICAST;
313: IFQ_SET_READY(&ifp->if_snd);
314:
315: /* Attach the interface. */
316: if_attach(ifp);
317: ether_ifattach(ifp);
318:
319: printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
320: }
321:
322: /*
323: * Pull data off an interface.
324: * Len is the length of data, with local net header stripped.
325: * We copy the data into mbufs. When full cluster sized units are present,
326: * we copy into clusters.
327: */
328: struct mbuf *
329: qe_get(sc, idx, totlen)
330: struct qe_softc *sc;
331: int idx, totlen;
332: {
333: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
334: struct mbuf *m;
335: struct mbuf *top, **mp;
336: int len, pad, boff = 0;
337: caddr_t bp;
338:
339: bp = sc->sc_rb.rb_rxbuf + (idx % sc->sc_rb.rb_nrbuf) * QE_PKT_BUF_SZ;
340:
341: MGETHDR(m, M_DONTWAIT, MT_DATA);
342: if (m == NULL)
343: return (NULL);
344: m->m_pkthdr.rcvif = ifp;
345: m->m_pkthdr.len = totlen;
346: pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
347: m->m_data += pad;
348: len = MHLEN - pad;
349: top = NULL;
350: mp = ⊤
351:
352: while (totlen > 0) {
353: if (top) {
354: MGET(m, M_DONTWAIT, MT_DATA);
355: if (m == NULL) {
356: m_freem(top);
357: return (NULL);
358: }
359: len = MLEN;
360: }
361: if (top && totlen >= MINCLSIZE) {
362: MCLGET(m, M_DONTWAIT);
363: if (m->m_flags & M_EXT)
364: len = MCLBYTES;
365: }
366: m->m_len = len = min(totlen, len);
367: bcopy(bp + boff, mtod(m, caddr_t), len);
368: boff += len;
369: totlen -= len;
370: *mp = m;
371: mp = &m->m_next;
372: }
373:
374: return (top);
375: }
376:
377: /*
378: * Routine to copy from mbuf chain to transmit buffer in
379: * network buffer memory.
380: */
381: __inline__ int
382: qe_put(sc, idx, m)
383: struct qe_softc *sc;
384: int idx;
385: struct mbuf *m;
386: {
387: struct mbuf *n;
388: int len, tlen = 0, boff = 0;
389: caddr_t bp;
390:
391: bp = sc->sc_rb.rb_txbuf + (idx % sc->sc_rb.rb_ntbuf) * QE_PKT_BUF_SZ;
392:
393: for (; m; m = n) {
394: len = m->m_len;
395: if (len == 0) {
396: MFREE(m, n);
397: continue;
398: }
399: bcopy(mtod(m, caddr_t), bp+boff, len);
400: boff += len;
401: tlen += len;
402: MFREE(m, n);
403: }
404: return (tlen);
405: }
406:
407: /*
408: * Pass a packet to the higher levels.
409: */
410: __inline__ void
411: qe_read(sc, idx, len)
412: struct qe_softc *sc;
413: int idx, len;
414: {
415: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
416: struct mbuf *m;
417:
418: if (len <= sizeof(struct ether_header) ||
419: len > ETHERMTU + sizeof(struct ether_header)) {
420:
421: printf("%s: invalid packet size %d; dropping\n",
422: ifp->if_xname, len);
423:
424: ifp->if_ierrors++;
425: return;
426: }
427:
428: /*
429: * Pull packet off interface.
430: */
431: m = qe_get(sc, idx, len);
432: if (m == NULL) {
433: ifp->if_ierrors++;
434: return;
435: }
436: ifp->if_ipackets++;
437:
438: #if NBPFILTER > 0
439: /*
440: * Check if there's a BPF listener on this interface.
441: * If so, hand off the raw packet to BPF.
442: */
443: if (ifp->if_bpf)
444: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
445: #endif
446: /* Pass the packet up. */
447: ether_input_mbuf(ifp, m);
448: }
449:
450: /*
451: * Start output on interface.
452: * We make two assumptions here:
453: * 1) that the current priority is set to splnet _before_ this code
454: * is called *and* is returned to the appropriate priority after
455: * return
456: * 2) that the IFF_OACTIVE flag is checked before this code is called
457: * (i.e. that the output part of the interface is idle)
458: */
459: void
460: qestart(ifp)
461: struct ifnet *ifp;
462: {
463: struct qe_softc *sc = (struct qe_softc *)ifp->if_softc;
464: struct qec_xd *txd = sc->sc_rb.rb_txd;
465: struct mbuf *m;
466: unsigned int bix, len;
467: unsigned int ntbuf = sc->sc_rb.rb_ntbuf;
468:
469: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
470: return;
471:
472: bix = sc->sc_rb.rb_tdhead;
473:
474: for (;;) {
475: IFQ_POLL(&ifp->if_snd, m);
476: if (m == NULL)
477: break;
478:
479: IFQ_DEQUEUE(&ifp->if_snd, m);
480:
481: #if NBPFILTER > 0
482: /*
483: * If BPF is listening on this interface, let it see the
484: * packet before we commit it to the wire.
485: */
486: if (ifp->if_bpf)
487: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
488: #endif
489:
490: /*
491: * Copy the mbuf chain into the transmit buffer.
492: */
493: len = qe_put(sc, bix, m);
494:
495: /*
496: * Initialize transmit registers and start transmission
497: */
498: txd[bix].xd_flags = QEC_XD_OWN | QEC_XD_SOP | QEC_XD_EOP |
499: (len & QEC_XD_LENGTH);
500: bus_space_write_4(sc->sc_bustag, sc->sc_cr, QE_CRI_CTRL,
501: QE_CR_CTRL_TWAKEUP);
502:
503: if (++bix == QEC_XD_RING_MAXSIZE)
504: bix = 0;
505:
506: if (++sc->sc_rb.rb_td_nbusy == ntbuf) {
507: ifp->if_flags |= IFF_OACTIVE;
508: break;
509: }
510: }
511:
512: sc->sc_rb.rb_tdhead = bix;
513: }
514:
515: void
516: qestop(sc)
517: struct qe_softc *sc;
518: {
519: bus_space_tag_t t = sc->sc_bustag;
520: bus_space_handle_t mr = sc->sc_mr;
521: bus_space_handle_t cr = sc->sc_cr;
522: int n;
523:
524: /* Stop the schwurst */
525: bus_space_write_1(t, mr, QE_MRI_BIUCC, QE_MR_BIUCC_SWRST);
526: for (n = 200; n > 0; n--) {
527: if ((bus_space_read_1(t, mr, QE_MRI_BIUCC) &
528: QE_MR_BIUCC_SWRST) == 0)
529: break;
530: DELAY(20);
531: }
532:
533: /* then reset */
534: bus_space_write_4(t, cr, QE_CRI_CTRL, QE_CR_CTRL_RESET);
535: for (n = 200; n > 0; n--) {
536: if ((bus_space_read_4(t, cr, QE_CRI_CTRL) &
537: QE_CR_CTRL_RESET) == 0)
538: break;
539: DELAY(20);
540: }
541: }
542:
543: /*
544: * Reset interface.
545: */
546: void
547: qereset(sc)
548: struct qe_softc *sc;
549: {
550: int s;
551:
552: s = splnet();
553: qestop(sc);
554: qeinit(sc);
555: splx(s);
556: }
557:
558: void
559: qewatchdog(ifp)
560: struct ifnet *ifp;
561: {
562: struct qe_softc *sc = ifp->if_softc;
563:
564: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
565: ifp->if_oerrors++;
566:
567: qereset(sc);
568: }
569:
570: /*
571: * Interrupt dispatch.
572: */
573: int
574: qeintr(arg)
575: void *arg;
576: {
577: struct qe_softc *sc = (struct qe_softc *)arg;
578: bus_space_tag_t t = sc->sc_bustag;
579: u_int32_t qecstat, qestat;
580: int r = 0;
581:
582: /* Read QEC status and channel status */
583: qecstat = bus_space_read_4(t, sc->sc_qr, QEC_QRI_STAT);
584: #ifdef QEDEBUG
585: if (sc->sc_debug) {
586: printf("qe%d: intr: qecstat=%x\n", sc->sc_channel, qecstat);
587: }
588: #endif
589:
590: /* Filter out status for this channel */
591: qecstat = qecstat >> (4 * sc->sc_channel);
592: if ((qecstat & 0xf) == 0)
593: return (r);
594:
595: qestat = bus_space_read_4(t, sc->sc_cr, QE_CRI_STAT);
596:
597: #ifdef QEDEBUG
598: if (sc->sc_debug) {
599: int i;
600: bus_space_tag_t t = sc->sc_bustag;
601: bus_space_handle_t mr = sc->sc_mr;
602:
603: printf("qe%d: intr: qestat=%b\n", sc->sc_channel,
604: qestat, QE_CR_STAT_BITS);
605:
606: printf("MACE registers:\n");
607: for (i = 0 ; i < 32; i++) {
608: printf(" m[%d]=%x,", i, bus_space_read_1(t, mr, i));
609: if (((i+1) & 7) == 0)
610: printf("\n");
611: }
612: }
613: #endif
614:
615: if (qestat & QE_CR_STAT_ALLERRORS) {
616: #ifdef QEDEBUG
617: if (sc->sc_debug)
618: printf("qe%d: eint: qestat=%b\n", sc->sc_channel,
619: qestat, QE_CR_STAT_BITS);
620: #endif
621: r |= qe_eint(sc, qestat);
622: if (r == -1)
623: return (1);
624: }
625:
626: if (qestat & QE_CR_STAT_TXIRQ)
627: r |= qe_tint(sc);
628:
629: if (qestat & QE_CR_STAT_RXIRQ)
630: r |= qe_rint(sc);
631:
632: return (1);
633: }
634:
635: /*
636: * Transmit interrupt.
637: */
638: int
639: qe_tint(sc)
640: struct qe_softc *sc;
641: {
642: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
643: unsigned int bix, txflags;
644:
645: bix = sc->sc_rb.rb_tdtail;
646:
647: for (;;) {
648: if (sc->sc_rb.rb_td_nbusy <= 0)
649: break;
650:
651: txflags = sc->sc_rb.rb_txd[bix].xd_flags;
652:
653: if (txflags & QEC_XD_OWN)
654: break;
655:
656: ifp->if_flags &= ~IFF_OACTIVE;
657: ifp->if_opackets++;
658:
659: if (++bix == QEC_XD_RING_MAXSIZE)
660: bix = 0;
661:
662: --sc->sc_rb.rb_td_nbusy;
663: }
664:
665: if (sc->sc_rb.rb_td_nbusy == 0)
666: ifp->if_timer = 0;
667:
668: if (sc->sc_rb.rb_tdtail != bix) {
669: sc->sc_rb.rb_tdtail = bix;
670: if (ifp->if_flags & IFF_OACTIVE) {
671: ifp->if_flags &= ~IFF_OACTIVE;
672: qestart(ifp);
673: }
674: }
675:
676: return (1);
677: }
678:
679: /*
680: * Receive interrupt.
681: */
682: int
683: qe_rint(sc)
684: struct qe_softc *sc;
685: {
686: struct qec_xd *xd = sc->sc_rb.rb_rxd;
687: unsigned int bix, len;
688: unsigned int nrbuf = sc->sc_rb.rb_nrbuf;
689: #ifdef QEDEBUG
690: int npackets = 0;
691: #endif
692:
693: bix = sc->sc_rb.rb_rdtail;
694:
695: /*
696: * Process all buffers with valid data.
697: */
698: for (;;) {
699: len = xd[bix].xd_flags;
700: if (len & QEC_XD_OWN)
701: break;
702:
703: #ifdef QEDEBUG
704: npackets++;
705: #endif
706:
707: len &= QEC_XD_LENGTH;
708: len -= 4;
709: qe_read(sc, bix, len);
710:
711: /* ... */
712: xd[(bix+nrbuf) % QEC_XD_RING_MAXSIZE].xd_flags =
713: QEC_XD_OWN | (QE_PKT_BUF_SZ & QEC_XD_LENGTH);
714:
715: if (++bix == QEC_XD_RING_MAXSIZE)
716: bix = 0;
717: }
718: #ifdef QEDEBUG
719: if (npackets == 0 && sc->sc_debug)
720: printf("%s: rint: no packets; rb index %d; status 0x%x\n",
721: sc->sc_dev.dv_xname, bix, len);
722: #endif
723:
724: sc->sc_rb.rb_rdtail = bix;
725:
726: return (1);
727: }
728:
729: /*
730: * Error interrupt.
731: */
732: int
733: qe_eint(sc, why)
734: struct qe_softc *sc;
735: u_int32_t why;
736: {
737: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
738: int r = 0, rst = 0;
739:
740: if (why & QE_CR_STAT_EDEFER) {
741: printf("%s: excessive tx defers.\n", sc->sc_dev.dv_xname);
742: r |= 1;
743: ifp->if_oerrors++;
744: }
745:
746: if (why & QE_CR_STAT_CLOSS) {
747: ifp->if_oerrors++;
748: r |= 1;
749: }
750:
751: if (why & QE_CR_STAT_ERETRIES) {
752: printf("%s: excessive tx retries\n", sc->sc_dev.dv_xname);
753: ifp->if_oerrors++;
754: r |= 1;
755: rst = 1;
756: }
757:
758:
759: if (why & QE_CR_STAT_LCOLL) {
760: printf("%s: late tx transmission\n", sc->sc_dev.dv_xname);
761: ifp->if_oerrors++;
762: r |= 1;
763: rst = 1;
764: }
765:
766: if (why & QE_CR_STAT_FUFLOW) {
767: printf("%s: tx fifo underflow\n", sc->sc_dev.dv_xname);
768: ifp->if_oerrors++;
769: r |= 1;
770: rst = 1;
771: }
772:
773: if (why & QE_CR_STAT_JERROR) {
774: printf("%s: jabber seen\n", sc->sc_dev.dv_xname);
775: r |= 1;
776: }
777:
778: if (why & QE_CR_STAT_BERROR) {
779: printf("%s: babble seen\n", sc->sc_dev.dv_xname);
780: r |= 1;
781: }
782:
783: if (why & QE_CR_STAT_TCCOFLOW) {
784: ifp->if_collisions += 256;
785: ifp->if_oerrors += 256;
786: r |= 1;
787: }
788:
789: if (why & QE_CR_STAT_TXDERROR) {
790: printf("%s: tx descriptor is bad\n", sc->sc_dev.dv_xname);
791: rst = 1;
792: r |= 1;
793: }
794:
795: if (why & QE_CR_STAT_TXLERR) {
796: printf("%s: tx late error\n", sc->sc_dev.dv_xname);
797: ifp->if_oerrors++;
798: rst = 1;
799: r |= 1;
800: }
801:
802: if (why & QE_CR_STAT_TXPERR) {
803: printf("%s: tx dma parity error\n", sc->sc_dev.dv_xname);
804: ifp->if_oerrors++;
805: rst = 1;
806: r |= 1;
807: }
808:
809: if (why & QE_CR_STAT_TXSERR) {
810: printf("%s: tx dma sbus error ack\n", sc->sc_dev.dv_xname);
811: ifp->if_oerrors++;
812: rst = 1;
813: r |= 1;
814: }
815:
816: if (why & QE_CR_STAT_RCCOFLOW) {
817: ifp->if_collisions += 256;
818: ifp->if_ierrors += 256;
819: r |= 1;
820: }
821:
822: if (why & QE_CR_STAT_RUOFLOW) {
823: ifp->if_ierrors += 256;
824: r |= 1;
825: }
826:
827: if (why & QE_CR_STAT_MCOFLOW) {
828: ifp->if_ierrors += 256;
829: r |= 1;
830: }
831:
832: if (why & QE_CR_STAT_RXFOFLOW) {
833: printf("%s: rx fifo overflow\n", sc->sc_dev.dv_xname);
834: ifp->if_ierrors++;
835: r |= 1;
836: }
837:
838: if (why & QE_CR_STAT_RLCOLL) {
839: printf("%s: rx late collision\n", sc->sc_dev.dv_xname);
840: ifp->if_ierrors++;
841: ifp->if_collisions++;
842: r |= 1;
843: }
844:
845: if (why & QE_CR_STAT_FCOFLOW) {
846: ifp->if_ierrors += 256;
847: r |= 1;
848: }
849:
850: if (why & QE_CR_STAT_CECOFLOW) {
851: ifp->if_ierrors += 256;
852: r |= 1;
853: }
854:
855: if (why & QE_CR_STAT_RXDROP) {
856: printf("%s: rx packet dropped\n", sc->sc_dev.dv_xname);
857: ifp->if_ierrors++;
858: r |= 1;
859: }
860:
861: if (why & QE_CR_STAT_RXSMALL) {
862: printf("%s: rx buffer too small\n", sc->sc_dev.dv_xname);
863: ifp->if_ierrors++;
864: r |= 1;
865: rst = 1;
866: }
867:
868: if (why & QE_CR_STAT_RXLERR) {
869: printf("%s: rx late error\n", sc->sc_dev.dv_xname);
870: ifp->if_ierrors++;
871: r |= 1;
872: rst = 1;
873: }
874:
875: if (why & QE_CR_STAT_RXPERR) {
876: printf("%s: rx dma parity error\n", sc->sc_dev.dv_xname);
877: ifp->if_ierrors++;
878: r |= 1;
879: rst = 1;
880: }
881:
882: if (why & QE_CR_STAT_RXSERR) {
883: printf("%s: rx dma sbus error ack\n", sc->sc_dev.dv_xname);
884: ifp->if_ierrors++;
885: r |= 1;
886: rst = 1;
887: }
888:
889: if (r == 0)
890: printf("%s: unexpected interrupt error: %08x\n",
891: sc->sc_dev.dv_xname, why);
892:
893: if (rst) {
894: printf("%s: resetting...\n", sc->sc_dev.dv_xname);
895: qereset(sc);
896: return (-1);
897: }
898:
899: return (r);
900: }
901:
902: int
903: qeioctl(ifp, cmd, data)
904: struct ifnet *ifp;
905: u_long cmd;
906: caddr_t data;
907: {
908: struct qe_softc *sc = ifp->if_softc;
909: struct ifaddr *ifa = (struct ifaddr *)data;
910: struct ifreq *ifr = (struct ifreq *)data;
911: int s, error = 0;
912:
913: s = splnet();
914:
915: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
916: splx(s);
917: return (error);
918: }
919:
920: switch (cmd) {
921: case SIOCSIFADDR:
922: ifp->if_flags |= IFF_UP;
923: switch (ifa->ifa_addr->sa_family) {
924: #ifdef INET
925: case AF_INET:
926: qeinit(sc);
927: arp_ifinit(&sc->sc_arpcom, ifa);
928: break;
929: #endif /* INET */
930: default:
931: qeinit(sc);
932: break;
933: }
934: break;
935:
936: case SIOCSIFFLAGS:
937: if ((ifp->if_flags & IFF_UP) == 0 &&
938: (ifp->if_flags & IFF_RUNNING) != 0) {
939: /*
940: * If interface is marked down and it is running, then
941: * stop it.
942: */
943: qestop(sc);
944: ifp->if_flags &= ~IFF_RUNNING;
945: } else if ((ifp->if_flags & IFF_UP) != 0 &&
946: (ifp->if_flags & IFF_RUNNING) == 0) {
947: /*
948: * If interface is marked up and it is stopped, then
949: * start it.
950: */
951: qeinit(sc);
952: } else {
953: /*
954: * Reset the interface to pick up changes in any other
955: * flags that affect hardware registers.
956: */
957: qestop(sc);
958: qeinit(sc);
959: }
960: #ifdef QEDEBUG
961: sc->sc_debug = (ifp->if_flags & IFF_DEBUG) != 0 ? 1 : 0;
962: #endif
963: break;
964:
965: case SIOCADDMULTI:
966: case SIOCDELMULTI:
967: error = (cmd == SIOCADDMULTI) ?
968: ether_addmulti(ifr, &sc->sc_arpcom):
969: ether_delmulti(ifr, &sc->sc_arpcom);
970:
971: if (error == ENETRESET) {
972: /*
973: * Multicast list has changed; set the hardware filter
974: * accordingly.
975: */
976: if (ifp->if_flags & IFF_RUNNING)
977: qe_mcreset(sc);
978: error = 0;
979: }
980: break;
981:
982: case SIOCGIFMEDIA:
983: case SIOCSIFMEDIA:
984: error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
985: break;
986:
987: default:
988: error = EINVAL;
989: break;
990: }
991:
992: splx(s);
993: return (error);
994: }
995:
996:
997: void
998: qeinit(sc)
999: struct qe_softc *sc;
1000: {
1001: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1002: bus_space_tag_t t = sc->sc_bustag;
1003: bus_space_handle_t cr = sc->sc_cr;
1004: bus_space_handle_t mr = sc->sc_mr;
1005: struct qec_softc *qec = sc->sc_qec;
1006: u_int32_t qecaddr;
1007: u_int8_t *ea;
1008: int s;
1009:
1010: s = splnet();
1011:
1012: qestop(sc);
1013:
1014: /*
1015: * Allocate descriptor ring and buffers
1016: */
1017: qec_meminit(&sc->sc_rb, QE_PKT_BUF_SZ);
1018:
1019: /* Channel registers: */
1020: bus_space_write_4(t, cr, QE_CRI_RXDS, (u_int32_t)sc->sc_rb.rb_rxddma);
1021: bus_space_write_4(t, cr, QE_CRI_TXDS, (u_int32_t)sc->sc_rb.rb_txddma);
1022:
1023: bus_space_write_4(t, cr, QE_CRI_RIMASK, 0);
1024: bus_space_write_4(t, cr, QE_CRI_TIMASK, 0);
1025: bus_space_write_4(t, cr, QE_CRI_QMASK, 0);
1026: bus_space_write_4(t, cr, QE_CRI_MMASK, QE_CR_MMASK_RXCOLL);
1027: bus_space_write_4(t, cr, QE_CRI_CCNT, 0);
1028: bus_space_write_4(t, cr, QE_CRI_PIPG, 0);
1029:
1030: qecaddr = sc->sc_channel * qec->sc_msize;
1031: bus_space_write_4(t, cr, QE_CRI_RXWBUF, qecaddr);
1032: bus_space_write_4(t, cr, QE_CRI_RXRBUF, qecaddr);
1033: bus_space_write_4(t, cr, QE_CRI_TXWBUF, qecaddr + qec->sc_rsize);
1034: bus_space_write_4(t, cr, QE_CRI_TXRBUF, qecaddr + qec->sc_rsize);
1035:
1036: /*
1037: * When switching from mace<->qec always guarantee an sbus
1038: * turnaround (if last op was read, perform a dummy write, and
1039: * vice versa).
1040: */
1041: bus_space_read_4(t, cr, QE_CRI_QMASK);
1042:
1043: /* MACE registers: */
1044: bus_space_write_1(t, mr, QE_MRI_PHYCC, QE_MR_PHYCC_ASEL);
1045: bus_space_write_1(t, mr, QE_MRI_XMTFC, QE_MR_XMTFC_APADXMT);
1046: bus_space_write_1(t, mr, QE_MRI_RCVFC, 0);
1047:
1048: /*
1049: * Mask MACE's receive interrupt, since we're being notified
1050: * by the QEC after DMA completes.
1051: */
1052: bus_space_write_1(t, mr, QE_MRI_IMR,
1053: QE_MR_IMR_CERRM | QE_MR_IMR_RCVINTM);
1054:
1055: bus_space_write_1(t, mr, QE_MRI_BIUCC,
1056: QE_MR_BIUCC_BSWAP | QE_MR_BIUCC_64TS);
1057:
1058: bus_space_write_1(t, mr, QE_MRI_FIFOFC,
1059: QE_MR_FIFOCC_TXF16 | QE_MR_FIFOCC_RXF32 |
1060: QE_MR_FIFOCC_RFWU | QE_MR_FIFOCC_TFWU);
1061:
1062: bus_space_write_1(t, mr, QE_MRI_PLSCC, QE_MR_PLSCC_TP);
1063:
1064: /*
1065: * Station address
1066: */
1067: ea = sc->sc_arpcom.ac_enaddr;
1068: bus_space_write_1(t, mr, QE_MRI_IAC,
1069: QE_MR_IAC_ADDRCHG | QE_MR_IAC_PHYADDR);
1070: bus_space_write_multi_1(t, mr, QE_MRI_PADR, ea, 6);
1071:
1072: /* Apply media settings */
1073: qe_ifmedia_upd(ifp);
1074:
1075: /*
1076: * Clear Logical address filter
1077: */
1078: bus_space_write_1(t, mr, QE_MRI_IAC,
1079: QE_MR_IAC_ADDRCHG | QE_MR_IAC_LOGADDR);
1080: bus_space_set_multi_1(t, mr, QE_MRI_LADRF, 0, 8);
1081: bus_space_write_1(t, mr, QE_MRI_IAC, 0);
1082:
1083: /* Clear missed packet count (register cleared on read) */
1084: (void)bus_space_read_1(t, mr, QE_MRI_MPC);
1085:
1086: #if 0
1087: /* test register: */
1088: bus_space_write_1(t, mr, QE_MRI_UTR, 0);
1089: #endif
1090:
1091: /* Reset multicast filter */
1092: qe_mcreset(sc);
1093:
1094: ifp->if_flags |= IFF_RUNNING;
1095: ifp->if_flags &= ~IFF_OACTIVE;
1096: splx(s);
1097: }
1098:
1099: /*
1100: * Reset multicast filter.
1101: */
1102: void
1103: qe_mcreset(sc)
1104: struct qe_softc *sc;
1105: {
1106: struct arpcom *ac = &sc->sc_arpcom;
1107: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1108: bus_space_tag_t t = sc->sc_bustag;
1109: bus_space_handle_t mr = sc->sc_mr;
1110: struct ether_multi *enm;
1111: struct ether_multistep step;
1112: u_int32_t crc;
1113: u_int16_t hash[4];
1114: u_int8_t octet, maccc, *ladrp = (u_int8_t *)&hash[0];
1115: int i, j;
1116:
1117: /* We also enable transmitter & receiver here */
1118: maccc = QE_MR_MACCC_ENXMT | QE_MR_MACCC_ENRCV;
1119:
1120: if (ifp->if_flags & IFF_PROMISC) {
1121: maccc |= QE_MR_MACCC_PROM;
1122: bus_space_write_1(t, mr, QE_MRI_MACCC, maccc);
1123: return;
1124: }
1125:
1126: if (ifp->if_flags & IFF_ALLMULTI) {
1127: bus_space_write_1(t, mr, QE_MRI_IAC,
1128: QE_MR_IAC_ADDRCHG | QE_MR_IAC_LOGADDR);
1129: bus_space_set_multi_1(t, mr, QE_MRI_LADRF, 0xff, 8);
1130: bus_space_write_1(t, mr, QE_MRI_IAC, 0);
1131: bus_space_write_1(t, mr, QE_MRI_MACCC, maccc);
1132: return;
1133: }
1134:
1135: hash[3] = hash[2] = hash[1] = hash[0] = 0;
1136:
1137: ETHER_FIRST_MULTI(step, ac, enm);
1138: while (enm != NULL) {
1139: if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
1140: ETHER_ADDR_LEN) != 0) {
1141: /*
1142: * We must listen to a range of multicast
1143: * addresses. For now, just accept all
1144: * multicasts, rather than trying to set only
1145: * those filter bits needed to match the range.
1146: * (At this time, the only use of address
1147: * ranges is for IP multicast routing, for
1148: * which the range is big enough to require
1149: * all bits set.)
1150: */
1151: bus_space_write_1(t, mr, QE_MRI_IAC,
1152: QE_MR_IAC_ADDRCHG | QE_MR_IAC_LOGADDR);
1153: bus_space_set_multi_1(t, mr, QE_MRI_LADRF, 0xff, 8);
1154: bus_space_write_1(t, mr, QE_MRI_IAC, 0);
1155: ifp->if_flags |= IFF_ALLMULTI;
1156: break;
1157: }
1158:
1159: crc = 0xffffffff;
1160:
1161: for (i = 0; i < ETHER_ADDR_LEN; i++) {
1162: octet = enm->enm_addrlo[i];
1163:
1164: for (j = 0; j < 8; j++) {
1165: if ((crc & 1) ^ (octet & 1)) {
1166: crc >>= 1;
1167: crc ^= MC_POLY_LE;
1168: }
1169: else
1170: crc >>= 1;
1171: octet >>= 1;
1172: }
1173: }
1174:
1175: crc >>= 26;
1176: hash[crc >> 4] |= 1 << (crc & 0xf);
1177: ETHER_NEXT_MULTI(step, enm);
1178: }
1179:
1180: bus_space_write_1(t, mr, QE_MRI_IAC,
1181: QE_MR_IAC_ADDRCHG | QE_MR_IAC_LOGADDR);
1182: bus_space_write_multi_1(t, mr, QE_MRI_LADRF, ladrp, 8);
1183: bus_space_write_1(t, mr, QE_MRI_IAC, 0);
1184: bus_space_write_1(t, mr, QE_MRI_MACCC, maccc);
1185: }
1186:
1187: /*
1188: * Get current media settings.
1189: */
1190: void
1191: qe_ifmedia_sts(ifp, ifmr)
1192: struct ifnet *ifp;
1193: struct ifmediareq *ifmr;
1194: {
1195: struct qe_softc *sc = ifp->if_softc;
1196: u_int8_t phycc;
1197:
1198: ifmr->ifm_active = IFM_ETHER | IFM_10_T;
1199: phycc = bus_space_read_1(sc->sc_bustag, sc->sc_mr, QE_MRI_PHYCC);
1200: if ((phycc & QE_MR_PHYCC_DLNKTST) == 0) {
1201: ifmr->ifm_status |= IFM_AVALID;
1202: if (phycc & QE_MR_PHYCC_LNKFL)
1203: ifmr->ifm_status &= ~IFM_ACTIVE;
1204: else
1205: ifmr->ifm_status |= IFM_ACTIVE;
1206: }
1207: }
1208:
1209: /*
1210: * Set media options.
1211: */
1212: int
1213: qe_ifmedia_upd(ifp)
1214: struct ifnet *ifp;
1215: {
1216: struct qe_softc *sc = ifp->if_softc;
1217: int media = sc->sc_ifmedia.ifm_media;
1218:
1219: if (IFM_TYPE(media) != IFM_ETHER)
1220: return (EINVAL);
1221:
1222: if (IFM_SUBTYPE(media) != IFM_10_T)
1223: return (EINVAL);
1224:
1225: return (0);
1226: }
CVSweb