Annotation of sys/dev/pci/if_bce.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_bce.c,v 1.20 2007/05/21 10:30:10 reyk Exp $ */
2: /* $NetBSD: if_bce.c,v 1.3 2003/09/29 01:53:02 mrg Exp $ */
3:
4: /*
5: * Copyright (c) 2003 Clifford Wright. 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: * 3. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: * SUCH DAMAGE.
29: */
30:
31: /*
32: * Broadcom BCM440x 10/100 ethernet (broadcom.com)
33: * SiliconBackplane is technology from Sonics, Inc.(sonicsinc.com)
34: *
35: * Cliff Wright cliff@snipe444.org
36: */
37:
38: #include "bpfilter.h"
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/timeout.h>
43: #include <sys/sockio.h>
44: #include <sys/mbuf.h>
45: #include <sys/malloc.h>
46: #include <sys/kernel.h>
47: #include <sys/device.h>
48: #include <sys/socket.h>
49:
50: #include <net/if.h>
51: #include <net/if_dl.h>
52: #include <net/if_media.h>
53:
54: #ifdef INET
55: #include <netinet/in.h>
56: #include <netinet/in_systm.h>
57: #include <netinet/in_var.h>
58: #include <netinet/ip.h>
59: #include <netinet/if_ether.h>
60: #endif
61: #if NBPFILTER > 0
62: #include <net/bpf.h>
63: #endif
64:
65: #include <dev/pci/pcireg.h>
66: #include <dev/pci/pcivar.h>
67: #include <dev/pci/pcidevs.h>
68:
69: #include <dev/mii/mii.h>
70: #include <dev/mii/miivar.h>
71: #include <dev/mii/miidevs.h>
72: #include <dev/mii/brgphyreg.h>
73:
74: #include <dev/pci/if_bcereg.h>
75:
76: #include <uvm/uvm_extern.h>
77:
78: /* transmit buffer max frags allowed */
79: #define BCE_NTXFRAGS 16
80:
81: /* ring descriptor */
82: struct bce_dma_slot {
83: u_int32_t ctrl;
84: u_int32_t addr;
85: };
86: #define CTRL_BC_MASK 0x1fff /* buffer byte count */
87: #define CTRL_EOT 0x10000000 /* end of descriptor table */
88: #define CTRL_IOC 0x20000000 /* interrupt on completion */
89: #define CTRL_EOF 0x40000000 /* end of frame */
90: #define CTRL_SOF 0x80000000 /* start of frame */
91:
92: /* Packet status is returned in a pre-packet header */
93: struct rx_pph {
94: u_int16_t len;
95: u_int16_t flags;
96: u_int16_t pad[12];
97: };
98:
99: #define BCE_PREPKT_HEADER_SIZE 30
100:
101: /* packet status flags bits */
102: #define RXF_NO 0x8 /* odd number of nibbles */
103: #define RXF_RXER 0x4 /* receive symbol error */
104: #define RXF_CRC 0x2 /* crc error */
105: #define RXF_OV 0x1 /* fifo overflow */
106:
107: /* number of descriptors used in a ring */
108: #define BCE_NRXDESC 128
109: #define BCE_NTXDESC 128
110:
111: /*
112: * Mbuf pointers. We need these to keep track of the virtual addresses
113: * of our mbuf chains since we can only convert from physical to virtual,
114: * not the other way around.
115: */
116: struct bce_chain_data {
117: struct mbuf *bce_tx_chain[BCE_NTXDESC];
118: struct mbuf *bce_rx_chain[BCE_NRXDESC];
119: bus_dmamap_t bce_tx_map[BCE_NTXDESC];
120: bus_dmamap_t bce_rx_map[BCE_NRXDESC];
121: };
122:
123: #define BCE_TIMEOUT 100 /* # 10us for mii read/write */
124:
125: struct bce_softc {
126: struct device bce_dev;
127: bus_space_tag_t bce_btag;
128: bus_space_handle_t bce_bhandle;
129: bus_dma_tag_t bce_dmatag;
130: struct arpcom bce_ac; /* interface info */
131: void *bce_intrhand;
132: struct pci_attach_args bce_pa;
133: struct mii_data bce_mii;
134: u_int32_t bce_phy; /* eeprom indicated phy */
135: struct bce_dma_slot *bce_rx_ring; /* receive ring */
136: struct bce_dma_slot *bce_tx_ring; /* transmit ring */
137: struct bce_chain_data bce_cdata; /* mbufs */
138: bus_dmamap_t bce_ring_map;
139: u_int32_t bce_intmask; /* current intr mask */
140: u_int32_t bce_rxin; /* last rx descriptor seen */
141: u_int32_t bce_txin; /* last tx descriptor seen */
142: int bce_txsfree; /* no. tx slots available */
143: int bce_txsnext; /* next available tx slot */
144: struct timeout bce_timeout;
145: };
146:
147: /* for ring descriptors */
148: #define BCE_RXBUF_LEN (MCLBYTES - 4)
149: #define BCE_INIT_RXDESC(sc, x) \
150: do { \
151: struct bce_dma_slot *__bced = &sc->bce_rx_ring[x]; \
152: \
153: *mtod(sc->bce_cdata.bce_rx_chain[x], u_int32_t *) = 0; \
154: __bced->addr = \
155: htole32(sc->bce_cdata.bce_rx_map[x]->dm_segs[0].ds_addr \
156: + 0x40000000); \
157: if (x != (BCE_NRXDESC - 1)) \
158: __bced->ctrl = htole32(BCE_RXBUF_LEN); \
159: else \
160: __bced->ctrl = htole32(BCE_RXBUF_LEN | CTRL_EOT); \
161: bus_dmamap_sync(sc->bce_dmatag, sc->bce_ring_map, \
162: sizeof(struct bce_dma_slot) * x, \
163: sizeof(struct bce_dma_slot), \
164: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
165: } while (/* CONSTCOND */ 0)
166:
167: int bce_probe(struct device *, void *, void *);
168: void bce_attach(struct device *, struct device *, void *);
169: int bce_ioctl(struct ifnet *, u_long, caddr_t);
170: void bce_start(struct ifnet *);
171: void bce_watchdog(struct ifnet *);
172: int bce_intr(void *);
173: void bce_rxintr(struct bce_softc *);
174: void bce_txintr(struct bce_softc *);
175: int bce_init(struct ifnet *);
176: void bce_add_mac(struct bce_softc *, u_int8_t *, unsigned long);
177: int bce_add_rxbuf(struct bce_softc *, int);
178: void bce_rxdrain(struct bce_softc *);
179: void bce_stop(struct ifnet *, int);
180: void bce_reset(struct bce_softc *);
181: void bce_set_filter(struct ifnet *);
182: int bce_mii_read(struct device *, int, int);
183: void bce_mii_write(struct device *, int, int, int);
184: void bce_statchg(struct device *);
185: int bce_mediachange(struct ifnet *);
186: void bce_mediastatus(struct ifnet *, struct ifmediareq *);
187: void bce_tick(void *);
188:
189: #ifdef BCE_DEBUG
190: #define DPRINTF(x) do { \
191: if (bcedebug) \
192: printf x; \
193: } while (/* CONSTCOND */ 0)
194: #define DPRINTFN(n,x) do { \
195: if (bcedebug >= (n)) \
196: printf x; \
197: } while (/* CONSTCOND */ 0)
198: int bcedebug = 0;
199: #else
200: #define DPRINTF(x)
201: #define DPRINTFN(n,x)
202: #endif
203:
204: struct cfattach bce_ca = {
205: sizeof(struct bce_softc), bce_probe, bce_attach
206: };
207: struct cfdriver bce_cd = {
208: 0, "bce", DV_IFNET
209: };
210:
211: const struct pci_matchid bce_devices[] = {
212: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4401 },
213: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4401B0 },
214: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4401B1 }
215: };
216:
217: int
218: bce_probe(struct device *parent, void *match, void *aux)
219: {
220: return (pci_matchbyid((struct pci_attach_args *)aux, bce_devices,
221: sizeof(bce_devices)/sizeof(bce_devices[0])));
222: }
223:
224: void
225: bce_attach(struct device *parent, struct device *self, void *aux)
226: {
227: struct bce_softc *sc = (struct bce_softc *) self;
228: struct pci_attach_args *pa = aux;
229: pci_chipset_tag_t pc = pa->pa_pc;
230: pci_intr_handle_t ih;
231: const char *intrstr = NULL;
232: caddr_t kva;
233: bus_dma_segment_t seg;
234: int rseg;
235: struct ifnet *ifp;
236: pcireg_t memtype;
237: bus_addr_t memaddr;
238: bus_size_t memsize;
239: int pmreg;
240: pcireg_t pmode;
241: int error;
242: int i;
243:
244: sc->bce_pa = *pa;
245: sc->bce_dmatag = pa->pa_dmat;
246:
247: /*
248: * Map control/status registers.
249: */
250: memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BCE_PCI_BAR0);
251: switch (memtype) {
252: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
253: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
254: if (pci_mapreg_map(pa, BCE_PCI_BAR0, memtype, 0, &sc->bce_btag,
255: &sc->bce_bhandle, &memaddr, &memsize, 0) == 0)
256: break;
257: default:
258: printf("%s: unable to find mem space\n",
259: sc->bce_dev.dv_xname);
260: return;
261: }
262:
263: /* Get it out of power save mode if needed. */
264: if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
265: pmode = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3;
266: if (pmode == 3) {
267: /*
268: * The card has lost all configuration data in
269: * this state, so punt.
270: */
271: printf("%s: unable to wake up from power state D3\n",
272: sc->bce_dev.dv_xname);
273: return;
274: }
275: if (pmode != 0) {
276: printf("%s: waking up from power state D%d\n",
277: sc->bce_dev.dv_xname, pmode);
278: pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0);
279: }
280: }
281: if (pci_intr_map(pa, &ih)) {
282: printf("%s: couldn't map interrupt\n",
283: sc->bce_dev.dv_xname);
284: return;
285: }
286: intrstr = pci_intr_string(pc, ih);
287:
288: sc->bce_intrhand = pci_intr_establish(pc, ih, IPL_NET, bce_intr, sc,
289: self->dv_xname);
290:
291: if (sc->bce_intrhand == NULL) {
292: printf("%s: couldn't establish interrupt",
293: sc->bce_dev.dv_xname);
294: if (intrstr != NULL)
295: printf(" at %s", intrstr);
296: printf("\n");
297: return;
298: }
299:
300: /* reset the chip */
301: bce_reset(sc);
302:
303: /*
304: * Allocate DMA-safe memory for ring descriptors.
305: * The receive, and transmit rings can not share the same
306: * 4k space, however both are allocated at once here.
307: */
308: /*
309: * XXX PAGE_SIZE is wasteful; we only need 1KB + 1KB, but
310: * due to the limition above. ??
311: */
312: if ((error = bus_dmamem_alloc(sc->bce_dmatag,
313: 2 * PAGE_SIZE, PAGE_SIZE, 2 * PAGE_SIZE,
314: &seg, 1, &rseg, BUS_DMA_NOWAIT))) {
315: printf("%s: unable to alloc space for ring descriptors, "
316: "error = %d\n", sc->bce_dev.dv_xname, error);
317: return;
318: }
319: /* map ring space to kernel */
320: if ((error = bus_dmamem_map(sc->bce_dmatag, &seg, rseg,
321: 2 * PAGE_SIZE, &kva, BUS_DMA_NOWAIT))) {
322: printf("%s: unable to map DMA buffers, error = %d\n",
323: sc->bce_dev.dv_xname, error);
324: bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
325: return;
326: }
327: /* create a dma map for the ring */
328: if ((error = bus_dmamap_create(sc->bce_dmatag,
329: 2 * PAGE_SIZE, 1, 2 * PAGE_SIZE, 0, BUS_DMA_NOWAIT,
330: &sc->bce_ring_map))) {
331: printf("%s: unable to create ring DMA map, error = %d\n",
332: sc->bce_dev.dv_xname, error);
333: bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE);
334: bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
335: return;
336: }
337: /* connect the ring space to the dma map */
338: if (bus_dmamap_load(sc->bce_dmatag, sc->bce_ring_map, kva,
339: 2 * PAGE_SIZE, NULL, BUS_DMA_NOWAIT)) {
340: bus_dmamap_destroy(sc->bce_dmatag, sc->bce_ring_map);
341: bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE);
342: bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
343: return;
344: }
345: /* save the ring space in softc */
346: sc->bce_rx_ring = (struct bce_dma_slot *) kva;
347: sc->bce_tx_ring = (struct bce_dma_slot *) (kva + PAGE_SIZE);
348:
349: /* Create the transmit buffer DMA maps. */
350: for (i = 0; i < BCE_NTXDESC; i++) {
351: if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES,
352: BCE_NTXFRAGS, MCLBYTES, 0, 0, &sc->bce_cdata.bce_tx_map[i])) != 0) {
353: printf("%s: unable to create tx DMA map, error = %d\n",
354: sc->bce_dev.dv_xname, error);
355: }
356: sc->bce_cdata.bce_tx_chain[i] = NULL;
357: }
358:
359: /* Create the receive buffer DMA maps. */
360: for (i = 0; i < BCE_NRXDESC; i++) {
361: if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, 1,
362: MCLBYTES, 0, 0, &sc->bce_cdata.bce_rx_map[i])) != 0) {
363: printf("%s: unable to create rx DMA map, error = %d\n",
364: sc->bce_dev.dv_xname, error);
365: }
366: sc->bce_cdata.bce_rx_chain[i] = NULL;
367: }
368:
369: /* Set up ifnet structure */
370: ifp = &sc->bce_ac.ac_if;
371: strlcpy(ifp->if_xname, sc->bce_dev.dv_xname, IF_NAMESIZE);
372: ifp->if_softc = sc;
373: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
374: ifp->if_ioctl = bce_ioctl;
375: ifp->if_start = bce_start;
376: ifp->if_watchdog = bce_watchdog;
377: ifp->if_init = bce_init;
378: IFQ_SET_READY(&ifp->if_snd);
379:
380: ifp->if_capabilities = IFCAP_VLAN_MTU;
381:
382: /* MAC address */
383: sc->bce_ac.ac_enaddr[0] =
384: bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET0);
385: sc->bce_ac.ac_enaddr[1] =
386: bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET1);
387: sc->bce_ac.ac_enaddr[2] =
388: bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET2);
389: sc->bce_ac.ac_enaddr[3] =
390: bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET3);
391: sc->bce_ac.ac_enaddr[4] =
392: bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET4);
393: sc->bce_ac.ac_enaddr[5] =
394: bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET5);
395: printf(": %s, address %s\n", intrstr,
396: ether_sprintf(sc->bce_ac.ac_enaddr));
397:
398: /* Initialize our media structures and probe the MII. */
399:
400: sc->bce_mii.mii_ifp = ifp;
401: sc->bce_mii.mii_readreg = bce_mii_read;
402: sc->bce_mii.mii_writereg = bce_mii_write;
403: sc->bce_mii.mii_statchg = bce_statchg;
404: ifmedia_init(&sc->bce_mii.mii_media, 0, bce_mediachange,
405: bce_mediastatus);
406: mii_attach(&sc->bce_dev, &sc->bce_mii, 0xffffffff, MII_PHY_ANY,
407: MII_OFFSET_ANY, 0);
408: if (LIST_FIRST(&sc->bce_mii.mii_phys) == NULL) {
409: ifmedia_add(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
410: ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE);
411: } else
412: ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_AUTO);
413: /* get the phy */
414: sc->bce_phy = bus_space_read_1(sc->bce_btag, sc->bce_bhandle,
415: BCE_PHY) & 0x1f;
416: /*
417: * Enable activity led.
418: * XXX This should be in a phy driver, but not currently.
419: */
420: bce_mii_write((struct device *) sc, 1, 26, /* MAGIC */
421: bce_mii_read((struct device *) sc, 1, 26) & 0x7fff); /* MAGIC */
422: /* enable traffic meter led mode */
423: bce_mii_write((struct device *) sc, 1, 27, /* MAGIC */
424: bce_mii_read((struct device *) sc, 1, 27) | (1 << 6)); /* MAGIC */
425:
426:
427: /* Attach the interface */
428: if_attach(ifp);
429: ether_ifattach(ifp);
430: timeout_set(&sc->bce_timeout, bce_tick, sc);
431: }
432:
433: /* handle media, and ethernet requests */
434: int
435: bce_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
436: {
437: struct bce_softc *sc = ifp->if_softc;
438: struct ifreq *ifr = (struct ifreq *) data;
439: struct ifaddr *ifa = (struct ifaddr *)data;
440: int s, error = 0;
441:
442: s = splnet();
443:
444: if ((error = ether_ioctl(ifp, &sc->bce_ac, cmd, data)) > 0) {
445: splx(s);
446: return (error);
447: }
448:
449: switch (cmd) {
450: case SIOCSIFADDR:
451: ifp->if_flags |= IFF_UP;
452:
453: switch (ifa->ifa_addr->sa_family) {
454: #ifdef INET
455: case AF_INET:
456: bce_init(ifp);
457: arp_ifinit(&sc->bce_ac, ifa);
458: break;
459: #endif /* INET */
460: default:
461: bce_init(ifp);
462: break;
463: }
464: break;
465: case SIOCSIFMTU:
466: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
467: error = EINVAL;
468: else if (ifp->if_mtu != ifr->ifr_mtu)
469: ifp->if_mtu = ifr->ifr_mtu;
470: break;
471: case SIOCSIFFLAGS:
472: if(ifp->if_flags & IFF_UP)
473: if(ifp->if_flags & IFF_RUNNING)
474: bce_set_filter(ifp);
475: else
476: bce_init(ifp);
477: else if(ifp->if_flags & IFF_RUNNING)
478: bce_stop(ifp, 0);
479:
480: break;
481: case SIOCADDMULTI:
482: case SIOCDELMULTI:
483: error = (cmd == SIOCADDMULTI) ?
484: ether_addmulti(ifr, &sc->bce_ac) :
485: ether_delmulti(ifr, &sc->bce_ac);
486:
487: if (error == ENETRESET) {
488: /*
489: * Multicast list has changed; set the hardware
490: * filter accordingly.
491: */
492: if (ifp->if_flags & IFF_RUNNING)
493: bce_set_filter(ifp);
494: error = 0;
495: }
496: break;
497: case SIOCSIFMEDIA:
498: case SIOCGIFMEDIA:
499: error = ifmedia_ioctl(ifp, ifr, &sc->bce_mii.mii_media, cmd);
500: break;
501: default:
502: error = ENOTTY;
503: break;
504: }
505:
506: if (error == 0) {
507: /* Try to get more packets going. */
508: bce_start(ifp);
509: }
510:
511: splx(s);
512: return error;
513: }
514:
515: /* Start packet transmission on the interface. */
516: void
517: bce_start(struct ifnet *ifp)
518: {
519: struct bce_softc *sc = ifp->if_softc;
520: struct mbuf *m0;
521: bus_dmamap_t dmamap;
522: int txstart;
523: int txsfree;
524: int newpkts = 0;
525: int error;
526:
527: /*
528: * do not start another if currently transmitting, and more
529: * descriptors(tx slots) are needed for next packet.
530: */
531: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
532: return;
533:
534: /* determine number of descriptors available */
535: if (sc->bce_txsnext >= sc->bce_txin)
536: txsfree = BCE_NTXDESC - 1 + sc->bce_txin - sc->bce_txsnext;
537: else
538: txsfree = sc->bce_txin - sc->bce_txsnext - 1;
539:
540: /*
541: * Loop through the send queue, setting up transmit descriptors
542: * until we drain the queue, or use up all available transmit
543: * descriptors.
544: */
545: while (txsfree > 0) {
546: int seg;
547:
548: /* Grab a packet off the queue. */
549: IFQ_POLL(&ifp->if_snd, m0);
550: if (m0 == NULL)
551: break;
552:
553: /* get the transmit slot dma map */
554: dmamap = sc->bce_cdata.bce_tx_map[sc->bce_txsnext];
555:
556: /*
557: * Load the DMA map. If this fails, the packet either
558: * didn't fit in the alloted number of segments, or we
559: * were short on resources. If the packet will not fit,
560: * it will be dropped. If short on resources, it will
561: * be tried again later.
562: */
563: error = bus_dmamap_load_mbuf(sc->bce_dmatag, dmamap, m0,
564: BUS_DMA_WRITE | BUS_DMA_NOWAIT);
565: if (error == EFBIG) {
566: printf("%s: Tx packet consumes too many DMA segments, "
567: "dropping...\n", sc->bce_dev.dv_xname);
568: IFQ_DEQUEUE(&ifp->if_snd, m0);
569: m_freem(m0);
570: ifp->if_oerrors++;
571: continue;
572: } else if (error) {
573: /* short on resources, come back later */
574: printf("%s: unable to load Tx buffer, error = %d\n",
575: sc->bce_dev.dv_xname, error);
576: break;
577: }
578: /* If not enough descriptors available, try again later */
579: if (dmamap->dm_nsegs > txsfree) {
580: ifp->if_flags |= IFF_OACTIVE;
581: bus_dmamap_unload(sc->bce_dmatag, dmamap);
582: break;
583: }
584: /* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. */
585:
586: /* So take it off the queue */
587: IFQ_DEQUEUE(&ifp->if_snd, m0);
588:
589: /* save the pointer so it can be freed later */
590: sc->bce_cdata.bce_tx_chain[sc->bce_txsnext] = m0;
591:
592: /* Sync the data DMA map. */
593: bus_dmamap_sync(sc->bce_dmatag, dmamap, 0, dmamap->dm_mapsize,
594: BUS_DMASYNC_PREWRITE);
595:
596: /* Initialize the transmit descriptor(s). */
597: txstart = sc->bce_txsnext;
598: for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
599: u_int32_t ctrl;
600:
601: ctrl = dmamap->dm_segs[seg].ds_len & CTRL_BC_MASK;
602: if (seg == 0)
603: ctrl |= CTRL_SOF;
604: if (seg == dmamap->dm_nsegs - 1)
605: ctrl |= CTRL_EOF;
606: if (sc->bce_txsnext == BCE_NTXDESC - 1)
607: ctrl |= CTRL_EOT;
608: ctrl |= CTRL_IOC;
609: sc->bce_tx_ring[sc->bce_txsnext].ctrl = htole32(ctrl);
610: sc->bce_tx_ring[sc->bce_txsnext].addr =
611: htole32(dmamap->dm_segs[seg].ds_addr + 0x40000000); /* MAGIC */
612: if (sc->bce_txsnext + 1 > BCE_NTXDESC - 1)
613: sc->bce_txsnext = 0;
614: else
615: sc->bce_txsnext++;
616: txsfree--;
617: }
618: /* sync descriptors being used */
619: bus_dmamap_sync(sc->bce_dmatag, sc->bce_ring_map,
620: sizeof(struct bce_dma_slot) * txstart + PAGE_SIZE,
621: sizeof(struct bce_dma_slot) * dmamap->dm_nsegs,
622: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
623:
624: /* Give the packet to the chip. */
625: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_DPTR,
626: sc->bce_txsnext * sizeof(struct bce_dma_slot));
627:
628: newpkts++;
629:
630: #if NBPFILTER > 0
631: /* Pass the packet to any BPF listeners. */
632: if (ifp->if_bpf)
633: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
634: #endif /* NBPFILTER > 0 */
635: }
636: if (txsfree == 0) {
637: /* No more slots left; notify upper layer. */
638: ifp->if_flags |= IFF_OACTIVE;
639: }
640: if (newpkts) {
641: /* Set a watchdog timer in case the chip flakes out. */
642: ifp->if_timer = 5;
643: }
644: }
645:
646: /* Watchdog timer handler. */
647: void
648: bce_watchdog(struct ifnet *ifp)
649: {
650: struct bce_softc *sc = ifp->if_softc;
651:
652: printf("%s: device timeout\n", sc->bce_dev.dv_xname);
653: ifp->if_oerrors++;
654:
655: (void) bce_init(ifp);
656:
657: /* Try to get more packets going. */
658: bce_start(ifp);
659: }
660:
661: int
662: bce_intr(void *xsc)
663: {
664: struct bce_softc *sc;
665: struct ifnet *ifp;
666: u_int32_t intstatus;
667: int wantinit;
668: int handled = 0;
669:
670: sc = xsc;
671: ifp = &sc->bce_ac.ac_if;
672:
673:
674: for (wantinit = 0; wantinit == 0;) {
675: intstatus = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
676: BCE_INT_STS);
677:
678: /* ignore if not ours, or unsolicited interrupts */
679: intstatus &= sc->bce_intmask;
680: if (intstatus == 0)
681: break;
682:
683: handled = 1;
684:
685: /* Ack interrupt */
686: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_INT_STS,
687: intstatus);
688:
689: /* Receive interrupts. */
690: if (intstatus & I_RI)
691: bce_rxintr(sc);
692: /* Transmit interrupts. */
693: if (intstatus & I_XI)
694: bce_txintr(sc);
695: /* Error interrupts */
696: if (intstatus & ~(I_RI | I_XI)) {
697: if (intstatus & I_XU)
698: printf("%s: transmit fifo underflow\n",
699: sc->bce_dev.dv_xname);
700: if (intstatus & I_RO) {
701: printf("%s: receive fifo overflow\n",
702: sc->bce_dev.dv_xname);
703: ifp->if_ierrors++;
704: }
705: if (intstatus & I_RU)
706: printf("%s: receive descriptor underflow\n",
707: sc->bce_dev.dv_xname);
708: if (intstatus & I_DE)
709: printf("%s: descriptor protocol error\n",
710: sc->bce_dev.dv_xname);
711: if (intstatus & I_PD)
712: printf("%s: data error\n",
713: sc->bce_dev.dv_xname);
714: if (intstatus & I_PC)
715: printf("%s: descriptor error\n",
716: sc->bce_dev.dv_xname);
717: if (intstatus & I_TO)
718: printf("%s: general purpose timeout\n",
719: sc->bce_dev.dv_xname);
720: wantinit = 1;
721: }
722: }
723:
724: if (handled) {
725: if (wantinit)
726: bce_init(ifp);
727: /* Try to get more packets going. */
728: bce_start(ifp);
729: }
730: return (handled);
731: }
732:
733: /* Receive interrupt handler */
734: void
735: bce_rxintr(struct bce_softc *sc)
736: {
737: struct ifnet *ifp = &sc->bce_ac.ac_if;
738: struct rx_pph *pph;
739: struct mbuf *m;
740: int curr;
741: int len;
742: int i;
743:
744: /* get pointer to active receive slot */
745: curr = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXSTATUS)
746: & RS_CD_MASK;
747: curr = curr / sizeof(struct bce_dma_slot);
748: if (curr >= BCE_NRXDESC)
749: curr = BCE_NRXDESC - 1;
750:
751: /* process packets up to but not current packet being worked on */
752: for (i = sc->bce_rxin; i != curr;
753: i + 1 > BCE_NRXDESC - 1 ? i = 0 : i++) {
754: /* complete any post dma memory ops on packet */
755: bus_dmamap_sync(sc->bce_dmatag, sc->bce_cdata.bce_rx_map[i], 0,
756: sc->bce_cdata.bce_rx_map[i]->dm_mapsize,
757: BUS_DMASYNC_POSTREAD);
758:
759: /*
760: * If the packet had an error, simply recycle the buffer,
761: * resetting the len, and flags.
762: */
763: pph = mtod(sc->bce_cdata.bce_rx_chain[i], struct rx_pph *);
764: if (pph->flags & (RXF_NO | RXF_RXER | RXF_CRC | RXF_OV)) {
765: ifp->if_ierrors++;
766: pph->len = 0;
767: pph->flags = 0;
768: continue;
769: }
770: /* receive the packet */
771: len = pph->len;
772: if (len == 0)
773: continue; /* no packet if empty */
774: pph->len = 0;
775: pph->flags = 0;
776: /* bump past pre header to packet */
777: sc->bce_cdata.bce_rx_chain[i]->m_data +=
778: BCE_PREPKT_HEADER_SIZE;
779:
780: /*
781: * The chip includes the CRC with every packet. Trim
782: * it off here.
783: */
784: len -= ETHER_CRC_LEN;
785:
786: /*
787: * If the packet is small enough to fit in a
788: * single header mbuf, allocate one and copy
789: * the data into it. This greatly reduces
790: * memory consumption when receiving lots
791: * of small packets.
792: *
793: * Otherwise, add a new buffer to the receive
794: * chain. If this fails, drop the packet and
795: * recycle the old buffer.
796: */
797: if (len <= (MHLEN - 2)) {
798: MGETHDR(m, M_DONTWAIT, MT_DATA);
799: if (m == NULL)
800: goto dropit;
801: m->m_data += 2;
802: memcpy(mtod(m, caddr_t),
803: mtod(sc->bce_cdata.bce_rx_chain[i], caddr_t), len);
804: sc->bce_cdata.bce_rx_chain[i]->m_data -=
805: BCE_PREPKT_HEADER_SIZE;
806: } else {
807: m = sc->bce_cdata.bce_rx_chain[i];
808: if (bce_add_rxbuf(sc, i) != 0) {
809: dropit:
810: ifp->if_ierrors++;
811: /* continue to use old buffer */
812: sc->bce_cdata.bce_rx_chain[i]->m_data -=
813: BCE_PREPKT_HEADER_SIZE;
814: bus_dmamap_sync(sc->bce_dmatag,
815: sc->bce_cdata.bce_rx_map[i], 0,
816: sc->bce_cdata.bce_rx_map[i]->dm_mapsize,
817: BUS_DMASYNC_PREREAD);
818: continue;
819: }
820: }
821:
822: m->m_pkthdr.rcvif = ifp;
823: m->m_pkthdr.len = m->m_len = len;
824: ifp->if_ipackets++;
825:
826: #if NBPFILTER > 0
827: /*
828: * Pass this up to any BPF listeners, but only
829: * pass it up the stack if it's for us.
830: */
831: if (ifp->if_bpf)
832: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
833: #endif /* NBPFILTER > 0 */
834:
835: /* Pass it on. */
836: ether_input_mbuf(ifp, m);
837:
838: /* re-check current in case it changed */
839: curr = (bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
840: BCE_DMA_RXSTATUS) & RS_CD_MASK) /
841: sizeof(struct bce_dma_slot);
842: if (curr >= BCE_NRXDESC)
843: curr = BCE_NRXDESC - 1;
844: }
845: sc->bce_rxin = curr;
846: }
847:
848: /* Transmit interrupt handler */
849: void
850: bce_txintr(struct bce_softc *sc)
851: {
852: struct ifnet *ifp = &sc->bce_ac.ac_if;
853: int curr;
854: int i;
855:
856: ifp->if_flags &= ~IFF_OACTIVE;
857:
858: /*
859: * Go through the Tx list and free mbufs for those
860: * frames which have been transmitted.
861: */
862: curr = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXSTATUS) &
863: RS_CD_MASK;
864: curr = curr / sizeof(struct bce_dma_slot);
865: if (curr >= BCE_NTXDESC)
866: curr = BCE_NTXDESC - 1;
867: for (i = sc->bce_txin; i != curr;
868: i + 1 > BCE_NTXDESC - 1 ? i = 0 : i++) {
869: /* do any post dma memory ops on transmit data */
870: if (sc->bce_cdata.bce_tx_chain[i] == NULL)
871: continue;
872: bus_dmamap_sync(sc->bce_dmatag, sc->bce_cdata.bce_tx_map[i], 0,
873: sc->bce_cdata.bce_tx_map[i]->dm_mapsize,
874: BUS_DMASYNC_POSTWRITE);
875: bus_dmamap_unload(sc->bce_dmatag, sc->bce_cdata.bce_tx_map[i]);
876: m_freem(sc->bce_cdata.bce_tx_chain[i]);
877: sc->bce_cdata.bce_tx_chain[i] = NULL;
878: ifp->if_opackets++;
879: }
880: sc->bce_txin = curr;
881:
882: /*
883: * If there are no more pending transmissions, cancel the watchdog
884: * timer
885: */
886: if (sc->bce_txsnext == sc->bce_txin)
887: ifp->if_timer = 0;
888: }
889:
890: /* initialize the interface */
891: int
892: bce_init(struct ifnet *ifp)
893: {
894: struct bce_softc *sc = ifp->if_softc;
895: u_int32_t reg_win;
896: int error;
897: int i;
898:
899: /* Cancel any pending I/O. */
900: bce_stop(ifp, 0);
901:
902: /* enable pci inerrupts, bursts, and prefetch */
903:
904: /* remap the pci registers to the Sonics config registers */
905:
906: /* save the current map, so it can be restored */
907: reg_win = pci_conf_read(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag,
908: BCE_REG_WIN);
909:
910: /* set register window to Sonics registers */
911: pci_conf_write(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag, BCE_REG_WIN,
912: BCE_SONICS_WIN);
913:
914: /* enable SB to PCI interrupt */
915: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBINTVEC,
916: bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBINTVEC) |
917: SBIV_ENET0);
918:
919: /* enable prefetch and bursts for sonics-to-pci translation 2 */
920: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SPCI_TR2,
921: bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SPCI_TR2) |
922: SBTOPCI_PREF | SBTOPCI_BURST);
923:
924: /* restore to ethernet register space */
925: pci_conf_write(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag, BCE_REG_WIN,
926: reg_win);
927:
928: /* Reset the chip to a known state. */
929: bce_reset(sc);
930:
931: /* Initialize transmit descriptors */
932: memset(sc->bce_tx_ring, 0, BCE_NTXDESC * sizeof(struct bce_dma_slot));
933: sc->bce_txsnext = 0;
934: sc->bce_txin = 0;
935:
936: /* enable crc32 generation and set proper LED modes */
937: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MACCTL,
938: bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MACCTL) |
939: BCE_EMC_CRC32_ENAB | BCE_EMC_LED);
940:
941: /* reset or clear powerdown control bit */
942: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MACCTL,
943: bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MACCTL) &
944: ~BCE_EMC_PDOWN);
945:
946: /* setup DMA interrupt control */
947: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMAI_CTL, 1 << 24); /* MAGIC */
948:
949: /* setup packet filter */
950: bce_set_filter(ifp);
951:
952: /* set max frame length, account for possible VLAN tag */
953: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_MAX,
954: ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
955: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_MAX,
956: ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
957:
958: /* set tx watermark */
959: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_WATER, 56);
960:
961: /* enable transmit */
962: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXCTL, XC_XE);
963: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXADDR,
964: sc->bce_ring_map->dm_segs[0].ds_addr + PAGE_SIZE + 0x40000000); /* MAGIC */
965:
966: /*
967: * Give the receive ring to the chip, and
968: * start the receive DMA engine.
969: */
970: sc->bce_rxin = 0;
971:
972: /* clear the rx descriptor ring */
973: memset(sc->bce_rx_ring, 0, BCE_NRXDESC * sizeof(struct bce_dma_slot));
974: /* enable receive */
975: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXCTL,
976: BCE_PREPKT_HEADER_SIZE << 1 | XC_XE);
977: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXADDR,
978: sc->bce_ring_map->dm_segs[0].ds_addr + 0x40000000); /* MAGIC */
979:
980: /* Initalize receive descriptors */
981: for (i = 0; i < BCE_NRXDESC; i++) {
982: if (sc->bce_cdata.bce_rx_chain[i] == NULL) {
983: if ((error = bce_add_rxbuf(sc, i)) != 0) {
984: printf("%s: unable to allocate or map rx(%d) "
985: "mbuf, error = %d\n", sc->bce_dev.dv_xname,
986: i, error);
987: bce_rxdrain(sc);
988: return (error);
989: }
990: } else
991: BCE_INIT_RXDESC(sc, i);
992: }
993:
994: /* Enable interrupts */
995: sc->bce_intmask =
996: I_XI | I_RI | I_XU | I_RO | I_RU | I_DE | I_PD | I_PC | I_TO;
997: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_INT_MASK,
998: sc->bce_intmask);
999:
1000: /* start the receive dma */
1001: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXDPTR,
1002: BCE_NRXDESC * sizeof(struct bce_dma_slot));
1003:
1004: /* set media */
1005: mii_mediachg(&sc->bce_mii);
1006:
1007: /* turn on the ethernet mac */
1008: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL,
1009: bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1010: BCE_ENET_CTL) | EC_EE);
1011:
1012: /* start timer */
1013: timeout_add(&sc->bce_timeout, hz);
1014:
1015: /* mark as running, and no outputs active */
1016: ifp->if_flags |= IFF_RUNNING;
1017: ifp->if_flags &= ~IFF_OACTIVE;
1018:
1019: return 0;
1020: }
1021:
1022: /* add a mac address to packet filter */
1023: void
1024: bce_add_mac(struct bce_softc *sc, u_int8_t *mac, unsigned long idx)
1025: {
1026: int i;
1027: u_int32_t rval;
1028:
1029: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_LOW,
1030: mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]);
1031: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_HI,
1032: mac[0] << 8 | mac[1] | 0x10000); /* MAGIC */
1033: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL,
1034: idx << 16 | 8); /* MAGIC */
1035: /* wait for write to complete */
1036: for (i = 0; i < 100; i++) {
1037: rval = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1038: BCE_FILT_CTL);
1039: if (!(rval & 0x80000000)) /* MAGIC */
1040: break;
1041: delay(10);
1042: }
1043: if (i == 100) {
1044: printf("%s: timed out writing pkt filter ctl\n",
1045: sc->bce_dev.dv_xname);
1046: }
1047: }
1048:
1049: /* Add a receive buffer to the indiciated descriptor. */
1050: int
1051: bce_add_rxbuf(struct bce_softc *sc, int idx)
1052: {
1053: struct mbuf *m;
1054: int error;
1055:
1056: MGETHDR(m, M_DONTWAIT, MT_DATA);
1057: if (m == NULL)
1058: return (ENOBUFS);
1059:
1060: MCLGET(m, M_DONTWAIT);
1061: if ((m->m_flags & M_EXT) == 0) {
1062: m_freem(m);
1063: return (ENOBUFS);
1064: }
1065: if (sc->bce_cdata.bce_rx_chain[idx] != NULL)
1066: bus_dmamap_unload(sc->bce_dmatag,
1067: sc->bce_cdata.bce_rx_map[idx]);
1068:
1069: sc->bce_cdata.bce_rx_chain[idx] = m;
1070:
1071: error = bus_dmamap_load(sc->bce_dmatag, sc->bce_cdata.bce_rx_map[idx],
1072: m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
1073: BUS_DMA_READ | BUS_DMA_NOWAIT);
1074: if (error)
1075: return (error);
1076:
1077: bus_dmamap_sync(sc->bce_dmatag, sc->bce_cdata.bce_rx_map[idx], 0,
1078: sc->bce_cdata.bce_rx_map[idx]->dm_mapsize, BUS_DMASYNC_PREREAD);
1079:
1080: BCE_INIT_RXDESC(sc, idx);
1081:
1082: return (0);
1083:
1084: }
1085:
1086: /* Drain the receive queue. */
1087: void
1088: bce_rxdrain(struct bce_softc *sc)
1089: {
1090: int i;
1091:
1092: for (i = 0; i < BCE_NRXDESC; i++) {
1093: if (sc->bce_cdata.bce_rx_chain[i] != NULL) {
1094: bus_dmamap_unload(sc->bce_dmatag,
1095: sc->bce_cdata.bce_rx_map[i]);
1096: m_freem(sc->bce_cdata.bce_rx_chain[i]);
1097: sc->bce_cdata.bce_rx_chain[i] = NULL;
1098: }
1099: }
1100: }
1101:
1102: /* Stop transmission on the interface */
1103: void
1104: bce_stop(struct ifnet *ifp, int disable)
1105: {
1106: struct bce_softc *sc = ifp->if_softc;
1107: int i;
1108: u_int32_t val;
1109:
1110: /* Stop the 1 second timer */
1111: timeout_del(&sc->bce_timeout);
1112:
1113: /* Mark the interface down and cancel the watchdog timer. */
1114: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1115: ifp->if_timer = 0;
1116:
1117: /* Down the MII. */
1118: mii_down(&sc->bce_mii);
1119:
1120: /* Disable interrupts. */
1121: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_INT_MASK, 0);
1122: sc->bce_intmask = 0;
1123: delay(10);
1124:
1125: /* Disable emac */
1126: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL, EC_ED);
1127: for (i = 0; i < 200; i++) {
1128: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1129: BCE_ENET_CTL);
1130: if (!(val & EC_ED))
1131: break;
1132: delay(10);
1133: }
1134:
1135: /* Stop the DMA */
1136: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXCTL, 0);
1137: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXCTL, 0);
1138: delay(10);
1139:
1140: /* Release any queued transmit buffers. */
1141: for (i = 0; i < BCE_NTXDESC; i++) {
1142: if (sc->bce_cdata.bce_tx_chain[i] != NULL) {
1143: bus_dmamap_unload(sc->bce_dmatag,
1144: sc->bce_cdata.bce_tx_map[i]);
1145: m_freem(sc->bce_cdata.bce_tx_chain[i]);
1146: sc->bce_cdata.bce_tx_chain[i] = NULL;
1147: }
1148: }
1149:
1150: /* drain receive queue */
1151: if (disable)
1152: bce_rxdrain(sc);
1153: }
1154:
1155: /* reset the chip */
1156: void
1157: bce_reset(struct bce_softc *sc)
1158: {
1159: u_int32_t val;
1160: u_int32_t sbval;
1161: int i;
1162:
1163: /* if SB core is up */
1164: sbval = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1165: BCE_SBTMSTATELOW);
1166: if ((sbval & (SBTML_RESET | SBTML_REJ | SBTML_CLK)) == SBTML_CLK) {
1167: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMAI_CTL,
1168: 0);
1169:
1170: /* disable emac */
1171: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL,
1172: EC_ED);
1173: for (i = 0; i < 200; i++) {
1174: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1175: BCE_ENET_CTL);
1176: if (!(val & EC_ED))
1177: break;
1178: delay(10);
1179: }
1180: if (i == 200)
1181: printf("%s: timed out disabling ethernet mac\n",
1182: sc->bce_dev.dv_xname);
1183:
1184: /* reset the dma engines */
1185: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXCTL, 0);
1186: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXSTATUS);
1187: /* if error on receive, wait to go idle */
1188: if (val & RS_ERROR) {
1189: for (i = 0; i < 100; i++) {
1190: val = bus_space_read_4(sc->bce_btag,
1191: sc->bce_bhandle, BCE_DMA_RXSTATUS);
1192: if (val & RS_DMA_IDLE)
1193: break;
1194: delay(10);
1195: }
1196: if (i == 100)
1197: printf("%s: receive dma did not go idle after"
1198: " error\n", sc->bce_dev.dv_xname);
1199: }
1200: bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
1201: BCE_DMA_RXSTATUS, 0);
1202:
1203: /* reset ethernet mac */
1204: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL,
1205: EC_ES);
1206: for (i = 0; i < 200; i++) {
1207: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1208: BCE_ENET_CTL);
1209: if (!(val & EC_ES))
1210: break;
1211: delay(10);
1212: }
1213: if (i == 200)
1214: printf("%s: timed out resetting ethernet mac\n",
1215: sc->bce_dev.dv_xname);
1216: } else {
1217: u_int32_t reg_win;
1218:
1219: /* remap the pci registers to the Sonics config registers */
1220:
1221: /* save the current map, so it can be restored */
1222: reg_win = pci_conf_read(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag,
1223: BCE_REG_WIN);
1224: /* set register window to Sonics registers */
1225: pci_conf_write(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag,
1226: BCE_REG_WIN, BCE_SONICS_WIN);
1227:
1228: /* enable SB to PCI interrupt */
1229: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBINTVEC,
1230: bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1231: BCE_SBINTVEC) |
1232: SBIV_ENET0);
1233:
1234: /* enable prefetch and bursts for sonics-to-pci translation 2 */
1235: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SPCI_TR2,
1236: bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1237: BCE_SPCI_TR2) |
1238: SBTOPCI_PREF | SBTOPCI_BURST);
1239:
1240: /* restore to ethernet register space */
1241: pci_conf_write(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag, BCE_REG_WIN,
1242: reg_win);
1243: }
1244:
1245: /* disable SB core if not in reset */
1246: if (!(sbval & SBTML_RESET)) {
1247:
1248: /* set the reject bit */
1249: bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
1250: BCE_SBTMSTATELOW, SBTML_REJ | SBTML_CLK);
1251: for (i = 0; i < 200; i++) {
1252: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1253: BCE_SBTMSTATELOW);
1254: if (val & SBTML_REJ)
1255: break;
1256: delay(1);
1257: }
1258: if (i == 200)
1259: printf("%s: while resetting core, reject did not set\n",
1260: sc->bce_dev.dv_xname);
1261: /* wait until busy is clear */
1262: for (i = 0; i < 200; i++) {
1263: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1264: BCE_SBTMSTATEHI);
1265: if (!(val & 0x4))
1266: break;
1267: delay(1);
1268: }
1269: if (i == 200)
1270: printf("%s: while resetting core, busy did not clear\n",
1271: sc->bce_dev.dv_xname);
1272: /* set reset and reject while enabling the clocks */
1273: bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
1274: BCE_SBTMSTATELOW,
1275: SBTML_FGC | SBTML_CLK | SBTML_REJ | SBTML_RESET);
1276: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1277: BCE_SBTMSTATELOW);
1278: delay(10);
1279: bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
1280: BCE_SBTMSTATELOW, SBTML_REJ | SBTML_RESET);
1281: delay(1);
1282: }
1283: /* enable clock */
1284: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW,
1285: SBTML_FGC | SBTML_CLK | SBTML_RESET);
1286: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW);
1287: delay(1);
1288:
1289: /* clear any error bits that may be on */
1290: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATEHI);
1291: if (val & 1)
1292: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATEHI,
1293: 0);
1294: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBIMSTATE);
1295: if (val & SBIM_ERRORBITS)
1296: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBIMSTATE,
1297: val & ~SBIM_ERRORBITS);
1298:
1299: /* clear reset and allow it to propagate throughout the core */
1300: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW,
1301: SBTML_FGC | SBTML_CLK);
1302: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW);
1303: delay(1);
1304:
1305: /* leave clock enabled */
1306: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW,
1307: SBTML_CLK);
1308: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW);
1309: delay(1);
1310:
1311: /* initialize MDC preamble, frequency */
1312: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_CTL, 0x8d); /* MAGIC */
1313:
1314: /* enable phy, differs for internal, and external */
1315: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DEVCTL);
1316: if (!(val & BCE_DC_IP)) {
1317: /* select external phy */
1318: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL, EC_EP);
1319: } else if (val & BCE_DC_ER) { /* internal, clear reset bit if on */
1320: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DEVCTL,
1321: val & ~BCE_DC_ER);
1322: delay(100);
1323: }
1324: }
1325:
1326: /* Set up the receive filter. */
1327: void
1328: bce_set_filter(struct ifnet *ifp)
1329: {
1330: struct bce_softc *sc = ifp->if_softc;
1331:
1332: if (ifp->if_flags & IFF_PROMISC) {
1333: ifp->if_flags |= IFF_ALLMULTI;
1334: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL,
1335: bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL)
1336: | ERC_PE);
1337: } else {
1338: ifp->if_flags &= ~IFF_ALLMULTI;
1339:
1340: /* turn off promiscuous */
1341: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL,
1342: bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1343: BCE_RX_CTL) & ~ERC_PE);
1344:
1345: /* enable/disable broadcast */
1346: if (ifp->if_flags & IFF_BROADCAST)
1347: bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
1348: BCE_RX_CTL, bus_space_read_4(sc->bce_btag,
1349: sc->bce_bhandle, BCE_RX_CTL) & ~ERC_DB);
1350: else
1351: bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
1352: BCE_RX_CTL, bus_space_read_4(sc->bce_btag,
1353: sc->bce_bhandle, BCE_RX_CTL) | ERC_DB);
1354:
1355: /* disable the filter */
1356: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL,
1357: 0);
1358:
1359: /* add our own address */
1360: bce_add_mac(sc, sc->bce_ac.ac_enaddr, 0);
1361:
1362: /* for now accept all multicast */
1363: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL,
1364: bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL) |
1365: ERC_AM);
1366: ifp->if_flags |= IFF_ALLMULTI;
1367:
1368: /* enable the filter */
1369: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL,
1370: bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1371: BCE_FILT_CTL) | 1);
1372: }
1373: }
1374:
1375: /* Read a PHY register on the MII. */
1376: int
1377: bce_mii_read(struct device *self, int phy, int reg)
1378: {
1379: struct bce_softc *sc = (struct bce_softc *) self;
1380: int i;
1381: u_int32_t val;
1382:
1383: /* clear mii_int */
1384: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_STS, BCE_MIINTR);
1385:
1386: /* Read the PHY register */
1387: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM,
1388: (MII_COMMAND_READ << 28) | (MII_COMMAND_START << 30) | /* MAGIC */
1389: (MII_COMMAND_ACK << 16) | BCE_MIPHY(phy) | BCE_MIREG(reg)); /* MAGIC */
1390:
1391: for (i = 0; i < BCE_TIMEOUT; i++) {
1392: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_STS);
1393: if (val & BCE_MIINTR)
1394: break;
1395: delay(10);
1396: }
1397: val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM);
1398: if (i == BCE_TIMEOUT) {
1399: printf("%s: PHY read timed out reading phy %d, reg %d, val = "
1400: "0x%08x\n", sc->bce_dev.dv_xname, phy, reg, val);
1401: return (0);
1402: }
1403: return (val & BCE_MICOMM_DATA);
1404: }
1405:
1406: /* Write a PHY register on the MII */
1407: void
1408: bce_mii_write(struct device *self, int phy, int reg, int val)
1409: {
1410: struct bce_softc *sc = (struct bce_softc *) self;
1411: int i;
1412: u_int32_t rval;
1413:
1414: /* clear mii_int */
1415: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_STS,
1416: BCE_MIINTR);
1417:
1418: /* Write the PHY register */
1419: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM,
1420: (MII_COMMAND_WRITE << 28) | (MII_COMMAND_START << 30) | /* MAGIC */
1421: (MII_COMMAND_ACK << 16) | (val & BCE_MICOMM_DATA) | /* MAGIC */
1422: BCE_MIPHY(phy) | BCE_MIREG(reg));
1423:
1424: /* wait for write to complete */
1425: for (i = 0; i < BCE_TIMEOUT; i++) {
1426: rval = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
1427: BCE_MI_STS);
1428: if (rval & BCE_MIINTR)
1429: break;
1430: delay(10);
1431: }
1432: rval = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM);
1433: if (i == BCE_TIMEOUT) {
1434: printf("%s: PHY timed out writing phy %d, reg %d, val "
1435: "= 0x%08x\n", sc->bce_dev.dv_xname, phy, reg, val);
1436: }
1437: }
1438:
1439: /* sync hardware duplex mode to software state */
1440: void
1441: bce_statchg(struct device *self)
1442: {
1443: struct bce_softc *sc = (struct bce_softc *) self;
1444: u_int32_t reg;
1445:
1446: /* if needed, change register to match duplex mode */
1447: reg = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_CTL);
1448: if (sc->bce_mii.mii_media_active & IFM_FDX && !(reg & EXC_FD))
1449: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_CTL,
1450: reg | EXC_FD);
1451: else if (!(sc->bce_mii.mii_media_active & IFM_FDX) && reg & EXC_FD)
1452: bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_CTL,
1453: reg & ~EXC_FD);
1454:
1455: /*
1456: * Enable activity led.
1457: * XXX This should be in a phy driver, but not currently.
1458: */
1459: bce_mii_write((struct device *) sc, 1, 26, /* MAGIC */
1460: bce_mii_read((struct device *) sc, 1, 26) & 0x7fff); /* MAGIC */
1461: /* enable traffic meter led mode */
1462: bce_mii_write((struct device *) sc, 1, 26, /* MAGIC */
1463: bce_mii_read((struct device *) sc, 1, 27) | (1 << 6)); /* MAGIC */
1464: }
1465:
1466: /* Set hardware to newly-selected media */
1467: int
1468: bce_mediachange(struct ifnet *ifp)
1469: {
1470: struct bce_softc *sc = ifp->if_softc;
1471:
1472: if (ifp->if_flags & IFF_UP)
1473: mii_mediachg(&sc->bce_mii);
1474: return (0);
1475: }
1476:
1477: /* Get the current interface media status */
1478: void
1479: bce_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1480: {
1481: struct bce_softc *sc = ifp->if_softc;
1482:
1483: mii_pollstat(&sc->bce_mii);
1484: ifmr->ifm_active = sc->bce_mii.mii_media_active;
1485: ifmr->ifm_status = sc->bce_mii.mii_media_status;
1486: }
1487:
1488: /* One second timer, checks link status */
1489: void
1490: bce_tick(void *v)
1491: {
1492: struct bce_softc *sc = v;
1493:
1494: /* Tick the MII. */
1495: mii_tick(&sc->bce_mii);
1496:
1497: timeout_add(&sc->bce_timeout, hz);
1498: }
CVSweb