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