1 /*- 2 * Copyright (c) 2016 Hiroki Mori 3 * Copyright (c) 2013 Luiz Otavio O Souza. 4 * Copyright (c) 2011-2012 Stefan Bethke. 5 * Copyright (c) 2012 Adrian Chadd. 6 * All rights reserved. 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 * $FreeBSD$ 30 */ 31 32 /* 33 * This code is Marvell 88E6060 ethernet switch support code on etherswitch 34 * framework. 35 * Current code is only support port base vlan. Not support ingress/egress 36 * trailer. This switch chip can't work vlan(4) support. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/bus.h> 41 #include <sys/errno.h> 42 #include <sys/kernel.h> 43 #include <sys/lock.h> 44 #include <sys/malloc.h> 45 #include <sys/module.h> 46 #include <sys/mutex.h> 47 #include <sys/socket.h> 48 #include <sys/sockio.h> 49 #include <sys/sysctl.h> 50 #include <sys/systm.h> 51 52 #include <net/if.h> 53 #include <net/if_var.h> 54 #include <net/ethernet.h> 55 #include <net/if_media.h> 56 #include <net/if_types.h> 57 58 #include <machine/bus.h> 59 #include <dev/mii/mii.h> 60 #include <dev/mii/miivar.h> 61 #include <dev/mdio/mdio.h> 62 63 #include <dev/etherswitch/etherswitch.h> 64 65 #include "mdio_if.h" 66 #include "miibus_if.h" 67 #include "etherswitch_if.h" 68 69 #define SMI_OFFSET 0x10 70 #define CORE_REGISTER (SMI_OFFSET + 8) 71 72 #define SWITCH_ID 3 73 #define PORT_VLAN_MAP 6 74 75 MALLOC_DECLARE(M_E6060SW); 76 MALLOC_DEFINE(M_E6060SW, "e6060sw", "e6060sw data structures"); 77 78 struct e6060sw_softc { 79 struct mtx sc_mtx; /* serialize access to softc */ 80 device_t sc_dev; 81 int vlan_mode; 82 int media; /* cpu port media */ 83 int cpuport; /* which PHY is connected to the CPU */ 84 int phymask; /* PHYs we manage */ 85 int numports; /* number of ports */ 86 int ifpport[MII_NPHY]; 87 int *portphy; 88 char **ifname; 89 device_t **miibus; 90 struct ifnet **ifp; 91 struct callout callout_tick; 92 etherswitch_info_t info; 93 }; 94 95 #define E6060SW_LOCK(_sc) \ 96 mtx_lock(&(_sc)->sc_mtx) 97 #define E6060SW_UNLOCK(_sc) \ 98 mtx_unlock(&(_sc)->sc_mtx) 99 #define E6060SW_LOCK_ASSERT(_sc, _what) \ 100 mtx_assert(&(_sc)->sc_mtx, (_what)) 101 #define E6060SW_TRYLOCK(_sc) \ 102 mtx_trylock(&(_sc)->sc_mtx) 103 104 #if defined(DEBUG) 105 #define DPRINTF(dev, args...) device_printf(dev, args) 106 #else 107 #define DPRINTF(dev, args...) 108 #endif 109 110 static inline int e6060sw_portforphy(struct e6060sw_softc *, int); 111 static void e6060sw_tick(void *); 112 static int e6060sw_ifmedia_upd(struct ifnet *); 113 static void e6060sw_ifmedia_sts(struct ifnet *, struct ifmediareq *); 114 115 static int 116 e6060sw_probe(device_t dev) 117 { 118 int data; 119 struct e6060sw_softc *sc; 120 121 sc = device_get_softc(dev); 122 bzero(sc, sizeof(*sc)); 123 124 data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER, SWITCH_ID); 125 if (bootverbose) 126 device_printf(dev,"Switch Identifier Register %x\n", data); 127 128 if ((data >> 4) != 0x060) { 129 return (ENXIO); 130 } 131 132 device_set_desc_copy(dev, "Marvell 88E6060 MDIO switch driver"); 133 return (BUS_PROBE_DEFAULT); 134 } 135 136 static int 137 e6060sw_attach_phys(struct e6060sw_softc *sc) 138 { 139 int phy, port, err; 140 char name[IFNAMSIZ]; 141 142 port = 0; 143 err = 0; 144 /* PHYs need an interface, so we generate a dummy one */ 145 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev)); 146 for (phy = 0; phy < sc->numports; phy++) { 147 if (((1 << phy) & sc->phymask) == 0) 148 continue; 149 sc->ifpport[phy] = port; 150 sc->portphy[port] = phy; 151 sc->ifp[port] = if_alloc(IFT_ETHER); 152 sc->ifp[port]->if_softc = sc; 153 sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST | 154 IFF_DRV_RUNNING | IFF_SIMPLEX; 155 if_initname(sc->ifp[port], name, port); 156 sc->miibus[port] = malloc(sizeof(device_t), M_E6060SW, 157 M_WAITOK | M_ZERO); 158 err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port], 159 e6060sw_ifmedia_upd, e6060sw_ifmedia_sts, \ 160 BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); 161 DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n", 162 device_get_nameunit(*sc->miibus[port]), 163 sc->ifp[port]->if_xname); 164 if (err != 0) { 165 device_printf(sc->sc_dev, 166 "attaching PHY %d failed\n", 167 phy); 168 break; 169 } 170 ++port; 171 } 172 sc->info.es_nports = port; 173 if (sc->cpuport != -1) { 174 /* assume cpuport is last one */ 175 sc->ifpport[sc->cpuport] = port; 176 sc->portphy[port] = sc->cpuport; 177 ++sc->info.es_nports; 178 } 179 return (err); 180 } 181 182 static int 183 e6060sw_attach(device_t dev) 184 { 185 struct e6060sw_softc *sc; 186 int err; 187 188 sc = device_get_softc(dev); 189 err = 0; 190 191 sc->sc_dev = dev; 192 mtx_init(&sc->sc_mtx, "e6060sw", NULL, MTX_DEF); 193 strlcpy(sc->info.es_name, device_get_desc(dev), 194 sizeof(sc->info.es_name)); 195 196 /* XXX Defaults */ 197 sc->numports = 6; 198 sc->phymask = 0x1f; 199 sc->cpuport = 5; 200 sc->media = 100; 201 202 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 203 "numports", &sc->numports); 204 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 205 "phymask", &sc->phymask); 206 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 207 "cpuport", &sc->cpuport); 208 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 209 "media", &sc->media); 210 211 sc->info.es_nvlangroups = sc->numports; 212 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT; 213 214 sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_E6060SW, 215 M_WAITOK | M_ZERO); 216 sc->ifname = malloc(sizeof(char *) * sc->numports, M_E6060SW, 217 M_WAITOK | M_ZERO); 218 sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_E6060SW, 219 M_WAITOK | M_ZERO); 220 sc->portphy = malloc(sizeof(int) * sc->numports, M_E6060SW, 221 M_WAITOK | M_ZERO); 222 223 /* 224 * Attach the PHYs and complete the bus enumeration. 225 */ 226 err = e6060sw_attach_phys(sc); 227 if (err != 0) 228 return (err); 229 230 bus_generic_probe(dev); 231 bus_enumerate_hinted_children(dev); 232 err = bus_generic_attach(dev); 233 if (err != 0) 234 return (err); 235 236 callout_init(&sc->callout_tick, 0); 237 238 e6060sw_tick(sc); 239 240 return (err); 241 } 242 243 static int 244 e6060sw_detach(device_t dev) 245 { 246 struct e6060sw_softc *sc; 247 int i, port; 248 249 sc = device_get_softc(dev); 250 251 callout_drain(&sc->callout_tick); 252 253 for (i = 0; i < MII_NPHY; i++) { 254 if (((1 << i) & sc->phymask) == 0) 255 continue; 256 port = e6060sw_portforphy(sc, i); 257 if (sc->miibus[port] != NULL) 258 device_delete_child(dev, (*sc->miibus[port])); 259 if (sc->ifp[port] != NULL) 260 if_free(sc->ifp[port]); 261 free(sc->ifname[port], M_E6060SW); 262 free(sc->miibus[port], M_E6060SW); 263 } 264 265 free(sc->portphy, M_E6060SW); 266 free(sc->miibus, M_E6060SW); 267 free(sc->ifname, M_E6060SW); 268 free(sc->ifp, M_E6060SW); 269 270 bus_generic_detach(dev); 271 mtx_destroy(&sc->sc_mtx); 272 273 return (0); 274 } 275 276 /* 277 * Convert PHY number to port number. 278 */ 279 static inline int 280 e6060sw_portforphy(struct e6060sw_softc *sc, int phy) 281 { 282 283 return (sc->ifpport[phy]); 284 } 285 286 static inline struct mii_data * 287 e6060sw_miiforport(struct e6060sw_softc *sc, int port) 288 { 289 290 if (port < 0 || port > sc->numports) 291 return (NULL); 292 if (port == sc->cpuport) 293 return (NULL); 294 return (device_get_softc(*sc->miibus[port])); 295 } 296 297 static inline struct ifnet * 298 e6060sw_ifpforport(struct e6060sw_softc *sc, int port) 299 { 300 301 if (port < 0 || port > sc->numports) 302 return (NULL); 303 return (sc->ifp[port]); 304 } 305 306 /* 307 * Poll the status for all PHYs. 308 */ 309 static void 310 e6060sw_miipollstat(struct e6060sw_softc *sc) 311 { 312 int i, port; 313 struct mii_data *mii; 314 struct mii_softc *miisc; 315 316 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); 317 318 for (i = 0; i < MII_NPHY; i++) { 319 if (((1 << i) & sc->phymask) == 0) 320 continue; 321 port = e6060sw_portforphy(sc, i); 322 if ((*sc->miibus[port]) == NULL) 323 continue; 324 mii = device_get_softc(*sc->miibus[port]); 325 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 326 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != 327 miisc->mii_inst) 328 continue; 329 ukphy_status(miisc); 330 mii_phy_update(miisc, MII_POLLSTAT); 331 } 332 } 333 } 334 335 static void 336 e6060sw_tick(void *arg) 337 { 338 struct e6060sw_softc *sc; 339 340 sc = arg; 341 342 e6060sw_miipollstat(sc); 343 callout_reset(&sc->callout_tick, hz, e6060sw_tick, sc); 344 } 345 346 static void 347 e6060sw_lock(device_t dev) 348 { 349 struct e6060sw_softc *sc; 350 351 sc = device_get_softc(dev); 352 353 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); 354 E6060SW_LOCK(sc); 355 } 356 357 static void 358 e6060sw_unlock(device_t dev) 359 { 360 struct e6060sw_softc *sc; 361 362 sc = device_get_softc(dev); 363 364 E6060SW_LOCK_ASSERT(sc, MA_OWNED); 365 E6060SW_UNLOCK(sc); 366 } 367 368 static etherswitch_info_t * 369 e6060sw_getinfo(device_t dev) 370 { 371 struct e6060sw_softc *sc; 372 373 sc = device_get_softc(dev); 374 375 return (&sc->info); 376 } 377 378 static int 379 e6060sw_getport(device_t dev, etherswitch_port_t *p) 380 { 381 struct e6060sw_softc *sc; 382 struct mii_data *mii; 383 struct ifmediareq *ifmr; 384 int err, phy; 385 386 sc = device_get_softc(dev); 387 ifmr = &p->es_ifmr; 388 389 if (p->es_port < 0 || p->es_port >= sc->numports) 390 return (ENXIO); 391 p->es_pvid = 0; 392 393 phy = sc->portphy[p->es_port]; 394 mii = e6060sw_miiforport(sc, p->es_port); 395 if (sc->cpuport != -1 && phy == sc->cpuport) { 396 /* fill in fixed values for CPU port */ 397 p->es_flags |= ETHERSWITCH_PORT_CPU; 398 ifmr->ifm_count = 0; 399 if (sc->media == 100) 400 ifmr->ifm_current = ifmr->ifm_active = 401 IFM_ETHER | IFM_100_TX | IFM_FDX; 402 else 403 ifmr->ifm_current = ifmr->ifm_active = 404 IFM_ETHER | IFM_1000_T | IFM_FDX; 405 ifmr->ifm_mask = 0; 406 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 407 } else if (mii != NULL) { 408 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 409 &mii->mii_media, SIOCGIFMEDIA); 410 if (err) 411 return (err); 412 } else { 413 return (ENXIO); 414 } 415 return (0); 416 } 417 418 static int 419 e6060sw_setport(device_t dev, etherswitch_port_t *p) 420 { 421 struct e6060sw_softc *sc; 422 struct ifmedia *ifm; 423 struct mii_data *mii; 424 struct ifnet *ifp; 425 int err; 426 427 sc = device_get_softc(dev); 428 429 if (p->es_port < 0 || p->es_port >= sc->numports) 430 return (ENXIO); 431 432 if (sc->portphy[p->es_port] == sc->cpuport) 433 return (ENXIO); 434 435 mii = e6060sw_miiforport(sc, p->es_port); 436 if (mii == NULL) 437 return (ENXIO); 438 439 ifp = e6060sw_ifpforport(sc, p->es_port); 440 441 ifm = &mii->mii_media; 442 err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA); 443 return (err); 444 } 445 446 static int 447 e6060sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 448 { 449 struct e6060sw_softc *sc; 450 int data; 451 452 sc = device_get_softc(dev); 453 454 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { 455 vg->es_vid = ETHERSWITCH_VID_VALID; 456 vg->es_vid |= vg->es_vlangroup; 457 data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP); 458 vg->es_member_ports = data & 0x3f; 459 vg->es_untagged_ports = vg->es_member_ports; 460 vg->es_fid = 0; 461 } else { 462 vg->es_vid = 0; 463 } 464 return (0); 465 } 466 467 static int 468 e6060sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 469 { 470 struct e6060sw_softc *sc; 471 int data; 472 473 sc = device_get_softc(dev); 474 475 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { 476 data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP); 477 data &= ~0x3f; 478 data |= vg->es_member_ports; 479 MDIO_WRITEREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP, data); 480 } 481 482 return (0); 483 } 484 485 static void 486 e6060sw_reset_vlans(device_t dev) 487 { 488 struct e6060sw_softc *sc; 489 uint32_t ports; 490 int i; 491 int data; 492 493 sc = device_get_softc(dev); 494 495 for (i = 0; i <= sc->numports; i++) { 496 ports = (1 << (sc->numports + 1)) - 1; 497 ports &= ~(1 << i); 498 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { 499 data = i << 12; 500 } else { 501 data = 0; 502 } 503 data |= ports; 504 MDIO_WRITEREG(device_get_parent(dev), CORE_REGISTER + i, PORT_VLAN_MAP, data); 505 } 506 } 507 508 static int 509 e6060sw_getconf(device_t dev, etherswitch_conf_t *conf) 510 { 511 struct e6060sw_softc *sc; 512 513 sc = device_get_softc(dev); 514 515 /* Return the VLAN mode. */ 516 conf->cmd = ETHERSWITCH_CONF_VLAN_MODE; 517 conf->vlan_mode = sc->vlan_mode; 518 519 return (0); 520 } 521 522 static int 523 e6060sw_setconf(device_t dev, etherswitch_conf_t *conf) 524 { 525 struct e6060sw_softc *sc; 526 527 sc = device_get_softc(dev); 528 529 /* Set the VLAN mode. */ 530 if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) { 531 if (conf->vlan_mode == ETHERSWITCH_VLAN_PORT) { 532 sc->vlan_mode = ETHERSWITCH_VLAN_PORT; 533 } else { 534 sc->vlan_mode = 0; 535 } 536 537 /* Reset VLANs. */ 538 e6060sw_reset_vlans(dev); 539 } 540 541 return (0); 542 } 543 544 static void 545 e6060sw_statchg(device_t dev) 546 { 547 548 DPRINTF(dev, "%s\n", __func__); 549 } 550 551 static int 552 e6060sw_ifmedia_upd(struct ifnet *ifp) 553 { 554 struct e6060sw_softc *sc; 555 struct mii_data *mii; 556 557 sc = ifp->if_softc; 558 mii = e6060sw_miiforport(sc, ifp->if_dunit); 559 560 DPRINTF(sc->sc_dev, "%s\n", __func__); 561 if (mii == NULL) 562 return (ENXIO); 563 mii_mediachg(mii); 564 return (0); 565 } 566 567 static void 568 e6060sw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 569 { 570 struct e6060sw_softc *sc; 571 struct mii_data *mii; 572 573 sc = ifp->if_softc; 574 mii = e6060sw_miiforport(sc, ifp->if_dunit); 575 576 DPRINTF(sc->sc_dev, "%s\n", __func__); 577 578 if (mii == NULL) 579 return; 580 mii_pollstat(mii); 581 ifmr->ifm_active = mii->mii_media_active; 582 ifmr->ifm_status = mii->mii_media_status; 583 } 584 585 static int 586 e6060sw_readphy(device_t dev, int phy, int reg) 587 { 588 struct e6060sw_softc *sc; 589 int data; 590 591 phy += SMI_OFFSET; 592 593 sc = device_get_softc(dev); 594 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); 595 596 if (phy < 0 || phy >= 32) 597 return (ENXIO); 598 if (reg < 0 || reg >= 32) 599 return (ENXIO); 600 601 E6060SW_LOCK(sc); 602 data = MDIO_READREG(device_get_parent(dev), phy, reg); 603 E6060SW_UNLOCK(sc); 604 605 return (data); 606 } 607 608 static int 609 e6060sw_writephy(device_t dev, int phy, int reg, int data) 610 { 611 struct e6060sw_softc *sc; 612 int err; 613 614 phy += SMI_OFFSET; 615 616 sc = device_get_softc(dev); 617 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); 618 619 if (phy < 0 || phy >= 32) 620 return (ENXIO); 621 if (reg < 0 || reg >= 32) 622 return (ENXIO); 623 624 E6060SW_LOCK(sc); 625 err = MDIO_WRITEREG(device_get_parent(dev), phy, reg, data); 626 E6060SW_UNLOCK(sc); 627 628 return (err); 629 } 630 631 /* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */ 632 633 static int 634 e6060sw_readreg(device_t dev, int addr) 635 { 636 int devaddr, regaddr; 637 638 devaddr = (addr >> 5) & 0xf; 639 regaddr = addr & 0x1f; 640 641 return MDIO_READREG(device_get_parent(dev), devaddr+SMI_OFFSET, regaddr); 642 } 643 644 /* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */ 645 646 static int 647 e6060sw_writereg(device_t dev, int addr, int value) 648 { 649 int devaddr, regaddr; 650 651 devaddr = (addr >> 5) & 0xf; 652 regaddr = addr & 0x1f; 653 654 return (MDIO_WRITEREG(device_get_parent(dev), devaddr+SMI_OFFSET, regaddr, value)); 655 } 656 657 static device_method_t e6060sw_methods[] = { 658 /* Device interface */ 659 DEVMETHOD(device_probe, e6060sw_probe), 660 DEVMETHOD(device_attach, e6060sw_attach), 661 DEVMETHOD(device_detach, e6060sw_detach), 662 663 /* bus interface */ 664 DEVMETHOD(bus_add_child, device_add_child_ordered), 665 666 /* MII interface */ 667 DEVMETHOD(miibus_readreg, e6060sw_readphy), 668 DEVMETHOD(miibus_writereg, e6060sw_writephy), 669 DEVMETHOD(miibus_statchg, e6060sw_statchg), 670 671 /* MDIO interface */ 672 DEVMETHOD(mdio_readreg, e6060sw_readphy), 673 DEVMETHOD(mdio_writereg, e6060sw_writephy), 674 675 /* etherswitch interface */ 676 DEVMETHOD(etherswitch_lock, e6060sw_lock), 677 DEVMETHOD(etherswitch_unlock, e6060sw_unlock), 678 DEVMETHOD(etherswitch_getinfo, e6060sw_getinfo), 679 DEVMETHOD(etherswitch_readreg, e6060sw_readreg), 680 DEVMETHOD(etherswitch_writereg, e6060sw_writereg), 681 DEVMETHOD(etherswitch_readphyreg, e6060sw_readphy), 682 DEVMETHOD(etherswitch_writephyreg, e6060sw_writephy), 683 DEVMETHOD(etherswitch_getport, e6060sw_getport), 684 DEVMETHOD(etherswitch_setport, e6060sw_setport), 685 DEVMETHOD(etherswitch_getvgroup, e6060sw_getvgroup), 686 DEVMETHOD(etherswitch_setvgroup, e6060sw_setvgroup), 687 DEVMETHOD(etherswitch_setconf, e6060sw_setconf), 688 DEVMETHOD(etherswitch_getconf, e6060sw_getconf), 689 690 DEVMETHOD_END 691 }; 692 693 DEFINE_CLASS_0(e6060sw, e6060sw_driver, e6060sw_methods, 694 sizeof(struct e6060sw_softc)); 695 static devclass_t e6060sw_devclass; 696 697 DRIVER_MODULE(e6060sw, mdio, e6060sw_driver, e6060sw_devclass, 0, 0); 698 DRIVER_MODULE(miibus, e6060sw, miibus_driver, miibus_devclass, 0, 0); 699 DRIVER_MODULE(mdio, e6060sw, mdio_driver, mdio_devclass, 0, 0); 700 DRIVER_MODULE(etherswitch, e6060sw, etherswitch_driver, etherswitch_devclass, 0, 0); 701 MODULE_VERSION(e6060sw, 1); 702 MODULE_DEPEND(e6060sw, miibus, 1, 1, 1); /* XXX which versions? */ 703 MODULE_DEPEND(e6060sw, etherswitch, 1, 1, 1); /* XXX which versions? */ 704