14574da7fSAdrian Chadd /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 44574da7fSAdrian Chadd * Copyright (c) 2011-2012 Stefan Bethke. 54574da7fSAdrian Chadd * All rights reserved. 64574da7fSAdrian Chadd * 74574da7fSAdrian Chadd * Redistribution and use in source and binary forms, with or without 84574da7fSAdrian Chadd * modification, are permitted provided that the following conditions 94574da7fSAdrian Chadd * are met: 104574da7fSAdrian Chadd * 1. Redistributions of source code must retain the above copyright 114574da7fSAdrian Chadd * notice, this list of conditions and the following disclaimer. 124574da7fSAdrian Chadd * 2. Redistributions in binary form must reproduce the above copyright 134574da7fSAdrian Chadd * notice, this list of conditions and the following disclaimer in the 144574da7fSAdrian Chadd * documentation and/or other materials provided with the distribution. 154574da7fSAdrian Chadd * 164574da7fSAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 174574da7fSAdrian Chadd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 184574da7fSAdrian Chadd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 194574da7fSAdrian Chadd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 204574da7fSAdrian Chadd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 214574da7fSAdrian Chadd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 224574da7fSAdrian Chadd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 234574da7fSAdrian Chadd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 244574da7fSAdrian Chadd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 254574da7fSAdrian Chadd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 264574da7fSAdrian Chadd * SUCH DAMAGE. 274574da7fSAdrian Chadd */ 284574da7fSAdrian Chadd 294574da7fSAdrian Chadd #include <sys/param.h> 304574da7fSAdrian Chadd #include <sys/bus.h> 314574da7fSAdrian Chadd #include <sys/kernel.h> 32104dc214SGleb Smirnoff #include <sys/malloc.h> 334574da7fSAdrian Chadd #include <sys/module.h> 344574da7fSAdrian Chadd #include <sys/socket.h> 354574da7fSAdrian Chadd #include <sys/sockio.h> 364574da7fSAdrian Chadd #include <sys/systm.h> 374574da7fSAdrian Chadd 384574da7fSAdrian Chadd #include <net/if.h> 394574da7fSAdrian Chadd #include <net/if_media.h> 404574da7fSAdrian Chadd 414574da7fSAdrian Chadd #include <dev/etherswitch/miiproxy.h> 424574da7fSAdrian Chadd #include <dev/mii/mii.h> 434574da7fSAdrian Chadd #include <dev/mii/miivar.h> 444574da7fSAdrian Chadd 454574da7fSAdrian Chadd #include "mdio_if.h" 464574da7fSAdrian Chadd #include "miibus_if.h" 474574da7fSAdrian Chadd 484574da7fSAdrian Chadd 494574da7fSAdrian Chadd MALLOC_DECLARE(M_MIIPROXY); 504574da7fSAdrian Chadd MALLOC_DEFINE(M_MIIPROXY, "miiproxy", "miiproxy data structures"); 514574da7fSAdrian Chadd 524574da7fSAdrian Chadd driver_t miiproxy_driver; 534574da7fSAdrian Chadd driver_t mdioproxy_driver; 544574da7fSAdrian Chadd 554574da7fSAdrian Chadd struct miiproxy_softc { 564574da7fSAdrian Chadd device_t parent; 574574da7fSAdrian Chadd device_t proxy; 584574da7fSAdrian Chadd device_t mdio; 594574da7fSAdrian Chadd }; 604574da7fSAdrian Chadd 614574da7fSAdrian Chadd struct mdioproxy_softc { 624574da7fSAdrian Chadd }; 634574da7fSAdrian Chadd 644574da7fSAdrian Chadd /* 6552f24367SRui Paulo * The rendezvous data structures and functions allow two device endpoints to 664574da7fSAdrian Chadd * match up, so that the proxy endpoint can be associated with a target 674574da7fSAdrian Chadd * endpoint. The proxy has to know the device name of the target that it 6852f24367SRui Paulo * wants to associate with, for example through a hint. The rendezvous code 694574da7fSAdrian Chadd * makes no assumptions about the devices that want to meet. 704574da7fSAdrian Chadd */ 7152f24367SRui Paulo struct rendezvous_entry; 724574da7fSAdrian Chadd 7352f24367SRui Paulo enum rendezvous_op { 7452f24367SRui Paulo RENDEZVOUS_ATTACH, 7552f24367SRui Paulo RENDEZVOUS_DETACH 764574da7fSAdrian Chadd }; 774574da7fSAdrian Chadd 7852f24367SRui Paulo typedef int (*rendezvous_callback_t)(enum rendezvous_op, 7952f24367SRui Paulo struct rendezvous_entry *); 804574da7fSAdrian Chadd 8152f24367SRui Paulo static SLIST_HEAD(rendezvoushead, rendezvous_entry) rendezvoushead = 8252f24367SRui Paulo SLIST_HEAD_INITIALIZER(rendezvoushead); 834574da7fSAdrian Chadd 8452f24367SRui Paulo struct rendezvous_endpoint { 854574da7fSAdrian Chadd device_t device; 864574da7fSAdrian Chadd const char *name; 8752f24367SRui Paulo rendezvous_callback_t callback; 884574da7fSAdrian Chadd }; 894574da7fSAdrian Chadd 9052f24367SRui Paulo struct rendezvous_entry { 9152f24367SRui Paulo SLIST_ENTRY(rendezvous_entry) entries; 9252f24367SRui Paulo struct rendezvous_endpoint proxy; 9352f24367SRui Paulo struct rendezvous_endpoint target; 944574da7fSAdrian Chadd }; 954574da7fSAdrian Chadd 964574da7fSAdrian Chadd /* 974574da7fSAdrian Chadd * Call the callback routines for both the proxy and the target. If either 984574da7fSAdrian Chadd * returns an error, undo the attachment. 994574da7fSAdrian Chadd */ 1004574da7fSAdrian Chadd static int 10152f24367SRui Paulo rendezvous_attach(struct rendezvous_entry *e, struct rendezvous_endpoint *ep) 1024574da7fSAdrian Chadd { 1034574da7fSAdrian Chadd int error; 1044574da7fSAdrian Chadd 10552f24367SRui Paulo error = e->proxy.callback(RENDEZVOUS_ATTACH, e); 1064574da7fSAdrian Chadd if (error == 0) { 10752f24367SRui Paulo error = e->target.callback(RENDEZVOUS_ATTACH, e); 1084574da7fSAdrian Chadd if (error != 0) { 10952f24367SRui Paulo e->proxy.callback(RENDEZVOUS_DETACH, e); 1104574da7fSAdrian Chadd ep->device = NULL; 1114574da7fSAdrian Chadd ep->callback = NULL; 1124574da7fSAdrian Chadd } 1134574da7fSAdrian Chadd } 1144574da7fSAdrian Chadd return (error); 1154574da7fSAdrian Chadd } 1164574da7fSAdrian Chadd 1174574da7fSAdrian Chadd /* 11852f24367SRui Paulo * Create an entry for the proxy in the rendezvous list. The name parameter 1194574da7fSAdrian Chadd * indicates the name of the device that is the target endpoint for this 12052f24367SRui Paulo * rendezvous. The callback will be invoked as soon as the target is 1214574da7fSAdrian Chadd * registered: either immediately if the target registered itself earlier, 1224574da7fSAdrian Chadd * or once the target registers. Returns ENXIO if the target has not yet 1234574da7fSAdrian Chadd * registered. 1244574da7fSAdrian Chadd */ 1254574da7fSAdrian Chadd static int 12652f24367SRui Paulo rendezvous_register_proxy(device_t dev, const char *name, 12752f24367SRui Paulo rendezvous_callback_t callback) 1284574da7fSAdrian Chadd { 12952f24367SRui Paulo struct rendezvous_entry *e; 1304574da7fSAdrian Chadd 1314574da7fSAdrian Chadd KASSERT(callback != NULL, ("callback must be set")); 13252f24367SRui Paulo SLIST_FOREACH(e, &rendezvoushead, entries) { 1334574da7fSAdrian Chadd if (strcmp(name, e->target.name) == 0) { 1344574da7fSAdrian Chadd /* the target is already attached */ 1354574da7fSAdrian Chadd e->proxy.name = device_get_nameunit(dev); 1364574da7fSAdrian Chadd e->proxy.device = dev; 1374574da7fSAdrian Chadd e->proxy.callback = callback; 13852f24367SRui Paulo return (rendezvous_attach(e, &e->proxy)); 1394574da7fSAdrian Chadd } 1404574da7fSAdrian Chadd } 1414574da7fSAdrian Chadd e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO); 1424574da7fSAdrian Chadd e->proxy.name = device_get_nameunit(dev); 1434574da7fSAdrian Chadd e->proxy.device = dev; 1444574da7fSAdrian Chadd e->proxy.callback = callback; 1454574da7fSAdrian Chadd e->target.name = name; 14652f24367SRui Paulo SLIST_INSERT_HEAD(&rendezvoushead, e, entries); 1474574da7fSAdrian Chadd return (ENXIO); 1484574da7fSAdrian Chadd } 1494574da7fSAdrian Chadd 1504574da7fSAdrian Chadd /* 15152f24367SRui Paulo * Create an entry in the rendezvous list for the target. 1524574da7fSAdrian Chadd * Returns ENXIO if the proxy has not yet registered. 1534574da7fSAdrian Chadd */ 1544574da7fSAdrian Chadd static int 15552f24367SRui Paulo rendezvous_register_target(device_t dev, rendezvous_callback_t callback) 1564574da7fSAdrian Chadd { 15752f24367SRui Paulo struct rendezvous_entry *e; 1584574da7fSAdrian Chadd const char *name; 1594574da7fSAdrian Chadd 1604574da7fSAdrian Chadd KASSERT(callback != NULL, ("callback must be set")); 1614574da7fSAdrian Chadd name = device_get_nameunit(dev); 16252f24367SRui Paulo SLIST_FOREACH(e, &rendezvoushead, entries) { 1634574da7fSAdrian Chadd if (strcmp(name, e->target.name) == 0) { 1644574da7fSAdrian Chadd e->target.device = dev; 1654574da7fSAdrian Chadd e->target.callback = callback; 16652f24367SRui Paulo return (rendezvous_attach(e, &e->target)); 1674574da7fSAdrian Chadd } 1684574da7fSAdrian Chadd } 1694574da7fSAdrian Chadd e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO); 1704574da7fSAdrian Chadd e->target.name = name; 1714574da7fSAdrian Chadd e->target.device = dev; 1724574da7fSAdrian Chadd e->target.callback = callback; 17352f24367SRui Paulo SLIST_INSERT_HEAD(&rendezvoushead, e, entries); 1744574da7fSAdrian Chadd return (ENXIO); 1754574da7fSAdrian Chadd } 1764574da7fSAdrian Chadd 1774574da7fSAdrian Chadd /* 1784574da7fSAdrian Chadd * Remove the registration for the proxy. 1794574da7fSAdrian Chadd */ 1804574da7fSAdrian Chadd static int 18152f24367SRui Paulo rendezvous_unregister_proxy(device_t dev) 1824574da7fSAdrian Chadd { 18352f24367SRui Paulo struct rendezvous_entry *e; 1844574da7fSAdrian Chadd int error = 0; 1854574da7fSAdrian Chadd 18652f24367SRui Paulo SLIST_FOREACH(e, &rendezvoushead, entries) { 1874574da7fSAdrian Chadd if (e->proxy.device == dev) { 1884574da7fSAdrian Chadd if (e->target.device == NULL) { 18952f24367SRui Paulo SLIST_REMOVE(&rendezvoushead, e, rendezvous_entry, entries); 1904574da7fSAdrian Chadd free(e, M_MIIPROXY); 1914574da7fSAdrian Chadd return (0); 1924574da7fSAdrian Chadd } else { 19352f24367SRui Paulo e->proxy.callback(RENDEZVOUS_DETACH, e); 19452f24367SRui Paulo e->target.callback(RENDEZVOUS_DETACH, e); 1954574da7fSAdrian Chadd } 1964574da7fSAdrian Chadd e->proxy.device = NULL; 1974574da7fSAdrian Chadd e->proxy.callback = NULL; 1984574da7fSAdrian Chadd return (error); 1994574da7fSAdrian Chadd } 2004574da7fSAdrian Chadd } 2014574da7fSAdrian Chadd return (ENOENT); 2024574da7fSAdrian Chadd } 2034574da7fSAdrian Chadd 2044574da7fSAdrian Chadd /* 2054574da7fSAdrian Chadd * Remove the registration for the target. 2064574da7fSAdrian Chadd */ 2074574da7fSAdrian Chadd static int 20852f24367SRui Paulo rendezvous_unregister_target(device_t dev) 2094574da7fSAdrian Chadd { 21052f24367SRui Paulo struct rendezvous_entry *e; 2114574da7fSAdrian Chadd int error = 0; 2124574da7fSAdrian Chadd 21352f24367SRui Paulo SLIST_FOREACH(e, &rendezvoushead, entries) { 2144574da7fSAdrian Chadd if (e->target.device == dev) { 2154574da7fSAdrian Chadd if (e->proxy.device == NULL) { 21652f24367SRui Paulo SLIST_REMOVE(&rendezvoushead, e, rendezvous_entry, entries); 2174574da7fSAdrian Chadd free(e, M_MIIPROXY); 2184574da7fSAdrian Chadd return (0); 2194574da7fSAdrian Chadd } else { 22052f24367SRui Paulo e->proxy.callback(RENDEZVOUS_DETACH, e); 22152f24367SRui Paulo e->target.callback(RENDEZVOUS_DETACH, e); 2224574da7fSAdrian Chadd } 2234574da7fSAdrian Chadd e->target.device = NULL; 2244574da7fSAdrian Chadd e->target.callback = NULL; 2254574da7fSAdrian Chadd return (error); 2264574da7fSAdrian Chadd } 2274574da7fSAdrian Chadd } 2284574da7fSAdrian Chadd return (ENOENT); 2294574da7fSAdrian Chadd } 2304574da7fSAdrian Chadd 2314574da7fSAdrian Chadd /* 2324574da7fSAdrian Chadd * Functions of the proxy that is interposed between the ethernet interface 2334574da7fSAdrian Chadd * driver and the miibus device. 2344574da7fSAdrian Chadd */ 2354574da7fSAdrian Chadd 2364574da7fSAdrian Chadd static int 23752f24367SRui Paulo miiproxy_rendezvous_callback(enum rendezvous_op op, struct rendezvous_entry *rendezvous) 2384574da7fSAdrian Chadd { 23952f24367SRui Paulo struct miiproxy_softc *sc = device_get_softc(rendezvous->proxy.device); 2404574da7fSAdrian Chadd 2414574da7fSAdrian Chadd switch (op) { 24252f24367SRui Paulo case RENDEZVOUS_ATTACH: 24352f24367SRui Paulo sc->mdio = device_get_parent(rendezvous->target.device); 2444574da7fSAdrian Chadd break; 24552f24367SRui Paulo case RENDEZVOUS_DETACH: 2464574da7fSAdrian Chadd sc->mdio = NULL; 2474574da7fSAdrian Chadd break; 2484574da7fSAdrian Chadd } 2494574da7fSAdrian Chadd return (0); 2504574da7fSAdrian Chadd } 2514574da7fSAdrian Chadd 2524574da7fSAdrian Chadd static int 2534574da7fSAdrian Chadd miiproxy_probe(device_t dev) 2544574da7fSAdrian Chadd { 2554574da7fSAdrian Chadd device_set_desc(dev, "MII/MDIO proxy, MII side"); 2564574da7fSAdrian Chadd 2574574da7fSAdrian Chadd return (BUS_PROBE_SPECIFIC); 2584574da7fSAdrian Chadd } 2594574da7fSAdrian Chadd 2604574da7fSAdrian Chadd static int 2614574da7fSAdrian Chadd miiproxy_attach(device_t dev) 2624574da7fSAdrian Chadd { 2634574da7fSAdrian Chadd 2644574da7fSAdrian Chadd /* 2654574da7fSAdrian Chadd * The ethernet interface needs to call mii_attach_proxy() to pass 26652f24367SRui Paulo * the relevant parameters for rendezvous with the MDIO target. 2674574da7fSAdrian Chadd */ 268*18250ec6SJohn Baldwin bus_attach_children(dev); 269*18250ec6SJohn Baldwin return (0); 2704574da7fSAdrian Chadd } 2714574da7fSAdrian Chadd 2724574da7fSAdrian Chadd static int 2734574da7fSAdrian Chadd miiproxy_detach(device_t dev) 2744574da7fSAdrian Chadd { 2754574da7fSAdrian Chadd 27652f24367SRui Paulo rendezvous_unregister_proxy(dev); 2774574da7fSAdrian Chadd bus_generic_detach(dev); 2784574da7fSAdrian Chadd return (0); 2794574da7fSAdrian Chadd } 2804574da7fSAdrian Chadd 2814574da7fSAdrian Chadd static int 2824574da7fSAdrian Chadd miiproxy_readreg(device_t dev, int phy, int reg) 2834574da7fSAdrian Chadd { 2844574da7fSAdrian Chadd struct miiproxy_softc *sc = device_get_softc(dev); 2854574da7fSAdrian Chadd 2864574da7fSAdrian Chadd if (sc->mdio != NULL) 2874574da7fSAdrian Chadd return (MDIO_READREG(sc->mdio, phy, reg)); 2884574da7fSAdrian Chadd return (-1); 2894574da7fSAdrian Chadd } 2904574da7fSAdrian Chadd 2914574da7fSAdrian Chadd static int 2924574da7fSAdrian Chadd miiproxy_writereg(device_t dev, int phy, int reg, int val) 2934574da7fSAdrian Chadd { 2944574da7fSAdrian Chadd struct miiproxy_softc *sc = device_get_softc(dev); 2954574da7fSAdrian Chadd 2964574da7fSAdrian Chadd if (sc->mdio != NULL) 2974574da7fSAdrian Chadd return (MDIO_WRITEREG(sc->mdio, phy, reg, val)); 2984574da7fSAdrian Chadd return (-1); 2994574da7fSAdrian Chadd } 3004574da7fSAdrian Chadd 3014574da7fSAdrian Chadd static void 3024574da7fSAdrian Chadd miiproxy_statchg(device_t dev) 3034574da7fSAdrian Chadd { 3044574da7fSAdrian Chadd 3054574da7fSAdrian Chadd MIIBUS_STATCHG(device_get_parent(dev)); 3064574da7fSAdrian Chadd } 3074574da7fSAdrian Chadd 3084574da7fSAdrian Chadd static void 3094574da7fSAdrian Chadd miiproxy_linkchg(device_t dev) 3104574da7fSAdrian Chadd { 3114574da7fSAdrian Chadd 3124574da7fSAdrian Chadd MIIBUS_LINKCHG(device_get_parent(dev)); 3134574da7fSAdrian Chadd } 3144574da7fSAdrian Chadd 3154574da7fSAdrian Chadd static void 3164574da7fSAdrian Chadd miiproxy_mediainit(device_t dev) 3174574da7fSAdrian Chadd { 3184574da7fSAdrian Chadd 3194574da7fSAdrian Chadd MIIBUS_MEDIAINIT(device_get_parent(dev)); 3204574da7fSAdrian Chadd } 3214574da7fSAdrian Chadd 3224574da7fSAdrian Chadd /* 3234574da7fSAdrian Chadd * Functions for the MDIO target device driver. 3244574da7fSAdrian Chadd */ 3254574da7fSAdrian Chadd static int 32652f24367SRui Paulo mdioproxy_rendezvous_callback(enum rendezvous_op op, struct rendezvous_entry *rendezvous) 3274574da7fSAdrian Chadd { 3284574da7fSAdrian Chadd return (0); 3294574da7fSAdrian Chadd } 3304574da7fSAdrian Chadd 3314574da7fSAdrian Chadd static void 3324574da7fSAdrian Chadd mdioproxy_identify(driver_t *driver, device_t parent) 3334574da7fSAdrian Chadd { 3344574da7fSAdrian Chadd if (device_find_child(parent, driver->name, -1) == NULL) { 335a05a6804SWarner Losh BUS_ADD_CHILD(parent, 0, driver->name, DEVICE_UNIT_ANY); 3364574da7fSAdrian Chadd } 3374574da7fSAdrian Chadd } 3384574da7fSAdrian Chadd 3394574da7fSAdrian Chadd static int 3404574da7fSAdrian Chadd mdioproxy_probe(device_t dev) 3414574da7fSAdrian Chadd { 3424574da7fSAdrian Chadd device_set_desc(dev, "MII/MDIO proxy, MDIO side"); 3434574da7fSAdrian Chadd 3444574da7fSAdrian Chadd return (BUS_PROBE_SPECIFIC); 3454574da7fSAdrian Chadd } 3464574da7fSAdrian Chadd 3474574da7fSAdrian Chadd static int 3484574da7fSAdrian Chadd mdioproxy_attach(device_t dev) 3494574da7fSAdrian Chadd { 3504574da7fSAdrian Chadd 35152f24367SRui Paulo rendezvous_register_target(dev, mdioproxy_rendezvous_callback); 352*18250ec6SJohn Baldwin bus_attach_children(dev); 353*18250ec6SJohn Baldwin return (0); 3544574da7fSAdrian Chadd } 3554574da7fSAdrian Chadd 3564574da7fSAdrian Chadd static int 3574574da7fSAdrian Chadd mdioproxy_detach(device_t dev) 3584574da7fSAdrian Chadd { 3594574da7fSAdrian Chadd 36052f24367SRui Paulo rendezvous_unregister_target(dev); 3614574da7fSAdrian Chadd bus_generic_detach(dev); 3624574da7fSAdrian Chadd return (0); 3634574da7fSAdrian Chadd } 3644574da7fSAdrian Chadd 3654574da7fSAdrian Chadd /* 3664574da7fSAdrian Chadd * Attach this proxy in place of miibus. The target MDIO must be attached 3674574da7fSAdrian Chadd * already. Returns NULL on error. 3684574da7fSAdrian Chadd */ 3694574da7fSAdrian Chadd device_t 3704574da7fSAdrian Chadd mii_attach_proxy(device_t dev) 3714574da7fSAdrian Chadd { 3724574da7fSAdrian Chadd struct miiproxy_softc *sc; 3734574da7fSAdrian Chadd const char *name; 3744574da7fSAdrian Chadd device_t miiproxy; 3754574da7fSAdrian Chadd 3764574da7fSAdrian Chadd if (resource_string_value(device_get_name(dev), 3774574da7fSAdrian Chadd device_get_unit(dev), "mdio", &name) != 0) { 3784574da7fSAdrian Chadd if (bootverbose) 3794574da7fSAdrian Chadd printf("mii_attach_proxy: not attaching, no mdio" 3804574da7fSAdrian Chadd " device hint for %s\n", device_get_nameunit(dev)); 3814574da7fSAdrian Chadd return (NULL); 3824574da7fSAdrian Chadd } 3834574da7fSAdrian Chadd 3845b56413dSWarner Losh miiproxy = device_add_child(dev, miiproxy_driver.name, DEVICE_UNIT_ANY); 385*18250ec6SJohn Baldwin bus_attach_children(dev); 3864574da7fSAdrian Chadd sc = device_get_softc(miiproxy); 3874574da7fSAdrian Chadd sc->parent = dev; 3884574da7fSAdrian Chadd sc->proxy = miiproxy; 38952f24367SRui Paulo if (rendezvous_register_proxy(miiproxy, name, miiproxy_rendezvous_callback) != 0) { 3904574da7fSAdrian Chadd device_printf(dev, "can't attach proxy\n"); 3914574da7fSAdrian Chadd return (NULL); 3924574da7fSAdrian Chadd } 3934574da7fSAdrian Chadd device_printf(miiproxy, "attached to target %s\n", device_get_nameunit(sc->mdio)); 3944574da7fSAdrian Chadd return (miiproxy); 3954574da7fSAdrian Chadd } 3964574da7fSAdrian Chadd 3974574da7fSAdrian Chadd static device_method_t miiproxy_methods[] = { 3984574da7fSAdrian Chadd /* device interface */ 3994574da7fSAdrian Chadd DEVMETHOD(device_probe, miiproxy_probe), 4004574da7fSAdrian Chadd DEVMETHOD(device_attach, miiproxy_attach), 4014574da7fSAdrian Chadd DEVMETHOD(device_detach, miiproxy_detach), 4024574da7fSAdrian Chadd DEVMETHOD(device_shutdown, bus_generic_shutdown), 4034574da7fSAdrian Chadd 4044574da7fSAdrian Chadd /* MII interface */ 4054574da7fSAdrian Chadd DEVMETHOD(miibus_readreg, miiproxy_readreg), 4064574da7fSAdrian Chadd DEVMETHOD(miibus_writereg, miiproxy_writereg), 4074574da7fSAdrian Chadd DEVMETHOD(miibus_statchg, miiproxy_statchg), 4084574da7fSAdrian Chadd DEVMETHOD(miibus_linkchg, miiproxy_linkchg), 4094574da7fSAdrian Chadd DEVMETHOD(miibus_mediainit, miiproxy_mediainit), 4104574da7fSAdrian Chadd 4114574da7fSAdrian Chadd DEVMETHOD_END 4124574da7fSAdrian Chadd }; 4134574da7fSAdrian Chadd 4144574da7fSAdrian Chadd static device_method_t mdioproxy_methods[] = { 4154574da7fSAdrian Chadd /* device interface */ 4164574da7fSAdrian Chadd DEVMETHOD(device_identify, mdioproxy_identify), 4174574da7fSAdrian Chadd DEVMETHOD(device_probe, mdioproxy_probe), 4184574da7fSAdrian Chadd DEVMETHOD(device_attach, mdioproxy_attach), 4194574da7fSAdrian Chadd DEVMETHOD(device_detach, mdioproxy_detach), 4204574da7fSAdrian Chadd DEVMETHOD(device_shutdown, bus_generic_shutdown), 4214574da7fSAdrian Chadd 4224574da7fSAdrian Chadd DEVMETHOD_END 4234574da7fSAdrian Chadd }; 4244574da7fSAdrian Chadd 4254574da7fSAdrian Chadd DEFINE_CLASS_0(miiproxy, miiproxy_driver, miiproxy_methods, 4264574da7fSAdrian Chadd sizeof(struct miiproxy_softc)); 4274574da7fSAdrian Chadd DEFINE_CLASS_0(mdioproxy, mdioproxy_driver, mdioproxy_methods, 4284574da7fSAdrian Chadd sizeof(struct mdioproxy_softc)); 4294574da7fSAdrian Chadd 43042726c2fSJohn Baldwin DRIVER_MODULE(mdioproxy, mdio, mdioproxy_driver, 0, 0); 4313e38757dSJohn Baldwin DRIVER_MODULE(miibus, miiproxy, miibus_driver, 0, 0); 4324574da7fSAdrian Chadd MODULE_VERSION(miiproxy, 1); 4334574da7fSAdrian Chadd MODULE_DEPEND(miiproxy, miibus, 1, 1, 1); 434