xref: /dragonfly/sys/dev/netif/sln/if_sln.c (revision b272101acc636ac635f83d03265ef6a44a3ba51a)
1 /*
2  * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  * 3. Neither the name of The DragonFly Project nor the names of its
15  *    contributors may be used to endorse or promote products derived
16  *    from this software without specific, prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD-4.7: /usr/src/sys/pci/silan.c,v 1.0 2003/01/10 gaoyonghong $
32  */
33 
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/endian.h>
37 #include <sys/kernel.h>
38 #include <sys/interrupt.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/resource.h>
42 #include <sys/rman.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/systm.h>
46 
47 #include "pcidevs.h"
48 #include <bus/pci/pcireg.h>
49 #include <bus/pci/pcivar.h>
50 
51 #include <machine/clock.h>
52 
53 #include <net/bpf.h>
54 #include <net/ethernet.h>
55 #include <net/if.h>
56 #include <net/if_var.h>
57 #include <net/if_arp.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/ifq_var.h>
61 
62 #include <vm/pmap.h>
63 #include <vm/vm.h>
64 
65 #include "if_slnreg.h"
66 #include "if_slnvar.h"
67 
68 /* Default to using PIO access for netcard driver */
69 #define SL_USEIOSPACE
70 
71 #ifdef SLN_DEBUG
72 #define PDEBUG(fmt, args...)  kprintf("%s: " fmt "\n" , __func__ , ## args)
73 #else
74 #define PDEBUG(fmt, args...)
75 #endif
76 
77 static const struct sln_dev {
78           uint16_t vid;
79           uint16_t did;
80           const char *desc;
81 } sln_devs[] = {
82           {PCI_VENDOR_SILAN, PCI_PRODUCT_SILAN_SC92031,
83            "Silan SC92031 Fast Ethernet" },
84           {PCI_VENDOR_SILAN, PCI_PRODUCT_SILAN_8139D,
85            "Silan Rsltek 8139D Fast Ethernet" },
86           {0, 0, NULL}
87 };
88 
89 static int          sln_probe(device_t);
90 static int          sln_attach(device_t);
91 static int          sln_detach(device_t);
92 static int          sln_shutdown(device_t);
93 static int          sln_suspend(device_t);
94 static int          sln_resume(device_t);
95 
96 static void         sln_reset(struct sln_softc *);
97 static void         sln_init(void *);
98 
99 static void         sln_tx(struct ifnet *, struct ifaltq_subque *);
100 static void         sln_rx(struct sln_softc *);
101 static void         sln_tx_intr(struct sln_softc *);
102 static void         sln_media_intr(struct sln_softc *);
103 static void         sln_interrupt(void *);
104 static int          sln_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
105 static void         sln_stop(struct sln_softc *);
106 static void         sln_watchdog(struct ifnet *);
107 
108 static int          sln_media_upd(struct ifnet *);
109 
110 static void         sln_media_stat(struct ifnet *, struct ifmediareq *);
111 static void         sln_mii_cmd(struct sln_softc *, uint32_t, u_long *);
112 static void         sln_media_cfg(struct sln_softc *);
113 static void         sln_mac_cfg(struct sln_softc *);
114 static uint32_t     sln_ether_crc32(caddr_t);
115 static void         sln_set_multi(struct sln_softc *);
116 static void         sln_init_tx(struct sln_softc *);
117 static void         sln_tick(void *);
118 
119 #ifdef SL_USEIOSPACE
120 #define SL_RID      SL_PCI_IOAD
121 #define SL_RES      SYS_RES_IOPORT
122 #else
123 #define SL_RID      SL_PCI_MEMAD
124 #define SL_RES      SYS_RES_MEMORY
125 #endif
126 
127 static device_method_t sln_methods[] = {
128           DEVMETHOD(device_probe,                 sln_probe),
129           DEVMETHOD(device_attach,      sln_attach),
130           DEVMETHOD(device_detach,      sln_detach),
131           DEVMETHOD(device_shutdown,    sln_shutdown),
132           DEVMETHOD(device_suspend,     sln_suspend),
133           DEVMETHOD(device_resume,      sln_resume),
134 
135           DEVMETHOD(bus_print_child,    bus_generic_print_child),
136           DEVMETHOD(bus_driver_added,   bus_generic_driver_added),
137 
138           DEVMETHOD_END
139 };
140 
141 static driver_t sln_driver = {
142           "sln",
143           sln_methods,
144           sizeof(struct sln_softc)
145 };
146 
147 static devclass_t sln_devclass;
148 
149 DRIVER_MODULE(sln, pci, sln_driver, sln_devclass, NULL, NULL);
150 
151 static int
sln_probe(device_t dev)152 sln_probe(device_t dev)
153 {
154           const struct sln_dev *d;
155           uint16_t did, vid;
156 
157           vid = pci_get_vendor(dev);
158           did = pci_get_device(dev);
159 
160           for (d = sln_devs; d->desc != NULL; d++) {
161                     if (vid == d->vid && did == d->did) {
162                               device_set_desc(dev, d->desc);
163                               return 0;
164                     }
165           }
166           return ENXIO;
167 }
168 
169 /* the chip reset */
170 static void
sln_reset(struct sln_softc * sc)171 sln_reset(struct sln_softc *sc)
172 {
173           SLN_WRITE_4(sc, SL_CFG0, SL_SOFT_RESET);
174           DELAY(200000);
175           SLN_WRITE_4(sc, SL_CFG0, 0x0);
176           DELAY(10000);
177 }
178 
179 /* Attach the interface. Allocate softc structures */
180 static int
sln_attach(device_t dev)181 sln_attach(device_t dev)
182 {
183           struct sln_softc *sc = device_get_softc(dev);
184           struct ifnet *ifp = &sc->arpcom.ac_if;
185           unsigned char eaddr[ETHER_ADDR_LEN];
186           int rid;
187           int error = 0;
188 
189           if_initname(ifp, device_get_name(dev), device_get_unit(dev));
190 
191           /* TODO: power state change */
192 
193           pci_enable_busmaster(dev);
194 
195           rid = SL_RID;
196           sc->sln_res = bus_alloc_resource_any(dev, SL_RES, &rid, RF_ACTIVE);
197           if (sc->sln_res == NULL) {
198                     device_printf(dev, "couldn't map ports/memory\n");
199                     error = ENXIO;
200                     goto fail;
201           }
202           sc->sln_bustag = rman_get_bustag(sc->sln_res);
203           sc->sln_bushandle = rman_get_bushandle(sc->sln_res);
204 
205           /* alloc pci irq */
206           rid = 0;
207           sc->sln_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
208               RF_SHAREABLE | RF_ACTIVE);
209           if (sc->sln_irq == NULL) {
210                     device_printf(dev, "couldn't map interrupt\n");
211                     bus_release_resource(dev, SL_RES, SL_RID, sc->sln_res);
212                     error = ENXIO;
213                     goto fail;
214           }
215 
216           /* Get MAC address */
217           ((uint32_t *)(&eaddr))[0] = be32toh(SLN_READ_4(sc, SL_MAC_ADDR0));
218           ((uint16_t *)(&eaddr))[2] = be16toh(SLN_READ_4(sc, SL_MAC_ADDR1));
219 
220           /* alloc rx buffer space */
221           sc->sln_bufdata.sln_rx_buf = contigmalloc(SL_RX_BUFLEN,
222               M_DEVBUF, M_WAITOK, 0, 0xffffffff, PAGE_SIZE, 0);
223           if (sc->sln_bufdata.sln_rx_buf == NULL) {
224                     device_printf(dev, "no memory for rx buffers!\n");
225                     bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sln_irq);
226                     bus_release_resource(dev, SL_RES, SL_RID, sc->sln_res);
227                     error = ENXIO;
228                     goto fail;
229           }
230           callout_init(&sc->sln_state);
231 
232           ifp->if_softc = sc;
233           ifp->if_mtu = ETHERMTU;
234           ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
235           ifp->if_init = sln_init;
236           ifp->if_start = sln_tx;
237           ifp->if_ioctl = sln_ioctl;
238           ifp->if_watchdog = sln_watchdog;
239           ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
240           ifq_set_ready(&ifp->if_snd);
241 
242           /* initial media */
243           ifmedia_init(&sc->ifmedia, 0, sln_media_upd, sln_media_stat);
244 
245           /* supported media types */
246           ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
247           ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T, 0, NULL);
248           ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_HDX, 0, NULL);
249           ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL);
250           ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_100_TX, 0, NULL);
251           ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_100_TX | IFM_HDX, 0, NULL);
252           ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL);
253 
254           /* Choose a default media. */
255           ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
256 
257           ether_ifattach(ifp, eaddr, NULL);
258 
259           ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->sln_irq));
260 
261           error = bus_setup_intr(dev, sc->sln_irq, INTR_MPSAFE, sln_interrupt, sc,
262                                      &sc->sln_intrhand, ifp->if_serializer);
263           if (error) {
264                     bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sln_irq);
265                     bus_release_resource(dev, SL_RES, SL_RID, sc->sln_res);
266                     ether_ifdetach(ifp);
267                     device_printf(dev, "couldn't set up irq\n");
268                     goto fail;
269           }
270 
271           return 0;
272 fail:
273           return error;
274 }
275 
276 /* Stop the adapter and free any mbufs allocated to the RX and TX buffers */
277 static void
sln_stop(struct sln_softc * sc)278 sln_stop(struct sln_softc *sc)
279 {
280           struct ifnet *ifp = &sc->arpcom.ac_if;
281           int i;
282 
283           ASSERT_SERIALIZED(ifp->if_serializer);
284 
285           ifp->if_timer = 0;
286           callout_stop(&sc->sln_state);
287 
288           /* disable Tx/Rx */
289           sc->txcfg &= ~SL_TXCFG_EN;
290           sc->rxcfg &= ~SL_RXCFG_EN;
291           SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
292           SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
293 
294           /* Clear interrupt */
295           SLN_WRITE_4(sc, SL_INT_MASK, 0);
296           SLN_READ_4(sc, SL_INT_STATUS);
297 
298           /* Free the TX list buffers */
299           for (i = 0; i < SL_TXD_CNT; i++) {
300                     if (sc->sln_bufdata.sln_tx_buf[i] != NULL) {
301                               m_freem(sc->sln_bufdata.sln_tx_buf[i]);
302                               sc->sln_bufdata.sln_tx_buf[i] = NULL;
303                               SLN_WRITE_4(sc, SL_TSAD0 + i * 4, 0);
304                     }
305           }
306 
307           ifp->if_flags &= ~IFF_RUNNING;
308           ifq_clr_oactive(&ifp->if_snd);
309 }
310 
311 static int
sln_detach(device_t dev)312 sln_detach(device_t dev)
313 {
314           struct sln_softc *sc = device_get_softc(dev);
315           struct ifnet *ifp = &sc->arpcom.ac_if;
316 
317           lwkt_serialize_enter(ifp->if_serializer);
318           sln_stop(sc);
319           bus_teardown_intr(dev, sc->sln_irq, sc->sln_intrhand);
320           lwkt_serialize_exit(ifp->if_serializer);
321 
322           ether_ifdetach(ifp);
323 
324           bus_generic_detach(dev);
325 
326           bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sln_irq);
327           bus_release_resource(dev, SL_RES, SL_RID, sc->sln_res);
328 
329           contigfree(sc->sln_bufdata.sln_rx_buf, SL_RX_BUFLEN, M_DEVBUF);
330 
331           return 0;
332 }
333 
334 static int
sln_media_upd(struct ifnet * ifp)335 sln_media_upd(struct ifnet *ifp)
336 {
337           struct sln_softc *sc = ifp->if_softc;
338           struct ifmedia *ifm = &sc->ifmedia;
339 
340           if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
341                     return EINVAL;
342 
343           if (ifp->if_flags & IFF_UP)
344                     sln_init(sc);
345 
346           return 0;
347 }
348 
349 static void
sln_media_stat(struct ifnet * ifp,struct ifmediareq * ifmr)350 sln_media_stat(struct ifnet *ifp, struct ifmediareq *ifmr)
351 {
352           struct sln_softc *sc = ifp->if_softc;
353           u_long phys[2];
354           uint32_t temp;
355 
356           ifmr->ifm_status = IFM_AVALID;
357           ifmr->ifm_active = IFM_ETHER;
358 
359           phys[0] = SL_MII_STAT;
360           sln_mii_cmd(sc, SL_MII0_READ, phys);
361 
362           if (phys[1] & SL_MIISTAT_LINK)
363                     ifmr->ifm_status |= IFM_ACTIVE;
364 
365           temp = SLN_READ_4(sc, SL_PHY_CTRL);
366 
367           if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10)) == 0x60800000)
368                     ifmr->ifm_active |= IFM_AUTO;
369           else if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD100)) == 0x40800000)
370                     ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
371           else if ((temp & SL_PHYCTL_SPD100) == 0x40000000)
372                     ifmr->ifm_active |= IFM_100_TX | IFM_HDX;
373           else if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD10)) == 0x20800000)
374                     ifmr->ifm_active |= IFM_10_T | IFM_FDX;
375           else if ((temp & SL_PHYCTL_SPD10) == 0x20000000)
376                     ifmr->ifm_active |= IFM_10_T | IFM_HDX;
377 
378           sln_mii_cmd(sc, SL_MII0_SCAN, phys);
379 }
380 
381 /* command selected in MII command register  */
382 static void
sln_mii_cmd(struct sln_softc * sc,uint32_t cmd,u_long * phys)383 sln_mii_cmd(struct sln_softc *sc, uint32_t cmd, u_long *phys)
384 {
385           uint32_t mii_status;
386 
387           SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER);
388 
389           do {
390                     mii_status = 0;
391                     DELAY(10);
392                     mii_status = SLN_READ_4(sc, SL_MII_STATUS);
393           } while (mii_status & SL_MIISTAT_BUSY);
394 
395           switch (cmd) {
396           case SL_MII0_SCAN:
397                     SLN_WRITE_4(sc, SL_MII_CMD1, 0x1 << 6);
398                     SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_SCAN);
399                     break;
400 
401           case SL_MII0_READ:
402                     SLN_WRITE_4(sc, SL_MII_CMD1, phys[0] << 6);
403                     SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_READ);
404                     break;
405 
406           default:            /* WRITE */
407                     SLN_WRITE_4(sc, SL_MII_CMD1, phys[0] << 6 | phys[1] << 11);
408                     SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_WRITE);
409                     break;
410           }
411 
412           do {
413                     DELAY(10);
414                     mii_status = SLN_READ_4(sc, SL_MII_STATUS);
415           } while (mii_status & SL_MIISTAT_BUSY);
416 
417           if (SL_MII0_READ == cmd)
418                     phys[1] = (mii_status >> 13) & 0xffff;
419 }
420 
421 /* Set media speed and duplex mode */
422 static void
sln_media_cfg(struct sln_softc * sc)423 sln_media_cfg(struct sln_softc *sc)
424 {
425           u_long phys[2];
426           uint32_t mediatype;
427           uint32_t temp;
428 
429           mediatype = (&sc->ifmedia)->ifm_cur->ifm_media;
430 
431           temp = SLN_READ_4(sc, SL_PHY_CTRL);
432           temp &= ~(SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10);
433           temp |= (SL_PHYCTL_ANE | SL_PHYCTL_RESET);
434 
435           /************************************************/
436           /* currently set media word by selected media   */
437           /*                                              */
438           /* IFM_ETHER = 0x00000020                       */
439           /* IFM_AUTO=0, IFM_10_T=3,  IFM_100_TX=6        */
440           /* IFM_FDX=0x00100000    IFM_HDX=0x00200000     */
441           /************************************************/
442           switch (mediatype) {
443           case 0x00000020:
444                     PDEBUG(" autoselet supported\n");
445                     temp |= (SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10);
446                     sc->ifmedia.ifm_media = IFM_ETHER | IFM_AUTO;
447                     ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
448                     break;
449           case 0x23:
450           case 0x00200023:
451                     PDEBUG(" 10Mbps half_duplex supported\n");
452                     temp |= SL_PHYCTL_SPD10;
453                     sc->ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX;
454                     ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_HDX);
455                     break;
456 
457           case 0x00100023:
458                     PDEBUG("10Mbps full_duplex supported\n");
459                     temp |= (SL_PHYCTL_SPD10 | SL_PHYCTL_DUX);
460                     sc->ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_FDX;
461                     ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX);
462                     break;
463 
464           case 0x26:
465           case 0x00200026:
466                     PDEBUG("100Mbps half_duplex supported\n");
467                     temp |= SL_PHYCTL_SPD100;
468                     sc->ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_HDX;
469                     ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_100_TX | IFM_HDX);
470                     break;
471 
472           case 0x00100026:
473                     PDEBUG("100Mbps full_duplex supported\n");
474                     temp |= (SL_PHYCTL_SPD100 | SL_PHYCTL_DUX);
475                     sc->ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_FDX;
476                     ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_100_TX | IFM_FDX);
477                     break;
478 
479           default:
480                     break;
481           }
482 
483           SLN_WRITE_4(sc, SL_PHY_CTRL, temp);
484 
485           DELAY(10000);
486           temp &= ~SL_PHYCTL_RESET;
487           SLN_WRITE_4(sc, SL_PHY_CTRL, temp);
488 
489           DELAY(1000);
490           phys[0] = SL_MII_JAB;
491           phys[1] = SL_PHY_16_JAB_ENB | SL_PHY_16_PORT_ENB;
492           sln_mii_cmd(sc, SL_MII0_WRITE, phys);
493 
494           sc->connect = 0;
495           sln_mii_cmd(sc, SL_MII0_SCAN, phys);
496 }
497 
498 static void
sln_mac_cfg(struct sln_softc * sc)499 sln_mac_cfg(struct sln_softc *sc)
500 {
501           struct ifnet *ifp = &sc->arpcom.ac_if;
502           u_long flowcfg = 0;
503 
504           /* Set the initial TX/RX/Flow Control configuration */
505           sc->rxcfg = SL_RXCFG_LOW_THRESHOLD | SL_RXCFG_HIGH_THRESHOLD;
506           sc->txcfg = TX_CFG_DEFAULT;
507 
508           if (sc->txenablepad)
509                     sc->txcfg |= 0x20000000;
510 
511           if (sc->media_speed == IFM_10_T)
512                     sc->txcfg |= SL_TXCFG_DATARATE;
513 
514           if (sc->media_duplex == IFM_FDX) {
515                     sc->rxcfg |= SL_RXCFG_FULLDX;
516                     sc->txcfg |= SL_TXCFG_FULLDX;
517                     flowcfg = SL_FLOWCTL_FULLDX | SL_FLOWCTL_EN;
518           } else {
519                     sc->rxcfg &= ~SL_RXCFG_FULLDX;
520                     sc->txcfg &= ~SL_TXCFG_FULLDX;
521           }
522 
523           /* if promiscuous mode, set the allframes bit. */
524           if (ifp->if_flags & IFF_PROMISC)
525                     sc->rxcfg |= (SL_RXCFG_EN | SL_RXCFG_RCV_SMALL | SL_RXCFG_RCV_HUGE | SL_RXCFG_RCV_ERR | SL_RXCFG_RCV_BROAD | SL_RXCFG_RCV_MULTI | SL_RXCFG_RCV_ALL);
526           else
527                     sc->rxcfg &= ~(SL_RXCFG_EN | SL_RXCFG_RCV_SMALL | SL_RXCFG_RCV_HUGE | SL_RXCFG_RCV_ERR | SL_RXCFG_RCV_BROAD | SL_RXCFG_RCV_MULTI | SL_RXCFG_RCV_ALL);
528 
529           /* Set capture broadcast bit to capture broadcast frames */
530           if (ifp->if_flags & IFF_BROADCAST)
531                     sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_BROAD;
532           else
533                     sc->rxcfg &= ~(SL_RXCFG_EN | SL_RXCFG_RCV_BROAD);
534 
535           /* Program the multicast filter, if necessary */
536           sln_set_multi(sc);
537 
538           SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
539           SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
540           SLN_WRITE_4(sc, SL_FLOW_CTRL, flowcfg);
541 }
542 
543 static u_char shade_map[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
544                                     0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
545 
546 /* Calculate CRC32 of a multicast group address */
547 static uint32_t
sln_ether_crc32(caddr_t addr)548 sln_ether_crc32(caddr_t addr)
549 {
550           uint32_t crc, crcr;
551           int i, j;
552           unsigned char data = 0;
553           /* Compute CRC for the address value. */
554 
555           crc = 0xFFFFFFFF;   /* initial value */
556 
557           for (i = ETHER_ADDR_LEN; i > 0; i--) {
558                     data = *addr++;
559 
560                     for (j = 0; j < 8; j++) {
561                               if (((data & 0x1) ^ (crc & 0x1)) != 0) {
562                                         crc >>= 1;
563                                         crc ^= 0xEDB88320;
564                               } else {
565                                         crc >>= 1;
566                               }
567                               data >>= 1;
568                     }
569           }
570 
571           crcr = shade_map[crc >> 28];
572           crcr |= (shade_map[(crc >> 24) & 0xf] << 4);
573           crcr |= (shade_map[(crc >> 20) & 0xf] << 8);
574           crcr |= (shade_map[(crc >> 16) & 0xf] << 12);
575           crcr |= (shade_map[(crc >> 12) & 0xf] << 16);
576           crcr |= (shade_map[(crc >> 8) & 0xf] << 20);
577           crcr |= (shade_map[(crc >> 4) & 0xf] << 24);
578           crcr |= (shade_map[crc & 0xf] << 28);
579 
580           return crcr;
581 }
582 
583 /* Program the 64-bit multicast hash filter */
584 static void
sln_set_multi(struct sln_softc * sc)585 sln_set_multi(struct sln_softc *sc)
586 {
587           struct ifnet *ifp = &sc->arpcom.ac_if;
588           uint32_t crc = 0;
589           uint32_t mc_g[2] = {0, 0};
590           struct ifmultiaddr *ifma;
591           int j;
592 
593           if (ifp->if_flags & IFF_PROMISC) {
594                     kprintf("Promisc mode is enabled\n");
595                     sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
596                     mc_g[0] = mc_g[1] = 0xFFFFFFFF;
597           } else if (ifp->if_flags & IFF_ALLMULTI) {
598                     kprintf("Allmulti mode is enabled\n");
599                     sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
600                     mc_g[0] = mc_g[1] = 0xFFFFFFFF;
601           } else if (ifp->if_flags & IFF_MULTICAST) {
602                     kprintf("Multicast mode is enabled\n");
603                     sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
604 
605                     /* first, zero all the existing hash bits */
606                     mc_g[0] = mc_g[1] = 0;
607 
608                     TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
609                               j = 0;
610 
611                               if ((ifma->ifma_addr->sa_family) != AF_LINK)
612                                         continue;
613 
614                               crc = ~sln_ether_crc32(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
615                               crc >>= 24;
616 
617                               if (crc & 0x1)
618                                         j |= 0x2;
619                               if (crc & 0x2)
620                                         j |= 0x1;
621                               if (crc & 0x10)
622                                         j |= 0x20;
623                               if (crc & 0x20)
624                                         j |= 0x10;
625                               if (crc & 0x40)
626                                         j |= 0x8;
627                               if (crc & 0x80)
628                                         j |= 0x4;
629 
630                               if (j > 31)
631                                         mc_g[0] |= (0x1 << (j - 32));
632                               else
633                                         mc_g[1] |= (0x1 << j);
634                     }
635           } else {
636                     sc->rxcfg &= ~(SL_RXCFG_EN | SL_RXCFG_RCV_MULTI);
637           }
638 
639           SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
640           SLN_WRITE_4(sc, SL_MULTI_GROUP0, mc_g[0]);
641           SLN_WRITE_4(sc, SL_MULTI_GROUP1, mc_g[1]);
642 }
643 
644 /* Initialize the TX/Rx descriptors */
645 static void
sln_init_tx(struct sln_softc * sc)646 sln_init_tx(struct sln_softc *sc)
647 {
648           int i;
649 
650           sc->sln_bufdata.cur_tx = 0;
651           sc->sln_bufdata.dirty_tx = 0;
652 
653           for (i = 0; i < SL_TXD_CNT; i++) {
654                     sc->sln_bufdata.sln_tx_buf[i] = NULL;
655                     SLN_WRITE_4(sc, SL_TSAD0 + (i * 4), 0);
656           }
657 }
658 
659 /* Software & Hardware Initialize */
660 static void
sln_init(void * x)661 sln_init(void *x)
662 {
663           struct sln_softc *sc = x;
664           struct ifnet *ifp = &sc->arpcom.ac_if;
665 
666           PDEBUG("sln_init\n");
667 
668           ASSERT_SERIALIZED(ifp->if_serializer);
669 
670           sln_stop(sc);
671 
672           /* soft reset the chip */
673           sln_reset(sc);
674 
675           /* disable interrupt */
676           SLN_WRITE_4(sc, SL_INT_MASK, 0);
677 
678           /* SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER); */
679 
680           /* clear multicast address */
681           SLN_WRITE_4(sc, SL_MULTI_GROUP0, 0);
682           SLN_WRITE_4(sc, SL_MULTI_GROUP1, 0);
683 
684           /* Init the RX buffer start address register. */
685           SLN_WRITE_4(sc, SL_RBSA, vtophys(sc->sln_bufdata.sln_rx_buf));
686           sc->sln_bufdata.dirty_rx = vtophys(sc->sln_bufdata.sln_rx_buf);
687 
688           /* Init TX descriptors. */
689           sln_init_tx(sc);
690 
691           /* configure RX buffer size */
692           if (sc->tx_early_ctrl && sc->rx_early_ctrl)
693                     SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_RX | SL_EARLY_TX | SL_RXBUF_64 | SL_RXFIFO_1024BYTES);
694           else if (sc->tx_early_ctrl)
695                     SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_TX | SL_RXBUF_64);
696           else if (sc->rx_early_ctrl)
697                     SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_RX | SL_RXBUF_64 | SL_RXFIFO_1024BYTES);
698           else
699                     SLN_WRITE_4(sc, SL_CFG1, SL_RXBUF_64);
700 
701           /* MII media configuration */
702           sln_media_cfg(sc);
703 
704           if (sc->connect) {
705                     /* Enable transmit and receive */
706                     sc->rxcfg |= SL_RXCFG_EN;
707                     sc->txcfg |= SL_TXCFG_EN;
708           } else {
709                     sc->rxcfg &= ~SL_RXCFG_EN;
710                     sc->txcfg &= ~SL_TXCFG_EN;
711           }
712 
713           SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
714           SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
715 
716           /* Enable interrupts */
717           SLN_WRITE_4(sc, SL_INT_MASK, SL_INRTS);
718 
719           sc->suspended = 0;
720 
721           ifp->if_flags |= IFF_RUNNING;
722           ifq_clr_oactive(&ifp->if_snd);
723 
724           callout_reset(&sc->sln_state, hz, sln_tick, sc);
725 }
726 
727 /* Transmit Packet */
728 static void
sln_tx(struct ifnet * ifp,struct ifaltq_subque * ifsq)729 sln_tx(struct ifnet *ifp, struct ifaltq_subque *ifsq)
730 {
731           struct sln_softc *sc = ifp->if_softc;
732           struct mbuf *m_head = NULL;
733           struct mbuf *m_new = NULL;
734           int entry;
735 
736           ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
737           ASSERT_SERIALIZED(ifp->if_serializer);
738 
739           if (!sc->connect) {
740                     ifq_purge(&ifp->if_snd);
741                     return;
742           }
743 
744           if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(&ifp->if_snd))
745                     return;
746 
747           while (SL_CUR_TXBUF(sc) == NULL) {      /* SL_CUR_TXBUF(x) = x->sln_bufdata.sln_tx_buf[x->sln_bufdata.cur_tx] */
748                     entry = sc->sln_bufdata.cur_tx;
749 
750                     m_head = ifq_dequeue(&ifp->if_snd);
751                     if (m_head == NULL)
752                               break;
753 
754                     MGETHDR(m_new, M_NOWAIT, MT_DATA);
755                     if (m_new == NULL) {
756                               if_printf(ifp, "no memory for tx descriptor");
757                               m_freem(m_head);
758                               break;
759                     }
760                     if ((m_head->m_pkthdr.len > MHLEN) || (60 > MHLEN)) {
761                               MCLGET(m_new, M_NOWAIT);
762                               if (!(m_new->m_flags & M_EXT)) {
763                                         m_freem(m_new);
764                                         m_freem(m_head);
765                                         if_printf(ifp, "no memory for tx descriptor");
766                                         break;
767                               }
768                     }
769                     m_copydata(m_head, 0, m_head->m_pkthdr.len, mtod(m_new, void *));
770                     m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
771                     m_freem(m_head);
772                     m_head = m_new;
773                     SL_CUR_TXBUF(sc) = m_head;
774 
775                     /*
776                      * if there's a BPF listener, bounce a copy of this frame to
777                      * him
778                      */
779                     BPF_MTAP(ifp, SL_CUR_TXBUF(sc));
780 
781                     /* Transmit the frame */
782                     SLN_WRITE_4(sc, ((entry * 4) + SL_TSAD0),
783                         vtophys(mtod(SL_CUR_TXBUF(sc), caddr_t)));
784 
785                     /* calculate length of the frame */
786                     if ((SL_CUR_TXBUF(sc)->m_pkthdr.len < 60) && (!sc->txenablepad)) {
787                               memset(mtod(m_head, char *)+m_head->m_pkthdr.len, 0x20, 60 - m_head->m_pkthdr.len);
788                               SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 60);
789                     } else if (SL_CUR_TXBUF(sc)->m_pkthdr.len < 100)
790                               SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, SL_CUR_TXBUF(sc)->m_pkthdr.len);
791                     else if (SL_CUR_TXBUF(sc)->m_pkthdr.len < 300)
792                               SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 0x30000 | SL_CUR_TXBUF(sc)->m_pkthdr.len);
793                     else
794                               SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 0x50000 | SL_CUR_TXBUF(sc)->m_pkthdr.len);
795                     sc->sln_bufdata.cur_tx = (entry + 1) % SL_TXD_CNT;
796 
797                     PDEBUG("Queue tx packet size %d to tx-descriptor %d.\n", m_head->m_pkthdr.len, entry);
798           }
799 
800           /* Tx buffer chain full */
801           if (SL_CUR_TXBUF(sc) != NULL)
802                     ifq_set_oactive(&ifp->if_snd);
803 
804           /* Set a timeout in case the chip goes out to lunch */
805           ifp->if_timer = 5;
806 }
807 
808 /* Receive Data handler */
809 static void
sln_rx(struct sln_softc * sc)810 sln_rx(struct sln_softc *sc)
811 {
812           struct mbuf *m;
813           struct ifnet *ifp = &sc->arpcom.ac_if;
814           uint32_t rxstat = 0;
815           uint32_t rx_offset;
816           caddr_t rx_bufpos = NULL;
817           uint32_t cur_rx = 0;
818           uint32_t dirty_rx;
819           long rx_len;
820           u_long rx_space;
821           u_long rx_size = 0;
822           u_long rx_size_align = 0;
823           u_long pkt_size = 0;
824 
825           cur_rx = SLN_READ_4(sc, SL_RBW_PTR);
826           dirty_rx = sc->sln_bufdata.dirty_rx;
827 
828           /*
829            * cur_rx is only 17 bits in the RxBufWPtr register. if cur_rx can be
830            * used in physical space, we need to change it to 32 bits physical
831            * address
832            */
833           cur_rx |= vtophys(sc->sln_bufdata.sln_rx_buf) & (~(u_long) (SL_RX_BUFLEN - 1));
834 
835           if (cur_rx < vtophys(sc->sln_bufdata.sln_rx_buf))
836                     cur_rx += SL_RX_BUFLEN;
837 
838           if (cur_rx >= dirty_rx)
839                     rx_len = (long)(cur_rx - dirty_rx);
840           else
841                     rx_len = SL_RX_BUFLEN - (long)(dirty_rx - cur_rx);
842 
843           if ((rx_len > SL_RX_BUFLEN) || (rx_len < 0)) {
844                     if_printf(ifp, "rx len is fail\n");
845                     return;
846           }
847           if (rx_len == 0)
848                     return;
849 
850           rx_offset = (dirty_rx - vtophys(sc->sln_bufdata.sln_rx_buf)) & (u_long) (SL_RX_BUFLEN - 1);
851 
852           while (rx_len > 0) {
853 #ifdef SLN_DEBUG
854                     u_long ipkts;
855 #endif
856 
857                     rx_bufpos = sc->sln_bufdata.sln_rx_buf + rx_offset;
858                     rxstat = *(uint32_t *) rx_bufpos;
859                     rx_size = (rxstat >> 20) & 0x0FFF;
860                     rx_size_align = (rx_size + 3) & ~3;     /* for 4 bytes aligned */
861                     pkt_size = rx_size - ETHER_CRC_LEN;     /* Omit the four octet
862                                                                        * CRC from the length. */
863 
864                     PDEBUG("rx len: %ld  rx frame size:%ld  rx state:0x%x\n", rx_len, rx_size, rxstat);
865 
866                     /* errors receive packets caculatation */
867                     if (rxstat == 0 || rx_size < 16 || !(rxstat & SL_RXSTAT_RXOK)) {
868                               IFNET_STAT_INC(ifp, ierrors, 1);
869 
870                               if (!(rxstat & SL_RXSTAT_RXOK))
871                                         if_printf(ifp, "receiver ok error\n");
872 
873                               if (!(rxstat & SL_RXSTAT_CRCOK))
874                                         if_printf(ifp, "crc error\n");
875 
876                               if (rxstat & SL_RXSTAT_ALIGNERR)
877                                         if_printf(ifp, "frame alignment error\n");
878 
879                               if (rxstat & (SL_RXSTAT_HUGEFRM | SL_RXSTAT_SMALLFRM))
880                                         if_printf(ifp, "received frame length is error\n");
881 
882                               break;
883                     }
884                     rx_len -= (long)(rx_size_align + 4);    /* 4 bytes for receive
885                                                                        * frame head */
886 
887                     if (rx_len < 0) {
888                               kprintf("rx packets len is too small\n");
889                               break;
890                     }
891 #ifdef SLN_PDEBUG
892                     caddr_t p = NULL;
893 
894                     if_printf(ifp, "rx frame content\n");
895                     p = rx_bufpos;
896                     for (i = 0; i < 30; i++, p++) {
897                               if (i % 10 == 0)
898                                         kprintf("\n");
899                               if_printf(ifp, "%x  ", (u_char)*p);
900                     }
901                     if_printf(ifp, "\n");
902 #endif
903                     /* No errors; receive the packet. */
904                     if (rx_bufpos == (sc->sln_bufdata.sln_rx_buf + SL_RX_BUFLEN))
905                               rx_bufpos = sc->sln_bufdata.sln_rx_buf;
906 
907                     rx_bufpos = rx_bufpos + 4;    /* 4 bytes for receive frame
908                                                              * header */
909                     rx_space = (u_long)((sc->sln_bufdata.sln_rx_buf + SL_RX_BUFLEN) - rx_bufpos);
910 
911                     if (pkt_size > rx_space) {
912                               /* 2 for etherer head align */
913                               m = m_devget(rx_bufpos - 2, pkt_size + 2, 0, ifp);
914 
915                               if (m == NULL) {
916                                         IFNET_STAT_INC(ifp, ierrors, 1);
917                                         if_printf(ifp,
918                                             "out of mbufs, tried to copy %ld bytes\n",
919                                             rx_space);
920                               } else {
921                                         m_adj(m, 2);
922                                         m_copyback(m, rx_space, pkt_size - rx_space,
923                                             sc->sln_bufdata.sln_rx_buf);
924                               }
925                     } else {
926                               m = m_devget(rx_bufpos - 2, pkt_size + 2, 0, ifp);
927 
928                               if (m == NULL) {
929                                         u_long ierr;
930 
931                                         IFNET_STAT_INC(ifp, ierrors, 1);
932                                         if_printf(ifp,
933                                             "out of mbufs, tried to copy %ld bytes\n",
934                                             pkt_size);
935 
936                                         IFNET_STAT_GET(ifp, ierrors, ierr);
937                                         if_printf(ifp, "ierrors = %lu\n", ierr);
938                               } else {
939                                         m_adj(m, 2);
940                               }
941                     }
942 
943                     IFNET_STAT_INC(ifp, ipackets, 1);
944 #ifdef SLN_DEBUG
945                     IFNET_STAT_GET(ifp, ipackets, ipkts);
946                     PDEBUG("ipackets = %lu\n", ipkts);
947 #endif
948 
949                     ifp->if_input(ifp, m, NULL, -1);
950 
951                     rx_offset = (rx_offset + rx_size + 4) & (u_long) (SL_RX_BUFLEN - 1);  /* 4 bytes for receive
952                                                                                                                * frame head */
953           }
954 
955           sc->sln_bufdata.dirty_rx = cur_rx;
956 
957           SLN_WRITE_4(sc, SL_RBR_PTR, cur_rx);
958 }
959 
960 /* Transmit OK/ERR handler */
961 static void
sln_tx_intr(struct sln_softc * sc)962 sln_tx_intr(struct sln_softc *sc)
963 {
964           struct ifnet *ifp = &sc->arpcom.ac_if;
965           uint32_t txstat;
966           int entry;
967 
968           do {
969                     entry = sc->sln_bufdata.dirty_tx;
970                     txstat = SLN_READ_4(sc, SL_TSD0 + entry * 4);
971 
972                     if (!(txstat & (SL_TXSD_TOK | SL_TXSD_TUN | SL_TXSD_TABT)))
973                               break;    /* It still hasn't been sent */
974 
975                     if (SL_DIRTY_TXBUF(sc) != NULL) {       /* SL_DIRTY_TXBUF(x) =
976                                                                        * x->sln_bufdata.sln_tx_
977                                                                        * buf[x->sln_bufdata.dir
978                                                                        * ty_tx] */
979                               m_freem(SL_DIRTY_TXBUF(sc));
980                               SL_DIRTY_TXBUF(sc) = NULL;
981                     }
982                     if (txstat & SL_TXSD_TOK) {
983 #ifdef SLN_DEBUG
984                               u_long opkts;
985 #endif
986 
987                               IFNET_STAT_INC(ifp, opackets, 1);
988                               IFNET_STAT_INC(ifp, obytes, txstat & SL_TXSD_LENMASK);
989 #ifdef SLN_DEBUG
990                               IFNET_STAT_GET(ifp, opackets, opkts);
991                               PDEBUG("opackets = %lu\n", opkts);
992 #endif
993                               IFNET_STAT_INC(ifp, collisions,
994                                   (txstat & SL_TXSD_NCC) >> 22);
995                     } else {
996                               IFNET_STAT_INC(ifp, oerrors, 1);
997                               if ((txstat & (SL_TXSD_TABT | SL_TXSD_OWC))) {
998                                         sc->txcfg = TX_CFG_DEFAULT;
999 
1000                                         if (sc->txenablepad)
1001                                                   sc->txcfg |= 0x20000000;
1002 
1003                                         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
1004                               }
1005                     }
1006                     PDEBUG("tx done descriprtor %x\n", entry);
1007                     sc->sln_bufdata.dirty_tx = (entry + 1) % SL_TXD_CNT;
1008 
1009                     ifq_clr_oactive(&ifp->if_snd);
1010           } while (sc->sln_bufdata.dirty_tx != sc->sln_bufdata.cur_tx);
1011 
1012           if (sc->sln_bufdata.dirty_tx == sc->sln_bufdata.cur_tx)
1013                     ifp->if_timer = 0;
1014           else
1015                     ifp->if_timer = 5;
1016 }
1017 
1018 static void
sln_media_intr(struct sln_softc * sc)1019 sln_media_intr(struct sln_softc *sc)
1020 {
1021           u_long phys[2];
1022           struct ifnet *ifp = &sc->arpcom.ac_if;
1023 
1024           phys[0] = SL_MII_STAT;
1025           sln_mii_cmd(sc, SL_MII0_READ, phys);
1026 
1027           PDEBUG("mii_stat:0x%lx\n", phys[1]);
1028 
1029           if (0 == (phys[1] & SL_MIISTAT_LINK)) {
1030                     kprintf("media is unconnect,linked down,or uncompatible\n");
1031                     sc->connect = 0;
1032                     sln_mii_cmd(sc, SL_MII0_SCAN, phys);
1033                     /* disable tx/rx */
1034                     sc->txcfg &= ~SL_TXCFG_EN;
1035                     sc->rxcfg &= ~SL_RXCFG_EN;
1036                     SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
1037                     SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
1038 
1039                     return;
1040           }
1041           /* Link is good. Report modes and set duplex mode. */
1042           PDEBUG("media is connecting---> ");
1043           sc->connect = 1;
1044 
1045           phys[0] = SL_MII_STAT_OUTPUT;
1046           sln_mii_cmd(sc, SL_MII0_READ, phys);
1047           sc->media_duplex = ((phys[1] & 0x0004) == 0) ? IFM_HDX : IFM_FDX;
1048           sc->media_speed = ((phys[1] & 0x0002) == 0) ? IFM_10_T : IFM_100_TX;
1049 
1050           if_printf(ifp, "media option:%dM %s-duplex\n",
1051               sc->media_speed == 0x6 ? 100 : 10,
1052               sc->media_duplex == 0x100000 ? "full" : "half");
1053 
1054           sln_mii_cmd(sc, SL_MII0_SCAN, phys);
1055 
1056           sln_mac_cfg(sc);
1057 
1058           /* Enable tx/rx */
1059           sc->rxcfg |= SL_RXCFG_EN;
1060           sc->txcfg |= SL_TXCFG_EN;
1061           SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
1062           SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
1063 }
1064 
1065 /* Interrupt Handler */
1066 static void
sln_interrupt(void * arg)1067 sln_interrupt(void *arg)
1068 {
1069           struct sln_softc *sc = arg;
1070           struct ifnet *ifp = &sc->arpcom.ac_if;
1071           uint32_t int_status;
1072 
1073           ASSERT_SERIALIZED(ifp->if_serializer);
1074 
1075           if (sc->suspended || (ifp->if_flags & IFF_RUNNING) == 0)
1076                     return;
1077 
1078           /* Disable interrupts. */
1079           SLN_WRITE_4(sc, SL_INT_MASK, 0);
1080 
1081           int_status = SLN_READ_4(sc, SL_INT_STATUS);
1082 
1083           if ((int_status == 0xffffffff) || (int_status & SL_INRTS) == 0)
1084                     goto back;
1085 
1086           int_status = int_status & SL_INRTS;
1087           PDEBUG("int_status = 0x%x\n", int_status);
1088 
1089           while (0 != int_status) {
1090                     if (int_status & SL_INT_ROK)
1091                               sln_rx(sc);
1092 
1093                     if (int_status & SL_INT_TOK)
1094                               sln_tx_intr(sc);
1095 
1096                     if (int_status & SL_INT_RBO) {
1097                               IFNET_STAT_INC(ifp, ierrors, 1);
1098                               PDEBUG("rx buffer is overflow\n");
1099                     }
1100 
1101                     if (int_status & (SL_INT_LINKFAIL | SL_INT_LINKOK))
1102                               sln_media_intr(sc);
1103 
1104                     int_status = SLN_READ_4(sc, SL_INT_STATUS);
1105           }
1106 
1107           /* Data in Tx buffer waiting for transimission */
1108           if (!ifq_is_empty(&ifp->if_snd))
1109                     if_devstart(ifp);
1110 back:
1111           /* Re-enable interrupts. */
1112           SLN_WRITE_4(sc, SL_INT_MASK, SL_INRTS);
1113 }
1114 
1115 static void
sln_tick(void * x)1116 sln_tick(void *x)
1117 {
1118           struct sln_softc *sc = x;
1119 
1120           callout_reset(&sc->sln_state, hz, sln_tick, sc);
1121 }
1122 
1123 static int
sln_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data,struct ucred * cr)1124 sln_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
1125 {
1126           struct sln_softc *sc = ifp->if_softc;
1127           struct ifreq *ifr = (struct ifreq *)data;
1128           int error = 0;
1129 
1130           ASSERT_SERIALIZED(ifp->if_serializer);
1131 
1132           switch (cmd) {
1133           case SIOCSIFFLAGS:
1134                     if (ifp->if_flags & IFF_UP) {
1135                               if ((ifp->if_flags & IFF_RUNNING) == 0)
1136                                         sln_init(sc);
1137                     } else {
1138                               if (ifp->if_flags & IFF_RUNNING)
1139                                         sln_stop(sc);
1140                     }
1141                     break;
1142           case SIOCADDMULTI:
1143           case SIOCDELMULTI:
1144                     sln_set_multi(sc);
1145                     break;
1146           case SIOCGIFMEDIA:
1147           case SIOCSIFMEDIA:
1148                     error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
1149                     break;
1150           default:
1151                     error = ether_ioctl(ifp, cmd, data);
1152                     break;
1153           }
1154           return error;
1155 }
1156 
1157 static void
sln_watchdog(struct ifnet * ifp)1158 sln_watchdog(struct ifnet *ifp)
1159 {
1160           struct sln_softc *sc = ifp->if_softc;
1161 
1162           ASSERT_SERIALIZED(ifp->if_serializer);
1163 
1164           if_printf(ifp, "watchdog timeout!\n");
1165           IFNET_STAT_INC(ifp, oerrors, 1);
1166 
1167           sln_tx_intr(sc);
1168           sln_rx(sc);
1169           sln_init(sc);
1170 
1171           if (!ifq_is_empty(&ifp->if_snd))
1172                     if_devstart(ifp);
1173 }
1174 
1175 /* Stop all chip I/O */
1176 static int
sln_shutdown(device_t dev)1177 sln_shutdown(device_t dev)
1178 {
1179           struct sln_softc *sc = device_get_softc(dev);
1180           struct ifnet *ifp = &sc->arpcom.ac_if;
1181 
1182           lwkt_serialize_enter(ifp->if_serializer);
1183           sln_stop(sc);
1184           lwkt_serialize_exit(ifp->if_serializer);
1185 
1186           return 0;
1187 }
1188 
1189 /* device suspend routine */
1190 static int
sln_suspend(device_t dev)1191 sln_suspend(device_t dev)
1192 {
1193           struct sln_softc *sc = device_get_softc(dev);
1194           struct ifnet *ifp = &sc->arpcom.ac_if;
1195 
1196           lwkt_serialize_enter(ifp->if_serializer);
1197           sln_stop(sc);
1198           sc->suspended = 1;
1199           lwkt_serialize_exit(ifp->if_serializer);
1200 
1201           return 0;
1202 }
1203 
1204 /* device resume routine */
1205 static int
sln_resume(device_t dev)1206 sln_resume(device_t dev)
1207 {
1208           struct sln_softc *sc = device_get_softc(dev);
1209           struct ifnet *ifp = &sc->arpcom.ac_if;
1210 
1211           lwkt_serialize_enter(ifp->if_serializer);
1212           if (ifp->if_flags & IFF_UP)
1213                     sln_init(sc);
1214           sc->suspended = 0;
1215           lwkt_serialize_exit(ifp->if_serializer);
1216 
1217           return 0;
1218 }
1219