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