Reduce ifnet.if_serializer contention on output path:
[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.2 2008/05/14 11:59:22 sephe Exp $
33  */
34
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 <bus/pci/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/ifq_var.h>
56 #include <net/if.h>
57 #include <net/if_arp.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_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_SC92301,
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 *);
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         {0, 0}
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, 0, 0);
150
151 static int
152 sln_probe(struct device *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
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
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         error = bus_setup_intr(dev, sc->sln_irq, INTR_MPSAFE, sln_interrupt, sc,
260                                &sc->sln_intrhand, ifp->if_serializer);
261         if (error) {
262                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sln_irq);
263                 bus_release_resource(dev, SL_RES, SL_RID, sc->sln_res);
264                 ether_ifdetach(ifp);
265                 device_printf(dev, "couldn't set up irq\n");
266                 goto fail;
267         }
268
269         ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->sln_irq));
270         KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus);
271
272         return 0;
273 fail:
274         return error;
275 }
276
277 /* Stop the adapter and free any mbufs allocated to the RX and TX buffers */
278 static void
279 sln_stop(struct sln_softc *sc)
280 {
281         struct ifnet *ifp = &sc->arpcom.ac_if;
282         uint32_t intr_status;
283         int i;
284
285         ASSERT_SERIALIZED(ifp->if_serializer);
286
287         ifp->if_timer = 0;
288         callout_stop(&sc->sln_state);
289
290         /* disable Tx/Rx */
291         sc->txcfg &= ~SL_TXCFG_EN;
292         sc->rxcfg &= ~SL_RXCFG_EN;
293         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
294         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
295
296         /* Clear interrupt */
297         SLN_WRITE_4(sc, SL_INT_MASK, 0);
298         intr_status = SLN_READ_4(sc, SL_INT_STATUS);
299
300         /* Free the TX list buffers */
301         for (i = 0; i < SL_TXD_CNT; i++) {
302                 if (sc->sln_bufdata.sln_tx_buf[i] != NULL) {
303                         m_freem(sc->sln_bufdata.sln_tx_buf[i]);
304                         sc->sln_bufdata.sln_tx_buf[i] = NULL;
305                         SLN_WRITE_4(sc, SL_TSAD0 + i * 4, 0);
306                 }
307         }
308
309         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
310 }
311
312 static int
313 sln_detach(device_t dev)
314 {
315         struct sln_softc *sc = device_get_softc(dev);
316         struct ifnet *ifp = &sc->arpcom.ac_if;
317
318         lwkt_serialize_enter(ifp->if_serializer);
319         sln_stop(sc);
320         bus_teardown_intr(dev, sc->sln_irq, sc->sln_intrhand);
321         lwkt_serialize_exit(ifp->if_serializer);
322
323         ether_ifdetach(ifp);
324
325         bus_generic_detach(dev);
326
327         bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sln_irq);
328         bus_release_resource(dev, SL_RES, SL_RID, sc->sln_res);
329         
330         contigfree(sc->sln_bufdata.sln_rx_buf, SL_RX_BUFLEN, M_DEVBUF);
331
332         return 0;
333 }
334
335 static int
336 sln_media_upd(struct ifnet *ifp)
337 {
338         struct sln_softc *sc = ifp->if_softc;
339         struct ifmedia *ifm = &sc->ifmedia;
340
341         if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
342                 return EINVAL;
343
344         if (ifp->if_flags & IFF_UP)
345                 sln_init(sc);
346
347         return 0;
348 }
349
350 static void
351 sln_media_stat(struct ifnet *ifp, struct ifmediareq *ifmr)
352 {
353         struct sln_softc *sc = ifp->if_softc;
354         u_long phys[2];
355         uint32_t temp;
356
357         ifmr->ifm_status = IFM_AVALID;
358         ifmr->ifm_active = IFM_ETHER;
359
360         phys[0] = SL_MII_STAT;
361         sln_mii_cmd(sc, SL_MII0_READ, phys);
362
363         if (phys[1] & SL_MIISTAT_LINK)
364                 ifmr->ifm_status |= IFM_ACTIVE;
365
366         temp = SLN_READ_4(sc, SL_PHY_CTRL);
367
368         if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10)) == 0x60800000)
369                 ifmr->ifm_active |= IFM_AUTO;
370         else if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD100)) == 0x40800000)
371                 ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
372         else if ((temp & SL_PHYCTL_SPD100) == 0x40000000)
373                 ifmr->ifm_active |= IFM_100_TX | IFM_HDX;
374         else if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD10)) == 0x20800000)
375                 ifmr->ifm_active |= IFM_10_T | IFM_FDX;
376         else if ((temp & SL_PHYCTL_SPD10) == 0x20000000)
377                 ifmr->ifm_active |= IFM_10_T | IFM_HDX;
378
379         sln_mii_cmd(sc, SL_MII0_SCAN, phys);
380 }
381
382 /* command selected in MII command register  */
383 static void
384 sln_mii_cmd(struct sln_softc *sc, uint32_t cmd, u_long *phys)
385 {
386         uint32_t mii_status;
387
388         SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER);
389
390         do {
391                 mii_status = 0;
392                 DELAY(10);
393                 mii_status = SLN_READ_4(sc, SL_MII_STATUS);
394         } while (mii_status & SL_MIISTAT_BUSY);
395
396         switch (cmd) {
397         case SL_MII0_SCAN:
398                 SLN_WRITE_4(sc, SL_MII_CMD1, 0x1 << 6);
399                 SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_SCAN);
400                 break;
401
402         case SL_MII0_READ:
403                 SLN_WRITE_4(sc, SL_MII_CMD1, phys[0] << 6);
404                 SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_READ);
405                 break;
406
407         default:                /* WRITE */
408                 SLN_WRITE_4(sc, SL_MII_CMD1, phys[0] << 6 | phys[1] << 11);
409                 SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_WRITE);
410                 break;
411         }
412
413         do {
414                 DELAY(10);
415                 mii_status = SLN_READ_4(sc, SL_MII_STATUS);
416         } while (mii_status & SL_MIISTAT_BUSY);
417
418         if (SL_MII0_READ == cmd)
419                 phys[1] = (mii_status >> 13) & 0xffff;
420 }
421
422 /* Set media speed and duplex mode */
423 static void
424 sln_media_cfg(struct sln_softc *sc)
425 {
426         u_long phys[2];
427         uint32_t mediatype;
428         uint32_t temp;
429
430         mediatype = (&sc->ifmedia)->ifm_cur->ifm_media;
431
432         temp = SLN_READ_4(sc, SL_PHY_CTRL);
433         temp &= ~(SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10);
434         temp |= (SL_PHYCTL_ANE | SL_PHYCTL_RESET);
435
436         /************************************************/
437         /* currently set media word by selected media   */
438         /*                                              */
439         /* IFM_ETHER = 0x00000020                       */
440         /* IFM_AUTO=0, IFM_10_T=3,  IFM_100_TX=6        */
441         /* IFM_FDX=0x00100000    IFM_HDX=0x00200000     */
442         /************************************************/
443         switch (mediatype) {
444         case 0x00000020:
445                 PDEBUG(" autoselet supported\n");
446                 temp |= (SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10);
447                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_AUTO;
448                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
449                 break;
450         case 0x23:
451         case 0x00200023:
452                 PDEBUG(" 10Mbps half_duplex supported\n");
453                 temp |= SL_PHYCTL_SPD10;
454                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX;
455                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_HDX);
456                 break;
457
458         case 0x00100023:
459                 PDEBUG("10Mbps full_duplex supported\n");
460                 temp |= (SL_PHYCTL_SPD10 | SL_PHYCTL_DUX);
461                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_FDX;
462                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX);
463                 break;
464
465         case 0x26:
466         case 0x00200026:
467                 PDEBUG("100Mbps half_duplex supported\n");
468                 temp |= SL_PHYCTL_SPD100;
469                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_HDX;
470                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_100_TX | IFM_HDX);
471                 break;
472
473         case 0x00100026:
474                 PDEBUG("100Mbps full_duplex supported\n");
475                 temp |= (SL_PHYCTL_SPD100 | SL_PHYCTL_DUX);
476                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_FDX;
477                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_100_TX | IFM_FDX);
478                 break;
479
480         default:
481                 break;
482         }
483
484         SLN_WRITE_4(sc, SL_PHY_CTRL, temp);
485
486         DELAY(10000);
487         temp &= ~SL_PHYCTL_RESET;
488         SLN_WRITE_4(sc, SL_PHY_CTRL, temp);
489
490         DELAY(1000);
491         phys[0] = SL_MII_JAB;
492         phys[1] = SL_PHY_16_JAB_ENB | SL_PHY_16_PORT_ENB;
493         sln_mii_cmd(sc, SL_MII0_WRITE, phys);
494
495         sc->connect = 0;
496         sln_mii_cmd(sc, SL_MII0_SCAN, phys);
497 }
498
499 static void
500 sln_mac_cfg(struct sln_softc *sc)
501 {
502         struct ifnet *ifp = &sc->arpcom.ac_if;
503         u_long flowcfg = 0;
504
505         /* Set the initial TX/RX/Flow Control configuration */
506         sc->rxcfg = SL_RXCFG_LOW_THRESHOLD | SL_RXCFG_HIGH_THRESHOLD;
507         sc->txcfg = TX_CFG_DEFAULT;
508
509         if (sc->txenablepad)
510                 sc->txcfg |= 0x20000000;
511
512         if (sc->media_speed == IFM_10_T)
513                 sc->txcfg |= SL_TXCFG_DATARATE;
514
515         if (sc->media_duplex == IFM_FDX) {
516                 sc->rxcfg |= SL_RXCFG_FULLDX;
517                 sc->txcfg |= SL_TXCFG_FULLDX;
518                 flowcfg = SL_FLOWCTL_FULLDX | SL_FLOWCTL_EN;
519         } else {
520                 sc->rxcfg &= ~SL_RXCFG_FULLDX;
521                 sc->txcfg &= ~SL_TXCFG_FULLDX;
522         }
523
524         /* if promiscuous mode, set the allframes bit. */
525         if (ifp->if_flags & IFF_PROMISC)
526                 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);
527         else
528                 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);
529
530         /* Set capture broadcast bit to capture broadcast frames */
531         if (ifp->if_flags & IFF_BROADCAST)
532                 sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_BROAD;
533         else
534                 sc->rxcfg &= ~(SL_RXCFG_EN | SL_RXCFG_RCV_BROAD);
535
536         /* Program the multicast filter, if necessary */
537         sln_set_multi(sc);
538
539         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
540         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
541         SLN_WRITE_4(sc, SL_FLOW_CTRL, flowcfg);
542 }
543
544 static u_char shade_map[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
545                               0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
546
547 /* Calculate CRC32 of a multicast group address */
548 static uint32_t
549 sln_ether_crc32(caddr_t addr)
550 {
551         uint32_t crc, crcr;
552         int i, j;
553         unsigned char data = 0;
554         /* Compute CRC for the address value. */
555
556         crc = 0xFFFFFFFF;       /* initial value */
557
558         for (i = ETHER_ADDR_LEN; i > 0; i--) {
559                 data = *addr++;
560
561                 for (j = 0; j < 8; j++) {
562                         if (((data & 0x1) ^ (crc & 0x1)) != 0) {
563                                 crc >>= 1;
564                                 crc ^= 0xEDB88320;
565                         } else {
566                                 crc >>= 1;
567                         }
568                         data >>= 1;
569                 }
570         }
571
572         crcr = shade_map[crc >> 28];
573         crcr |= (shade_map[(crc >> 24) & 0xf] << 4);
574         crcr |= (shade_map[(crc >> 20) & 0xf] << 8);
575         crcr |= (shade_map[(crc >> 16) & 0xf] << 12);
576         crcr |= (shade_map[(crc >> 12) & 0xf] << 16);
577         crcr |= (shade_map[(crc >> 8) & 0xf] << 20);
578         crcr |= (shade_map[(crc >> 4) & 0xf] << 24);
579         crcr |= (shade_map[crc & 0xf] << 28);
580
581         return crcr;
582 }
583
584 /* Program the 64-bit multicast hash filter */
585 static void
586 sln_set_multi(struct sln_softc *sc)
587 {
588         struct ifnet *ifp = &sc->arpcom.ac_if;
589         uint32_t crc = 0;
590         uint32_t mc_g[2] = {0, 0};
591         struct ifmultiaddr *ifma;
592         int i, j;
593
594         if (ifp->if_flags & IFF_PROMISC) {
595                 kprintf("Promisc mode is enabled\n");
596                 sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
597                 mc_g[0] = mc_g[1] = 0xFFFFFFFF;
598         } else if (ifp->if_flags & IFF_ALLMULTI) {
599                 kprintf("Allmulti mode is enabled\n");
600                 sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
601                 mc_g[0] = mc_g[1] = 0xFFFFFFFF;
602         } else if (ifp->if_flags & IFF_MULTICAST) {
603                 kprintf("Multicast mode is enabled\n");
604                 sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
605
606                 /* first, zero all the existing hash bits */
607                 mc_g[0] = mc_g[1] = 0;
608
609                 for (i = 0, ifma = (ifp->if_multiaddrs.lh_first);
610                      ifma != NULL && (i < ifma->ifma_refcount);
611                      i++, ifma = (ifma->ifma_link.le_next)) {
612                         j = 0;
613
614                         if ((ifma->ifma_addr->sa_family) != AF_LINK)
615                                 continue;
616
617                         crc = ~sln_ether_crc32(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
618                         crc >>= 24;
619
620                         if (crc & 0x1)
621                                 j |= 0x2;
622                         if (crc & 0x2)
623                                 j |= 0x1;
624                         if (crc & 0x10)
625                                 j |= 0x20;
626                         if (crc & 0x20)
627                                 j |= 0x10;
628                         if (crc & 0x40)
629                                 j |= 0x8;
630                         if (crc & 0x80)
631                                 j |= 0x4;
632
633                         if (j > 31)
634                                 mc_g[0] |= (0x1 << (j - 32));
635                         else
636                                 mc_g[1] |= (0x1 << j);
637                 }
638         } else {
639                 sc->rxcfg &= ~(SL_RXCFG_EN | SL_RXCFG_RCV_MULTI);
640         }
641
642         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
643         SLN_WRITE_4(sc, SL_MULTI_GROUP0, mc_g[0]);
644         SLN_WRITE_4(sc, SL_MULTI_GROUP1, mc_g[1]);
645 }
646
647 /* Initialize the TX/Rx descriptors */
648 static void
649 sln_init_tx(struct sln_softc *sc)
650 {
651         int i;
652
653         sc->sln_bufdata.cur_tx = 0;
654         sc->sln_bufdata.dirty_tx = 0;
655
656         for (i = 0; i < SL_TXD_CNT; i++) {
657                 sc->sln_bufdata.sln_tx_buf[i] = NULL;
658                 SLN_WRITE_4(sc, SL_TSAD0 + (i * 4), 0);
659         }
660 }
661
662 /* Software & Hardware Initialize */
663 static void
664 sln_init(void *x)
665 {
666         struct sln_softc *sc = x;
667         struct ifnet *ifp = &sc->arpcom.ac_if;
668
669         PDEBUG("sln_init\n");
670
671         ASSERT_SERIALIZED(ifp->if_serializer);
672
673         sln_stop(sc);
674
675         /* soft reset the chip */
676         sln_reset(sc);
677
678         /* disable interrupt */
679         SLN_WRITE_4(sc, SL_INT_MASK, 0);
680
681         /* SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER); */
682
683         /* clear multicast address */
684         SLN_WRITE_4(sc, SL_MULTI_GROUP0, 0);
685         SLN_WRITE_4(sc, SL_MULTI_GROUP1, 0);
686
687         /* Init the RX buffer start address register. */
688         SLN_WRITE_4(sc, SL_RBSA, vtophys(sc->sln_bufdata.sln_rx_buf));
689         sc->sln_bufdata.dirty_rx = vtophys(sc->sln_bufdata.sln_rx_buf);
690
691         /* Init TX descriptors. */
692         sln_init_tx(sc);
693
694         /* configure RX buffer size */
695         if (sc->tx_early_ctrl && sc->rx_early_ctrl)
696                 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_RX | SL_EARLY_TX | SL_RXBUF_64 | SL_RXFIFO_1024BYTES);
697         else if (sc->tx_early_ctrl)
698                 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_TX | SL_RXBUF_64);
699         else if (sc->rx_early_ctrl)
700                 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_RX | SL_RXBUF_64 | SL_RXFIFO_1024BYTES);
701         else
702                 SLN_WRITE_4(sc, SL_CFG1, SL_RXBUF_64);
703
704         /* MII media configuration */
705         sln_media_cfg(sc);
706
707         if (sc->connect) {
708                 /* Enable transmit and receive */
709                 sc->rxcfg |= SL_RXCFG_EN;
710                 sc->txcfg |= SL_TXCFG_EN;
711         } else {
712                 sc->rxcfg &= ~SL_RXCFG_EN;
713                 sc->txcfg &= ~SL_TXCFG_EN;
714         }
715
716         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
717         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
718
719         /* Enable interrupts */
720         SLN_WRITE_4(sc, SL_INT_MASK, SL_INRTS);
721
722         sc->suspended = 0;
723
724         ifp->if_flags |= IFF_RUNNING;
725         ifp->if_flags &= ~IFF_OACTIVE;
726
727         callout_reset(&sc->sln_state, hz, sln_tick, sc);
728 }
729
730 /* Transmit Packet */
731 static void
732 sln_tx(struct ifnet *ifp)
733 {
734         struct sln_softc *sc = ifp->if_softc;
735         struct mbuf *m_head = NULL;
736         struct mbuf *m_new = NULL;
737         int entry;
738
739         ASSERT_SERIALIZED(ifp->if_serializer);
740
741         if (!sc->connect) {
742                 ifq_purge(&ifp->if_snd);
743                 return;
744         }
745
746         if ((ifp->if_flags & (IFF_OACTIVE | IFF_RUNNING)) != IFF_RUNNING)
747                 return;
748
749         while (SL_CUR_TXBUF(sc) == NULL) {      /* SL_CUR_TXBUF(x) = x->sln_bufdata.sln_tx_buf[x->sln_bufdata.cur_tx] */
750                 entry = sc->sln_bufdata.cur_tx;
751
752                 m_head = ifq_dequeue(&ifp->if_snd, NULL);
753                 if (m_head == NULL)
754                         break;
755
756                 MGETHDR(m_new, MB_DONTWAIT, MT_DATA);
757                 if (m_new == NULL) {
758                         if_printf(ifp, "no memory for tx descriptor");
759                         m_freem(m_head);
760                         break;
761                 }
762                 if ((m_head->m_pkthdr.len > MHLEN) || (60 > MHLEN)) {
763                         MCLGET(m_new, MB_DONTWAIT);
764                         if (!(m_new->m_flags & M_EXT)) {
765                                 m_freem(m_new);
766                                 m_freem(m_head);
767                                 if_printf(ifp, "no memory for tx descriptor");
768                                 break;
769                         }
770                 }
771                 m_copydata(m_head, 0, m_head->m_pkthdr.len, mtod(m_new, caddr_t));
772                 m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
773                 m_freem(m_head);
774                 m_head = m_new;
775                 SL_CUR_TXBUF(sc) = m_head;
776
777                 /*
778                  * if there's a BPF listener, bounce a copy of this frame to
779                  * him
780                  */
781                 BPF_MTAP(ifp, SL_CUR_TXBUF(sc));
782
783                 /* Transmit the frame */
784                 SLN_WRITE_4(sc, ((entry * 4) + SL_TSAD0),
785                     vtophys(mtod(SL_CUR_TXBUF(sc), caddr_t)));
786
787                 /* calculate length of the frame */
788                 if ((SL_CUR_TXBUF(sc)->m_pkthdr.len < 60) && (!sc->txenablepad)) {
789                         memset(mtod(m_head, char *)+m_head->m_pkthdr.len, 0x20, 60 - m_head->m_pkthdr.len);
790                         SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 60);
791                 } else if (SL_CUR_TXBUF(sc)->m_pkthdr.len < 100)
792                         SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, SL_CUR_TXBUF(sc)->m_pkthdr.len);
793                 else if (SL_CUR_TXBUF(sc)->m_pkthdr.len < 300)
794                         SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 0x30000 | SL_CUR_TXBUF(sc)->m_pkthdr.len);
795                 else
796                         SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 0x50000 | SL_CUR_TXBUF(sc)->m_pkthdr.len);
797                 sc->sln_bufdata.cur_tx = (entry + 1) % SL_TXD_CNT;
798
799                 PDEBUG("Queue tx packet size %d to tx-descriptor %d.\n", m_head->m_pkthdr.len, entry);
800         }
801
802         /* Tx buffer chain full */
803         if (SL_CUR_TXBUF(sc) != NULL)
804                 ifp->if_flags |= IFF_OACTIVE;
805
806         /* Set a timeout in case the chip goes out to lunch */
807         ifp->if_timer = 5;
808 }
809
810 /* Receive Data handler */
811 static void
812 sln_rx(struct sln_softc *sc)
813 {
814         struct mbuf *m;
815         struct ifnet *ifp = &sc->arpcom.ac_if;
816         uint32_t rxstat = 0;
817         uint32_t rx_offset;
818         caddr_t rx_bufpos = NULL;
819         uint32_t cur_rx = 0;
820         uint32_t dirty_rx;
821         long rx_len;
822         u_long rx_space;
823         u_long rx_size = 0;
824         u_long rx_size_align = 0;
825         uint32_t rx_bytes = 0;
826         u_long pkt_size = 0;
827
828         cur_rx = SLN_READ_4(sc, SL_RBW_PTR);
829         dirty_rx = sc->sln_bufdata.dirty_rx;
830
831         /*
832          * cur_rx is only 17 bits in the RxBufWPtr register. if cur_rx can be
833          * used in physical space, we need to change it to 32 bits physical
834          * address
835          */
836         cur_rx |= vtophys(sc->sln_bufdata.sln_rx_buf) & (~(u_long) (SL_RX_BUFLEN - 1));
837
838         if (cur_rx < vtophys(sc->sln_bufdata.sln_rx_buf))
839                 cur_rx += SL_RX_BUFLEN;
840
841         if (cur_rx >= dirty_rx)
842                 rx_len = (long)(cur_rx - dirty_rx);
843         else
844                 rx_len = SL_RX_BUFLEN - (long)(dirty_rx - cur_rx);
845
846         if ((rx_len > SL_RX_BUFLEN) || (rx_len < 0)) {
847                 if_printf(ifp, "rx len is fail\n");
848                 return;
849         }
850         if (rx_len == 0)
851                 return;
852
853         rx_offset = (dirty_rx - vtophys(sc->sln_bufdata.sln_rx_buf)) & (u_long) (SL_RX_BUFLEN - 1);
854
855         while (rx_len > 0) {
856                 rx_bufpos = sc->sln_bufdata.sln_rx_buf + rx_offset;
857                 rxstat = *(uint32_t *) rx_bufpos;
858                 rx_size = (rxstat >> 20) & 0x0FFF;
859                 rx_size_align = (rx_size + 3) & ~3;     /* for 4 bytes aligned */
860                 pkt_size = rx_size - ETHER_CRC_LEN;     /* Omit the four octet
861                                                          * CRC from the length. */
862
863                 PDEBUG("rx len: %ld  rx frame size:%ld  rx state:0x%x\n", rx_len, rx_size, rxstat);
864
865                 /* errors receive packets caculatation */
866                 if (rxstat == 0 || rx_size < 16 || !(rxstat & SL_RXSTAT_RXOK)) {
867                         ifp->if_ierrors++;
868
869                         if (!(rxstat & SL_RXSTAT_RXOK))
870                                 if_printf(ifp, "receiver ok error\n");
871
872                         if (!(rxstat & SL_RXSTAT_CRCOK))
873                                 if_printf(ifp, "crc error\n");
874
875                         if (rxstat & SL_RXSTAT_ALIGNERR)
876                                 if_printf(ifp, "frame alignment error\n");
877
878                         if (rxstat & (SL_RXSTAT_HUGEFRM | SL_RXSTAT_SMALLFRM))
879                                 if_printf(ifp, "received frame length is error\n");
880
881                         break;
882                 }
883                 rx_len -= (long)(rx_size_align + 4);    /* 4 bytes for receive
884                                                          * frame head */
885
886                 if (rx_len < 0) {
887                         kprintf("rx packets len is too small\n");
888                         break;
889                 }
890 #ifdef SLN_PDEBUG
891                 caddr_t p = NULL;
892
893                 if_printf(ifp, "rx frame content\n");
894                 p = rx_bufpos;
895                 for (i = 0; i < 30; i++, p++) {
896                         if (i % 10 == 0)
897                                 kprintf("\n");
898                         if_printf(ifp, "%x  ", (u_char)*p);
899                 }
900                 if_printf(ifp, "\n");
901 #endif
902                 /* No errors; receive the packet. */
903                 rx_bytes = rx_bytes + rx_size + 4;      /* 4 bytes for receive
904                                                          * frame header */
905
906                 if (rx_bufpos == (sc->sln_bufdata.sln_rx_buf + SL_RX_BUFLEN))
907                         rx_bufpos = sc->sln_bufdata.sln_rx_buf;
908
909                 rx_bufpos = rx_bufpos + 4;      /* 4 bytes for receive frame
910                                                  * header */
911                 rx_space = (u_long)((sc->sln_bufdata.sln_rx_buf + SL_RX_BUFLEN) - rx_bufpos);
912
913                 if (pkt_size > rx_space) {
914                         m = m_devget(rx_bufpos - 2, pkt_size + 2, 0, ifp, NULL);        /* 2 for etherer head
915                                                                                          * align */
916
917                         if (m == NULL) {
918                                 ifp->if_ierrors++;
919                                 if_printf(ifp,
920                                     "out of mbufs, tried to copy %ld bytes\n",
921                                     rx_space);
922                         } else {
923                                 m_adj(m, 2);
924                                 m_copyback(m, rx_space, pkt_size - rx_space, sc->sln_bufdata.sln_rx_buf);
925                         }
926                 } else {
927                         m = m_devget(rx_bufpos - 2, pkt_size + 2, 0, ifp, NULL);
928
929                         if (m == NULL) {
930                                 ifp->if_ierrors++;
931                                 if_printf(ifp,
932                                     "out of mbufs, tried to copy %ld bytes\n",
933                                     pkt_size);
934                                 if_printf(ifp, "ierrors = %ld\n", ifp->if_ierrors);
935
936                         } else {
937                                 m_adj(m, 2);
938                         }
939                 }
940
941                 ifp->if_ipackets++;
942                 PDEBUG("ipackets = %ld\n", ifp->if_ipackets);
943
944                 ifp->if_input(ifp, m);
945
946                 rx_offset = (rx_offset + rx_size + 4) & (u_long) (SL_RX_BUFLEN - 1);    /* 4 bytes for receive
947                                                                                          * frame head */
948         }
949
950         sc->sln_bufdata.dirty_rx = cur_rx;
951
952         SLN_WRITE_4(sc, SL_RBR_PTR, cur_rx);
953 }
954
955 /* Transmit OK/ERR handler */
956 static void
957 sln_tx_intr(struct sln_softc *sc)
958 {
959         struct ifnet *ifp = &sc->arpcom.ac_if;
960         uint32_t txstat;
961         int entry;
962
963         do {
964                 entry = sc->sln_bufdata.dirty_tx;
965                 txstat = SLN_READ_4(sc, SL_TSD0 + entry * 4);
966
967                 if (!(txstat & (SL_TXSD_TOK | SL_TXSD_TUN | SL_TXSD_TABT)))
968                         break;  /* It still hasn't been sent */
969
970                 if (SL_DIRTY_TXBUF(sc) != NULL) {       /* SL_DIRTY_TXBUF(x) =
971                                                          * x->sln_bufdata.sln_tx_
972                                                          * buf[x->sln_bufdata.dir
973                                                          * ty_tx] */
974                         m_freem(SL_DIRTY_TXBUF(sc));
975                         SL_DIRTY_TXBUF(sc) = NULL;
976                 }
977                 if (txstat & SL_TXSD_TOK) {
978                         ifp->if_opackets++;
979                         ifp->if_obytes += txstat & SL_TXSD_LENMASK;
980                         PDEBUG("opackets = %ld\n", ifp->if_opackets);
981                         ifp->if_collisions += (txstat & SL_TXSD_NCC) >> 22;
982                 } else {
983                         ifp->if_oerrors++;
984                         if ((txstat & (SL_TXSD_TABT | SL_TXSD_OWC))) {
985                                 sc->txcfg = TX_CFG_DEFAULT;
986
987                                 if (sc->txenablepad)
988                                         sc->txcfg |= 0x20000000;
989
990                                 SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
991                         }
992                 }
993                 PDEBUG("tx done descriprtor %x\n", entry);
994                 sc->sln_bufdata.dirty_tx = (entry + 1) % SL_TXD_CNT;
995
996                 ifp->if_flags &= ~IFF_OACTIVE;
997         } while (sc->sln_bufdata.dirty_tx != sc->sln_bufdata.cur_tx);
998
999         if (sc->sln_bufdata.dirty_tx == sc->sln_bufdata.cur_tx)
1000                 ifp->if_timer = 0;
1001         else
1002                 ifp->if_timer = 5;
1003 }
1004
1005 static void
1006 sln_media_intr(struct sln_softc *sc)
1007 {
1008         u_long phys[2];
1009         struct ifnet *ifp = &sc->arpcom.ac_if;
1010
1011         phys[0] = SL_MII_STAT;
1012         sln_mii_cmd(sc, SL_MII0_READ, phys);
1013
1014         PDEBUG("mii_stat:0x%lx\n", phys[1]);
1015
1016         if (0 == (phys[1] & SL_MIISTAT_LINK)) {
1017                 kprintf("media is unconnect,linked down,or uncompatible\n");
1018                 sc->connect = 0;
1019                 sln_mii_cmd(sc, SL_MII0_SCAN, phys);
1020                 /* disable tx/rx */
1021                 sc->txcfg &= ~SL_TXCFG_EN;
1022                 sc->rxcfg &= ~SL_RXCFG_EN;
1023                 SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
1024                 SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
1025
1026                 return;
1027         }
1028         /* Link is good. Report modes and set duplex mode. */
1029         PDEBUG("media is connecting---> ");
1030         sc->connect = 1;
1031
1032         phys[0] = SL_MII_STAT_OUTPUT;
1033         sln_mii_cmd(sc, SL_MII0_READ, phys);
1034         sc->media_duplex = ((phys[1] & 0x0004) == 0) ? IFM_HDX : IFM_FDX;
1035         sc->media_speed = ((phys[1] & 0x0002) == 0) ? IFM_10_T : IFM_100_TX;
1036
1037         if_printf(ifp, "media option:%dM %s-duplex\n",
1038             sc->media_speed == 0x6 ? 100 : 10,
1039             sc->media_duplex == 0x100000 ? "full" : "half");
1040
1041         sln_mii_cmd(sc, SL_MII0_SCAN, phys);
1042
1043         sln_mac_cfg(sc);
1044
1045         /* Enable tx/rx */
1046         sc->rxcfg |= SL_RXCFG_EN;
1047         sc->txcfg |= SL_TXCFG_EN;
1048         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
1049         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
1050 }
1051
1052 /* Interrupt Handler */
1053 static void
1054 sln_interrupt(void *arg)
1055 {
1056         struct sln_softc *sc = arg;
1057         struct ifnet *ifp = &sc->arpcom.ac_if;
1058         uint32_t int_status;
1059
1060         ASSERT_SERIALIZED(ifp->if_serializer);
1061
1062         if (sc->suspended || (ifp->if_flags & IFF_RUNNING) == 0)
1063                 return;
1064
1065         /* Disable interrupts. */
1066         SLN_WRITE_4(sc, SL_INT_MASK, 0);
1067
1068         int_status = SLN_READ_4(sc, SL_INT_STATUS);
1069
1070         if ((int_status == 0xffffffff) || (int_status & SL_INRTS) == 0)
1071                 goto back;
1072
1073         int_status = int_status & SL_INRTS;
1074         PDEBUG("int_status = 0x%x\n", int_status);
1075
1076         while (0 != int_status) {
1077                 if (int_status & SL_INT_ROK)
1078                         sln_rx(sc);
1079
1080                 if (int_status & SL_INT_TOK)
1081                         sln_tx_intr(sc);
1082
1083                 if (int_status & SL_INT_RBO) {
1084                         ifp->if_ierrors++;
1085                         PDEBUG("rx buffer is overflow\n");
1086                 }
1087
1088                 if (int_status & (SL_INT_LINKFAIL | SL_INT_LINKOK))
1089                         sln_media_intr(sc);
1090
1091                 int_status = SLN_READ_4(sc, SL_INT_STATUS);
1092         }
1093
1094         /* Data in Tx buffer waiting for transimission */
1095         if (!ifq_is_empty(&ifp->if_snd))
1096                 if_devstart(ifp);
1097 back:
1098         /* Re-enable interrupts. */
1099         SLN_WRITE_4(sc, SL_INT_MASK, SL_INRTS);
1100 }
1101
1102 static void
1103 sln_tick(void *x)
1104 {
1105         struct sln_softc *sc = x;
1106
1107         callout_reset(&sc->sln_state, hz, sln_tick, sc);
1108 }
1109
1110 static int
1111 sln_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
1112 {
1113         struct sln_softc *sc = ifp->if_softc;
1114         struct ifreq *ifr = (struct ifreq *)data;
1115         int error = 0;
1116
1117         ASSERT_SERIALIZED(ifp->if_serializer);
1118
1119         switch (cmd) {
1120         case SIOCSIFFLAGS:
1121                 if (ifp->if_flags & IFF_UP) {
1122                         if ((ifp->if_flags & IFF_RUNNING) == 0)
1123                                 sln_init(sc);
1124                 } else {
1125                         if (ifp->if_flags & IFF_RUNNING)
1126                                 sln_stop(sc);
1127                 }
1128                 break;
1129         case SIOCADDMULTI:
1130         case SIOCDELMULTI:
1131                 sln_set_multi(sc);
1132                 break;
1133         case SIOCGIFMEDIA:
1134         case SIOCSIFMEDIA:
1135                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
1136                 break;
1137         default:
1138                 error = ether_ioctl(ifp, cmd, data);
1139                 break;
1140         }
1141         return error;
1142 }
1143
1144 static void
1145 sln_watchdog(struct ifnet *ifp)
1146 {
1147         struct sln_softc *sc = ifp->if_softc;
1148
1149         ASSERT_SERIALIZED(ifp->if_serializer);
1150
1151         if_printf(ifp, "watchdog timeout!\n");
1152         ifp->if_oerrors++;
1153
1154         sln_tx_intr(sc);
1155         sln_rx(sc);
1156         sln_init(sc);
1157
1158         if (!ifq_is_empty(&ifp->if_snd))
1159                 if_devstart(ifp);
1160 }
1161
1162 /* Stop all chip I/O */
1163 static int
1164 sln_shutdown(device_t dev)
1165 {
1166         struct sln_softc *sc = device_get_softc(dev);
1167         struct ifnet *ifp = &sc->arpcom.ac_if;
1168
1169         lwkt_serialize_enter(ifp->if_serializer);
1170         sln_stop(sc);
1171         lwkt_serialize_exit(ifp->if_serializer);
1172
1173         return 0;
1174 }
1175
1176 /* device suspend routine */
1177 static int
1178 sln_suspend(device_t dev)
1179 {
1180         struct sln_softc *sc = device_get_softc(dev);
1181         struct ifnet *ifp = &sc->arpcom.ac_if;
1182
1183         lwkt_serialize_enter(ifp->if_serializer);
1184         sln_stop(sc);
1185         sc->suspended = 1;
1186         lwkt_serialize_exit(ifp->if_serializer);
1187
1188         return 0;
1189 }
1190
1191 /* device resume routine */
1192 static int
1193 sln_resume(device_t dev)
1194 {
1195         struct sln_softc *sc = device_get_softc(dev);
1196         struct ifnet *ifp = &sc->arpcom.ac_if;
1197
1198         lwkt_serialize_enter(ifp->if_serializer);
1199         if (ifp->if_flags & IFF_UP)
1200                 sln_init(sc);
1201         sc->suspended = 0;
1202         lwkt_serialize_exit(ifp->if_serializer);
1203
1204         return 0;
1205 }