1235288Sadrian/*- 2315330Smizhka * Copyright (c) 2015-2016 Hiroki Mori. 3235288Sadrian * Copyright (c) 2011-2012 Stefan Bethke. 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: stable/11/sys/dev/etherswitch/rtl8366/rtl8366rb.c 315330 2017-03-15 21:03:51Z mizhka $ 28235288Sadrian */ 29235288Sadrian 30315330Smizhka#include "opt_etherswitch.h" 31315330Smizhka 32235288Sadrian#include <sys/param.h> 33235288Sadrian#include <sys/bus.h> 34235288Sadrian#include <sys/errno.h> 35235288Sadrian#include <sys/kernel.h> 36257346Sloos#include <sys/lock.h> 37257346Sloos#include <sys/malloc.h> 38235288Sadrian#include <sys/module.h> 39257346Sloos#include <sys/mutex.h> 40235288Sadrian#include <sys/socket.h> 41235288Sadrian#include <sys/sockio.h> 42235288Sadrian#include <sys/sysctl.h> 43235288Sadrian#include <sys/systm.h> 44235288Sadrian 45235288Sadrian#include <net/if.h> 46257346Sloos#include <net/if_var.h> 47235288Sadrian#include <net/ethernet.h> 48235288Sadrian#include <net/if_media.h> 49235288Sadrian#include <net/if_types.h> 50235288Sadrian 51235288Sadrian#include <machine/bus.h> 52268564Srpaulo#include <dev/iicbus/iic.h> 53235288Sadrian#include <dev/iicbus/iiconf.h> 54235288Sadrian#include <dev/iicbus/iicbus.h> 55235288Sadrian#include <dev/mii/mii.h> 56235288Sadrian#include <dev/mii/miivar.h> 57235288Sadrian 58235288Sadrian#include <dev/etherswitch/etherswitch.h> 59235288Sadrian#include <dev/etherswitch/rtl8366/rtl8366rbvar.h> 60235288Sadrian 61235288Sadrian#include "iicbus_if.h" 62235288Sadrian#include "miibus_if.h" 63235288Sadrian#include "etherswitch_if.h" 64235288Sadrian 65235288Sadrian 66235288Sadrianstruct rtl8366rb_softc { 67235288Sadrian struct mtx sc_mtx; /* serialize access to softc */ 68235288Sadrian int smi_acquired; /* serialize access to SMI/I2C bus */ 69235288Sadrian struct mtx callout_mtx; /* serialize callout */ 70235288Sadrian device_t dev; 71315330Smizhka int vid[RTL8366_NUM_VLANS]; 72315330Smizhka char *ifname[RTL8366_NUM_PHYS]; 73315330Smizhka device_t miibus[RTL8366_NUM_PHYS]; 74315330Smizhka struct ifnet *ifp[RTL8366_NUM_PHYS]; 75235288Sadrian struct callout callout_tick; 76315330Smizhka etherswitch_info_t info; 77315330Smizhka int chip_type; /* 0 = RTL8366RB, 1 = RTL8366SR */ 78235288Sadrian}; 79235288Sadrian 80235288Sadrian#define RTL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 81235288Sadrian#define RTL_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 82235288Sadrian#define RTL_LOCK_ASSERT(_sc, _what) mtx_assert(&(_s)c->sc_mtx, (_what)) 83235288Sadrian#define RTL_TRYLOCK(_sc) mtx_trylock(&(_sc)->sc_mtx) 84235288Sadrian 85235288Sadrian#define RTL_WAITOK 0 86235288Sadrian#define RTL_NOWAIT 1 87235288Sadrian 88235288Sadrian#define RTL_SMI_ACQUIRED 1 89235288Sadrian#define RTL_SMI_ACQUIRED_ASSERT(_sc) \ 90235288Sadrian KASSERT((_sc)->smi_acquired == RTL_SMI_ACQUIRED, ("smi must be acquired @%s", __FUNCTION__)) 91235288Sadrian 92235288Sadrian#if defined(DEBUG) 93235288Sadrian#define DPRINTF(dev, args...) device_printf(dev, args) 94235288Sadrian#define DEVERR(dev, err, fmt, args...) do { \ 95235288Sadrian if (err != 0) device_printf(dev, fmt, err, args); \ 96235288Sadrian } while (0) 97235288Sadrian#define DEBUG_INCRVAR(var) do { \ 98235288Sadrian var++; \ 99235288Sadrian } while (0) 100235288Sadrian 101235288Sadrianstatic int callout_blocked = 0; 102235288Sadrianstatic int iic_select_retries = 0; 103235288Sadrianstatic int phy_access_retries = 0; 104235288Sadrianstatic SYSCTL_NODE(_debug, OID_AUTO, rtl8366rb, CTLFLAG_RD, 0, "rtl8366rb"); 105235288SadrianSYSCTL_INT(_debug_rtl8366rb, OID_AUTO, callout_blocked, CTLFLAG_RW, &callout_blocked, 0, 106235288Sadrian "number of times the callout couldn't acquire the bus"); 107235288SadrianSYSCTL_INT(_debug_rtl8366rb, OID_AUTO, iic_select_retries, CTLFLAG_RW, &iic_select_retries, 0, 108235288Sadrian "number of times the I2C bus selection had to be retried"); 109235288SadrianSYSCTL_INT(_debug_rtl8366rb, OID_AUTO, phy_access_retries, CTLFLAG_RW, &phy_access_retries, 0, 110235288Sadrian "number of times PHY register access had to be retried"); 111235288Sadrian#else 112235288Sadrian#define DPRINTF(dev, args...) 113235288Sadrian#define DEVERR(dev, err, fmt, args...) 114235288Sadrian#define DEBUG_INCRVAR(var) 115235288Sadrian#endif 116235288Sadrian 117235288Sadrianstatic int smi_probe(device_t dev); 118235288Sadrianstatic int smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep); 119235288Sadrianstatic int smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep); 120235288Sadrianstatic int smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep); 121235288Sadrianstatic void rtl8366rb_tick(void *arg); 122235288Sadrianstatic int rtl8366rb_ifmedia_upd(struct ifnet *); 123235288Sadrianstatic void rtl8366rb_ifmedia_sts(struct ifnet *, struct ifmediareq *); 124235288Sadrian 125235288Sadrianstatic void 126235288Sadrianrtl8366rb_identify(driver_t *driver, device_t parent) 127235288Sadrian{ 128235288Sadrian device_t child; 129235288Sadrian struct iicbus_ivar *devi; 130235288Sadrian 131235288Sadrian if (device_find_child(parent, "rtl8366rb", -1) == NULL) { 132235288Sadrian child = BUS_ADD_CHILD(parent, 0, "rtl8366rb", -1); 133235288Sadrian devi = IICBUS_IVAR(child); 134315330Smizhka devi->addr = RTL8366_IIC_ADDR; 135235288Sadrian } 136235288Sadrian} 137235288Sadrian 138235288Sadrianstatic int 139235288Sadrianrtl8366rb_probe(device_t dev) 140235288Sadrian{ 141315330Smizhka struct rtl8366rb_softc *sc; 142315330Smizhka 143315330Smizhka sc = device_get_softc(dev); 144315330Smizhka 145315330Smizhka bzero(sc, sizeof(*sc)); 146235288Sadrian if (smi_probe(dev) != 0) 147235288Sadrian return (ENXIO); 148315330Smizhka if(sc->chip_type == 0) 149315330Smizhka device_set_desc(dev, "RTL8366RB Ethernet Switch Controller"); 150315330Smizhka else 151315330Smizhka device_set_desc(dev, "RTL8366SR Ethernet Switch Controller"); 152235288Sadrian return (BUS_PROBE_DEFAULT); 153235288Sadrian} 154235288Sadrian 155235288Sadrianstatic void 156235288Sadrianrtl8366rb_init(device_t dev) 157235288Sadrian{ 158315330Smizhka struct rtl8366rb_softc *sc; 159268233Sloos int i; 160268233Sloos 161315330Smizhka sc = device_get_softc(dev); 162315330Smizhka 163235288Sadrian /* Initialisation for TL-WR1043ND */ 164315330Smizhka#ifdef RTL8366_SOFT_RESET 165315330Smizhka smi_rmw(dev, RTL8366_RCR, 166315330Smizhka RTL8366_RCR_SOFT_RESET, 167315330Smizhka RTL8366_RCR_SOFT_RESET, RTL_WAITOK); 168315330Smizhka#else 169315330Smizhka smi_rmw(dev, RTL8366_RCR, 170315330Smizhka RTL8366_RCR_HARD_RESET, 171315330Smizhka RTL8366_RCR_HARD_RESET, RTL_WAITOK); 172315330Smizhka#endif 173315330Smizhka /* hard reset not return ack */ 174235288Sadrian DELAY(100000); 175235288Sadrian /* Enable 16 VLAN mode */ 176315330Smizhka smi_rmw(dev, RTL8366_SGCR, 177315330Smizhka RTL8366_SGCR_EN_VLAN | RTL8366_SGCR_EN_VLAN_4KTB, 178315330Smizhka RTL8366_SGCR_EN_VLAN, RTL_WAITOK); 179268233Sloos /* Initialize our vlan table. */ 180268233Sloos for (i = 0; i <= 1; i++) 181268233Sloos sc->vid[i] = (i + 1) | ETHERSWITCH_VID_VALID; 182268233Sloos /* Remove port 0 from VLAN 1. */ 183315330Smizhka smi_rmw(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, 0), 184235288Sadrian (1 << 0), 0, RTL_WAITOK); 185268233Sloos /* Add port 0 untagged and port 5 tagged to VLAN 2. */ 186315330Smizhka smi_rmw(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, 1), 187315330Smizhka ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_MEMBER_SHIFT) 188315330Smizhka | ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_UNTAG_SHIFT), 189315330Smizhka ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_MEMBER_SHIFT 190315330Smizhka | ((1 << 0) << RTL8366_VMCR_MU_UNTAG_SHIFT)), 191235288Sadrian RTL_WAITOK); 192268233Sloos /* Set PVID 2 for port 0. */ 193315330Smizhka smi_rmw(dev, RTL8366_PVCR_REG(0), 194315330Smizhka RTL8366_PVCR_VAL(0, RTL8366_PVCR_PORT_MASK), 195315330Smizhka RTL8366_PVCR_VAL(0, 1), RTL_WAITOK); 196235288Sadrian} 197235288Sadrian 198235288Sadrianstatic int 199235288Sadrianrtl8366rb_attach(device_t dev) 200235288Sadrian{ 201315330Smizhka struct rtl8366rb_softc *sc; 202235288Sadrian uint16_t rev = 0; 203235288Sadrian char name[IFNAMSIZ]; 204235288Sadrian int err = 0; 205235288Sadrian int i; 206235288Sadrian 207235288Sadrian sc = device_get_softc(dev); 208315330Smizhka 209235288Sadrian sc->dev = dev; 210235288Sadrian mtx_init(&sc->sc_mtx, "rtl8366rb", NULL, MTX_DEF); 211235288Sadrian sc->smi_acquired = 0; 212235288Sadrian mtx_init(&sc->callout_mtx, "rtl8366rbcallout", NULL, MTX_DEF); 213235288Sadrian 214235288Sadrian rtl8366rb_init(dev); 215315330Smizhka smi_read(dev, RTL8366_CVCR, &rev, RTL_WAITOK); 216235288Sadrian device_printf(dev, "rev. %d\n", rev & 0x000f); 217235288Sadrian 218315330Smizhka sc->info.es_nports = RTL8366_NUM_PORTS; 219315330Smizhka sc->info.es_nvlangroups = RTL8366_NUM_VLANS; 220315330Smizhka sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q; 221315330Smizhka if(sc->chip_type == 0) 222315330Smizhka sprintf(sc->info.es_name, "Realtek RTL8366RB"); 223315330Smizhka else 224315330Smizhka sprintf(sc->info.es_name, "Realtek RTL8366SR"); 225315330Smizhka 226235288Sadrian /* attach miibus and phys */ 227235288Sadrian /* PHYs need an interface, so we generate a dummy one */ 228315330Smizhka for (i = 0; i < RTL8366_NUM_PHYS; i++) { 229235288Sadrian sc->ifp[i] = if_alloc(IFT_ETHER); 230235288Sadrian sc->ifp[i]->if_softc = sc; 231235288Sadrian sc->ifp[i]->if_flags |= IFF_UP | IFF_BROADCAST | IFF_DRV_RUNNING 232235288Sadrian | IFF_SIMPLEX; 233235288Sadrian snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(dev)); 234235288Sadrian sc->ifname[i] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK); 235235288Sadrian bcopy(name, sc->ifname[i], strlen(name)+1); 236235288Sadrian if_initname(sc->ifp[i], sc->ifname[i], i); 237235288Sadrian err = mii_attach(dev, &sc->miibus[i], sc->ifp[i], rtl8366rb_ifmedia_upd, \ 238235288Sadrian rtl8366rb_ifmedia_sts, BMSR_DEFCAPMASK, \ 239235288Sadrian i, MII_OFFSET_ANY, 0); 240235288Sadrian if (err != 0) { 241235288Sadrian device_printf(dev, "attaching PHY %d failed\n", i); 242235288Sadrian return (err); 243235288Sadrian } 244235288Sadrian } 245235288Sadrian 246235288Sadrian bus_generic_probe(dev); 247235288Sadrian bus_enumerate_hinted_children(dev); 248235288Sadrian err = bus_generic_attach(dev); 249235288Sadrian if (err != 0) 250235288Sadrian return (err); 251235288Sadrian 252235288Sadrian callout_init_mtx(&sc->callout_tick, &sc->callout_mtx, 0); 253235288Sadrian rtl8366rb_tick(sc); 254235288Sadrian 255235288Sadrian return (err); 256235288Sadrian} 257235288Sadrian 258235288Sadrianstatic int 259235288Sadrianrtl8366rb_detach(device_t dev) 260235288Sadrian{ 261315330Smizhka struct rtl8366rb_softc *sc; 262235288Sadrian int i; 263235288Sadrian 264315330Smizhka sc = device_get_softc(dev); 265315330Smizhka 266315330Smizhka for (i=0; i < RTL8366_NUM_PHYS; i++) { 267235288Sadrian if (sc->miibus[i]) 268235288Sadrian device_delete_child(dev, sc->miibus[i]); 269235288Sadrian if (sc->ifp[i] != NULL) 270235288Sadrian if_free(sc->ifp[i]); 271235288Sadrian free(sc->ifname[i], M_DEVBUF); 272235288Sadrian } 273235288Sadrian bus_generic_detach(dev); 274235288Sadrian callout_drain(&sc->callout_tick); 275235288Sadrian mtx_destroy(&sc->callout_mtx); 276235288Sadrian mtx_destroy(&sc->sc_mtx); 277235288Sadrian 278235288Sadrian return (0); 279235288Sadrian} 280235288Sadrian 281235288Sadrianstatic void 282235288Sadrianrtl8366rb_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active) 283235288Sadrian{ 284235288Sadrian *media_active = IFM_ETHER; 285235288Sadrian *media_status = IFM_AVALID; 286315330Smizhka if ((portstatus & RTL8366_PLSR_LINK) != 0) 287235288Sadrian *media_status |= IFM_ACTIVE; 288235288Sadrian else { 289235288Sadrian *media_active |= IFM_NONE; 290235288Sadrian return; 291235288Sadrian } 292315330Smizhka switch (portstatus & RTL8366_PLSR_SPEED_MASK) { 293315330Smizhka case RTL8366_PLSR_SPEED_10: 294235288Sadrian *media_active |= IFM_10_T; 295235288Sadrian break; 296315330Smizhka case RTL8366_PLSR_SPEED_100: 297235288Sadrian *media_active |= IFM_100_TX; 298235288Sadrian break; 299315330Smizhka case RTL8366_PLSR_SPEED_1000: 300235288Sadrian *media_active |= IFM_1000_T; 301235288Sadrian break; 302235288Sadrian } 303315330Smizhka if ((portstatus & RTL8366_PLSR_FULLDUPLEX) != 0) 304235288Sadrian *media_active |= IFM_FDX; 305235288Sadrian else 306235288Sadrian *media_active |= IFM_HDX; 307315330Smizhka if ((portstatus & RTL8366_PLSR_TXPAUSE) != 0) 308235288Sadrian *media_active |= IFM_ETH_TXPAUSE; 309315330Smizhka if ((portstatus & RTL8366_PLSR_RXPAUSE) != 0) 310235288Sadrian *media_active |= IFM_ETH_RXPAUSE; 311235288Sadrian} 312235288Sadrian 313235288Sadrianstatic void 314235288Sadrianrtl833rb_miipollstat(struct rtl8366rb_softc *sc) 315235288Sadrian{ 316235288Sadrian int i; 317235288Sadrian struct mii_data *mii; 318235288Sadrian struct mii_softc *miisc; 319235288Sadrian uint16_t value; 320235288Sadrian int portstatus; 321235288Sadrian 322315330Smizhka for (i = 0; i < RTL8366_NUM_PHYS; i++) { 323235288Sadrian mii = device_get_softc(sc->miibus[i]); 324235288Sadrian if ((i % 2) == 0) { 325315330Smizhka if (smi_read(sc->dev, RTL8366_PLSR_BASE + i/2, &value, RTL_NOWAIT) != 0) { 326235288Sadrian DEBUG_INCRVAR(callout_blocked); 327235288Sadrian return; 328235288Sadrian } 329235288Sadrian portstatus = value & 0xff; 330235288Sadrian } else { 331235288Sadrian portstatus = (value >> 8) & 0xff; 332235288Sadrian } 333235288Sadrian rtl8366rb_update_ifmedia(portstatus, &mii->mii_media_status, &mii->mii_media_active); 334235288Sadrian LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 335235288Sadrian if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != miisc->mii_inst) 336235288Sadrian continue; 337235288Sadrian mii_phy_update(miisc, MII_POLLSTAT); 338235288Sadrian } 339235288Sadrian } 340235288Sadrian} 341235288Sadrian 342235288Sadrianstatic void 343235288Sadrianrtl8366rb_tick(void *arg) 344235288Sadrian{ 345315330Smizhka struct rtl8366rb_softc *sc; 346235288Sadrian 347315330Smizhka sc = arg; 348315330Smizhka 349235288Sadrian rtl833rb_miipollstat(sc); 350235288Sadrian callout_reset(&sc->callout_tick, hz, rtl8366rb_tick, sc); 351235288Sadrian} 352235288Sadrian 353235288Sadrianstatic int 354235288Sadriansmi_probe(device_t dev) 355235288Sadrian{ 356315330Smizhka struct rtl8366rb_softc *sc; 357235288Sadrian device_t iicbus, iicha; 358315330Smizhka int err, i, j; 359235288Sadrian uint16_t chipid; 360235288Sadrian char bytes[2]; 361235288Sadrian int xferd; 362235288Sadrian 363315330Smizhka sc = device_get_softc(dev); 364315330Smizhka 365235288Sadrian iicbus = device_get_parent(dev); 366235288Sadrian iicha = device_get_parent(iicbus); 367315330Smizhka 368315330Smizhka for(i = 0; i < 2; ++i) { 369315330Smizhka iicbus_reset(iicbus, IIC_FASTEST, RTL8366_IIC_ADDR, NULL); 370315330Smizhka for (j=3; j--; ) { 371315330Smizhka IICBUS_STOP(iicha); 372315330Smizhka /* 373315330Smizhka * we go directly to the host adapter because iicbus.c 374315330Smizhka * only issues a stop on a bus that was successfully started. 375315330Smizhka */ 376315330Smizhka } 377315330Smizhka err = iicbus_request_bus(iicbus, dev, IIC_WAIT); 378315330Smizhka if (err != 0) 379315330Smizhka goto out; 380315330Smizhka err = iicbus_start(iicbus, RTL8366_IIC_ADDR | RTL_IICBUS_READ, RTL_IICBUS_TIMEOUT); 381315330Smizhka if (err != 0) 382315330Smizhka goto out; 383315330Smizhka if(i == 0) { 384315330Smizhka bytes[0] = RTL8366RB_CIR & 0xff; 385315330Smizhka bytes[1] = (RTL8366RB_CIR >> 8) & 0xff; 386315330Smizhka } else { 387315330Smizhka bytes[0] = RTL8366SR_CIR & 0xff; 388315330Smizhka bytes[1] = (RTL8366SR_CIR >> 8) & 0xff; 389315330Smizhka } 390315330Smizhka err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT); 391315330Smizhka if (err != 0) 392315330Smizhka goto out; 393315330Smizhka err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0); 394315330Smizhka if (err != 0) 395315330Smizhka goto out; 396315330Smizhka chipid = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff); 397315330Smizhka if (i == 0 && chipid == RTL8366RB_CIR_ID8366RB) { 398315330Smizhka DPRINTF(dev, "chip id 0x%04x\n", chipid); 399315330Smizhka sc->chip_type = 0; 400315330Smizhka err = 0; 401315330Smizhka break; 402315330Smizhka } 403315330Smizhka if (i == 1 && chipid == RTL8366SR_CIR_ID8366SR) { 404315330Smizhka DPRINTF(dev, "chip id 0x%04x\n", chipid); 405315330Smizhka sc->chip_type = 1; 406315330Smizhka err = 0; 407315330Smizhka break; 408315330Smizhka } 409315330Smizhka if(i == 0) { 410315330Smizhka iicbus_stop(iicbus); 411315330Smizhka iicbus_release_bus(iicbus, dev); 412315330Smizhka } 413235288Sadrian } 414315330Smizhka if(i == 2) 415235288Sadrian err = ENXIO; 416235288Sadrianout: 417235288Sadrian iicbus_stop(iicbus); 418235288Sadrian iicbus_release_bus(iicbus, dev); 419235288Sadrian return (err == 0 ? 0 : ENXIO); 420235288Sadrian} 421235288Sadrian 422235288Sadrianstatic int 423235288Sadriansmi_acquire(struct rtl8366rb_softc *sc, int sleep) 424235288Sadrian{ 425235288Sadrian int r = 0; 426235288Sadrian if (sleep == RTL_WAITOK) 427235288Sadrian RTL_LOCK(sc); 428235288Sadrian else 429235288Sadrian if (RTL_TRYLOCK(sc) == 0) 430235288Sadrian return (EWOULDBLOCK); 431235288Sadrian if (sc->smi_acquired == RTL_SMI_ACQUIRED) 432235288Sadrian r = EBUSY; 433235288Sadrian else { 434235288Sadrian r = iicbus_request_bus(device_get_parent(sc->dev), sc->dev, \ 435235288Sadrian sleep == RTL_WAITOK ? IIC_WAIT : IIC_DONTWAIT); 436235288Sadrian if (r == 0) 437235288Sadrian sc->smi_acquired = RTL_SMI_ACQUIRED; 438235288Sadrian } 439235288Sadrian RTL_UNLOCK(sc); 440235288Sadrian return (r); 441235288Sadrian} 442235288Sadrian 443235288Sadrianstatic int 444235288Sadriansmi_release(struct rtl8366rb_softc *sc, int sleep) 445235288Sadrian{ 446235288Sadrian if (sleep == RTL_WAITOK) 447235288Sadrian RTL_LOCK(sc); 448235288Sadrian else 449235288Sadrian if (RTL_TRYLOCK(sc) == 0) 450235288Sadrian return (EWOULDBLOCK); 451235288Sadrian RTL_SMI_ACQUIRED_ASSERT(sc); 452235288Sadrian iicbus_release_bus(device_get_parent(sc->dev), sc->dev); 453235288Sadrian sc->smi_acquired = 0; 454235288Sadrian RTL_UNLOCK(sc); 455235288Sadrian return (0); 456235288Sadrian} 457235288Sadrian 458235288Sadrianstatic int 459235288Sadriansmi_select(device_t dev, int op, int sleep) 460235288Sadrian{ 461315330Smizhka struct rtl8366rb_softc *sc; 462235288Sadrian int err, i; 463315330Smizhka device_t iicbus; 464315330Smizhka struct iicbus_ivar *devi; 465315330Smizhka int slave; 466235288Sadrian 467315330Smizhka sc = device_get_softc(dev); 468315330Smizhka 469315330Smizhka iicbus = device_get_parent(dev); 470315330Smizhka devi = IICBUS_IVAR(dev); 471315330Smizhka slave = devi->addr; 472315330Smizhka 473235288Sadrian RTL_SMI_ACQUIRED_ASSERT((struct rtl8366rb_softc *)device_get_softc(dev)); 474315330Smizhka 475315330Smizhka if(sc->chip_type == 1) { // RTL8366SR work around 476315330Smizhka // this is same work around at probe 477315330Smizhka for (int i=3; i--; ) 478315330Smizhka IICBUS_STOP(device_get_parent(device_get_parent(dev))); 479315330Smizhka } 480235288Sadrian /* 481235288Sadrian * The chip does not use clock stretching when it is busy, 482235288Sadrian * instead ignoring the command. Retry a few times. 483235288Sadrian */ 484235288Sadrian for (i = RTL_IICBUS_RETRIES; i--; ) { 485235288Sadrian err = iicbus_start(iicbus, slave | op, RTL_IICBUS_TIMEOUT); 486235288Sadrian if (err != IIC_ENOACK) 487235288Sadrian break; 488235288Sadrian if (sleep == RTL_WAITOK) { 489235288Sadrian DEBUG_INCRVAR(iic_select_retries); 490235288Sadrian pause("smi_select", RTL_IICBUS_RETRY_SLEEP); 491235288Sadrian } else 492235288Sadrian break; 493235288Sadrian } 494235288Sadrian return (err); 495235288Sadrian} 496235288Sadrian 497235288Sadrianstatic int 498235288Sadriansmi_read_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t *data, int sleep) 499235288Sadrian{ 500235288Sadrian int err; 501315330Smizhka device_t iicbus; 502235288Sadrian char bytes[2]; 503235288Sadrian int xferd; 504235288Sadrian 505315330Smizhka iicbus = device_get_parent(sc->dev); 506315330Smizhka 507235288Sadrian RTL_SMI_ACQUIRED_ASSERT(sc); 508235288Sadrian bytes[0] = addr & 0xff; 509235288Sadrian bytes[1] = (addr >> 8) & 0xff; 510235288Sadrian err = smi_select(sc->dev, RTL_IICBUS_READ, sleep); 511235288Sadrian if (err != 0) 512235288Sadrian goto out; 513235288Sadrian err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT); 514235288Sadrian if (err != 0) 515235288Sadrian goto out; 516235288Sadrian err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0); 517235288Sadrian if (err != 0) 518235288Sadrian goto out; 519235288Sadrian *data = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff); 520235288Sadrian 521235288Sadrianout: 522235288Sadrian iicbus_stop(iicbus); 523235288Sadrian return (err); 524235288Sadrian} 525235288Sadrian 526235288Sadrianstatic int 527235288Sadriansmi_write_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t data, int sleep) 528235288Sadrian{ 529235288Sadrian int err; 530315330Smizhka device_t iicbus; 531235288Sadrian char bytes[4]; 532235288Sadrian int xferd; 533235288Sadrian 534315330Smizhka iicbus = device_get_parent(sc->dev); 535315330Smizhka 536235288Sadrian RTL_SMI_ACQUIRED_ASSERT(sc); 537235288Sadrian bytes[0] = addr & 0xff; 538235288Sadrian bytes[1] = (addr >> 8) & 0xff; 539235288Sadrian bytes[2] = data & 0xff; 540235288Sadrian bytes[3] = (data >> 8) & 0xff; 541235288Sadrian 542235288Sadrian err = smi_select(sc->dev, RTL_IICBUS_WRITE, sleep); 543235288Sadrian if (err == 0) 544235288Sadrian err = iicbus_write(iicbus, bytes, 4, &xferd, RTL_IICBUS_TIMEOUT); 545235288Sadrian iicbus_stop(iicbus); 546235288Sadrian 547235288Sadrian return (err); 548235288Sadrian} 549235288Sadrian 550235288Sadrianstatic int 551235288Sadriansmi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep) 552235288Sadrian{ 553315330Smizhka struct rtl8366rb_softc *sc; 554235288Sadrian int err; 555235288Sadrian 556315330Smizhka sc = device_get_softc(dev); 557315330Smizhka 558235288Sadrian err = smi_acquire(sc, sleep); 559235288Sadrian if (err != 0) 560235288Sadrian return (EBUSY); 561235288Sadrian err = smi_read_locked(sc, addr, data, sleep); 562235288Sadrian smi_release(sc, sleep); 563235288Sadrian DEVERR(dev, err, "smi_read()=%d: addr=%04x\n", addr); 564235288Sadrian return (err == 0 ? 0 : EIO); 565235288Sadrian} 566235288Sadrian 567235288Sadrianstatic int 568235288Sadriansmi_write(device_t dev, uint16_t addr, uint16_t data, int sleep) 569235288Sadrian{ 570315330Smizhka struct rtl8366rb_softc *sc; 571235288Sadrian int err; 572235288Sadrian 573315330Smizhka sc = device_get_softc(dev); 574315330Smizhka 575235288Sadrian err = smi_acquire(sc, sleep); 576235288Sadrian if (err != 0) 577235288Sadrian return (EBUSY); 578235288Sadrian err = smi_write_locked(sc, addr, data, sleep); 579235288Sadrian smi_release(sc, sleep); 580235288Sadrian DEVERR(dev, err, "smi_write()=%d: addr=%04x\n", addr); 581235288Sadrian return (err == 0 ? 0 : EIO); 582235288Sadrian} 583235288Sadrian 584235288Sadrianstatic int 585235288Sadriansmi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep) 586235288Sadrian{ 587315330Smizhka struct rtl8366rb_softc *sc; 588235288Sadrian int err; 589235288Sadrian uint16_t oldv, newv; 590235288Sadrian 591315330Smizhka sc = device_get_softc(dev); 592315330Smizhka 593235288Sadrian err = smi_acquire(sc, sleep); 594235288Sadrian if (err != 0) 595235288Sadrian return (EBUSY); 596235288Sadrian if (err == 0) { 597235288Sadrian err = smi_read_locked(sc, addr, &oldv, sleep); 598235288Sadrian if (err == 0) { 599235288Sadrian newv = oldv & ~mask; 600235288Sadrian newv |= data & mask; 601235288Sadrian if (newv != oldv) 602235288Sadrian err = smi_write_locked(sc, addr, newv, sleep); 603235288Sadrian } 604235288Sadrian } 605235288Sadrian smi_release(sc, sleep); 606235288Sadrian DEVERR(dev, err, "smi_rmw()=%d: addr=%04x\n", addr); 607235288Sadrian return (err == 0 ? 0 : EIO); 608235288Sadrian} 609235288Sadrian 610235288Sadrianstatic etherswitch_info_t * 611235288Sadrianrtl_getinfo(device_t dev) 612235288Sadrian{ 613315330Smizhka struct rtl8366rb_softc *sc; 614315330Smizhka 615315330Smizhka sc = device_get_softc(dev); 616315330Smizhka 617315330Smizhka return (&sc->info); 618235288Sadrian} 619235288Sadrian 620235288Sadrianstatic int 621235288Sadrianrtl_readreg(device_t dev, int reg) 622235288Sadrian{ 623315330Smizhka uint16_t data; 624235288Sadrian 625315330Smizhka data = 0; 626315330Smizhka 627235288Sadrian smi_read(dev, reg, &data, RTL_WAITOK); 628235288Sadrian return (data); 629235288Sadrian} 630235288Sadrian 631235288Sadrianstatic int 632235288Sadrianrtl_writereg(device_t dev, int reg, int value) 633235288Sadrian{ 634235288Sadrian return (smi_write(dev, reg, value, RTL_WAITOK)); 635235288Sadrian} 636235288Sadrian 637235288Sadrianstatic int 638235288Sadrianrtl_getport(device_t dev, etherswitch_port_t *p) 639235288Sadrian{ 640235288Sadrian struct rtl8366rb_softc *sc; 641235288Sadrian struct ifmedia *ifm; 642235288Sadrian struct mii_data *mii; 643315330Smizhka struct ifmediareq *ifmr; 644235288Sadrian uint16_t v; 645249752Sadrian int err, vlangroup; 646235288Sadrian 647315330Smizhka sc = device_get_softc(dev); 648315330Smizhka 649315330Smizhka ifmr = &p->es_ifmr; 650315330Smizhka 651315330Smizhka if (p->es_port < 0 || p->es_port >= RTL8366_NUM_PORTS) 652235288Sadrian return (ENXIO); 653315330Smizhka vlangroup = RTL8366_PVCR_GET(p->es_port, 654315330Smizhka rtl_readreg(dev, RTL8366_PVCR_REG(p->es_port))); 655268233Sloos p->es_pvid = sc->vid[vlangroup] & ETHERSWITCH_VID_MASK; 656235288Sadrian 657315330Smizhka if (p->es_port < RTL8366_NUM_PHYS) { 658235288Sadrian mii = device_get_softc(sc->miibus[p->es_port]); 659235288Sadrian ifm = &mii->mii_media; 660235288Sadrian err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCGIFMEDIA); 661235288Sadrian if (err) 662235288Sadrian return (err); 663235288Sadrian } else { 664235288Sadrian /* fill in fixed values for CPU port */ 665268093Sloos p->es_flags |= ETHERSWITCH_PORT_CPU; 666315330Smizhka smi_read(dev, RTL8366_PLSR_BASE + (RTL8366_NUM_PHYS)/2, &v, RTL_WAITOK); 667315330Smizhka v = v >> (8 * ((RTL8366_NUM_PHYS) % 2)); 668235288Sadrian rtl8366rb_update_ifmedia(v, &ifmr->ifm_status, &ifmr->ifm_active); 669235288Sadrian ifmr->ifm_current = ifmr->ifm_active; 670235288Sadrian ifmr->ifm_mask = 0; 671235288Sadrian ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 672268294Sloos /* Return our static media list. */ 673268294Sloos if (ifmr->ifm_count > 0) { 674268294Sloos ifmr->ifm_count = 1; 675268294Sloos ifmr->ifm_ulist[0] = IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 676268294Sloos IFM_FDX, 0); 677268294Sloos } else 678268294Sloos ifmr->ifm_count = 0; 679235288Sadrian } 680235288Sadrian return (0); 681235288Sadrian} 682235288Sadrian 683235288Sadrianstatic int 684235288Sadrianrtl_setport(device_t dev, etherswitch_port_t *p) 685235288Sadrian{ 686315330Smizhka struct rtl8366rb_softc *sc; 687249752Sadrian int i, err, vlangroup; 688235288Sadrian struct ifmedia *ifm; 689235288Sadrian struct mii_data *mii; 690235288Sadrian 691315330Smizhka sc = device_get_softc(dev); 692315330Smizhka 693315330Smizhka if (p->es_port < 0 || p->es_port >= RTL8366_NUM_PORTS) 694235288Sadrian return (ENXIO); 695249752Sadrian vlangroup = -1; 696315330Smizhka for (i = 0; i < RTL8366_NUM_VLANS; i++) { 697268233Sloos if ((sc->vid[i] & ETHERSWITCH_VID_MASK) == p->es_pvid) { 698249752Sadrian vlangroup = i; 699249752Sadrian break; 700249752Sadrian } 701249752Sadrian } 702249752Sadrian if (vlangroup == -1) 703249752Sadrian return (ENXIO); 704315330Smizhka err = smi_rmw(dev, RTL8366_PVCR_REG(p->es_port), 705315330Smizhka RTL8366_PVCR_VAL(p->es_port, RTL8366_PVCR_PORT_MASK), 706315330Smizhka RTL8366_PVCR_VAL(p->es_port, vlangroup), RTL_WAITOK); 707235288Sadrian if (err) 708235288Sadrian return (err); 709315330Smizhka if (p->es_port == RTL8366_CPU_PORT) 710268093Sloos return (0); 711235288Sadrian mii = device_get_softc(sc->miibus[p->es_port]); 712235288Sadrian ifm = &mii->mii_media; 713235288Sadrian err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCSIFMEDIA); 714235288Sadrian return (err); 715235288Sadrian} 716235288Sadrian 717235288Sadrianstatic int 718235288Sadrianrtl_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 719235288Sadrian{ 720268233Sloos struct rtl8366rb_softc *sc; 721235288Sadrian uint16_t vmcr[3]; 722235288Sadrian int i; 723235288Sadrian 724315330Smizhka sc = device_get_softc(dev); 725315330Smizhka 726315330Smizhka for (i=0; i<RTL8366_VMCR_MULT; i++) 727315330Smizhka vmcr[i] = rtl_readreg(dev, RTL8366_VMCR(i, vg->es_vlangroup)); 728235288Sadrian 729268233Sloos vg->es_vid = sc->vid[vg->es_vlangroup]; 730315330Smizhka vg->es_member_ports = RTL8366_VMCR_MEMBER(vmcr); 731315330Smizhka vg->es_untagged_ports = RTL8366_VMCR_UNTAG(vmcr); 732315330Smizhka vg->es_fid = RTL8366_VMCR_FID(vmcr); 733235288Sadrian return (0); 734235288Sadrian} 735235288Sadrian 736235288Sadrianstatic int 737235288Sadrianrtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 738235288Sadrian{ 739249752Sadrian struct rtl8366rb_softc *sc; 740315330Smizhka int g; 741235288Sadrian 742249752Sadrian sc = device_get_softc(dev); 743315330Smizhka 744315330Smizhka g = vg->es_vlangroup; 745315330Smizhka 746249752Sadrian sc->vid[g] = vg->es_vid; 747268233Sloos /* VLAN group disabled ? */ 748268233Sloos if (vg->es_member_ports == 0 && vg->es_untagged_ports == 0 && vg->es_vid == 0) 749268233Sloos return (0); 750268233Sloos sc->vid[g] |= ETHERSWITCH_VID_VALID; 751315330Smizhka rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_DOT1Q_REG, g), 752315330Smizhka (vg->es_vid << RTL8366_VMCR_DOT1Q_VID_SHIFT) & RTL8366_VMCR_DOT1Q_VID_MASK); 753315330Smizhka if(sc->chip_type == 0) { 754315330Smizhka rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, g), 755315330Smizhka ((vg->es_member_ports << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) | 756315330Smizhka ((vg->es_untagged_ports << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK)); 757315330Smizhka rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_FID_REG, g), 758315330Smizhka vg->es_fid); 759315330Smizhka } else { 760315330Smizhka rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, g), 761315330Smizhka ((vg->es_member_ports << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) | 762315330Smizhka ((vg->es_untagged_ports << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK) | 763315330Smizhka ((vg->es_fid << RTL8366_VMCR_FID_FID_SHIFT) & RTL8366_VMCR_FID_FID_MASK)); 764315330Smizhka } 765235288Sadrian return (0); 766235288Sadrian} 767235288Sadrian 768235288Sadrianstatic int 769268233Sloosrtl_getconf(device_t dev, etherswitch_conf_t *conf) 770268233Sloos{ 771268233Sloos 772268233Sloos /* Return the VLAN mode. */ 773268233Sloos conf->cmd = ETHERSWITCH_CONF_VLAN_MODE; 774268233Sloos conf->vlan_mode = ETHERSWITCH_VLAN_DOT1Q; 775268233Sloos 776268233Sloos return (0); 777268233Sloos} 778268233Sloos 779268233Sloosstatic int 780235288Sadrianrtl_readphy(device_t dev, int phy, int reg) 781235288Sadrian{ 782315330Smizhka struct rtl8366rb_softc *sc; 783315330Smizhka uint16_t data; 784235288Sadrian int err, i, sleep; 785235288Sadrian 786315330Smizhka sc = device_get_softc(dev); 787315330Smizhka 788315330Smizhka data = 0; 789315330Smizhka 790315330Smizhka if (phy < 0 || phy >= RTL8366_NUM_PHYS) 791235288Sadrian return (ENXIO); 792315330Smizhka if (reg < 0 || reg >= RTL8366_NUM_PHY_REG) 793235288Sadrian return (ENXIO); 794235288Sadrian sleep = RTL_WAITOK; 795235288Sadrian err = smi_acquire(sc, sleep); 796235288Sadrian if (err != 0) 797235288Sadrian return (EBUSY); 798235288Sadrian for (i = RTL_IICBUS_RETRIES; i--; ) { 799315330Smizhka err = smi_write_locked(sc, RTL8366_PACR, RTL8366_PACR_READ, sleep); 800235288Sadrian if (err == 0) 801315330Smizhka err = smi_write_locked(sc, RTL8366_PHYREG(phy, 0, reg), 0, sleep); 802235288Sadrian if (err == 0) { 803315330Smizhka err = smi_read_locked(sc, RTL8366_PADR, &data, sleep); 804235288Sadrian break; 805235288Sadrian } 806235288Sadrian DEBUG_INCRVAR(phy_access_retries); 807235288Sadrian DPRINTF(dev, "rtl_readphy(): chip not responsive, retrying %d more times\n", i); 808235288Sadrian pause("rtl_readphy", RTL_IICBUS_RETRY_SLEEP); 809235288Sadrian } 810235288Sadrian smi_release(sc, sleep); 811235288Sadrian DEVERR(dev, err, "rtl_readphy()=%d: phy=%d.%02x\n", phy, reg); 812235288Sadrian return (data); 813235288Sadrian} 814235288Sadrian 815235288Sadrianstatic int 816235288Sadrianrtl_writephy(device_t dev, int phy, int reg, int data) 817235288Sadrian{ 818315330Smizhka struct rtl8366rb_softc *sc; 819235288Sadrian int err, i, sleep; 820235288Sadrian 821315330Smizhka sc = device_get_softc(dev); 822315330Smizhka 823315330Smizhka if (phy < 0 || phy >= RTL8366_NUM_PHYS) 824235288Sadrian return (ENXIO); 825315330Smizhka if (reg < 0 || reg >= RTL8366_NUM_PHY_REG) 826235288Sadrian return (ENXIO); 827235288Sadrian sleep = RTL_WAITOK; 828235288Sadrian err = smi_acquire(sc, sleep); 829235288Sadrian if (err != 0) 830235288Sadrian return (EBUSY); 831235288Sadrian for (i = RTL_IICBUS_RETRIES; i--; ) { 832315330Smizhka err = smi_write_locked(sc, RTL8366_PACR, RTL8366_PACR_WRITE, sleep); 833235288Sadrian if (err == 0) 834315330Smizhka err = smi_write_locked(sc, RTL8366_PHYREG(phy, 0, reg), data, sleep); 835235288Sadrian if (err == 0) { 836235288Sadrian break; 837235288Sadrian } 838235288Sadrian DEBUG_INCRVAR(phy_access_retries); 839235288Sadrian DPRINTF(dev, "rtl_writephy(): chip not responsive, retrying %d more tiems\n", i); 840235288Sadrian pause("rtl_writephy", RTL_IICBUS_RETRY_SLEEP); 841235288Sadrian } 842235288Sadrian smi_release(sc, sleep); 843235288Sadrian DEVERR(dev, err, "rtl_writephy()=%d: phy=%d.%02x\n", phy, reg); 844235288Sadrian return (err == 0 ? 0 : EIO); 845235288Sadrian} 846235288Sadrian 847235288Sadrianstatic int 848235288Sadrianrtl8366rb_ifmedia_upd(struct ifnet *ifp) 849235288Sadrian{ 850315330Smizhka struct rtl8366rb_softc *sc; 851315330Smizhka struct mii_data *mii; 852235288Sadrian 853315330Smizhka sc = ifp->if_softc; 854315330Smizhka mii = device_get_softc(sc->miibus[ifp->if_dunit]); 855315330Smizhka 856235288Sadrian mii_mediachg(mii); 857235288Sadrian return (0); 858235288Sadrian} 859235288Sadrian 860235288Sadrianstatic void 861235288Sadrianrtl8366rb_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 862235288Sadrian{ 863315330Smizhka struct rtl8366rb_softc *sc; 864315330Smizhka struct mii_data *mii; 865235288Sadrian 866315330Smizhka sc = ifp->if_softc; 867315330Smizhka mii = device_get_softc(sc->miibus[ifp->if_dunit]); 868315330Smizhka 869235288Sadrian mii_pollstat(mii); 870235288Sadrian ifmr->ifm_active = mii->mii_media_active; 871235288Sadrian ifmr->ifm_status = mii->mii_media_status; 872235288Sadrian} 873235288Sadrian 874235288Sadrian 875235288Sadrianstatic device_method_t rtl8366rb_methods[] = { 876235288Sadrian /* Device interface */ 877235288Sadrian DEVMETHOD(device_identify, rtl8366rb_identify), 878235288Sadrian DEVMETHOD(device_probe, rtl8366rb_probe), 879235288Sadrian DEVMETHOD(device_attach, rtl8366rb_attach), 880235288Sadrian DEVMETHOD(device_detach, rtl8366rb_detach), 881235288Sadrian 882235288Sadrian /* bus interface */ 883235288Sadrian DEVMETHOD(bus_add_child, device_add_child_ordered), 884235288Sadrian 885235288Sadrian /* MII interface */ 886235288Sadrian DEVMETHOD(miibus_readreg, rtl_readphy), 887235288Sadrian DEVMETHOD(miibus_writereg, rtl_writephy), 888235288Sadrian 889235288Sadrian /* etherswitch interface */ 890268233Sloos DEVMETHOD(etherswitch_getconf, rtl_getconf), 891235288Sadrian DEVMETHOD(etherswitch_getinfo, rtl_getinfo), 892235288Sadrian DEVMETHOD(etherswitch_readreg, rtl_readreg), 893235288Sadrian DEVMETHOD(etherswitch_writereg, rtl_writereg), 894235288Sadrian DEVMETHOD(etherswitch_readphyreg, rtl_readphy), 895235288Sadrian DEVMETHOD(etherswitch_writephyreg, rtl_writephy), 896235288Sadrian DEVMETHOD(etherswitch_getport, rtl_getport), 897235288Sadrian DEVMETHOD(etherswitch_setport, rtl_setport), 898235288Sadrian DEVMETHOD(etherswitch_getvgroup, rtl_getvgroup), 899235288Sadrian DEVMETHOD(etherswitch_setvgroup, rtl_setvgroup), 900235288Sadrian 901235288Sadrian DEVMETHOD_END 902235288Sadrian}; 903235288Sadrian 904235288SadrianDEFINE_CLASS_0(rtl8366rb, rtl8366rb_driver, rtl8366rb_methods, 905235288Sadrian sizeof(struct rtl8366rb_softc)); 906235288Sadrianstatic devclass_t rtl8366rb_devclass; 907235288Sadrian 908235288SadrianDRIVER_MODULE(rtl8366rb, iicbus, rtl8366rb_driver, rtl8366rb_devclass, 0, 0); 909235288SadrianDRIVER_MODULE(miibus, rtl8366rb, miibus_driver, miibus_devclass, 0, 0); 910235288SadrianDRIVER_MODULE(etherswitch, rtl8366rb, etherswitch_driver, etherswitch_devclass, 0, 0); 911235288SadrianMODULE_VERSION(rtl8366rb, 1); 912235288SadrianMODULE_DEPEND(rtl8366rb, iicbus, 1, 1, 1); /* XXX which versions? */ 913235288SadrianMODULE_DEPEND(rtl8366rb, miibus, 1, 1, 1); /* XXX which versions? */ 914235288SadrianMODULE_DEPEND(rtl8366rb, etherswitch, 1, 1, 1); /* XXX which versions? */ 915