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