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 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 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 611 j = 0; 612 613 if ((ifma->ifma_addr->sa_family) != AF_LINK) 614 continue; 615 616 crc = ~sln_ether_crc32(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); 617 crc >>= 24; 618 619 if (crc & 0x1) 620 j |= 0x2; 621 if (crc & 0x2) 622 j |= 0x1; 623 if (crc & 0x10) 624 j |= 0x20; 625 if (crc & 0x20) 626 j |= 0x10; 627 if (crc & 0x40) 628 j |= 0x8; 629 if (crc & 0x80) 630 j |= 0x4; 631 632 if (j > 31) 633 mc_g[0] |= (0x1 << (j - 32)); 634 else 635 mc_g[1] |= (0x1 << j); 636 } 637 } else { 638 sc->rxcfg &= ~(SL_RXCFG_EN | SL_RXCFG_RCV_MULTI); 639 } 640 641 SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg); 642 SLN_WRITE_4(sc, SL_MULTI_GROUP0, mc_g[0]); 643 SLN_WRITE_4(sc, SL_MULTI_GROUP1, mc_g[1]); 644 } 645 646 /* Initialize the TX/Rx descriptors */ 647 static void 648 sln_init_tx(struct sln_softc *sc) 649 { 650 int i; 651 652 sc->sln_bufdata.cur_tx = 0; 653 sc->sln_bufdata.dirty_tx = 0; 654 655 for (i = 0; i < SL_TXD_CNT; i++) { 656 sc->sln_bufdata.sln_tx_buf[i] = NULL; 657 SLN_WRITE_4(sc, SL_TSAD0 + (i * 4), 0); 658 } 659 } 660 661 /* Software & Hardware Initialize */ 662 static void 663 sln_init(void *x) 664 { 665 struct sln_softc *sc = x; 666 struct ifnet *ifp = &sc->arpcom.ac_if; 667 668 PDEBUG("sln_init\n"); 669 670 ASSERT_SERIALIZED(ifp->if_serializer); 671 672 sln_stop(sc); 673 674 /* soft reset the chip */ 675 sln_reset(sc); 676 677 /* disable interrupt */ 678 SLN_WRITE_4(sc, SL_INT_MASK, 0); 679 680 /* SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER); */ 681 682 /* clear multicast address */ 683 SLN_WRITE_4(sc, SL_MULTI_GROUP0, 0); 684 SLN_WRITE_4(sc, SL_MULTI_GROUP1, 0); 685 686 /* Init the RX buffer start address register. */ 687 SLN_WRITE_4(sc, SL_RBSA, vtophys(sc->sln_bufdata.sln_rx_buf)); 688 sc->sln_bufdata.dirty_rx = vtophys(sc->sln_bufdata.sln_rx_buf); 689 690 /* Init TX descriptors. */ 691 sln_init_tx(sc); 692 693 /* configure RX buffer size */ 694 if (sc->tx_early_ctrl && sc->rx_early_ctrl) 695 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_RX | SL_EARLY_TX | SL_RXBUF_64 | SL_RXFIFO_1024BYTES); 696 else if (sc->tx_early_ctrl) 697 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_TX | SL_RXBUF_64); 698 else if (sc->rx_early_ctrl) 699 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_RX | SL_RXBUF_64 | SL_RXFIFO_1024BYTES); 700 else 701 SLN_WRITE_4(sc, SL_CFG1, SL_RXBUF_64); 702 703 /* MII media configuration */ 704 sln_media_cfg(sc); 705 706 if (sc->connect) { 707 /* Enable transmit and receive */ 708 sc->rxcfg |= SL_RXCFG_EN; 709 sc->txcfg |= SL_TXCFG_EN; 710 } else { 711 sc->rxcfg &= ~SL_RXCFG_EN; 712 sc->txcfg &= ~SL_TXCFG_EN; 713 } 714 715 SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg); 716 SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg); 717 718 /* Enable interrupts */ 719 SLN_WRITE_4(sc, SL_INT_MASK, SL_INRTS); 720 721 sc->suspended = 0; 722 723 ifp->if_flags |= IFF_RUNNING; 724 ifp->if_flags &= ~IFF_OACTIVE; 725 726 callout_reset(&sc->sln_state, hz, sln_tick, sc); 727 } 728 729 /* Transmit Packet */ 730 static void 731 sln_tx(struct ifnet *ifp) 732 { 733 struct sln_softc *sc = ifp->if_softc; 734 struct mbuf *m_head = NULL; 735 struct mbuf *m_new = NULL; 736 int entry; 737 738 ASSERT_SERIALIZED(ifp->if_serializer); 739 740 if (!sc->connect) { 741 ifq_purge(&ifp->if_snd); 742 return; 743 } 744 745 if ((ifp->if_flags & (IFF_OACTIVE | IFF_RUNNING)) != IFF_RUNNING) 746 return; 747 748 while (SL_CUR_TXBUF(sc) == NULL) { /* SL_CUR_TXBUF(x) = x->sln_bufdata.sln_tx_buf[x->sln_bufdata.cur_tx] */ 749 entry = sc->sln_bufdata.cur_tx; 750 751 m_head = ifq_dequeue(&ifp->if_snd, NULL); 752 if (m_head == NULL) 753 break; 754 755 MGETHDR(m_new, MB_DONTWAIT, MT_DATA); 756 if (m_new == NULL) { 757 if_printf(ifp, "no memory for tx descriptor"); 758 m_freem(m_head); 759 break; 760 } 761 if ((m_head->m_pkthdr.len > MHLEN) || (60 > MHLEN)) { 762 MCLGET(m_new, MB_DONTWAIT); 763 if (!(m_new->m_flags & M_EXT)) { 764 m_freem(m_new); 765 m_freem(m_head); 766 if_printf(ifp, "no memory for tx descriptor"); 767 break; 768 } 769 } 770 m_copydata(m_head, 0, m_head->m_pkthdr.len, mtod(m_new, caddr_t)); 771 m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len; 772 m_freem(m_head); 773 m_head = m_new; 774 SL_CUR_TXBUF(sc) = m_head; 775 776 /* 777 * if there's a BPF listener, bounce a copy of this frame to 778 * him 779 */ 780 BPF_MTAP(ifp, SL_CUR_TXBUF(sc)); 781 782 /* Transmit the frame */ 783 SLN_WRITE_4(sc, ((entry * 4) + SL_TSAD0), 784 vtophys(mtod(SL_CUR_TXBUF(sc), caddr_t))); 785 786 /* calculate length of the frame */ 787 if ((SL_CUR_TXBUF(sc)->m_pkthdr.len < 60) && (!sc->txenablepad)) { 788 memset(mtod(m_head, char *)+m_head->m_pkthdr.len, 0x20, 60 - m_head->m_pkthdr.len); 789 SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 60); 790 } else if (SL_CUR_TXBUF(sc)->m_pkthdr.len < 100) 791 SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, SL_CUR_TXBUF(sc)->m_pkthdr.len); 792 else if (SL_CUR_TXBUF(sc)->m_pkthdr.len < 300) 793 SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 0x30000 | SL_CUR_TXBUF(sc)->m_pkthdr.len); 794 else 795 SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 0x50000 | SL_CUR_TXBUF(sc)->m_pkthdr.len); 796 sc->sln_bufdata.cur_tx = (entry + 1) % SL_TXD_CNT; 797 798 PDEBUG("Queue tx packet size %d to tx-descriptor %d.\n", m_head->m_pkthdr.len, entry); 799 } 800 801 /* Tx buffer chain full */ 802 if (SL_CUR_TXBUF(sc) != NULL) 803 ifp->if_flags |= IFF_OACTIVE; 804 805 /* Set a timeout in case the chip goes out to lunch */ 806 ifp->if_timer = 5; 807 } 808 809 /* Receive Data handler */ 810 static void 811 sln_rx(struct sln_softc *sc) 812 { 813 struct mbuf *m; 814 struct ifnet *ifp = &sc->arpcom.ac_if; 815 uint32_t rxstat = 0; 816 uint32_t rx_offset; 817 caddr_t rx_bufpos = NULL; 818 uint32_t cur_rx = 0; 819 uint32_t dirty_rx; 820 long rx_len; 821 u_long rx_space; 822 u_long rx_size = 0; 823 u_long rx_size_align = 0; 824 uint32_t rx_bytes = 0; 825 u_long pkt_size = 0; 826 827 cur_rx = SLN_READ_4(sc, SL_RBW_PTR); 828 dirty_rx = sc->sln_bufdata.dirty_rx; 829 830 /* 831 * cur_rx is only 17 bits in the RxBufWPtr register. if cur_rx can be 832 * used in physical space, we need to change it to 32 bits physical 833 * address 834 */ 835 cur_rx |= vtophys(sc->sln_bufdata.sln_rx_buf) & (~(u_long) (SL_RX_BUFLEN - 1)); 836 837 if (cur_rx < vtophys(sc->sln_bufdata.sln_rx_buf)) 838 cur_rx += SL_RX_BUFLEN; 839 840 if (cur_rx >= dirty_rx) 841 rx_len = (long)(cur_rx - dirty_rx); 842 else 843 rx_len = SL_RX_BUFLEN - (long)(dirty_rx - cur_rx); 844 845 if ((rx_len > SL_RX_BUFLEN) || (rx_len < 0)) { 846 if_printf(ifp, "rx len is fail\n"); 847 return; 848 } 849 if (rx_len == 0) 850 return; 851 852 rx_offset = (dirty_rx - vtophys(sc->sln_bufdata.sln_rx_buf)) & (u_long) (SL_RX_BUFLEN - 1); 853 854 while (rx_len > 0) { 855 rx_bufpos = sc->sln_bufdata.sln_rx_buf + rx_offset; 856 rxstat = *(uint32_t *) rx_bufpos; 857 rx_size = (rxstat >> 20) & 0x0FFF; 858 rx_size_align = (rx_size + 3) & ~3; /* for 4 bytes aligned */ 859 pkt_size = rx_size - ETHER_CRC_LEN; /* Omit the four octet 860 * CRC from the length. */ 861 862 PDEBUG("rx len: %ld rx frame size:%ld rx state:0x%x\n", rx_len, rx_size, rxstat); 863 864 /* errors receive packets caculatation */ 865 if (rxstat == 0 || rx_size < 16 || !(rxstat & SL_RXSTAT_RXOK)) { 866 ifp->if_ierrors++; 867 868 if (!(rxstat & SL_RXSTAT_RXOK)) 869 if_printf(ifp, "receiver ok error\n"); 870 871 if (!(rxstat & SL_RXSTAT_CRCOK)) 872 if_printf(ifp, "crc error\n"); 873 874 if (rxstat & SL_RXSTAT_ALIGNERR) 875 if_printf(ifp, "frame alignment error\n"); 876 877 if (rxstat & (SL_RXSTAT_HUGEFRM | SL_RXSTAT_SMALLFRM)) 878 if_printf(ifp, "received frame length is error\n"); 879 880 break; 881 } 882 rx_len -= (long)(rx_size_align + 4); /* 4 bytes for receive 883 * frame head */ 884 885 if (rx_len < 0) { 886 kprintf("rx packets len is too small\n"); 887 break; 888 } 889 #ifdef SLN_PDEBUG 890 caddr_t p = NULL; 891 892 if_printf(ifp, "rx frame content\n"); 893 p = rx_bufpos; 894 for (i = 0; i < 30; i++, p++) { 895 if (i % 10 == 0) 896 kprintf("\n"); 897 if_printf(ifp, "%x ", (u_char)*p); 898 } 899 if_printf(ifp, "\n"); 900 #endif 901 /* No errors; receive the packet. */ 902 rx_bytes = rx_bytes + rx_size + 4; /* 4 bytes for receive 903 * frame header */ 904 905 if (rx_bufpos == (sc->sln_bufdata.sln_rx_buf + SL_RX_BUFLEN)) 906 rx_bufpos = sc->sln_bufdata.sln_rx_buf; 907 908 rx_bufpos = rx_bufpos + 4; /* 4 bytes for receive frame 909 * header */ 910 rx_space = (u_long)((sc->sln_bufdata.sln_rx_buf + SL_RX_BUFLEN) - rx_bufpos); 911 912 if (pkt_size > rx_space) { 913 m = m_devget(rx_bufpos - 2, pkt_size + 2, 0, ifp, NULL); /* 2 for etherer head 914 * align */ 915 916 if (m == NULL) { 917 ifp->if_ierrors++; 918 if_printf(ifp, 919 "out of mbufs, tried to copy %ld bytes\n", 920 rx_space); 921 } else { 922 m_adj(m, 2); 923 m_copyback(m, rx_space, pkt_size - rx_space, sc->sln_bufdata.sln_rx_buf); 924 } 925 } else { 926 m = m_devget(rx_bufpos - 2, pkt_size + 2, 0, ifp, NULL); 927 928 if (m == NULL) { 929 ifp->if_ierrors++; 930 if_printf(ifp, 931 "out of mbufs, tried to copy %ld bytes\n", 932 pkt_size); 933 if_printf(ifp, "ierrors = %ld\n", ifp->if_ierrors); 934 935 } else { 936 m_adj(m, 2); 937 } 938 } 939 940 ifp->if_ipackets++; 941 PDEBUG("ipackets = %ld\n", ifp->if_ipackets); 942 943 ifp->if_input(ifp, m); 944 945 rx_offset = (rx_offset + rx_size + 4) & (u_long) (SL_RX_BUFLEN - 1); /* 4 bytes for receive 946 * frame head */ 947 } 948 949 sc->sln_bufdata.dirty_rx = cur_rx; 950 951 SLN_WRITE_4(sc, SL_RBR_PTR, cur_rx); 952 } 953 954 /* Transmit OK/ERR handler */ 955 static void 956 sln_tx_intr(struct sln_softc *sc) 957 { 958 struct ifnet *ifp = &sc->arpcom.ac_if; 959 uint32_t txstat; 960 int entry; 961 962 do { 963 entry = sc->sln_bufdata.dirty_tx; 964 txstat = SLN_READ_4(sc, SL_TSD0 + entry * 4); 965 966 if (!(txstat & (SL_TXSD_TOK | SL_TXSD_TUN | SL_TXSD_TABT))) 967 break; /* It still hasn't been sent */ 968 969 if (SL_DIRTY_TXBUF(sc) != NULL) { /* SL_DIRTY_TXBUF(x) = 970 * x->sln_bufdata.sln_tx_ 971 * buf[x->sln_bufdata.dir 972 * ty_tx] */ 973 m_freem(SL_DIRTY_TXBUF(sc)); 974 SL_DIRTY_TXBUF(sc) = NULL; 975 } 976 if (txstat & SL_TXSD_TOK) { 977 ifp->if_opackets++; 978 ifp->if_obytes += txstat & SL_TXSD_LENMASK; 979 PDEBUG("opackets = %ld\n", ifp->if_opackets); 980 ifp->if_collisions += (txstat & SL_TXSD_NCC) >> 22; 981 } else { 982 ifp->if_oerrors++; 983 if ((txstat & (SL_TXSD_TABT | SL_TXSD_OWC))) { 984 sc->txcfg = TX_CFG_DEFAULT; 985 986 if (sc->txenablepad) 987 sc->txcfg |= 0x20000000; 988 989 SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg); 990 } 991 } 992 PDEBUG("tx done descriprtor %x\n", entry); 993 sc->sln_bufdata.dirty_tx = (entry + 1) % SL_TXD_CNT; 994 995 ifp->if_flags &= ~IFF_OACTIVE; 996 } while (sc->sln_bufdata.dirty_tx != sc->sln_bufdata.cur_tx); 997 998 if (sc->sln_bufdata.dirty_tx == sc->sln_bufdata.cur_tx) 999 ifp->if_timer = 0; 1000 else 1001 ifp->if_timer = 5; 1002 } 1003 1004 static void 1005 sln_media_intr(struct sln_softc *sc) 1006 { 1007 u_long phys[2]; 1008 struct ifnet *ifp = &sc->arpcom.ac_if; 1009 1010 phys[0] = SL_MII_STAT; 1011 sln_mii_cmd(sc, SL_MII0_READ, phys); 1012 1013 PDEBUG("mii_stat:0x%lx\n", phys[1]); 1014 1015 if (0 == (phys[1] & SL_MIISTAT_LINK)) { 1016 kprintf("media is unconnect,linked down,or uncompatible\n"); 1017 sc->connect = 0; 1018 sln_mii_cmd(sc, SL_MII0_SCAN, phys); 1019 /* disable tx/rx */ 1020 sc->txcfg &= ~SL_TXCFG_EN; 1021 sc->rxcfg &= ~SL_RXCFG_EN; 1022 SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg); 1023 SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg); 1024 1025 return; 1026 } 1027 /* Link is good. Report modes and set duplex mode. */ 1028 PDEBUG("media is connecting---> "); 1029 sc->connect = 1; 1030 1031 phys[0] = SL_MII_STAT_OUTPUT; 1032 sln_mii_cmd(sc, SL_MII0_READ, phys); 1033 sc->media_duplex = ((phys[1] & 0x0004) == 0) ? IFM_HDX : IFM_FDX; 1034 sc->media_speed = ((phys[1] & 0x0002) == 0) ? IFM_10_T : IFM_100_TX; 1035 1036 if_printf(ifp, "media option:%dM %s-duplex\n", 1037 sc->media_speed == 0x6 ? 100 : 10, 1038 sc->media_duplex == 0x100000 ? "full" : "half"); 1039 1040 sln_mii_cmd(sc, SL_MII0_SCAN, phys); 1041 1042 sln_mac_cfg(sc); 1043 1044 /* Enable tx/rx */ 1045 sc->rxcfg |= SL_RXCFG_EN; 1046 sc->txcfg |= SL_TXCFG_EN; 1047 SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg); 1048 SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg); 1049 } 1050 1051 /* Interrupt Handler */ 1052 static void 1053 sln_interrupt(void *arg) 1054 { 1055 struct sln_softc *sc = arg; 1056 struct ifnet *ifp = &sc->arpcom.ac_if; 1057 uint32_t int_status; 1058 1059 ASSERT_SERIALIZED(ifp->if_serializer); 1060 1061 if (sc->suspended || (ifp->if_flags & IFF_RUNNING) == 0) 1062 return; 1063 1064 /* Disable interrupts. */ 1065 SLN_WRITE_4(sc, SL_INT_MASK, 0); 1066 1067 int_status = SLN_READ_4(sc, SL_INT_STATUS); 1068 1069 if ((int_status == 0xffffffff) || (int_status & SL_INRTS) == 0) 1070 goto back; 1071 1072 int_status = int_status & SL_INRTS; 1073 PDEBUG("int_status = 0x%x\n", int_status); 1074 1075 while (0 != int_status) { 1076 if (int_status & SL_INT_ROK) 1077 sln_rx(sc); 1078 1079 if (int_status & SL_INT_TOK) 1080 sln_tx_intr(sc); 1081 1082 if (int_status & SL_INT_RBO) { 1083 ifp->if_ierrors++; 1084 PDEBUG("rx buffer is overflow\n"); 1085 } 1086 1087 if (int_status & (SL_INT_LINKFAIL | SL_INT_LINKOK)) 1088 sln_media_intr(sc); 1089 1090 int_status = SLN_READ_4(sc, SL_INT_STATUS); 1091 } 1092 1093 /* Data in Tx buffer waiting for transimission */ 1094 if (!ifq_is_empty(&ifp->if_snd)) 1095 if_devstart(ifp); 1096 back: 1097 /* Re-enable interrupts. */ 1098 SLN_WRITE_4(sc, SL_INT_MASK, SL_INRTS); 1099 } 1100 1101 static void 1102 sln_tick(void *x) 1103 { 1104 struct sln_softc *sc = x; 1105 1106 callout_reset(&sc->sln_state, hz, sln_tick, sc); 1107 } 1108 1109 static int 1110 sln_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 1111 { 1112 struct sln_softc *sc = ifp->if_softc; 1113 struct ifreq *ifr = (struct ifreq *)data; 1114 int error = 0; 1115 1116 ASSERT_SERIALIZED(ifp->if_serializer); 1117 1118 switch (cmd) { 1119 case SIOCSIFFLAGS: 1120 if (ifp->if_flags & IFF_UP) { 1121 if ((ifp->if_flags & IFF_RUNNING) == 0) 1122 sln_init(sc); 1123 } else { 1124 if (ifp->if_flags & IFF_RUNNING) 1125 sln_stop(sc); 1126 } 1127 break; 1128 case SIOCADDMULTI: 1129 case SIOCDELMULTI: 1130 sln_set_multi(sc); 1131 break; 1132 case SIOCGIFMEDIA: 1133 case SIOCSIFMEDIA: 1134 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd); 1135 break; 1136 default: 1137 error = ether_ioctl(ifp, cmd, data); 1138 break; 1139 } 1140 return error; 1141 } 1142 1143 static void 1144 sln_watchdog(struct ifnet *ifp) 1145 { 1146 struct sln_softc *sc = ifp->if_softc; 1147 1148 ASSERT_SERIALIZED(ifp->if_serializer); 1149 1150 if_printf(ifp, "watchdog timeout!\n"); 1151 ifp->if_oerrors++; 1152 1153 sln_tx_intr(sc); 1154 sln_rx(sc); 1155 sln_init(sc); 1156 1157 if (!ifq_is_empty(&ifp->if_snd)) 1158 if_devstart(ifp); 1159 } 1160 1161 /* Stop all chip I/O */ 1162 static int 1163 sln_shutdown(device_t dev) 1164 { 1165 struct sln_softc *sc = device_get_softc(dev); 1166 struct ifnet *ifp = &sc->arpcom.ac_if; 1167 1168 lwkt_serialize_enter(ifp->if_serializer); 1169 sln_stop(sc); 1170 lwkt_serialize_exit(ifp->if_serializer); 1171 1172 return 0; 1173 } 1174 1175 /* device suspend routine */ 1176 static int 1177 sln_suspend(device_t dev) 1178 { 1179 struct sln_softc *sc = device_get_softc(dev); 1180 struct ifnet *ifp = &sc->arpcom.ac_if; 1181 1182 lwkt_serialize_enter(ifp->if_serializer); 1183 sln_stop(sc); 1184 sc->suspended = 1; 1185 lwkt_serialize_exit(ifp->if_serializer); 1186 1187 return 0; 1188 } 1189 1190 /* device resume routine */ 1191 static int 1192 sln_resume(device_t dev) 1193 { 1194 struct sln_softc *sc = device_get_softc(dev); 1195 struct ifnet *ifp = &sc->arpcom.ac_if; 1196 1197 lwkt_serialize_enter(ifp->if_serializer); 1198 if (ifp->if_flags & IFF_UP) 1199 sln_init(sc); 1200 sc->suspended = 0; 1201 lwkt_serialize_exit(ifp->if_serializer); 1202 1203 return 0; 1204 } 1205