arswitch.c revision 235323
185892Smike/*- 285892Smike * Copyright (c) 2011-2012 Stefan Bethke. 385892Smike * Copyright (c) 2012 Adrian Chadd. 485892Smike * All rights reserved. 585892Smike * 685892Smike * Redistribution and use in source and binary forms, with or without 785892Smike * modification, are permitted provided that the following conditions 885892Smike * are met: 985892Smike * 1. Redistributions of source code must retain the above copyright 1085892Smike * notice, this list of conditions and the following disclaimer. 1185892Smike * 2. Redistributions in binary form must reproduce the above copyright 1285892Smike * notice, this list of conditions and the following disclaimer in the 1385892Smike * documentation and/or other materials provided with the distribution. 1485892Smike * 1585892Smike * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1685892Smike * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1785892Smike * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1885892Smike * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1985892Smike * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2085892Smike * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2185892Smike * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2285892Smike * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2385892Smike * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2485892Smike * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2585892Smike * SUCH DAMAGE. 2685892Smike * 2785892Smike * $FreeBSD: head/sys/dev/etherswitch/arswitch/arswitch.c 235323 2012-05-12 05:26:49Z adrian $ 2885892Smike */ 2985892Smike 3085892Smike#include <sys/param.h> 3185892Smike#include <sys/bus.h> 3285892Smike#include <sys/errno.h> 3385892Smike#include <sys/kernel.h> 3485892Smike#include <sys/module.h> 3585892Smike#include <sys/socket.h> 3685892Smike#include <sys/sockio.h> 3785892Smike#include <sys/sysctl.h> 3885892Smike#include <sys/systm.h> 3985892Smike 40217147Stijl#include <net/if.h> 41209975Snwhitehorn#include <net/if_arp.h> 42209975Snwhitehorn#include <net/ethernet.h> 43209975Snwhitehorn#include <net/if_dl.h> 44209975Snwhitehorn#include <net/if_media.h> 45209975Snwhitehorn#include <net/if_types.h> 46209975Snwhitehorn 47209975Snwhitehorn#include <machine/bus.h> 4885892Smike#include <dev/iicbus/iic.h> 4985892Smike#include <dev/iicbus/iiconf.h> 5085892Smike#include <dev/iicbus/iicbus.h> 5185892Smike#include <dev/mii/mii.h> 5285892Smike#include <dev/mii/miivar.h> 53209975Snwhitehorn#include <dev/etherswitch/mdio.h> 5485892Smike 5585892Smike#include <dev/etherswitch/etherswitch.h> 5685892Smike 57209975Snwhitehorn#include <dev/etherswitch/arswitch/arswitchreg.h> 5885892Smike#include <dev/etherswitch/arswitch/arswitchvar.h> 5985892Smike#include <dev/etherswitch/arswitch/arswitch_reg.h> 6085892Smike#include <dev/etherswitch/arswitch/arswitch_phy.h> 61209975Snwhitehorn 6299117Smike#include <dev/etherswitch/arswitch/arswitch_7240.h> 63209975Snwhitehorn#include <dev/etherswitch/arswitch/arswitch_8216.h> 6485892Smike#include <dev/etherswitch/arswitch/arswitch_8226.h> 6585892Smike#include <dev/etherswitch/arswitch/arswitch_8316.h> 6685892Smike 6785892Smike#include "mdio_if.h" 68209975Snwhitehorn#include "miibus_if.h" 6985892Smike#include "etherswitch_if.h" 7085892Smike 7185892Smike#if defined(DEBUG) 72209975Snwhitehornstatic SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch"); 7385892Smike#endif 7485892Smike 7585892Smikestatic inline int arswitch_portforphy(int phy); 76209975Snwhitehornstatic void arswitch_tick(void *arg); 7799117Smikestatic int arswitch_ifmedia_upd(struct ifnet *); 78209975Snwhitehornstatic void arswitch_ifmedia_sts(struct ifnet *, struct ifmediareq *); 7985892Smike 8085892Smikestatic void 8185892Smikearswitch_identify(driver_t *driver, device_t parent) 8285892Smike{ 8385892Smike device_t child; 8485892Smike 85209975Snwhitehorn if (device_find_child(parent, driver->name, -1) == NULL) { 8685892Smike child = BUS_ADD_CHILD(parent, 0, driver->name, -1); 8785892Smike } 8885892Smike} 89209975Snwhitehorn 9085892Smikestatic int 9185892Smikearswitch_probe(device_t dev) 9285892Smike{ 93209975Snwhitehorn struct arswitch_softc *sc; 9499117Smike uint32_t id; 95209975Snwhitehorn char *chipname, desc[256]; 9685892Smike 9785892Smike sc = device_get_softc(dev); 9885892Smike bzero(sc, sizeof(*sc)); 9985892Smike sc->page = -1; 100209975Snwhitehorn 10185892Smike /* AR7240 probe */ 10285892Smike if (ar7240_probe(dev) == 0) { 10385892Smike chipname = "AR7240"; 104209975Snwhitehorn sc->sc_switchtype = AR8X16_SWITCH_AR7240; 10585892Smike goto done; 10685892Smike } 10785892Smike 108209975Snwhitehorn /* AR8xxx probe */ 10999117Smike id = arswitch_readreg(dev, AR8X16_REG_MASK_CTRL); 110209975Snwhitehorn switch ((id & AR8X16_MASK_CTRL_VER_MASK) >> 11185892Smike AR8X16_MASK_CTRL_VER_SHIFT) { 11285892Smike case 1: 11385892Smike chipname = "AR8216"; 11485892Smike sc->sc_switchtype = AR8X16_SWITCH_AR8216; 115209975Snwhitehorn break; 11685892Smike case 2: 11785892Smike chipname = "AR8226"; 11885892Smike sc->sc_switchtype = AR8X16_SWITCH_AR8226; 119209975Snwhitehorn break; 12085892Smike case 16: 12185892Smike chipname = "AR8316"; 12285892Smike sc->sc_switchtype = AR8X16_SWITCH_AR8316; 123209975Snwhitehorn break; 12499117Smike default: 125209975Snwhitehorn chipname = NULL; 12685892Smike } 12785892Smike 12885892Smikedone: 12985892Smike DPRINTF(dev, "chipname=%s, rev=%02x\n", chipname, 130209975Snwhitehorn id & AR8X16_MASK_CTRL_REV_MASK); 13185892Smike if (chipname != NULL) { 13285892Smike snprintf(desc, sizeof(desc), 13385892Smike "Atheros %s Ethernet Switch", 134209975Snwhitehorn chipname); 13585892Smike device_set_desc_copy(dev, desc); 13685892Smike return (BUS_PROBE_DEFAULT); 13785892Smike } 138209975Snwhitehorn return (ENXIO); 13999117Smike} 140209975Snwhitehorn 14185892Smikestatic int 14285892Smikearswitch_attach_phys(struct arswitch_softc *sc) 14385892Smike{ 14485892Smike int phy, err = 0; 14585892Smike char name[IFNAMSIZ]; 14685892Smike 147209975Snwhitehorn /* PHYs need an interface, so we generate a dummy one */ 14885892Smike snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev)); 14985892Smike for (phy = 0; phy < sc->numphys; phy++) { 15085892Smike sc->ifp[phy] = if_alloc(IFT_ETHER); 151209975Snwhitehorn sc->ifp[phy]->if_softc = sc; 15285892Smike sc->ifp[phy]->if_flags |= IFF_UP | IFF_BROADCAST | 15385892Smike IFF_DRV_RUNNING | IFF_SIMPLEX; 15485892Smike sc->ifname[phy] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK); 155209975Snwhitehorn bcopy(name, sc->ifname[phy], strlen(name)+1); 15699117Smike if_initname(sc->ifp[phy], sc->ifname[phy], 157209975Snwhitehorn arswitch_portforphy(phy)); 15885892Smike err = mii_attach(sc->sc_dev, &sc->miibus[phy], sc->ifp[phy], 15985892Smike arswitch_ifmedia_upd, arswitch_ifmedia_sts, \ 16085892Smike BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); 16185892Smike DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n", 162209975Snwhitehorn device_get_nameunit(sc->miibus[phy]), 16385892Smike sc->ifp[phy]->if_xname); 16485892Smike if (err != 0) { 16585892Smike device_printf(sc->sc_dev, 166209975Snwhitehorn "attaching PHY %d failed\n", 16785892Smike phy); 16885892Smike } 16985892Smike } 170209975Snwhitehorn return (err); 17199117Smike} 172209975Snwhitehorn 17385892Smikestatic int 17485892Smikearswitch_attach(device_t dev) 17585892Smike{ 17685892Smike struct arswitch_softc *sc; 17785892Smike int err = 0; 17885892Smike 179209975Snwhitehorn sc = device_get_softc(dev); 18085892Smike 18185892Smike /* sc->sc_switchtype is already decided in arswitch_probe() */ 18285892Smike sc->sc_dev = dev; 183209975Snwhitehorn mtx_init(&sc->sc_mtx, "arswitch", NULL, MTX_DEF); 18485892Smike sc->page = -1; 18585892Smike strlcpy(sc->info.es_name, device_get_desc(dev), 18685892Smike sizeof(sc->info.es_name)); 187209975Snwhitehorn 18899117Smike /* 189209975Snwhitehorn * Attach switch related functions 19085892Smike */ 19185892Smike if (AR8X16_IS_SWITCH(sc, AR7240)) 19285892Smike ar7240_attach(sc); 19385892Smike else if (AR8X16_IS_SWITCH(sc, AR8216)) 194209975Snwhitehorn ar8216_attach(sc); 19585892Smike else if (AR8X16_IS_SWITCH(sc, AR8226)) 19685892Smike ar8226_attach(sc); 19785892Smike else if (AR8X16_IS_SWITCH(sc, AR8316)) 198209975Snwhitehorn ar8316_attach(sc); 19985892Smike else 20085892Smike return (ENXIO); 20185892Smike 202209975Snwhitehorn /* 20399117Smike * XXX these two should be part of the switch attach function 204209975Snwhitehorn */ 20585892Smike sc->info.es_nports = 5; /* XXX technically 6, but 6th not used */ 20685892Smike sc->info.es_nvlangroups = 16; 20785892Smike 20885892Smike /* XXX Defaults for externally connected AR8316 */ 209209975Snwhitehorn sc->numphys = 4; 21085892Smike sc->phy4cpu = 1; 21185892Smike sc->is_rgmii = 1; 21285892Smike sc->is_gmii = 0; 213209975Snwhitehorn 21485892Smike (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 21585892Smike "numphys", &sc->numphys); 21685892Smike (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 217209975Snwhitehorn "phy4cpu", &sc->phy4cpu); 21899117Smike (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 219209975Snwhitehorn "is_rgmii", &sc->is_rgmii); 22085892Smike (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 22185892Smike "is_gmii", &sc->is_gmii); 222 223#ifdef NOTYET 224 arswitch_writereg(dev, AR8X16_REG_MASK_CTRL, 225 AR8X16_MASK_CTRL_SOFT_RESET); 226 DELAY(1000); 227 if (arswitch_readreg(dev, AR8X16_REG_MASK_CTRL) & 228 AR8X16_MASK_CTRL_SOFT_RESET) { 229 device_printf(dev, "unable to reset switch\n"); 230 return (ENXIO); 231 } 232 arswitch_modifyreg(dev, AR8X16_REG_GLOBAL_CTRL, 233 AR8X16_FLOOD_MASK_BCAST_TO_CPU, 234 AR8X16_FLOOD_MASK_BCAST_TO_CPU); 235#endif 236 237 err = sc->hal.arswitch_hw_setup(sc); 238 if (err != 0) 239 return (err); 240 241 err = sc->hal.arswitch_hw_global_setup(sc); 242 if (err != 0) 243 return (err); 244 245 /* 246 * Attach the PHYs and complete the bus enumeration. 247 */ 248 err = arswitch_attach_phys(sc); 249 if (err != 0) 250 return (err); 251 252 bus_generic_probe(dev); 253 bus_enumerate_hinted_children(dev); 254 err = bus_generic_attach(dev); 255 if (err != 0) 256 return (err); 257 258 callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0); 259 arswitch_tick(sc); 260 261 return (err); 262} 263 264static int 265arswitch_detach(device_t dev) 266{ 267 struct arswitch_softc *sc = device_get_softc(dev); 268 int i; 269 270 callout_drain(&sc->callout_tick); 271 272 for (i=0; i < sc->numphys; i++) { 273 if (sc->miibus[i] != NULL) 274 device_delete_child(dev, sc->miibus[i]); 275 if (sc->ifp[i] != NULL) 276 if_free(sc->ifp[i]); 277 free(sc->ifname[i], M_DEVBUF); 278 } 279 280 bus_generic_detach(dev); 281 mtx_destroy(&sc->sc_mtx); 282 283 return (0); 284} 285 286/* 287 * Convert PHY number to port number. PHY0 is connected to port 1, PHY1 to 288 * port 2, etc. 289 */ 290static inline int 291arswitch_portforphy(int phy) 292{ 293 return (phy+1); 294} 295 296static inline struct mii_data * 297arswitch_miiforport(struct arswitch_softc *sc, int port) 298{ 299 int phy = port-1; 300 301 if (phy < 0 || phy >= sc->numphys) 302 return (NULL); 303 return (device_get_softc(sc->miibus[phy])); 304} 305 306static inline struct ifnet * 307arswitch_ifpforport(struct arswitch_softc *sc, int port) 308{ 309 int phy = port-1; 310 311 if (phy < 0 || phy >= sc->numphys) 312 return (NULL); 313 return (sc->ifp[phy]); 314} 315 316/* 317 * Convert port status to ifmedia. 318 */ 319static void 320arswitch_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active) 321{ 322 *media_active = IFM_ETHER; 323 *media_status = IFM_AVALID; 324 325 if ((portstatus & AR8X16_PORT_STS_LINK_UP) != 0) 326 *media_status |= IFM_ACTIVE; 327 else { 328 *media_active |= IFM_NONE; 329 return; 330 } 331 switch (portstatus & AR8X16_PORT_STS_SPEED_MASK) { 332 case AR8X16_PORT_STS_SPEED_10: 333 *media_active |= IFM_10_T; 334 break; 335 case AR8X16_PORT_STS_SPEED_100: 336 *media_active |= IFM_100_TX; 337 break; 338 case AR8X16_PORT_STS_SPEED_1000: 339 *media_active |= IFM_1000_T; 340 break; 341 } 342 if ((portstatus & AR8X16_PORT_STS_DUPLEX) == 0) 343 *media_active |= IFM_FDX; 344 else 345 *media_active |= IFM_HDX; 346 if ((portstatus & AR8X16_PORT_STS_TXFLOW) != 0) 347 *media_active |= IFM_ETH_TXPAUSE; 348 if ((portstatus & AR8X16_PORT_STS_RXFLOW) != 0) 349 *media_active |= IFM_ETH_RXPAUSE; 350} 351 352/* 353 * Poll the status for all PHYs. We're using the switch port status because 354 * thats a lot quicker to read than talking to all the PHYs. Care must be 355 * taken that the resulting ifmedia_active is identical to what the PHY will 356 * compute, or gratuitous link status changes will occur whenever the PHYs 357 * update function is called. 358 */ 359static void 360arswitch_miipollstat(struct arswitch_softc *sc) 361{ 362 int i; 363 struct mii_data *mii; 364 struct mii_softc *miisc; 365 int portstatus; 366 367 for (i = 0; i < sc->numphys; i++) { 368 if (sc->miibus[i] == NULL) 369 continue; 370 mii = device_get_softc(sc->miibus[i]); 371 portstatus = arswitch_readreg(sc->sc_dev, 372 AR8X16_REG_PORT_STS(arswitch_portforphy(i))); 373#if 0 374 DPRINTF(sc->sc_dev, "p[%d]=%b\n", 375 arge_portforphy(i), 376 portstatus, 377 "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7" 378 "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE"); 379#endif 380 arswitch_update_ifmedia(portstatus, &mii->mii_media_status, 381 &mii->mii_media_active); 382 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 383 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != 384 miisc->mii_inst) 385 continue; 386 mii_phy_update(miisc, MII_POLLSTAT); 387 } 388 } 389} 390 391static void 392arswitch_tick(void *arg) 393{ 394 struct arswitch_softc *sc = arg; 395 396 arswitch_miipollstat(sc); 397 callout_reset(&sc->callout_tick, hz, arswitch_tick, sc); 398} 399 400static etherswitch_info_t * 401arswitch_getinfo(device_t dev) 402{ 403 struct arswitch_softc *sc = device_get_softc(dev); 404 405 return (&sc->info); 406} 407 408static int 409arswitch_getport(device_t dev, etherswitch_port_t *p) 410{ 411 struct arswitch_softc *sc = device_get_softc(dev); 412 struct mii_data *mii; 413 struct ifmediareq *ifmr = &p->es_ifmr; 414 int err; 415 416 if (p->es_port < 0 || p->es_port >= AR8X16_NUM_PORTS) 417 return (ENXIO); 418 p->es_vlangroup = 0; 419 420 mii = arswitch_miiforport(sc, p->es_port); 421 if (p->es_port == 0) { 422 /* fill in fixed values for CPU port */ 423 ifmr->ifm_count = 0; 424 ifmr->ifm_current = ifmr->ifm_active = 425 IFM_ETHER | IFM_1000_T | IFM_FDX; 426 ifmr->ifm_mask = 0; 427 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 428 } else if (mii != NULL) { 429 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 430 &mii->mii_media, SIOCGIFMEDIA); 431 if (err) 432 return (err); 433 } else { 434 return (ENXIO); 435 } 436 return (0); 437} 438 439/* 440 * XXX doesn't yet work? 441 */ 442static int 443arswitch_setport(device_t dev, etherswitch_port_t *p) 444{ 445 int err; 446 struct arswitch_softc *sc; 447 struct ifmedia *ifm; 448 struct mii_data *mii; 449 struct ifnet *ifp; 450 451 /* 452 * XXX check the sc numphys, or the #define ? 453 */ 454 if (p->es_port < 0 || p->es_port >= AR8X16_NUM_PHYS) 455 return (ENXIO); 456 457 sc = device_get_softc(dev); 458 459 /* 460 * XXX TODO: don't set the CPU port? 461 */ 462 463 mii = arswitch_miiforport(sc, p->es_port); 464 if (mii == NULL) 465 return (ENXIO); 466 467 ifp = arswitch_ifpforport(sc, p->es_port); 468 469 ifm = &mii->mii_media; 470 err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA); 471 return (err); 472} 473 474static int 475arswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 476{ 477 478 /* XXX not implemented yet */ 479 vg->es_vid = 0; 480 vg->es_member_ports = 0; 481 vg->es_untagged_ports = 0; 482 vg->es_fid = 0; 483 return (0); 484} 485 486static int 487arswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 488{ 489 490 /* XXX not implemented yet */ 491 return (0); 492} 493 494static void 495arswitch_statchg(device_t dev) 496{ 497 498 DPRINTF(dev, "%s\n", __func__); 499} 500 501static int 502arswitch_ifmedia_upd(struct ifnet *ifp) 503{ 504 struct arswitch_softc *sc = ifp->if_softc; 505 struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit); 506 507 if (mii == NULL) 508 return (ENXIO); 509 mii_mediachg(mii); 510 return (0); 511} 512 513static void 514arswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 515{ 516 struct arswitch_softc *sc = ifp->if_softc; 517 struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit); 518 519 DPRINTF(sc->sc_dev, "%s\n", __func__); 520 521 if (mii == NULL) 522 return; 523 mii_pollstat(mii); 524 ifmr->ifm_active = mii->mii_media_active; 525 ifmr->ifm_status = mii->mii_media_status; 526} 527 528static device_method_t arswitch_methods[] = { 529 /* Device interface */ 530 DEVMETHOD(device_identify, arswitch_identify), 531 DEVMETHOD(device_probe, arswitch_probe), 532 DEVMETHOD(device_attach, arswitch_attach), 533 DEVMETHOD(device_detach, arswitch_detach), 534 535 /* bus interface */ 536 DEVMETHOD(bus_add_child, device_add_child_ordered), 537 538 /* MII interface */ 539 DEVMETHOD(miibus_readreg, arswitch_readphy), 540 DEVMETHOD(miibus_writereg, arswitch_writephy), 541 DEVMETHOD(miibus_statchg, arswitch_statchg), 542 543 /* MDIO interface */ 544 DEVMETHOD(mdio_readreg, arswitch_readphy), 545 DEVMETHOD(mdio_writereg, arswitch_writephy), 546 547 /* etherswitch interface */ 548 DEVMETHOD(etherswitch_getinfo, arswitch_getinfo), 549 DEVMETHOD(etherswitch_readreg, arswitch_readreg), 550 DEVMETHOD(etherswitch_writereg, arswitch_writereg), 551 DEVMETHOD(etherswitch_readphyreg, arswitch_readphy), 552 DEVMETHOD(etherswitch_writephyreg, arswitch_writephy), 553 DEVMETHOD(etherswitch_getport, arswitch_getport), 554 DEVMETHOD(etherswitch_setport, arswitch_setport), 555 DEVMETHOD(etherswitch_getvgroup, arswitch_getvgroup), 556 DEVMETHOD(etherswitch_setvgroup, arswitch_setvgroup), 557 558 DEVMETHOD_END 559}; 560 561DEFINE_CLASS_0(arswitch, arswitch_driver, arswitch_methods, 562 sizeof(struct arswitch_softc)); 563static devclass_t arswitch_devclass; 564 565DRIVER_MODULE(arswitch, mdio, arswitch_driver, arswitch_devclass, 0, 0); 566DRIVER_MODULE(miibus, arswitch, miibus_driver, miibus_devclass, 0, 0); 567DRIVER_MODULE(mdio, arswitch, mdio_driver, mdio_devclass, 0, 0); 568DRIVER_MODULE(etherswitch, arswitch, etherswitch_driver, etherswitch_devclass, 0, 0); 569MODULE_VERSION(arswitch, 1); 570MODULE_DEPEND(arswitch, miibus, 1, 1, 1); /* XXX which versions? */ 571MODULE_DEPEND(arswitch, etherswitch, 1, 1, 1); /* XXX which versions? */ 572