1 /*- 2 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> 3 * 4 * This software was developed by SRI International and the University of 5 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 6 * ("CTSRD"), as part of the DARPA CRASH research programme. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * Ethernet media access controller (EMAC) 32 * Chapter 17, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22) 33 * 34 * EMAC is an instance of the Synopsys DesignWare 3504-0 35 * Universal 10/100/1000 Ethernet MAC (DWC_gmac). 36 */ 37 38 #include <sys/cdefs.h> 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/bus.h> 42 #include <sys/gpio.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/mbuf.h> 47 #include <sys/module.h> 48 #include <sys/mutex.h> 49 #include <sys/rman.h> 50 #include <sys/socket.h> 51 #include <sys/sockio.h> 52 53 #include <net/bpf.h> 54 #include <net/if.h> 55 #include <net/ethernet.h> 56 #include <net/if_dl.h> 57 #include <net/if_media.h> 58 #include <net/if_types.h> 59 #include <net/if_var.h> 60 61 #include <machine/bus.h> 62 63 #include <dev/extres/clk/clk.h> 64 #include <dev/extres/hwreset/hwreset.h> 65 66 #include <dev/mii/mii.h> 67 #include <dev/mii/miivar.h> 68 #include <dev/ofw/ofw_bus.h> 69 #include <dev/ofw/ofw_bus_subr.h> 70 #include <dev/mii/mii_fdt.h> 71 72 #include <dev/dwc/if_dwcvar.h> 73 #include <dev/dwc/dwc1000_reg.h> 74 #include <dev/dwc/dwc1000_core.h> 75 #include <dev/dwc/dwc1000_dma.h> 76 77 #include "if_dwc_if.h" 78 #include "gpio_if.h" 79 #include "miibus_if.h" 80 81 static struct resource_spec dwc_spec[] = { 82 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 83 { SYS_RES_IRQ, 0, RF_ACTIVE }, 84 { -1, 0 } 85 }; 86 87 static void dwc_stop_locked(struct dwc_softc *sc); 88 89 static void dwc_tick(void *arg); 90 91 /* 92 * Media functions 93 */ 94 95 static void 96 dwc_media_status(if_t ifp, struct ifmediareq *ifmr) 97 { 98 struct dwc_softc *sc; 99 struct mii_data *mii; 100 101 sc = if_getsoftc(ifp); 102 mii = sc->mii_softc; 103 DWC_LOCK(sc); 104 mii_pollstat(mii); 105 ifmr->ifm_active = mii->mii_media_active; 106 ifmr->ifm_status = mii->mii_media_status; 107 DWC_UNLOCK(sc); 108 } 109 110 static int 111 dwc_media_change_locked(struct dwc_softc *sc) 112 { 113 114 return (mii_mediachg(sc->mii_softc)); 115 } 116 117 static int 118 dwc_media_change(if_t ifp) 119 { 120 struct dwc_softc *sc; 121 int error; 122 123 sc = if_getsoftc(ifp); 124 125 DWC_LOCK(sc); 126 error = dwc_media_change_locked(sc); 127 DWC_UNLOCK(sc); 128 return (error); 129 } 130 131 /* 132 * if_ functions 133 */ 134 135 static void 136 dwc_txstart_locked(struct dwc_softc *sc) 137 { 138 if_t ifp; 139 140 DWC_ASSERT_LOCKED(sc); 141 142 if (!sc->link_is_up) 143 return; 144 145 ifp = sc->ifp; 146 147 if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != 148 IFF_DRV_RUNNING) 149 return; 150 dma1000_txstart(sc); 151 } 152 153 static void 154 dwc_txstart(if_t ifp) 155 { 156 struct dwc_softc *sc = if_getsoftc(ifp); 157 158 DWC_LOCK(sc); 159 dwc_txstart_locked(sc); 160 DWC_UNLOCK(sc); 161 } 162 163 static void 164 dwc_init_locked(struct dwc_softc *sc) 165 { 166 if_t ifp = sc->ifp; 167 168 DWC_ASSERT_LOCKED(sc); 169 170 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) 171 return; 172 173 /* 174 * Call mii_mediachg() which will call back into dwc1000_miibus_statchg() 175 * to set up the remaining config registers based on current media. 176 */ 177 mii_mediachg(sc->mii_softc); 178 179 dwc1000_setup_rxfilter(sc); 180 dwc1000_core_setup(sc); 181 dwc1000_enable_mac(sc, true); 182 dwc1000_enable_csum_offload(sc); 183 dma1000_start(sc); 184 185 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE); 186 187 callout_reset(&sc->dwc_callout, hz, dwc_tick, sc); 188 } 189 190 static void 191 dwc_init(void *if_softc) 192 { 193 struct dwc_softc *sc = if_softc; 194 195 DWC_LOCK(sc); 196 dwc_init_locked(sc); 197 DWC_UNLOCK(sc); 198 } 199 200 static void 201 dwc_stop_locked(struct dwc_softc *sc) 202 { 203 if_t ifp; 204 205 DWC_ASSERT_LOCKED(sc); 206 207 ifp = sc->ifp; 208 if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 209 sc->tx_watchdog_count = 0; 210 sc->stats_harvest_count = 0; 211 212 callout_stop(&sc->dwc_callout); 213 214 dma1000_stop(sc); 215 dwc1000_enable_mac(sc, false); 216 } 217 218 static int 219 dwc_ioctl(if_t ifp, u_long cmd, caddr_t data) 220 { 221 struct dwc_softc *sc; 222 struct mii_data *mii; 223 struct ifreq *ifr; 224 int flags, mask, error; 225 226 sc = if_getsoftc(ifp); 227 ifr = (struct ifreq *)data; 228 229 error = 0; 230 switch (cmd) { 231 case SIOCSIFFLAGS: 232 DWC_LOCK(sc); 233 if (if_getflags(ifp) & IFF_UP) { 234 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { 235 flags = if_getflags(ifp) ^ sc->if_flags; 236 if ((flags & (IFF_PROMISC|IFF_ALLMULTI)) != 0) 237 dwc1000_setup_rxfilter(sc); 238 } else { 239 if (!sc->is_detaching) 240 dwc_init_locked(sc); 241 } 242 } else { 243 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) 244 dwc_stop_locked(sc); 245 } 246 sc->if_flags = if_getflags(ifp); 247 DWC_UNLOCK(sc); 248 break; 249 case SIOCADDMULTI: 250 case SIOCDELMULTI: 251 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { 252 DWC_LOCK(sc); 253 dwc1000_setup_rxfilter(sc); 254 DWC_UNLOCK(sc); 255 } 256 break; 257 case SIOCSIFMEDIA: 258 case SIOCGIFMEDIA: 259 mii = sc->mii_softc; 260 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 261 break; 262 case SIOCSIFCAP: 263 mask = ifr->ifr_reqcap ^ if_getcapenable(ifp); 264 if (mask & IFCAP_VLAN_MTU) { 265 /* No work to do except acknowledge the change took */ 266 if_togglecapenable(ifp, IFCAP_VLAN_MTU); 267 } 268 if (mask & IFCAP_RXCSUM) 269 if_togglecapenable(ifp, IFCAP_RXCSUM); 270 if (mask & IFCAP_TXCSUM) 271 if_togglecapenable(ifp, IFCAP_TXCSUM); 272 if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0) 273 if_sethwassistbits(ifp, CSUM_IP | CSUM_UDP | CSUM_TCP, 0); 274 else 275 if_sethwassistbits(ifp, 0, CSUM_IP | CSUM_UDP | CSUM_TCP); 276 277 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { 278 DWC_LOCK(sc); 279 dwc1000_enable_csum_offload(sc); 280 DWC_UNLOCK(sc); 281 } 282 break; 283 284 default: 285 error = ether_ioctl(ifp, cmd, data); 286 break; 287 } 288 289 return (error); 290 } 291 292 /* 293 * Interrupts functions 294 */ 295 296 297 static void 298 dwc_intr(void *arg) 299 { 300 struct dwc_softc *sc; 301 int rv; 302 303 sc = arg; 304 DWC_LOCK(sc); 305 dwc1000_intr(sc); 306 rv = dma1000_intr(sc); 307 if (rv == EIO) { 308 device_printf(sc->dev, 309 "Ethernet DMA error, restarting controller.\n"); 310 dwc_stop_locked(sc); 311 dwc_init_locked(sc); 312 } 313 DWC_UNLOCK(sc); 314 } 315 316 static void 317 dwc_tick(void *arg) 318 { 319 struct dwc_softc *sc; 320 if_t ifp; 321 int link_was_up; 322 323 sc = arg; 324 325 DWC_ASSERT_LOCKED(sc); 326 327 ifp = sc->ifp; 328 329 if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) 330 return; 331 332 /* 333 * Typical tx watchdog. If this fires it indicates that we enqueued 334 * packets for output and never got a txdone interrupt for them. Maybe 335 * it's a missed interrupt somehow, just pretend we got one. 336 */ 337 if (sc->tx_watchdog_count > 0) { 338 if (--sc->tx_watchdog_count == 0) { 339 dma1000_txfinish_locked(sc); 340 } 341 } 342 343 /* Gather stats from hardware counters. */ 344 dwc1000_harvest_stats(sc); 345 346 /* Check the media status. */ 347 link_was_up = sc->link_is_up; 348 mii_tick(sc->mii_softc); 349 if (sc->link_is_up && !link_was_up) 350 dwc_txstart_locked(sc); 351 352 /* Schedule another check one second from now. */ 353 callout_reset(&sc->dwc_callout, hz, dwc_tick, sc); 354 } 355 356 static int 357 dwc_reset_phy(struct dwc_softc *sc) 358 { 359 pcell_t gpio_prop[4]; 360 pcell_t delay_prop[3]; 361 phandle_t gpio_node; 362 device_t gpio; 363 uint32_t pin, flags; 364 uint32_t pin_value; 365 366 /* 367 * All those properties are deprecated but still used in some DTS. 368 * The new way to deal with this is to use the generic bindings 369 * present in the ethernet-phy node. 370 */ 371 if (OF_getencprop(sc->node, "snps,reset-gpio", 372 gpio_prop, sizeof(gpio_prop)) <= 0) 373 return (0); 374 375 if (OF_getencprop(sc->node, "snps,reset-delays-us", 376 delay_prop, sizeof(delay_prop)) <= 0) { 377 device_printf(sc->dev, 378 "Wrong property for snps,reset-delays-us"); 379 return (ENXIO); 380 } 381 382 gpio_node = OF_node_from_xref(gpio_prop[0]); 383 if ((gpio = OF_device_from_xref(gpio_prop[0])) == NULL) { 384 device_printf(sc->dev, 385 "Can't find gpio controller for phy reset\n"); 386 return (ENXIO); 387 } 388 389 if (GPIO_MAP_GPIOS(gpio, sc->node, gpio_node, 390 nitems(gpio_prop) - 1, 391 gpio_prop + 1, &pin, &flags) != 0) { 392 device_printf(sc->dev, "Can't map gpio for phy reset\n"); 393 return (ENXIO); 394 } 395 396 pin_value = GPIO_PIN_LOW; 397 if (OF_hasprop(sc->node, "snps,reset-active-low")) 398 pin_value = GPIO_PIN_HIGH; 399 400 GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT); 401 GPIO_PIN_SET(gpio, pin, pin_value); 402 DELAY(delay_prop[0] * 5); 403 GPIO_PIN_SET(gpio, pin, !pin_value); 404 DELAY(delay_prop[1] * 5); 405 GPIO_PIN_SET(gpio, pin, pin_value); 406 DELAY(delay_prop[2] * 5); 407 408 return (0); 409 } 410 411 static int 412 dwc_clock_init(struct dwc_softc *sc) 413 { 414 int rv; 415 int64_t freq; 416 417 /* Required clock */ 418 rv = clk_get_by_ofw_name(sc->dev, 0, "stmmaceth", &sc->clk_stmmaceth); 419 if (rv != 0) { 420 device_printf(sc->dev, "Cannot get GMAC main clock\n"); 421 return (ENXIO); 422 } 423 if ((rv = clk_enable(sc->clk_stmmaceth)) != 0) { 424 device_printf(sc->dev, "could not enable main clock\n"); 425 return (rv); 426 } 427 428 /* Optional clock */ 429 rv = clk_get_by_ofw_name(sc->dev, 0, "pclk", &sc->clk_pclk); 430 if (rv != 0) 431 return (0); 432 if ((rv = clk_enable(sc->clk_pclk)) != 0) { 433 device_printf(sc->dev, "could not enable peripheral clock\n"); 434 return (rv); 435 } 436 437 if (bootverbose) { 438 clk_get_freq(sc->clk_stmmaceth, &freq); 439 device_printf(sc->dev, "MAC clock(%s) freq: %jd\n", 440 clk_get_name(sc->clk_stmmaceth), (intmax_t)freq); 441 } 442 443 return (0); 444 } 445 446 static int 447 dwc_reset_deassert(struct dwc_softc *sc) 448 { 449 int rv; 450 451 /* Required reset */ 452 rv = hwreset_get_by_ofw_name(sc->dev, 0, "stmmaceth", &sc->rst_stmmaceth); 453 if (rv != 0) { 454 device_printf(sc->dev, "Cannot get GMAC reset\n"); 455 return (ENXIO); 456 } 457 rv = hwreset_deassert(sc->rst_stmmaceth); 458 if (rv != 0) { 459 device_printf(sc->dev, "could not de-assert GMAC reset\n"); 460 return (rv); 461 } 462 463 /* Optional reset */ 464 rv = hwreset_get_by_ofw_name(sc->dev, 0, "ahb", &sc->rst_ahb); 465 if (rv != 0) 466 return (0); 467 rv = hwreset_deassert(sc->rst_ahb); 468 if (rv != 0) { 469 device_printf(sc->dev, "could not de-assert AHB reset\n"); 470 return (rv); 471 } 472 473 return (0); 474 } 475 476 /* 477 * Probe/Attach functions 478 */ 479 480 static int 481 dwc_probe(device_t dev) 482 { 483 484 if (!ofw_bus_status_okay(dev)) 485 return (ENXIO); 486 487 if (!ofw_bus_is_compatible(dev, "snps,dwmac")) 488 return (ENXIO); 489 490 device_set_desc(dev, "Gigabit Ethernet Controller"); 491 return (BUS_PROBE_DEFAULT); 492 } 493 494 static int 495 dwc_attach(device_t dev) 496 { 497 uint8_t macaddr[ETHER_ADDR_LEN]; 498 struct dwc_softc *sc; 499 if_t ifp; 500 int error; 501 uint32_t pbl; 502 503 sc = device_get_softc(dev); 504 sc->dev = dev; 505 sc->rx_idx = 0; 506 sc->tx_desccount = TX_DESC_COUNT; 507 sc->tx_mapcount = 0; 508 sc->mii_clk = IF_DWC_MII_CLK(dev); 509 sc->mactype = IF_DWC_MAC_TYPE(dev); 510 511 sc->node = ofw_bus_get_node(dev); 512 switch (mii_fdt_get_contype(sc->node)) { 513 case MII_CONTYPE_RGMII: 514 case MII_CONTYPE_RGMII_ID: 515 case MII_CONTYPE_RGMII_RXID: 516 case MII_CONTYPE_RGMII_TXID: 517 sc->phy_mode = PHY_MODE_RGMII; 518 break; 519 case MII_CONTYPE_RMII: 520 sc->phy_mode = PHY_MODE_RMII; 521 break; 522 case MII_CONTYPE_MII: 523 sc->phy_mode = PHY_MODE_MII; 524 break; 525 default: 526 device_printf(dev, "Unsupported MII type\n"); 527 return (ENXIO); 528 } 529 530 if (OF_getencprop(sc->node, "snps,pbl", &pbl, sizeof(uint32_t)) <= 0) 531 pbl = BUS_MODE_DEFAULT_PBL; 532 if (OF_getencprop(sc->node, "snps,txpbl", &sc->txpbl, sizeof(uint32_t)) <= 0) 533 sc->txpbl = pbl; 534 if (OF_getencprop(sc->node, "snps,rxpbl", &sc->rxpbl, sizeof(uint32_t)) <= 0) 535 sc->rxpbl = pbl; 536 if (OF_hasprop(sc->node, "snps,no-pbl-x8") == 1) 537 sc->nopblx8 = true; 538 if (OF_hasprop(sc->node, "snps,fixed-burst") == 1) 539 sc->fixed_burst = true; 540 if (OF_hasprop(sc->node, "snps,mixed-burst") == 1) 541 sc->mixed_burst = true; 542 if (OF_hasprop(sc->node, "snps,aal") == 1) 543 sc->aal = true; 544 545 error = clk_set_assigned(dev, ofw_bus_get_node(dev)); 546 if (error != 0) { 547 device_printf(dev, "clk_set_assigned failed\n"); 548 return (error); 549 } 550 551 /* Enable main clock */ 552 if ((error = dwc_clock_init(sc)) != 0) 553 return (error); 554 /* De-assert main reset */ 555 if ((error = dwc_reset_deassert(sc)) != 0) 556 return (error); 557 558 if (IF_DWC_INIT(dev) != 0) 559 return (ENXIO); 560 561 if (bus_alloc_resources(dev, dwc_spec, sc->res)) { 562 device_printf(dev, "could not allocate resources\n"); 563 return (ENXIO); 564 } 565 566 /* Read MAC before reset */ 567 dwc1000_get_hwaddr(sc, macaddr); 568 569 /* Reset the PHY if needed */ 570 if (dwc_reset_phy(sc) != 0) { 571 device_printf(dev, "Can't reset the PHY\n"); 572 bus_release_resources(dev, dwc_spec, sc->res); 573 return (ENXIO); 574 } 575 576 /* Reset */ 577 if ((error = dma1000_reset(sc)) != 0) { 578 device_printf(sc->dev, "Can't reset DMA controller.\n"); 579 bus_release_resources(sc->dev, dwc_spec, sc->res); 580 return (error); 581 } 582 583 if (dma1000_init(sc)) { 584 bus_release_resources(dev, dwc_spec, sc->res); 585 return (ENXIO); 586 } 587 588 mtx_init(&sc->mtx, device_get_nameunit(sc->dev), 589 MTX_NETWORK_LOCK, MTX_DEF); 590 591 callout_init_mtx(&sc->dwc_callout, &sc->mtx, 0); 592 593 /* Setup interrupt handler. */ 594 error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE, 595 NULL, dwc_intr, sc, &sc->intr_cookie); 596 if (error != 0) { 597 device_printf(dev, "could not setup interrupt handler.\n"); 598 bus_release_resources(dev, dwc_spec, sc->res); 599 return (ENXIO); 600 } 601 602 /* Set up the ethernet interface. */ 603 sc->ifp = ifp = if_alloc(IFT_ETHER); 604 605 if_setsoftc(ifp, sc); 606 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 607 if_setflags(sc->ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); 608 if_setstartfn(ifp, dwc_txstart); 609 if_setioctlfn(ifp, dwc_ioctl); 610 if_setinitfn(ifp, dwc_init); 611 if_setsendqlen(ifp, TX_MAP_COUNT - 1); 612 if_setsendqready(sc->ifp); 613 if_sethwassist(sc->ifp, CSUM_IP | CSUM_UDP | CSUM_TCP); 614 if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM); 615 if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp)); 616 617 /* Attach the mii driver. */ 618 error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change, 619 dwc_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY, 620 MII_OFFSET_ANY, 0); 621 622 if (error != 0) { 623 device_printf(dev, "PHY attach failed\n"); 624 bus_teardown_intr(dev, sc->res[1], sc->intr_cookie); 625 bus_release_resources(dev, dwc_spec, sc->res); 626 return (ENXIO); 627 } 628 sc->mii_softc = device_get_softc(sc->miibus); 629 630 /* All ready to run, attach the ethernet interface. */ 631 ether_ifattach(ifp, macaddr); 632 sc->is_attached = true; 633 634 return (0); 635 } 636 637 static int 638 dwc_detach(device_t dev) 639 { 640 struct dwc_softc *sc; 641 642 sc = device_get_softc(dev); 643 644 /* 645 * Disable and tear down interrupts before anything else, so we don't 646 * race with the handler. 647 */ 648 dwc1000_intr_disable(sc); 649 if (sc->intr_cookie != NULL) { 650 bus_teardown_intr(dev, sc->res[1], sc->intr_cookie); 651 } 652 653 if (sc->is_attached) { 654 DWC_LOCK(sc); 655 sc->is_detaching = true; 656 dwc_stop_locked(sc); 657 DWC_UNLOCK(sc); 658 callout_drain(&sc->dwc_callout); 659 ether_ifdetach(sc->ifp); 660 } 661 662 if (sc->miibus != NULL) { 663 device_delete_child(dev, sc->miibus); 664 sc->miibus = NULL; 665 } 666 bus_generic_detach(dev); 667 668 /* Free DMA descriptors */ 669 dma1000_free(sc); 670 671 if (sc->ifp != NULL) { 672 if_free(sc->ifp); 673 sc->ifp = NULL; 674 } 675 676 bus_release_resources(dev, dwc_spec, sc->res); 677 678 mtx_destroy(&sc->mtx); 679 return (0); 680 } 681 682 static device_method_t dwc_methods[] = { 683 DEVMETHOD(device_probe, dwc_probe), 684 DEVMETHOD(device_attach, dwc_attach), 685 DEVMETHOD(device_detach, dwc_detach), 686 687 /* MII Interface */ 688 DEVMETHOD(miibus_readreg, dwc1000_miibus_read_reg), 689 DEVMETHOD(miibus_writereg, dwc1000_miibus_write_reg), 690 DEVMETHOD(miibus_statchg, dwc1000_miibus_statchg), 691 692 { 0, 0 } 693 }; 694 695 driver_t dwc_driver = { 696 "dwc", 697 dwc_methods, 698 sizeof(struct dwc_softc), 699 }; 700 701 DRIVER_MODULE(dwc, simplebus, dwc_driver, 0, 0); 702 DRIVER_MODULE(miibus, dwc, miibus_driver, 0, 0); 703 704 MODULE_DEPEND(dwc, ether, 1, 1, 1); 705 MODULE_DEPEND(dwc, miibus, 1, 1, 1); 706