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