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