14574da7fSAdrian Chadd /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 * $FreeBSD$ 294574da7fSAdrian Chadd */ 304574da7fSAdrian Chadd 314574da7fSAdrian Chadd #include <sys/param.h> 324574da7fSAdrian Chadd #include <sys/bus.h> 334574da7fSAdrian Chadd #include <sys/kernel.h> 34104dc214SGleb Smirnoff #include <sys/malloc.h> 354574da7fSAdrian Chadd #include <sys/module.h> 364574da7fSAdrian Chadd #include <sys/socket.h> 374574da7fSAdrian Chadd #include <sys/sockio.h> 384574da7fSAdrian Chadd #include <sys/systm.h> 394574da7fSAdrian Chadd 404574da7fSAdrian Chadd #include <net/if.h> 414574da7fSAdrian Chadd #include <net/if_media.h> 424574da7fSAdrian Chadd 434574da7fSAdrian Chadd #include <dev/etherswitch/miiproxy.h> 444574da7fSAdrian Chadd #include <dev/mii/mii.h> 454574da7fSAdrian Chadd #include <dev/mii/miivar.h> 464574da7fSAdrian Chadd 474574da7fSAdrian Chadd #include "mdio_if.h" 484574da7fSAdrian Chadd #include "miibus_if.h" 494574da7fSAdrian Chadd 504574da7fSAdrian Chadd 514574da7fSAdrian Chadd MALLOC_DECLARE(M_MIIPROXY); 524574da7fSAdrian Chadd MALLOC_DEFINE(M_MIIPROXY, "miiproxy", "miiproxy data structures"); 534574da7fSAdrian Chadd 544574da7fSAdrian Chadd driver_t miiproxy_driver; 554574da7fSAdrian Chadd driver_t mdioproxy_driver; 564574da7fSAdrian Chadd 574574da7fSAdrian Chadd struct miiproxy_softc { 584574da7fSAdrian Chadd device_t parent; 594574da7fSAdrian Chadd device_t proxy; 604574da7fSAdrian Chadd device_t mdio; 614574da7fSAdrian Chadd }; 624574da7fSAdrian Chadd 634574da7fSAdrian Chadd struct mdioproxy_softc { 644574da7fSAdrian Chadd }; 654574da7fSAdrian Chadd 664574da7fSAdrian Chadd /* 6752f24367SRui Paulo * The rendezvous data structures and functions allow two device endpoints to 684574da7fSAdrian Chadd * match up, so that the proxy endpoint can be associated with a target 694574da7fSAdrian Chadd * endpoint. The proxy has to know the device name of the target that it 7052f24367SRui Paulo * wants to associate with, for example through a hint. The rendezvous code 714574da7fSAdrian Chadd * makes no assumptions about the devices that want to meet. 724574da7fSAdrian Chadd */ 7352f24367SRui Paulo struct rendezvous_entry; 744574da7fSAdrian Chadd 7552f24367SRui Paulo enum rendezvous_op { 7652f24367SRui Paulo RENDEZVOUS_ATTACH, 7752f24367SRui Paulo RENDEZVOUS_DETACH 784574da7fSAdrian Chadd }; 794574da7fSAdrian Chadd 8052f24367SRui Paulo typedef int (*rendezvous_callback_t)(enum rendezvous_op, 8152f24367SRui Paulo struct rendezvous_entry *); 824574da7fSAdrian Chadd 8352f24367SRui Paulo static SLIST_HEAD(rendezvoushead, rendezvous_entry) rendezvoushead = 8452f24367SRui Paulo SLIST_HEAD_INITIALIZER(rendezvoushead); 854574da7fSAdrian Chadd 8652f24367SRui Paulo struct rendezvous_endpoint { 874574da7fSAdrian Chadd device_t device; 884574da7fSAdrian Chadd const char *name; 8952f24367SRui Paulo rendezvous_callback_t callback; 904574da7fSAdrian Chadd }; 914574da7fSAdrian Chadd 9252f24367SRui Paulo struct rendezvous_entry { 9352f24367SRui Paulo SLIST_ENTRY(rendezvous_entry) entries; 9452f24367SRui Paulo struct rendezvous_endpoint proxy; 9552f24367SRui Paulo struct rendezvous_endpoint target; 964574da7fSAdrian Chadd }; 974574da7fSAdrian Chadd 984574da7fSAdrian Chadd /* 994574da7fSAdrian Chadd * Call the callback routines for both the proxy and the target. If either 1004574da7fSAdrian Chadd * returns an error, undo the attachment. 1014574da7fSAdrian Chadd */ 1024574da7fSAdrian Chadd static int 10352f24367SRui Paulo rendezvous_attach(struct rendezvous_entry *e, struct rendezvous_endpoint *ep) 1044574da7fSAdrian Chadd { 1054574da7fSAdrian Chadd int error; 1064574da7fSAdrian Chadd 10752f24367SRui Paulo error = e->proxy.callback(RENDEZVOUS_ATTACH, e); 1084574da7fSAdrian Chadd if (error == 0) { 10952f24367SRui Paulo error = e->target.callback(RENDEZVOUS_ATTACH, e); 1104574da7fSAdrian Chadd if (error != 0) { 11152f24367SRui Paulo e->proxy.callback(RENDEZVOUS_DETACH, e); 1124574da7fSAdrian Chadd ep->device = NULL; 1134574da7fSAdrian Chadd ep->callback = NULL; 1144574da7fSAdrian Chadd } 1154574da7fSAdrian Chadd } 1164574da7fSAdrian Chadd return (error); 1174574da7fSAdrian Chadd } 1184574da7fSAdrian Chadd 1194574da7fSAdrian Chadd /* 12052f24367SRui Paulo * Create an entry for the proxy in the rendezvous list. The name parameter 1214574da7fSAdrian Chadd * indicates the name of the device that is the target endpoint for this 12252f24367SRui Paulo * rendezvous. The callback will be invoked as soon as the target is 1234574da7fSAdrian Chadd * registered: either immediately if the target registered itself earlier, 1244574da7fSAdrian Chadd * or once the target registers. Returns ENXIO if the target has not yet 1254574da7fSAdrian Chadd * registered. 1264574da7fSAdrian Chadd */ 1274574da7fSAdrian Chadd static int 12852f24367SRui Paulo rendezvous_register_proxy(device_t dev, const char *name, 12952f24367SRui Paulo rendezvous_callback_t callback) 1304574da7fSAdrian Chadd { 13152f24367SRui Paulo struct rendezvous_entry *e; 1324574da7fSAdrian Chadd 1334574da7fSAdrian Chadd KASSERT(callback != NULL, ("callback must be set")); 13452f24367SRui Paulo SLIST_FOREACH(e, &rendezvoushead, entries) { 1354574da7fSAdrian Chadd if (strcmp(name, e->target.name) == 0) { 1364574da7fSAdrian Chadd /* the target is already attached */ 1374574da7fSAdrian Chadd e->proxy.name = device_get_nameunit(dev); 1384574da7fSAdrian Chadd e->proxy.device = dev; 1394574da7fSAdrian Chadd e->proxy.callback = callback; 14052f24367SRui Paulo return (rendezvous_attach(e, &e->proxy)); 1414574da7fSAdrian Chadd } 1424574da7fSAdrian Chadd } 1434574da7fSAdrian Chadd e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO); 1444574da7fSAdrian Chadd e->proxy.name = device_get_nameunit(dev); 1454574da7fSAdrian Chadd e->proxy.device = dev; 1464574da7fSAdrian Chadd e->proxy.callback = callback; 1474574da7fSAdrian Chadd e->target.name = name; 14852f24367SRui Paulo SLIST_INSERT_HEAD(&rendezvoushead, e, entries); 1494574da7fSAdrian Chadd return (ENXIO); 1504574da7fSAdrian Chadd } 1514574da7fSAdrian Chadd 1524574da7fSAdrian Chadd /* 15352f24367SRui Paulo * Create an entry in the rendezvous list for the target. 1544574da7fSAdrian Chadd * Returns ENXIO if the proxy has not yet registered. 1554574da7fSAdrian Chadd */ 1564574da7fSAdrian Chadd static int 15752f24367SRui Paulo rendezvous_register_target(device_t dev, rendezvous_callback_t callback) 1584574da7fSAdrian Chadd { 15952f24367SRui Paulo struct rendezvous_entry *e; 1604574da7fSAdrian Chadd const char *name; 1614574da7fSAdrian Chadd 1624574da7fSAdrian Chadd KASSERT(callback != NULL, ("callback must be set")); 1634574da7fSAdrian Chadd name = device_get_nameunit(dev); 16452f24367SRui Paulo SLIST_FOREACH(e, &rendezvoushead, entries) { 1654574da7fSAdrian Chadd if (strcmp(name, e->target.name) == 0) { 1664574da7fSAdrian Chadd e->target.device = dev; 1674574da7fSAdrian Chadd e->target.callback = callback; 16852f24367SRui Paulo return (rendezvous_attach(e, &e->target)); 1694574da7fSAdrian Chadd } 1704574da7fSAdrian Chadd } 1714574da7fSAdrian Chadd e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO); 1724574da7fSAdrian Chadd e->target.name = name; 1734574da7fSAdrian Chadd e->target.device = dev; 1744574da7fSAdrian Chadd e->target.callback = callback; 17552f24367SRui Paulo SLIST_INSERT_HEAD(&rendezvoushead, e, entries); 1764574da7fSAdrian Chadd return (ENXIO); 1774574da7fSAdrian Chadd } 1784574da7fSAdrian Chadd 1794574da7fSAdrian Chadd /* 1804574da7fSAdrian Chadd * Remove the registration for the proxy. 1814574da7fSAdrian Chadd */ 1824574da7fSAdrian Chadd static int 18352f24367SRui Paulo rendezvous_unregister_proxy(device_t dev) 1844574da7fSAdrian Chadd { 18552f24367SRui Paulo struct rendezvous_entry *e; 1864574da7fSAdrian Chadd int error = 0; 1874574da7fSAdrian Chadd 18852f24367SRui Paulo SLIST_FOREACH(e, &rendezvoushead, entries) { 1894574da7fSAdrian Chadd if (e->proxy.device == dev) { 1904574da7fSAdrian Chadd if (e->target.device == NULL) { 19152f24367SRui Paulo SLIST_REMOVE(&rendezvoushead, e, rendezvous_entry, entries); 1924574da7fSAdrian Chadd free(e, M_MIIPROXY); 1934574da7fSAdrian Chadd return (0); 1944574da7fSAdrian Chadd } else { 19552f24367SRui Paulo e->proxy.callback(RENDEZVOUS_DETACH, e); 19652f24367SRui Paulo e->target.callback(RENDEZVOUS_DETACH, e); 1974574da7fSAdrian Chadd } 1984574da7fSAdrian Chadd e->proxy.device = NULL; 1994574da7fSAdrian Chadd e->proxy.callback = NULL; 2004574da7fSAdrian Chadd return (error); 2014574da7fSAdrian Chadd } 2024574da7fSAdrian Chadd } 2034574da7fSAdrian Chadd return (ENOENT); 2044574da7fSAdrian Chadd } 2054574da7fSAdrian Chadd 2064574da7fSAdrian Chadd /* 2074574da7fSAdrian Chadd * Remove the registration for the target. 2084574da7fSAdrian Chadd */ 2094574da7fSAdrian Chadd static int 21052f24367SRui Paulo rendezvous_unregister_target(device_t dev) 2114574da7fSAdrian Chadd { 21252f24367SRui Paulo struct rendezvous_entry *e; 2134574da7fSAdrian Chadd int error = 0; 2144574da7fSAdrian Chadd 21552f24367SRui Paulo SLIST_FOREACH(e, &rendezvoushead, entries) { 2164574da7fSAdrian Chadd if (e->target.device == dev) { 2174574da7fSAdrian Chadd if (e->proxy.device == NULL) { 21852f24367SRui Paulo SLIST_REMOVE(&rendezvoushead, e, rendezvous_entry, entries); 2194574da7fSAdrian Chadd free(e, M_MIIPROXY); 2204574da7fSAdrian Chadd return (0); 2214574da7fSAdrian Chadd } else { 22252f24367SRui Paulo e->proxy.callback(RENDEZVOUS_DETACH, e); 22352f24367SRui Paulo e->target.callback(RENDEZVOUS_DETACH, e); 2244574da7fSAdrian Chadd } 2254574da7fSAdrian Chadd e->target.device = NULL; 2264574da7fSAdrian Chadd e->target.callback = NULL; 2274574da7fSAdrian Chadd return (error); 2284574da7fSAdrian Chadd } 2294574da7fSAdrian Chadd } 2304574da7fSAdrian Chadd return (ENOENT); 2314574da7fSAdrian Chadd } 2324574da7fSAdrian Chadd 2334574da7fSAdrian Chadd /* 2344574da7fSAdrian Chadd * Functions of the proxy that is interposed between the ethernet interface 2354574da7fSAdrian Chadd * driver and the miibus device. 2364574da7fSAdrian Chadd */ 2374574da7fSAdrian Chadd 2384574da7fSAdrian Chadd static int 23952f24367SRui Paulo miiproxy_rendezvous_callback(enum rendezvous_op op, struct rendezvous_entry *rendezvous) 2404574da7fSAdrian Chadd { 24152f24367SRui Paulo struct miiproxy_softc *sc = device_get_softc(rendezvous->proxy.device); 2424574da7fSAdrian Chadd 2434574da7fSAdrian Chadd switch (op) { 24452f24367SRui Paulo case RENDEZVOUS_ATTACH: 24552f24367SRui Paulo sc->mdio = device_get_parent(rendezvous->target.device); 2464574da7fSAdrian Chadd break; 24752f24367SRui Paulo case RENDEZVOUS_DETACH: 2484574da7fSAdrian Chadd sc->mdio = NULL; 2494574da7fSAdrian Chadd break; 2504574da7fSAdrian Chadd } 2514574da7fSAdrian Chadd return (0); 2524574da7fSAdrian Chadd } 2534574da7fSAdrian Chadd 2544574da7fSAdrian Chadd static int 2554574da7fSAdrian Chadd miiproxy_probe(device_t dev) 2564574da7fSAdrian Chadd { 2574574da7fSAdrian Chadd device_set_desc(dev, "MII/MDIO proxy, MII side"); 2584574da7fSAdrian Chadd 2594574da7fSAdrian Chadd return (BUS_PROBE_SPECIFIC); 2604574da7fSAdrian Chadd } 2614574da7fSAdrian Chadd 2624574da7fSAdrian Chadd static int 2634574da7fSAdrian Chadd miiproxy_attach(device_t dev) 2644574da7fSAdrian Chadd { 2654574da7fSAdrian Chadd 2664574da7fSAdrian Chadd /* 2674574da7fSAdrian Chadd * The ethernet interface needs to call mii_attach_proxy() to pass 26852f24367SRui Paulo * the relevant parameters for rendezvous with the MDIO target. 2694574da7fSAdrian Chadd */ 2704574da7fSAdrian Chadd return (bus_generic_attach(dev)); 2714574da7fSAdrian Chadd } 2724574da7fSAdrian Chadd 2734574da7fSAdrian Chadd static int 2744574da7fSAdrian Chadd miiproxy_detach(device_t dev) 2754574da7fSAdrian Chadd { 2764574da7fSAdrian Chadd 27752f24367SRui Paulo rendezvous_unregister_proxy(dev); 2784574da7fSAdrian Chadd bus_generic_detach(dev); 2794574da7fSAdrian Chadd return (0); 2804574da7fSAdrian Chadd } 2814574da7fSAdrian Chadd 2824574da7fSAdrian Chadd static int 2834574da7fSAdrian Chadd miiproxy_readreg(device_t dev, int phy, int reg) 2844574da7fSAdrian Chadd { 2854574da7fSAdrian Chadd struct miiproxy_softc *sc = device_get_softc(dev); 2864574da7fSAdrian Chadd 2874574da7fSAdrian Chadd if (sc->mdio != NULL) 2884574da7fSAdrian Chadd return (MDIO_READREG(sc->mdio, phy, reg)); 2894574da7fSAdrian Chadd return (-1); 2904574da7fSAdrian Chadd } 2914574da7fSAdrian Chadd 2924574da7fSAdrian Chadd static int 2934574da7fSAdrian Chadd miiproxy_writereg(device_t dev, int phy, int reg, int val) 2944574da7fSAdrian Chadd { 2954574da7fSAdrian Chadd struct miiproxy_softc *sc = device_get_softc(dev); 2964574da7fSAdrian Chadd 2974574da7fSAdrian Chadd if (sc->mdio != NULL) 2984574da7fSAdrian Chadd return (MDIO_WRITEREG(sc->mdio, phy, reg, val)); 2994574da7fSAdrian Chadd return (-1); 3004574da7fSAdrian Chadd } 3014574da7fSAdrian Chadd 3024574da7fSAdrian Chadd static void 3034574da7fSAdrian Chadd miiproxy_statchg(device_t dev) 3044574da7fSAdrian Chadd { 3054574da7fSAdrian Chadd 3064574da7fSAdrian Chadd MIIBUS_STATCHG(device_get_parent(dev)); 3074574da7fSAdrian Chadd } 3084574da7fSAdrian Chadd 3094574da7fSAdrian Chadd static void 3104574da7fSAdrian Chadd miiproxy_linkchg(device_t dev) 3114574da7fSAdrian Chadd { 3124574da7fSAdrian Chadd 3134574da7fSAdrian Chadd MIIBUS_LINKCHG(device_get_parent(dev)); 3144574da7fSAdrian Chadd } 3154574da7fSAdrian Chadd 3164574da7fSAdrian Chadd static void 3174574da7fSAdrian Chadd miiproxy_mediainit(device_t dev) 3184574da7fSAdrian Chadd { 3194574da7fSAdrian Chadd 3204574da7fSAdrian Chadd MIIBUS_MEDIAINIT(device_get_parent(dev)); 3214574da7fSAdrian Chadd } 3224574da7fSAdrian Chadd 3234574da7fSAdrian Chadd /* 3244574da7fSAdrian Chadd * Functions for the MDIO target device driver. 3254574da7fSAdrian Chadd */ 3264574da7fSAdrian Chadd static int 32752f24367SRui Paulo mdioproxy_rendezvous_callback(enum rendezvous_op op, struct rendezvous_entry *rendezvous) 3284574da7fSAdrian Chadd { 3294574da7fSAdrian Chadd return (0); 3304574da7fSAdrian Chadd } 3314574da7fSAdrian Chadd 3324574da7fSAdrian Chadd static void 3334574da7fSAdrian Chadd mdioproxy_identify(driver_t *driver, device_t parent) 3344574da7fSAdrian Chadd { 3354574da7fSAdrian Chadd if (device_find_child(parent, driver->name, -1) == NULL) { 336683ca803SJohn Baldwin BUS_ADD_CHILD(parent, 0, driver->name, -1); 3374574da7fSAdrian Chadd } 3384574da7fSAdrian Chadd } 3394574da7fSAdrian Chadd 3404574da7fSAdrian Chadd static int 3414574da7fSAdrian Chadd mdioproxy_probe(device_t dev) 3424574da7fSAdrian Chadd { 3434574da7fSAdrian Chadd device_set_desc(dev, "MII/MDIO proxy, MDIO side"); 3444574da7fSAdrian Chadd 3454574da7fSAdrian Chadd return (BUS_PROBE_SPECIFIC); 3464574da7fSAdrian Chadd } 3474574da7fSAdrian Chadd 3484574da7fSAdrian Chadd static int 3494574da7fSAdrian Chadd mdioproxy_attach(device_t dev) 3504574da7fSAdrian Chadd { 3514574da7fSAdrian Chadd 35252f24367SRui Paulo rendezvous_register_target(dev, mdioproxy_rendezvous_callback); 3534574da7fSAdrian Chadd return (bus_generic_attach(dev)); 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 int error; 3744574da7fSAdrian Chadd const char *name; 3754574da7fSAdrian Chadd device_t miiproxy; 3764574da7fSAdrian Chadd 3774574da7fSAdrian Chadd if (resource_string_value(device_get_name(dev), 3784574da7fSAdrian Chadd device_get_unit(dev), "mdio", &name) != 0) { 3794574da7fSAdrian Chadd if (bootverbose) 3804574da7fSAdrian Chadd printf("mii_attach_proxy: not attaching, no mdio" 3814574da7fSAdrian Chadd " device hint for %s\n", device_get_nameunit(dev)); 3824574da7fSAdrian Chadd return (NULL); 3834574da7fSAdrian Chadd } 3844574da7fSAdrian Chadd 3854574da7fSAdrian Chadd miiproxy = device_add_child(dev, miiproxy_driver.name, -1); 3864574da7fSAdrian Chadd error = bus_generic_attach(dev); 3874574da7fSAdrian Chadd if (error != 0) { 3884574da7fSAdrian Chadd device_printf(dev, "can't attach miiproxy\n"); 3894574da7fSAdrian Chadd return (NULL); 3904574da7fSAdrian Chadd } 3914574da7fSAdrian Chadd sc = device_get_softc(miiproxy); 3924574da7fSAdrian Chadd sc->parent = dev; 3934574da7fSAdrian Chadd sc->proxy = miiproxy; 39452f24367SRui Paulo if (rendezvous_register_proxy(miiproxy, name, miiproxy_rendezvous_callback) != 0) { 3954574da7fSAdrian Chadd device_printf(dev, "can't attach proxy\n"); 3964574da7fSAdrian Chadd return (NULL); 3974574da7fSAdrian Chadd } 3984574da7fSAdrian Chadd device_printf(miiproxy, "attached to target %s\n", device_get_nameunit(sc->mdio)); 3994574da7fSAdrian Chadd return (miiproxy); 4004574da7fSAdrian Chadd } 4014574da7fSAdrian Chadd 4024574da7fSAdrian Chadd static device_method_t miiproxy_methods[] = { 4034574da7fSAdrian Chadd /* device interface */ 4044574da7fSAdrian Chadd DEVMETHOD(device_probe, miiproxy_probe), 4054574da7fSAdrian Chadd DEVMETHOD(device_attach, miiproxy_attach), 4064574da7fSAdrian Chadd DEVMETHOD(device_detach, miiproxy_detach), 4074574da7fSAdrian Chadd DEVMETHOD(device_shutdown, bus_generic_shutdown), 4084574da7fSAdrian Chadd 4094574da7fSAdrian Chadd /* MII interface */ 4104574da7fSAdrian Chadd DEVMETHOD(miibus_readreg, miiproxy_readreg), 4114574da7fSAdrian Chadd DEVMETHOD(miibus_writereg, miiproxy_writereg), 4124574da7fSAdrian Chadd DEVMETHOD(miibus_statchg, miiproxy_statchg), 4134574da7fSAdrian Chadd DEVMETHOD(miibus_linkchg, miiproxy_linkchg), 4144574da7fSAdrian Chadd DEVMETHOD(miibus_mediainit, miiproxy_mediainit), 4154574da7fSAdrian Chadd 4164574da7fSAdrian Chadd DEVMETHOD_END 4174574da7fSAdrian Chadd }; 4184574da7fSAdrian Chadd 4194574da7fSAdrian Chadd static device_method_t mdioproxy_methods[] = { 4204574da7fSAdrian Chadd /* device interface */ 4214574da7fSAdrian Chadd DEVMETHOD(device_identify, mdioproxy_identify), 4224574da7fSAdrian Chadd DEVMETHOD(device_probe, mdioproxy_probe), 4234574da7fSAdrian Chadd DEVMETHOD(device_attach, mdioproxy_attach), 4244574da7fSAdrian Chadd DEVMETHOD(device_detach, mdioproxy_detach), 4254574da7fSAdrian Chadd DEVMETHOD(device_shutdown, bus_generic_shutdown), 4264574da7fSAdrian Chadd 4274574da7fSAdrian Chadd DEVMETHOD_END 4284574da7fSAdrian Chadd }; 4294574da7fSAdrian Chadd 4304574da7fSAdrian Chadd DEFINE_CLASS_0(miiproxy, miiproxy_driver, miiproxy_methods, 4314574da7fSAdrian Chadd sizeof(struct miiproxy_softc)); 4324574da7fSAdrian Chadd DEFINE_CLASS_0(mdioproxy, mdioproxy_driver, mdioproxy_methods, 4334574da7fSAdrian Chadd sizeof(struct mdioproxy_softc)); 4344574da7fSAdrian Chadd 435*42726c2fSJohn Baldwin DRIVER_MODULE(mdioproxy, mdio, mdioproxy_driver, 0, 0); 4363e38757dSJohn Baldwin DRIVER_MODULE(miibus, miiproxy, miibus_driver, 0, 0); 4374574da7fSAdrian Chadd MODULE_VERSION(miiproxy, 1); 4384574da7fSAdrian Chadd MODULE_DEPEND(miiproxy, miibus, 1, 1, 1); 439