arswitch.c revision 241578
1235288Sadrian/*- 2235288Sadrian * Copyright (c) 2011-2012 Stefan Bethke. 3235288Sadrian * Copyright (c) 2012 Adrian Chadd. 4235288Sadrian * All rights reserved. 5235288Sadrian * 6235288Sadrian * Redistribution and use in source and binary forms, with or without 7235288Sadrian * modification, are permitted provided that the following conditions 8235288Sadrian * are met: 9235288Sadrian * 1. Redistributions of source code must retain the above copyright 10235288Sadrian * notice, this list of conditions and the following disclaimer. 11235288Sadrian * 2. Redistributions in binary form must reproduce the above copyright 12235288Sadrian * notice, this list of conditions and the following disclaimer in the 13235288Sadrian * documentation and/or other materials provided with the distribution. 14235288Sadrian * 15235288Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16235288Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17235288Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18235288Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19235288Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20235288Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21235288Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22235288Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23235288Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24235288Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25235288Sadrian * SUCH DAMAGE. 26235288Sadrian * 27235288Sadrian * $FreeBSD: head/sys/dev/etherswitch/arswitch/arswitch.c 241578 2012-10-15 12:20:40Z ray $ 28235288Sadrian */ 29235288Sadrian 30235288Sadrian#include <sys/param.h> 31235288Sadrian#include <sys/bus.h> 32235288Sadrian#include <sys/errno.h> 33235288Sadrian#include <sys/kernel.h> 34235288Sadrian#include <sys/module.h> 35235288Sadrian#include <sys/socket.h> 36235288Sadrian#include <sys/sockio.h> 37235288Sadrian#include <sys/sysctl.h> 38235288Sadrian#include <sys/systm.h> 39235288Sadrian 40235288Sadrian#include <net/if.h> 41235288Sadrian#include <net/if_arp.h> 42235288Sadrian#include <net/ethernet.h> 43235288Sadrian#include <net/if_dl.h> 44235288Sadrian#include <net/if_media.h> 45235288Sadrian#include <net/if_types.h> 46235288Sadrian 47235288Sadrian#include <machine/bus.h> 48235288Sadrian#include <dev/iicbus/iic.h> 49235288Sadrian#include <dev/iicbus/iiconf.h> 50235288Sadrian#include <dev/iicbus/iicbus.h> 51235288Sadrian#include <dev/mii/mii.h> 52235288Sadrian#include <dev/mii/miivar.h> 53235288Sadrian#include <dev/etherswitch/mdio.h> 54235288Sadrian 55235288Sadrian#include <dev/etherswitch/etherswitch.h> 56235288Sadrian 57235288Sadrian#include <dev/etherswitch/arswitch/arswitchreg.h> 58235288Sadrian#include <dev/etherswitch/arswitch/arswitchvar.h> 59235288Sadrian#include <dev/etherswitch/arswitch/arswitch_reg.h> 60235288Sadrian#include <dev/etherswitch/arswitch/arswitch_phy.h> 61235288Sadrian 62235323Sadrian#include <dev/etherswitch/arswitch/arswitch_7240.h> 63235288Sadrian#include <dev/etherswitch/arswitch/arswitch_8216.h> 64235288Sadrian#include <dev/etherswitch/arswitch/arswitch_8226.h> 65235288Sadrian#include <dev/etherswitch/arswitch/arswitch_8316.h> 66235288Sadrian 67235288Sadrian#include "mdio_if.h" 68235288Sadrian#include "miibus_if.h" 69235288Sadrian#include "etherswitch_if.h" 70235288Sadrian 71235288Sadrian#if defined(DEBUG) 72235288Sadrianstatic SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch"); 73235288Sadrian#endif 74235288Sadrian 75235288Sadrianstatic inline int arswitch_portforphy(int phy); 76235288Sadrianstatic void arswitch_tick(void *arg); 77235288Sadrianstatic int arswitch_ifmedia_upd(struct ifnet *); 78235288Sadrianstatic void arswitch_ifmedia_sts(struct ifnet *, struct ifmediareq *); 79235288Sadrian 80235288Sadrianstatic void 81235288Sadrianarswitch_identify(driver_t *driver, device_t parent) 82235288Sadrian{ 83235288Sadrian device_t child; 84235288Sadrian 85235288Sadrian if (device_find_child(parent, driver->name, -1) == NULL) { 86235288Sadrian child = BUS_ADD_CHILD(parent, 0, driver->name, -1); 87235288Sadrian } 88235288Sadrian} 89235288Sadrian 90235288Sadrianstatic int 91235288Sadrianarswitch_probe(device_t dev) 92235288Sadrian{ 93235288Sadrian struct arswitch_softc *sc; 94235288Sadrian uint32_t id; 95235288Sadrian char *chipname, desc[256]; 96235288Sadrian 97235288Sadrian sc = device_get_softc(dev); 98235288Sadrian bzero(sc, sizeof(*sc)); 99235288Sadrian sc->page = -1; 100235323Sadrian 101235323Sadrian /* AR7240 probe */ 102235323Sadrian if (ar7240_probe(dev) == 0) { 103235323Sadrian chipname = "AR7240"; 104235323Sadrian sc->sc_switchtype = AR8X16_SWITCH_AR7240; 105241577Sray id = 0; 106235323Sadrian goto done; 107235323Sadrian } 108235323Sadrian 109235323Sadrian /* AR8xxx probe */ 110235288Sadrian id = arswitch_readreg(dev, AR8X16_REG_MASK_CTRL); 111235288Sadrian switch ((id & AR8X16_MASK_CTRL_VER_MASK) >> 112235288Sadrian AR8X16_MASK_CTRL_VER_SHIFT) { 113235288Sadrian case 1: 114235288Sadrian chipname = "AR8216"; 115235288Sadrian sc->sc_switchtype = AR8X16_SWITCH_AR8216; 116235288Sadrian break; 117235288Sadrian case 2: 118235288Sadrian chipname = "AR8226"; 119235288Sadrian sc->sc_switchtype = AR8X16_SWITCH_AR8226; 120235288Sadrian break; 121235288Sadrian case 16: 122235288Sadrian chipname = "AR8316"; 123235288Sadrian sc->sc_switchtype = AR8X16_SWITCH_AR8316; 124235288Sadrian break; 125235288Sadrian default: 126235288Sadrian chipname = NULL; 127235288Sadrian } 128235323Sadrian 129235323Sadriandone: 130235288Sadrian DPRINTF(dev, "chipname=%s, rev=%02x\n", chipname, 131235288Sadrian id & AR8X16_MASK_CTRL_REV_MASK); 132235288Sadrian if (chipname != NULL) { 133235288Sadrian snprintf(desc, sizeof(desc), 134235288Sadrian "Atheros %s Ethernet Switch", 135235288Sadrian chipname); 136235288Sadrian device_set_desc_copy(dev, desc); 137235288Sadrian return (BUS_PROBE_DEFAULT); 138235288Sadrian } 139235288Sadrian return (ENXIO); 140235288Sadrian} 141235288Sadrian 142235288Sadrianstatic int 143235288Sadrianarswitch_attach_phys(struct arswitch_softc *sc) 144235288Sadrian{ 145235288Sadrian int phy, err = 0; 146235288Sadrian char name[IFNAMSIZ]; 147235288Sadrian 148235288Sadrian /* PHYs need an interface, so we generate a dummy one */ 149235288Sadrian snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev)); 150235288Sadrian for (phy = 0; phy < sc->numphys; phy++) { 151235288Sadrian sc->ifp[phy] = if_alloc(IFT_ETHER); 152235288Sadrian sc->ifp[phy]->if_softc = sc; 153235288Sadrian sc->ifp[phy]->if_flags |= IFF_UP | IFF_BROADCAST | 154235288Sadrian IFF_DRV_RUNNING | IFF_SIMPLEX; 155235288Sadrian sc->ifname[phy] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK); 156235288Sadrian bcopy(name, sc->ifname[phy], strlen(name)+1); 157235288Sadrian if_initname(sc->ifp[phy], sc->ifname[phy], 158235288Sadrian arswitch_portforphy(phy)); 159235288Sadrian err = mii_attach(sc->sc_dev, &sc->miibus[phy], sc->ifp[phy], 160235288Sadrian arswitch_ifmedia_upd, arswitch_ifmedia_sts, \ 161235288Sadrian BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); 162235288Sadrian DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n", 163235288Sadrian device_get_nameunit(sc->miibus[phy]), 164235288Sadrian sc->ifp[phy]->if_xname); 165235288Sadrian if (err != 0) { 166235288Sadrian device_printf(sc->sc_dev, 167235288Sadrian "attaching PHY %d failed\n", 168235288Sadrian phy); 169235288Sadrian } 170235288Sadrian } 171235288Sadrian return (err); 172235288Sadrian} 173235288Sadrian 174235288Sadrianstatic int 175235288Sadrianarswitch_attach(device_t dev) 176235288Sadrian{ 177235288Sadrian struct arswitch_softc *sc; 178235288Sadrian int err = 0; 179235288Sadrian 180235288Sadrian sc = device_get_softc(dev); 181235288Sadrian 182235288Sadrian /* sc->sc_switchtype is already decided in arswitch_probe() */ 183235288Sadrian sc->sc_dev = dev; 184235288Sadrian mtx_init(&sc->sc_mtx, "arswitch", NULL, MTX_DEF); 185235288Sadrian sc->page = -1; 186235288Sadrian strlcpy(sc->info.es_name, device_get_desc(dev), 187235288Sadrian sizeof(sc->info.es_name)); 188235288Sadrian 189235288Sadrian /* 190235288Sadrian * Attach switch related functions 191235288Sadrian */ 192235323Sadrian if (AR8X16_IS_SWITCH(sc, AR7240)) 193235323Sadrian ar7240_attach(sc); 194235323Sadrian else if (AR8X16_IS_SWITCH(sc, AR8216)) 195235288Sadrian ar8216_attach(sc); 196235288Sadrian else if (AR8X16_IS_SWITCH(sc, AR8226)) 197235288Sadrian ar8226_attach(sc); 198235288Sadrian else if (AR8X16_IS_SWITCH(sc, AR8316)) 199235288Sadrian ar8316_attach(sc); 200235288Sadrian else 201235288Sadrian return (ENXIO); 202235288Sadrian 203235288Sadrian /* 204235288Sadrian * XXX these two should be part of the switch attach function 205235288Sadrian */ 206235288Sadrian sc->info.es_nports = 5; /* XXX technically 6, but 6th not used */ 207235288Sadrian sc->info.es_nvlangroups = 16; 208235288Sadrian 209235288Sadrian /* XXX Defaults for externally connected AR8316 */ 210235288Sadrian sc->numphys = 4; 211235288Sadrian sc->phy4cpu = 1; 212235288Sadrian sc->is_rgmii = 1; 213235288Sadrian sc->is_gmii = 0; 214235288Sadrian 215235288Sadrian (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 216235288Sadrian "numphys", &sc->numphys); 217235288Sadrian (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 218235288Sadrian "phy4cpu", &sc->phy4cpu); 219235288Sadrian (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 220235288Sadrian "is_rgmii", &sc->is_rgmii); 221235288Sadrian (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 222235288Sadrian "is_gmii", &sc->is_gmii); 223235288Sadrian 224235377Sadrian /* 225235377Sadrian * This requires much more setup depending upon each chip, including: 226235377Sadrian * 227235377Sadrian * + Proper reinitialisation of the PHYs; 228235377Sadrian * + Initialising the VLAN table; 229235377Sadrian * + Initialising the port access table and CPU flood/broadcast 230235377Sadrian * configuration; 231235377Sadrian * + Other things I haven't yet thought of. 232235377Sadrian */ 233235288Sadrian#ifdef NOTYET 234235288Sadrian arswitch_writereg(dev, AR8X16_REG_MASK_CTRL, 235235288Sadrian AR8X16_MASK_CTRL_SOFT_RESET); 236235288Sadrian DELAY(1000); 237235288Sadrian if (arswitch_readreg(dev, AR8X16_REG_MASK_CTRL) & 238235288Sadrian AR8X16_MASK_CTRL_SOFT_RESET) { 239235288Sadrian device_printf(dev, "unable to reset switch\n"); 240235288Sadrian return (ENXIO); 241235288Sadrian } 242235288Sadrian#endif 243235288Sadrian 244235288Sadrian err = sc->hal.arswitch_hw_setup(sc); 245235288Sadrian if (err != 0) 246235288Sadrian return (err); 247235288Sadrian 248235288Sadrian err = sc->hal.arswitch_hw_global_setup(sc); 249235288Sadrian if (err != 0) 250235288Sadrian return (err); 251235288Sadrian 252235288Sadrian /* 253235288Sadrian * Attach the PHYs and complete the bus enumeration. 254235288Sadrian */ 255235288Sadrian err = arswitch_attach_phys(sc); 256235288Sadrian if (err != 0) 257235288Sadrian return (err); 258235288Sadrian 259235288Sadrian bus_generic_probe(dev); 260235288Sadrian bus_enumerate_hinted_children(dev); 261235288Sadrian err = bus_generic_attach(dev); 262235288Sadrian if (err != 0) 263235288Sadrian return (err); 264235288Sadrian 265235288Sadrian callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0); 266241578Sray 267241578Sray ARSWITCH_LOCK(sc); 268235288Sadrian arswitch_tick(sc); 269241578Sray ARSWITCH_UNLOCK(sc); 270235288Sadrian 271235288Sadrian return (err); 272235288Sadrian} 273235288Sadrian 274235288Sadrianstatic int 275235288Sadrianarswitch_detach(device_t dev) 276235288Sadrian{ 277235288Sadrian struct arswitch_softc *sc = device_get_softc(dev); 278235288Sadrian int i; 279235288Sadrian 280235288Sadrian callout_drain(&sc->callout_tick); 281235288Sadrian 282235288Sadrian for (i=0; i < sc->numphys; i++) { 283235288Sadrian if (sc->miibus[i] != NULL) 284235288Sadrian device_delete_child(dev, sc->miibus[i]); 285235288Sadrian if (sc->ifp[i] != NULL) 286235288Sadrian if_free(sc->ifp[i]); 287235288Sadrian free(sc->ifname[i], M_DEVBUF); 288235288Sadrian } 289235288Sadrian 290235288Sadrian bus_generic_detach(dev); 291235288Sadrian mtx_destroy(&sc->sc_mtx); 292235288Sadrian 293235288Sadrian return (0); 294235288Sadrian} 295235288Sadrian 296235288Sadrian/* 297235288Sadrian * Convert PHY number to port number. PHY0 is connected to port 1, PHY1 to 298235288Sadrian * port 2, etc. 299235288Sadrian */ 300235288Sadrianstatic inline int 301235288Sadrianarswitch_portforphy(int phy) 302235288Sadrian{ 303235288Sadrian return (phy+1); 304235288Sadrian} 305235288Sadrian 306235288Sadrianstatic inline struct mii_data * 307235288Sadrianarswitch_miiforport(struct arswitch_softc *sc, int port) 308235288Sadrian{ 309235288Sadrian int phy = port-1; 310235288Sadrian 311235288Sadrian if (phy < 0 || phy >= sc->numphys) 312235288Sadrian return (NULL); 313235288Sadrian return (device_get_softc(sc->miibus[phy])); 314235288Sadrian} 315235288Sadrian 316235288Sadrianstatic inline struct ifnet * 317235288Sadrianarswitch_ifpforport(struct arswitch_softc *sc, int port) 318235288Sadrian{ 319235288Sadrian int phy = port-1; 320235288Sadrian 321235288Sadrian if (phy < 0 || phy >= sc->numphys) 322235288Sadrian return (NULL); 323235288Sadrian return (sc->ifp[phy]); 324235288Sadrian} 325235288Sadrian 326235288Sadrian/* 327235288Sadrian * Convert port status to ifmedia. 328235288Sadrian */ 329235288Sadrianstatic void 330235288Sadrianarswitch_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active) 331235288Sadrian{ 332235288Sadrian *media_active = IFM_ETHER; 333235288Sadrian *media_status = IFM_AVALID; 334235288Sadrian 335235288Sadrian if ((portstatus & AR8X16_PORT_STS_LINK_UP) != 0) 336235288Sadrian *media_status |= IFM_ACTIVE; 337235288Sadrian else { 338235288Sadrian *media_active |= IFM_NONE; 339235288Sadrian return; 340235288Sadrian } 341235288Sadrian switch (portstatus & AR8X16_PORT_STS_SPEED_MASK) { 342235288Sadrian case AR8X16_PORT_STS_SPEED_10: 343235288Sadrian *media_active |= IFM_10_T; 344235288Sadrian break; 345235288Sadrian case AR8X16_PORT_STS_SPEED_100: 346235288Sadrian *media_active |= IFM_100_TX; 347235288Sadrian break; 348235288Sadrian case AR8X16_PORT_STS_SPEED_1000: 349235288Sadrian *media_active |= IFM_1000_T; 350235288Sadrian break; 351235288Sadrian } 352235288Sadrian if ((portstatus & AR8X16_PORT_STS_DUPLEX) == 0) 353235288Sadrian *media_active |= IFM_FDX; 354235288Sadrian else 355235288Sadrian *media_active |= IFM_HDX; 356235288Sadrian if ((portstatus & AR8X16_PORT_STS_TXFLOW) != 0) 357235288Sadrian *media_active |= IFM_ETH_TXPAUSE; 358235288Sadrian if ((portstatus & AR8X16_PORT_STS_RXFLOW) != 0) 359235288Sadrian *media_active |= IFM_ETH_RXPAUSE; 360235288Sadrian} 361235288Sadrian 362235288Sadrian/* 363235288Sadrian * Poll the status for all PHYs. We're using the switch port status because 364235288Sadrian * thats a lot quicker to read than talking to all the PHYs. Care must be 365235288Sadrian * taken that the resulting ifmedia_active is identical to what the PHY will 366235288Sadrian * compute, or gratuitous link status changes will occur whenever the PHYs 367235288Sadrian * update function is called. 368235288Sadrian */ 369235288Sadrianstatic void 370235288Sadrianarswitch_miipollstat(struct arswitch_softc *sc) 371235288Sadrian{ 372235288Sadrian int i; 373235288Sadrian struct mii_data *mii; 374235288Sadrian struct mii_softc *miisc; 375235288Sadrian int portstatus; 376235288Sadrian 377241578Sray ARSWITCH_LOCK_ASSERT(sc, MA_OWNED); 378241578Sray 379235288Sadrian for (i = 0; i < sc->numphys; i++) { 380235288Sadrian if (sc->miibus[i] == NULL) 381235288Sadrian continue; 382235288Sadrian mii = device_get_softc(sc->miibus[i]); 383235288Sadrian portstatus = arswitch_readreg(sc->sc_dev, 384235288Sadrian AR8X16_REG_PORT_STS(arswitch_portforphy(i))); 385235288Sadrian#if 0 386235288Sadrian DPRINTF(sc->sc_dev, "p[%d]=%b\n", 387235288Sadrian arge_portforphy(i), 388235288Sadrian portstatus, 389235288Sadrian "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7" 390235288Sadrian "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE"); 391235288Sadrian#endif 392235288Sadrian arswitch_update_ifmedia(portstatus, &mii->mii_media_status, 393235288Sadrian &mii->mii_media_active); 394235288Sadrian LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 395235288Sadrian if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != 396235288Sadrian miisc->mii_inst) 397235288Sadrian continue; 398235288Sadrian mii_phy_update(miisc, MII_POLLSTAT); 399235288Sadrian } 400235288Sadrian } 401235288Sadrian} 402235288Sadrian 403235288Sadrianstatic void 404235288Sadrianarswitch_tick(void *arg) 405235288Sadrian{ 406235288Sadrian struct arswitch_softc *sc = arg; 407235288Sadrian 408235288Sadrian arswitch_miipollstat(sc); 409235288Sadrian callout_reset(&sc->callout_tick, hz, arswitch_tick, sc); 410235288Sadrian} 411235288Sadrian 412241578Sraystatic void 413241578Srayarswitch_lock(device_t dev) 414241578Sray{ 415241578Sray struct arswitch_softc *sc = device_get_softc(dev); 416241578Sray 417241578Sray ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 418241578Sray ARSWITCH_LOCK(sc); 419241578Sray} 420241578Sray 421241578Sraystatic void 422241578Srayarswitch_unlock(device_t dev) 423241578Sray{ 424241578Sray struct arswitch_softc *sc = device_get_softc(dev); 425241578Sray 426241578Sray ARSWITCH_LOCK_ASSERT(sc, MA_OWNED); 427241578Sray ARSWITCH_UNLOCK(sc); 428241578Sray} 429241578Sray 430235288Sadrianstatic etherswitch_info_t * 431235288Sadrianarswitch_getinfo(device_t dev) 432235288Sadrian{ 433235288Sadrian struct arswitch_softc *sc = device_get_softc(dev); 434235288Sadrian 435235288Sadrian return (&sc->info); 436235288Sadrian} 437235288Sadrian 438235288Sadrianstatic int 439235288Sadrianarswitch_getport(device_t dev, etherswitch_port_t *p) 440235288Sadrian{ 441235288Sadrian struct arswitch_softc *sc = device_get_softc(dev); 442235288Sadrian struct mii_data *mii; 443235288Sadrian struct ifmediareq *ifmr = &p->es_ifmr; 444235288Sadrian int err; 445235288Sadrian 446235288Sadrian if (p->es_port < 0 || p->es_port >= AR8X16_NUM_PORTS) 447235288Sadrian return (ENXIO); 448235288Sadrian p->es_vlangroup = 0; 449235288Sadrian 450235288Sadrian mii = arswitch_miiforport(sc, p->es_port); 451235288Sadrian if (p->es_port == 0) { 452235288Sadrian /* fill in fixed values for CPU port */ 453235288Sadrian ifmr->ifm_count = 0; 454235288Sadrian ifmr->ifm_current = ifmr->ifm_active = 455235288Sadrian IFM_ETHER | IFM_1000_T | IFM_FDX; 456235288Sadrian ifmr->ifm_mask = 0; 457235288Sadrian ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 458235288Sadrian } else if (mii != NULL) { 459235288Sadrian err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 460235288Sadrian &mii->mii_media, SIOCGIFMEDIA); 461235288Sadrian if (err) 462235288Sadrian return (err); 463235288Sadrian } else { 464235288Sadrian return (ENXIO); 465235288Sadrian } 466235288Sadrian return (0); 467235288Sadrian} 468235288Sadrian 469235288Sadrian/* 470235288Sadrian * XXX doesn't yet work? 471235288Sadrian */ 472235288Sadrianstatic int 473235288Sadrianarswitch_setport(device_t dev, etherswitch_port_t *p) 474235288Sadrian{ 475235288Sadrian int err; 476235288Sadrian struct arswitch_softc *sc; 477235288Sadrian struct ifmedia *ifm; 478235288Sadrian struct mii_data *mii; 479235288Sadrian struct ifnet *ifp; 480235288Sadrian 481235288Sadrian /* 482235288Sadrian * XXX check the sc numphys, or the #define ? 483235288Sadrian */ 484235288Sadrian if (p->es_port < 0 || p->es_port >= AR8X16_NUM_PHYS) 485235288Sadrian return (ENXIO); 486235288Sadrian 487235288Sadrian sc = device_get_softc(dev); 488235288Sadrian 489235288Sadrian /* 490235288Sadrian * XXX TODO: don't set the CPU port? 491235288Sadrian */ 492235288Sadrian 493235288Sadrian mii = arswitch_miiforport(sc, p->es_port); 494235288Sadrian if (mii == NULL) 495235288Sadrian return (ENXIO); 496235288Sadrian 497235288Sadrian ifp = arswitch_ifpforport(sc, p->es_port); 498235288Sadrian 499235288Sadrian ifm = &mii->mii_media; 500235288Sadrian err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA); 501235288Sadrian return (err); 502235288Sadrian} 503235288Sadrian 504235288Sadrianstatic int 505235288Sadrianarswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 506235288Sadrian{ 507235288Sadrian 508235288Sadrian /* XXX not implemented yet */ 509235288Sadrian vg->es_vid = 0; 510235288Sadrian vg->es_member_ports = 0; 511235288Sadrian vg->es_untagged_ports = 0; 512235288Sadrian vg->es_fid = 0; 513235288Sadrian return (0); 514235288Sadrian} 515235288Sadrian 516235288Sadrianstatic int 517235288Sadrianarswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 518235288Sadrian{ 519235288Sadrian 520235288Sadrian /* XXX not implemented yet */ 521235288Sadrian return (0); 522235288Sadrian} 523235288Sadrian 524235288Sadrianstatic void 525235288Sadrianarswitch_statchg(device_t dev) 526235288Sadrian{ 527235288Sadrian 528235288Sadrian DPRINTF(dev, "%s\n", __func__); 529235288Sadrian} 530235288Sadrian 531235288Sadrianstatic int 532235288Sadrianarswitch_ifmedia_upd(struct ifnet *ifp) 533235288Sadrian{ 534235288Sadrian struct arswitch_softc *sc = ifp->if_softc; 535235288Sadrian struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit); 536235288Sadrian 537235288Sadrian if (mii == NULL) 538235288Sadrian return (ENXIO); 539235288Sadrian mii_mediachg(mii); 540235288Sadrian return (0); 541235288Sadrian} 542235288Sadrian 543235288Sadrianstatic void 544235288Sadrianarswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 545235288Sadrian{ 546235288Sadrian struct arswitch_softc *sc = ifp->if_softc; 547235288Sadrian struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit); 548235288Sadrian 549235288Sadrian DPRINTF(sc->sc_dev, "%s\n", __func__); 550235288Sadrian 551235288Sadrian if (mii == NULL) 552235288Sadrian return; 553235288Sadrian mii_pollstat(mii); 554235288Sadrian ifmr->ifm_active = mii->mii_media_active; 555235288Sadrian ifmr->ifm_status = mii->mii_media_status; 556235288Sadrian} 557235288Sadrian 558235288Sadrianstatic device_method_t arswitch_methods[] = { 559235288Sadrian /* Device interface */ 560235288Sadrian DEVMETHOD(device_identify, arswitch_identify), 561235288Sadrian DEVMETHOD(device_probe, arswitch_probe), 562235288Sadrian DEVMETHOD(device_attach, arswitch_attach), 563235288Sadrian DEVMETHOD(device_detach, arswitch_detach), 564235288Sadrian 565235288Sadrian /* bus interface */ 566235288Sadrian DEVMETHOD(bus_add_child, device_add_child_ordered), 567235288Sadrian 568235288Sadrian /* MII interface */ 569235288Sadrian DEVMETHOD(miibus_readreg, arswitch_readphy), 570235288Sadrian DEVMETHOD(miibus_writereg, arswitch_writephy), 571235288Sadrian DEVMETHOD(miibus_statchg, arswitch_statchg), 572235288Sadrian 573235288Sadrian /* MDIO interface */ 574235288Sadrian DEVMETHOD(mdio_readreg, arswitch_readphy), 575235288Sadrian DEVMETHOD(mdio_writereg, arswitch_writephy), 576235288Sadrian 577235288Sadrian /* etherswitch interface */ 578241578Sray DEVMETHOD(etherswitch_lock, arswitch_lock), 579241578Sray DEVMETHOD(etherswitch_unlock, arswitch_unlock), 580235288Sadrian DEVMETHOD(etherswitch_getinfo, arswitch_getinfo), 581235288Sadrian DEVMETHOD(etherswitch_readreg, arswitch_readreg), 582235288Sadrian DEVMETHOD(etherswitch_writereg, arswitch_writereg), 583235288Sadrian DEVMETHOD(etherswitch_readphyreg, arswitch_readphy), 584235288Sadrian DEVMETHOD(etherswitch_writephyreg, arswitch_writephy), 585235288Sadrian DEVMETHOD(etherswitch_getport, arswitch_getport), 586235288Sadrian DEVMETHOD(etherswitch_setport, arswitch_setport), 587235288Sadrian DEVMETHOD(etherswitch_getvgroup, arswitch_getvgroup), 588235288Sadrian DEVMETHOD(etherswitch_setvgroup, arswitch_setvgroup), 589235288Sadrian 590235288Sadrian DEVMETHOD_END 591235288Sadrian}; 592235288Sadrian 593235288SadrianDEFINE_CLASS_0(arswitch, arswitch_driver, arswitch_methods, 594235288Sadrian sizeof(struct arswitch_softc)); 595235288Sadrianstatic devclass_t arswitch_devclass; 596235288Sadrian 597235288SadrianDRIVER_MODULE(arswitch, mdio, arswitch_driver, arswitch_devclass, 0, 0); 598235288SadrianDRIVER_MODULE(miibus, arswitch, miibus_driver, miibus_devclass, 0, 0); 599235288SadrianDRIVER_MODULE(mdio, arswitch, mdio_driver, mdio_devclass, 0, 0); 600235288SadrianDRIVER_MODULE(etherswitch, arswitch, etherswitch_driver, etherswitch_devclass, 0, 0); 601235288SadrianMODULE_VERSION(arswitch, 1); 602235288SadrianMODULE_DEPEND(arswitch, miibus, 1, 1, 1); /* XXX which versions? */ 603235288SadrianMODULE_DEPEND(arswitch, etherswitch, 1, 1, 1); /* XXX which versions? */ 604