Date: Sat, 21 Jan 2012 00:08:34 +0100 From: Stefan Bethke <stb@lassitu.de> To: FreeBSD-arch <freebsd-arch@freebsd.org> Subject: Re: Extending sys/dev/mii Message-ID: <66DDA0A2-F878-43FF-8824-54868F493B18@lassitu.de> In-Reply-To: <20120111193738.GB44286@alchemy.franken.de> References: <8D025847-4BE4-4B2C-87D7-97E72CC9D325@lassitu.de> <20120104215930.GM90831@alchemy.franken.de> <47ABA638-7E08-4350-A03C-3D4A23BF2D7E@lassitu.de> <1763C3FF-1EA0-4DC0-891D-63816EBF4A04@lassitu.de> <20120106182756.GA88161@alchemy.franken.de> <95372FB3-406F-46C2-8684-4FDB672D9FCF@lassitu.de> <20120106214741.GB88161@alchemy.franken.de> <F60B2B70-049F-4497-BBA8-3C421088C1EA@lassitu.de> <20120108130039.GG88161@alchemy.franken.de> <23477898-8D85-498C-8E30-192810BD68A8@lassitu.de> <20120111193738.GB44286@alchemy.franken.de>
next in thread | previous in thread | raw e-mail | index | archive | help
--Apple-Mail=_213E4B8A-6009-4FF8-A23A-C6A4E1D4CE37
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
charset=us-ascii
Am 11.01.2012 um 20:37 schrieb Marius Strobl:
> Okay, I suggest to postpone this discussion until then. For the
> scenario when mdiobus is the parent of miibus I see no technical
> need to change miibus to support what you want to do, just implement
> the miibus_if in mdiobus and redirect it to the device_t of the
> MAC there. Moreover, that way the hack to sidestep newbus is contained
> in the layer that actually needs it and not scattered over multiple
> frameworks.
I've posted to -net a patch that implements a workaround along those =
lines. It solves two issues: talking to two upstream devices, and =
providing a proper attachment for miibus.
There's a number of things that made this harder than I would have =
liked:
- miibus has a funny way of attaching to it's parent. Making the parent =
a bus that automatically attaches matching children does not lead to =
good results.
- miibus uses it's parents ivars. To clarify: device_get_ivars get's a =
devices ivars, but those are owned by the parent; the bus uses =
device_[gs]et_ivars(9) to manipulate it's own private per-child data =
storage. The device must not manipulate them. I believe those =
variables can be moved to mii_data.
- miibus makes assumptions about it's children, namely that they have =
specific softc's and that they provide callbacks outside of the newbus =
method mechanism
- miibus assumes that all devices attached to that mdio have certain =
registers that have certain bits set or cleared
- miibus calls it's parent methods and two explicit callbacks, plus =
various calls into the interface management code.
The second problem is that there's currently no way to express a =
dependency between two devices other than a parent-child relationship. =
I would be interested to learn why this appears to be so uncommon that I =
could not find any discussion of such a feature. Has it really never =
before come up?
Leaving aside the miibus issue, the newbus problem is that the ethernet =
driver (which is attached to some bus) needs to associate with some =
other driver that might not be in it's vincinity, in particular neither =
it's parent nor one of it's children. Compounding the problem is that =
there is no way to express an attachment ordering constraint so that the =
ethernet driver is only attached once the required mdio driver has =
attached.
Stefan
--=20
Stefan Bethke <stb@lassitu.de> Fon +49 151 14070811
--Apple-Mail=_213E4B8A-6009-4FF8-A23A-C6A4E1D4CE37
Content-Disposition: attachment;
filename=miiproxy.patch
Content-Type: application/octet-stream;
name="miiproxy.patch"
Content-Transfer-Encoding: 7bit
diff --git a/sys/dev/etherswitch/mdio.c b/sys/dev/etherswitch/mdio.c
new file mode 100644
index 0000000..9302075
--- /dev/null
+++ b/sys/dev/etherswitch/mdio.c
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+
+#include <dev/etherswitch/mdio.h>
+
+#include "mdio_if.h"
+
+static void
+mdio_identify(driver_t *driver, device_t parent)
+{
+ if (device_find_child(parent, mdio_driver.name, -1) == NULL)
+ BUS_ADD_CHILD(parent, 0, mdio_driver.name, -1);
+}
+
+static int
+mdio_probe(device_t dev)
+{
+ device_set_desc(dev, "MDIO");
+
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+mdio_attach(device_t dev)
+{
+ bus_generic_probe(dev);
+ bus_enumerate_hinted_children(dev);
+ return (bus_generic_attach(dev));
+}
+
+static int
+mdio_detach(device_t dev)
+{
+ bus_generic_detach(dev);
+ return (0);
+}
+
+static int
+mdio_readreg(device_t dev, int phy, int reg)
+{
+ return MDIO_READREG(device_get_parent(dev), phy, reg);
+}
+
+static int
+mdio_writereg(device_t dev, int phy, int reg, int val)
+{
+ return MDIO_WRITEREG(device_get_parent(dev), phy, reg, val);
+}
+
+static int
+mdio_print_child(device_t dev, device_t child)
+{
+ int retval;
+
+ retval = bus_print_child_header(dev, child);
+ retval += bus_print_child_footer(dev, child);
+
+ return (retval);
+}
+
+static int
+mdio_read_ivar(device_t dev, device_t child __unused, int which,
+ uintptr_t *result)
+{
+ struct miibus_ivars *ivars;
+
+ ivars = device_get_ivars(dev);
+ switch (which) {
+ default:
+ return (ENOENT);
+ }
+ return (0);
+}
+
+static int
+mdio_child_pnpinfo_str(device_t dev __unused, device_t child, char *buf,
+ size_t buflen)
+{
+ buf[0] = '\0';
+ return (0);
+}
+
+static int
+mdio_child_location_str(device_t dev __unused, device_t child, char *buf,
+ size_t buflen)
+{
+ buf[0] = '\0';
+ return (0);
+}
+
+static void
+mdio_hinted_child(device_t dev, const char *name, int unit)
+{
+ device_add_child(dev, name, unit);
+}
+
+static device_method_t mdio_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_identify, mdio_identify),
+ DEVMETHOD(device_probe, mdio_probe),
+ DEVMETHOD(device_attach, mdio_attach),
+ DEVMETHOD(device_detach, mdio_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* bus interface */
+ DEVMETHOD(bus_print_child, mdio_print_child),
+ DEVMETHOD(bus_read_ivar, mdio_read_ivar),
+ DEVMETHOD(bus_child_pnpinfo_str, mdio_child_pnpinfo_str),
+ DEVMETHOD(bus_child_location_str, mdio_child_location_str),
+ DEVMETHOD(bus_add_child, device_add_child_ordered),
+ DEVMETHOD(bus_hinted_child, mdio_hinted_child),
+
+ /* MDIO access */
+ DEVMETHOD(mdio_readreg, mdio_readreg),
+ DEVMETHOD(mdio_writereg, mdio_writereg),
+
+ DEVMETHOD_END
+};
+
+driver_t mdio_driver = {
+ "mdio",
+ mdio_methods,
+ 0
+};
+
+devclass_t mdio_devclass;
+
diff --git a/sys/dev/etherswitch/mdio.h b/sys/dev/etherswitch/mdio.h
new file mode 100644
index 0000000..52eddbd
--- /dev/null
+++ b/sys/dev/etherswitch/mdio.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_MII_MDIO_H_
+#define _DEV_MII_MDIO_H_
+
+extern driver_t mdio_driver;
+extern devclass_t mdio_devclass;
+
+#endif
diff --git a/sys/dev/etherswitch/mdio_if.m b/sys/dev/etherswitch/mdio_if.m
new file mode 100644
index 0000000..9aedd92
--- /dev/null
+++ b/sys/dev/etherswitch/mdio_if.m
@@ -0,0 +1,24 @@
+# $FreeBSD$
+
+#include <sys/bus.h>
+
+INTERFACE mdio;
+
+#
+# Read register from device on MDIO bus
+#
+METHOD int readreg {
+ device_t dev;
+ int phy;
+ int reg;
+};
+
+#
+# Write register to device on MDIO bus
+#
+METHOD int writereg {
+ device_t dev;
+ int phy;
+ int reg;
+ int val;
+};
diff --git a/sys/dev/etherswitch/miiproxy.c b/sys/dev/etherswitch/miiproxy.c
new file mode 100644
index 0000000..2791082
--- /dev/null
+++ b/sys/dev/etherswitch/miiproxy.c
@@ -0,0 +1,437 @@
+/*-
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <dev/etherswitch/miiproxy.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include "mdio_if.h"
+#include "miibus_if.h"
+
+
+MALLOC_DECLARE(M_MIIPROXY);
+MALLOC_DEFINE(M_MIIPROXY, "miiproxy", "miiproxy data structures");
+
+driver_t miiproxy_driver;
+driver_t mdioproxy_driver;
+
+struct miiproxy_softc {
+ device_t parent;
+ device_t proxy;
+ device_t mdio;
+ miiproxy_attach_callback_t attach_callback;
+ void *attach_arg;
+};
+
+struct mdioproxy_softc {
+};
+
+/*
+ * The rendevous data structures and functions allow two device endpoints to
+ * match up, so that the proxy endpoint can be associated with a target
+ * endpoint. The proxy has to know the device name of the target that it
+ * wants to associate with, for example through a hint. The rendevous code
+ * makes no assumptions about the devices that want to meet.
+ */
+struct rendevous_entry;
+
+enum rendevous_op {
+ RENDEVOUS_ATTACH,
+ RENDEVOUS_DETACH
+};
+
+typedef int (*rendevous_callback_t)(enum rendevous_op,
+ struct rendevous_entry *);
+
+static SLIST_HEAD(rendevoushead, rendevous_entry) rendevoushead =
+ SLIST_HEAD_INITIALIZER(rendevoushead);
+
+struct rendevous_endpoint {
+ device_t device;
+ const char *name;
+ rendevous_callback_t callback;
+};
+
+struct rendevous_entry {
+ SLIST_ENTRY(rendevous_entry) entries;
+ struct rendevous_endpoint proxy;
+ struct rendevous_endpoint target;
+};
+
+/*
+ * Call the callback routines for both the proxy and the target. If either
+ * returns an error, undo the attachment.
+ */
+static int
+rendevous_attach(struct rendevous_entry *e, struct rendevous_endpoint *ep)
+{
+ int error;
+
+ error = e->proxy.callback(RENDEVOUS_ATTACH, e);
+ if (error == 0)
+ error = e->target.callback(RENDEVOUS_ATTACH, e);
+ if (error != 0) {
+ e->proxy.callback(RENDEVOUS_DETACH, e);
+ ep->device = NULL;
+ ep->callback = NULL;
+ }
+ return (error);
+}
+
+/*
+ * Create an entry for the proxy in the rendevous list. The name parameter
+ * indicates the name of the device that is the target endpoint for this
+ * rendevous. The callback will be invoked as soon as the target is
+ * registered: either immediately if the target registered itself earlier,
+ * or once the target registers.
+ */
+static int
+rendevous_register_proxy(device_t dev, const char *name,
+ rendevous_callback_t callback)
+{
+ struct rendevous_entry *e;
+
+ KASSERT(callback != NULL, ("callback must not be NULL"));
+ SLIST_FOREACH(e, &rendevoushead, entries) {
+ if (strcmp(name, e->target.name) == 0) {
+ /* the target is already attached */
+ e->proxy.name = device_get_nameunit(dev);
+ e->proxy.device = dev;
+ e->proxy.callback = callback;
+ return (rendevous_attach(e, &e->proxy));
+ }
+ }
+ e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO);
+ e->proxy.name = device_get_nameunit(dev);
+ e->proxy.device = dev;
+ e->proxy.callback = callback;
+ e->target.name = name;
+ SLIST_INSERT_HEAD(&rendevoushead, e, entries);
+ return (0);
+}
+
+/*
+ * Create an entry in the rendevous list for the target. The callback will
+ * be called once the proxy has registered.
+ */
+static int
+rendevous_register_target(device_t dev, rendevous_callback_t callback)
+{
+ struct rendevous_entry *e;
+ const char *name;
+
+ KASSERT(callback != NULL, ("callback must not be NULL"));
+ name = device_get_nameunit(dev);
+ SLIST_FOREACH(e, &rendevoushead, entries) {
+ if (strcmp(name, e->target.name) == 0) {
+ e->target.device = dev;
+ e->target.callback = callback;
+ return (rendevous_attach(e, &e->target));
+ }
+ }
+ e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO);
+ e->target.name = name;
+ e->target.device = dev;
+ e->target.callback = callback;
+ SLIST_INSERT_HEAD(&rendevoushead, e, entries);
+ return (0);
+}
+
+/*
+ * Remove the registration for the proxy.
+ */
+static int
+rendevous_unregister_proxy(device_t dev)
+{
+ struct rendevous_entry *e;
+ int error = 0;
+
+ SLIST_FOREACH(e, &rendevoushead, entries) {
+ if (e->proxy.device == dev) {
+ if (e->target.device == NULL) {
+ SLIST_REMOVE(&rendevoushead, e, rendevous_entry, entries);
+ free(e, M_MIIPROXY);
+ return (0);
+ } else {
+ e->proxy.callback(RENDEVOUS_DETACH, e);
+ e->target.callback(RENDEVOUS_DETACH, e);
+ }
+ e->proxy.device = NULL;
+ e->proxy.callback = NULL;
+ return (error);
+ }
+ }
+ return (ENOENT);
+}
+
+/*
+ * Remove the registration for the target.
+ */
+static int
+rendevous_unregister_target(device_t dev)
+{
+ struct rendevous_entry *e;
+ int error = 0;
+
+ SLIST_FOREACH(e, &rendevoushead, entries) {
+ if (e->target.device == dev) {
+ if (e->proxy.device == NULL) {
+ SLIST_REMOVE(&rendevoushead, e, rendevous_entry, entries);
+ free(e, M_MIIPROXY);
+ return (0);
+ } else {
+ e->proxy.callback(RENDEVOUS_DETACH, e);
+ e->target.callback(RENDEVOUS_DETACH, e);
+ }
+ e->target.device = NULL;
+ e->target.callback = NULL;
+ return (error);
+ }
+ }
+ return (ENOENT);
+}
+
+/*
+ * Functions of the proxy that is interposed between the ethernet interface
+ * driver and the miibus device.
+ */
+
+static int
+miiproxy_rendevous_callback(enum rendevous_op op, struct rendevous_entry *rendevous)
+{
+ struct miiproxy_softc *sc = device_get_softc(rendevous->proxy.device);
+
+ switch (op) {
+ case RENDEVOUS_ATTACH:
+ sc->mdio = device_get_parent(rendevous->target.device);
+ (sc->attach_callback)(sc->attach_arg);
+ break;
+ case RENDEVOUS_DETACH:
+ sc->mdio = NULL;
+ /* detach miibus */
+ }
+ return (0);
+}
+
+static int
+miiproxy_probe(device_t dev)
+{
+ device_set_desc(dev, "MII/MDIO proxy, MII side");
+
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+miiproxy_attach(device_t dev)
+{
+ /*
+ * The ethernet interface needs to call mii_attach_proxy() to pass
+ * the relevant parameters for rendevous with the MDIO target.
+ */
+ return (bus_generic_attach(dev));
+}
+
+static int
+miiproxy_detach(device_t dev)
+{
+ rendevous_unregister_proxy(dev);
+ bus_generic_detach(dev);
+ return (0);
+}
+
+static int
+miiproxy_readreg(device_t dev, int phy, int reg)
+{
+ struct miiproxy_softc *sc = device_get_softc(dev);
+
+ if (sc->mdio != NULL)
+ return (MDIO_READREG(sc->mdio, phy, reg));
+ return (-1);
+}
+
+static int
+miiproxy_writereg(device_t dev, int phy, int reg, int val)
+{
+ struct miiproxy_softc *sc = device_get_softc(dev);
+
+ if (sc->mdio != NULL)
+ return (MDIO_WRITEREG(sc->mdio, phy, reg, val));
+ return (-1);
+}
+
+static void
+miiproxy_statchg(device_t dev)
+{
+ MIIBUS_STATCHG(device_get_parent(dev));
+}
+
+static void
+miiproxy_linkchg(device_t dev)
+{
+ MIIBUS_LINKCHG(device_get_parent(dev));
+}
+
+static void
+miiproxy_mediainit(device_t dev)
+{
+ MIIBUS_MEDIAINIT(device_get_parent(dev));
+}
+
+/*
+ * Functions for the MDIO target device driver.
+ */
+static int
+mdioproxy_rendevous_callback(enum rendevous_op op, struct rendevous_entry *rendevous)
+{
+ return (0);
+}
+
+static void
+mdioproxy_identify(driver_t *driver, device_t parent)
+{
+ device_t child;
+
+ if (device_find_child(parent, driver->name, -1) == NULL) {
+ child = BUS_ADD_CHILD(parent, 0, driver->name, -1);
+ }
+}
+
+static int
+mdioproxy_probe(device_t dev)
+{
+ device_set_desc(dev, "MII/MDIO proxy, MDIO side");
+
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+mdioproxy_attach(device_t dev)
+{
+ rendevous_register_target(dev, mdioproxy_rendevous_callback);
+ return (bus_generic_attach(dev));
+}
+
+static int
+mdioproxy_detach(device_t dev)
+{
+ rendevous_unregister_target(dev);
+ bus_generic_detach(dev);
+ return (0);
+}
+
+/*
+ * Attach this proxy in place of miibus. The callback is called once all
+ * parts are in place, so that it can attach the miibus to the proxy device,
+ * and finish interface initialization.
+ */
+device_t
+mii_attach_proxy(device_t dev, miiproxy_attach_callback_t cb, void *aa)
+{
+ struct miiproxy_softc *sc;
+ int error;
+ const char *name;
+ device_t miiproxy;
+
+ if (resource_string_value(device_get_name(dev),
+ device_get_unit(dev), "mdio", &name) != 0) {
+ if (bootverbose)
+ printf("mii_attach_proxy: not attaching, no mdio"
+ " device hint for %s\n", device_get_nameunit(dev));
+ return (NULL);
+ }
+
+ miiproxy = device_add_child(dev, miiproxy_driver.name, -1);
+ error = bus_generic_attach(dev);
+ if (error != 0) {
+ device_printf(dev, "can't attach miiproxy\n");
+ return (NULL);
+ }
+ sc = device_get_softc(miiproxy);
+ sc->parent = dev;
+ sc->proxy = miiproxy;
+ sc->attach_callback = cb;
+ sc->attach_arg = aa;
+ rendevous_register_proxy(miiproxy, name, miiproxy_rendevous_callback);
+ return (miiproxy);
+}
+
+static device_method_t miiproxy_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, miiproxy_probe),
+ DEVMETHOD(device_attach, miiproxy_attach),
+ DEVMETHOD(device_detach, miiproxy_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, miiproxy_readreg),
+ DEVMETHOD(miibus_writereg, miiproxy_writereg),
+ DEVMETHOD(miibus_statchg, miiproxy_statchg),
+ DEVMETHOD(miibus_linkchg, miiproxy_linkchg),
+ DEVMETHOD(miibus_mediainit, miiproxy_mediainit),
+
+ DEVMETHOD_END
+};
+
+static device_method_t mdioproxy_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_identify, mdioproxy_identify),
+ DEVMETHOD(device_probe, mdioproxy_probe),
+ DEVMETHOD(device_attach, mdioproxy_attach),
+ DEVMETHOD(device_detach, mdioproxy_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(miiproxy, miiproxy_driver, miiproxy_methods,
+ sizeof(struct miiproxy_softc));
+DEFINE_CLASS_0(mdioproxy, mdioproxy_driver, mdioproxy_methods,
+ sizeof(struct mdioproxy_softc));
+
+devclass_t miiproxy_devclass;
+static devclass_t mdioproxy_devclass;
+
+DRIVER_MODULE(mdioproxy, mdio, mdioproxy_driver, mdioproxy_devclass, 0, 0);
+DRIVER_MODULE(miibus, miiproxy, miibus_driver, miibus_devclass, 0, 0);
+MODULE_VERSION(miiproxy, 1);
+MODULE_DEPEND(miiproxy, miibus, 1, 1, 1);
diff --git a/sys/dev/etherswitch/miiproxy.h b/sys/dev/etherswitch/miiproxy.h
new file mode 100644
index 0000000..5b8ee7c
--- /dev/null
+++ b/sys/dev/etherswitch/miiproxy.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_ETHERSWITCH_MIIPROXY_H_
+#define _DEV_ETHERSWITCH_MIIPROXY_H_
+
+typedef void (*miiproxy_attach_callback_t)(void *);
+
+extern devclass_t miiproxy_devclass;
+extern driver_t miiproxy_driver;
+
+device_t mii_attach_proxy(device_t dev, miiproxy_attach_callback_t cb, void *aa);
+
+#endif
diff --git a/sys/mips/atheros/if_arge.c b/sys/mips/atheros/if_arge.c
index 0154ae2..3dd2e15 100644
--- a/sys/mips/atheros/if_arge.c
+++ b/sys/mips/atheros/if_arge.c
@@ -72,8 +72,18 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+#include <opt_arge.h>
+
+#if defined(ARGE_MDIO)
+#include <dev/etherswitch/mdio.h>
+#include <dev/etherswitch/miiproxy.h>
+#include "mdio_if.h"
+#endif
+
+
MODULE_DEPEND(arge, ether, 1, 1, 1);
MODULE_DEPEND(arge, miibus, 1, 1, 1);
+MODULE_VERSION(arge, 1);
#include "miibus_if.h"
@@ -102,6 +112,7 @@ typedef enum {
#endif
static int arge_attach(device_t);
+static int arge_attach_finish(struct arge_softc *sc);
static int arge_detach(device_t);
static void arge_flush_ddr(struct arge_softc *);
static int arge_ifmedia_upd(struct ifnet *);
@@ -134,6 +145,8 @@ static void arge_intr(void *);
static int arge_intr_filter(void *);
static void arge_tick(void *);
+static void arge_hinted_child(device_t bus, const char *dname, int dunit);
+
/*
* ifmedia callbacks for multiPHY MAC
*/
@@ -160,6 +173,10 @@ static device_method_t arge_methods[] = {
DEVMETHOD(miibus_writereg, arge_miibus_writereg),
DEVMETHOD(miibus_statchg, arge_miibus_statchg),
+ /* bus interface */
+ DEVMETHOD(bus_add_child, device_add_child_ordered),
+ DEVMETHOD(bus_hinted_child, arge_hinted_child),
+
DEVMETHOD_END
};
@@ -174,6 +191,37 @@ static devclass_t arge_devclass;
DRIVER_MODULE(arge, nexus, arge_driver, arge_devclass, 0, 0);
DRIVER_MODULE(miibus, arge, miibus_driver, miibus_devclass, 0, 0);
+#if defined(ARGE_MDIO)
+static int argemdio_probe(device_t);
+static int argemdio_attach(device_t);
+static int argemdio_detach(device_t);
+
+/*
+ * Declare an additional, separate driver for accessing the MDIO bus.
+ */
+static device_method_t argemdio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, argemdio_probe),
+ DEVMETHOD(device_attach, argemdio_attach),
+ DEVMETHOD(device_detach, argemdio_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_add_child, device_add_child_ordered),
+
+ /* MDIO access */
+ DEVMETHOD(mdio_readreg, arge_miibus_readreg),
+ DEVMETHOD(mdio_writereg, arge_miibus_writereg),
+};
+
+DEFINE_CLASS_0(argemdio, argemdio_driver, argemdio_methods,
+ sizeof(struct arge_softc));
+static devclass_t argemdio_devclass;
+
+DRIVER_MODULE(miiproxy, arge, miiproxy_driver, miiproxy_devclass, 0, 0);
+DRIVER_MODULE(argemdio, nexus, argemdio_driver, argemdio_devclass, 0, 0);
+DRIVER_MODULE(mdio, argemdio, mdio_driver, mdio_devclass, 0, 0);
+#endif
+
/*
* RedBoot passes MAC address to entry point as environment
* variable. platfrom_start parses it and stores in this variable
@@ -234,15 +282,22 @@ arge_attach_sysctl(device_t dev)
#endif
}
+#if defined(ARGE_MDIO)
+static void
+arge_attach_proxy(void *aa)
+{
+ arge_attach_finish(aa);
+}
+#endif
+
static int
arge_attach(device_t dev)
{
- uint8_t eaddr[ETHER_ADDR_LEN];
struct ifnet *ifp;
struct arge_softc *sc;
- int error = 0, rid, phymask;
+ int error = 0, rid;
uint32_t reg, rnd;
- int is_base_mac_empty, i, phys_total;
+ int is_base_mac_empty, i;
uint32_t hint;
long eeprom_mac_addr = 0;
@@ -277,18 +332,18 @@ arge_attach(device_t dev)
* Get which PHY of 5 available we should use for this unit
*/
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "phymask", &phymask) != 0) {
+ "phymask", &sc->arge_phymask) != 0) {
/*
* Use port 4 (WAN) for GE0. For any other port use
* its PHY the same as its unit number
*/
if (sc->arge_mac_unit == 0)
- phymask = (1 << 4);
+ sc->arge_phymask = (1 << 4);
else
/* Use all phys up to 4 */
- phymask = (1 << 4) - 1;
+ sc->arge_phymask = (1 << 4) - 1;
- device_printf(dev, "No PHY specified, using mask %d\n", phymask);
+ device_printf(dev, "No PHY specified, using mask %d\n", sc->arge_phymask);
}
/*
@@ -313,8 +368,6 @@ arge_attach(device_t dev)
else
sc->arge_duplex_mode = 0;
- sc->arge_phymask = phymask;
-
mtx_init(&sc->arge_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
callout_init_mtx(&sc->arge_stat_callout, &sc->arge_mtx, 0);
@@ -323,7 +376,7 @@ arge_attach(device_t dev)
/* Map control/status registers. */
sc->arge_rid = 0;
sc->arge_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->arge_rid, RF_ACTIVE);
+ &sc->arge_rid, RF_ACTIVE | RF_SHAREABLE);
if (sc->arge_res == NULL) {
device_printf(dev, "couldn't map memory\n");
@@ -371,8 +424,8 @@ arge_attach(device_t dev)
is_base_mac_empty = 1;
for (i = 0; i < ETHER_ADDR_LEN; i++) {
- eaddr[i] = ar711_base_mac[i] & 0xff;
- if (eaddr[i] != 0)
+ sc->arge_eaddr[i] = ar711_base_mac[i] & 0xff;
+ if (sc->arge_eaddr[i] != 0)
is_base_mac_empty = 0;
}
@@ -385,16 +438,15 @@ arge_attach(device_t dev)
"Generating random ethernet address.\n");
rnd = arc4random();
- eaddr[0] = 'b';
- eaddr[1] = 's';
- eaddr[2] = 'd';
- eaddr[3] = (rnd >> 24) & 0xff;
- eaddr[4] = (rnd >> 16) & 0xff;
- eaddr[5] = (rnd >> 8) & 0xff;
+ sc->arge_eaddr[0] = 'b';
+ sc->arge_eaddr[1] = 's';
+ sc->arge_eaddr[2] = 'd';
+ sc->arge_eaddr[3] = (rnd >> 24) & 0xff;
+ sc->arge_eaddr[4] = (rnd >> 16) & 0xff;
+ sc->arge_eaddr[5] = (rnd >> 8) & 0xff;
}
-
if (sc->arge_mac_unit != 0)
- eaddr[5] += sc->arge_mac_unit;
+ sc->arge_eaddr[5] += sc->arge_mac_unit;
if (arge_dma_alloc(sc) != 0) {
error = ENXIO;
@@ -423,19 +475,23 @@ arge_attach(device_t dev)
ARGE_WRITE(sc, AR71XX_MAC_MAX_FRAME_LEN, 1536);
+#if !defined(ARGE_MDIO)
/* Reset MII bus */
ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_RESET);
DELAY(100);
ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_CLOCK_DIV_28);
DELAY(100);
+#endif
/*
* Set all Ethernet address registers to the same initial values
* set all four addresses to 66-88-aa-cc-dd-ee
*/
- ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR1,
- (eaddr[2] << 24) | (eaddr[3] << 16) | (eaddr[4] << 8) | eaddr[5]);
- ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR2, (eaddr[0] << 8) | eaddr[1]);
+ ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR1, (sc->arge_eaddr[2] << 24)
+ | (sc->arge_eaddr[3] << 16) | (sc->arge_eaddr[4] << 8)
+ | sc->arge_eaddr[5]);
+ ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR2, (sc->arge_eaddr[0] << 8)
+ | sc->arge_eaddr[1]);
ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG0,
FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT);
@@ -458,30 +514,44 @@ arge_attach(device_t dev)
ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMASK,
FIFO_RX_FILTMASK_DEFAULT);
- /*
- * Check if we have single-PHY MAC or multi-PHY
- */
- phys_total = 0;
- for (i = 0; i < ARGE_NPHY; i++)
- if (phymask & (1 << i))
- phys_total ++;
+#if defined(ARGE_MDIO)
+ sc->arge_miiproxy = mii_attach_proxy(sc->arge_dev, arge_attach_proxy, sc);
+ if (sc->arge_miiproxy == NULL)
+ return (arge_attach_finish(sc));
+#else
+ return (arge_attach_finish(sc));
+#endif
+fail:
+ if (error)
+ arge_detach(dev);
- if (phys_total == 0) {
- error = EINVAL;
- goto fail;
- }
+ return (error);
+}
- if (phys_total == 1) {
- /* Do MII setup. */
- error = mii_attach(dev, &sc->arge_miibus, ifp,
- arge_ifmedia_upd, arge_ifmedia_sts, BMSR_DEFCAPMASK,
- MII_PHY_ANY, MII_OFFSET_ANY, 0);
- if (error != 0) {
- device_printf(dev, "attaching PHYs failed\n");
- goto fail;
+static int
+arge_attach_finish(struct arge_softc *sc)
+{
+ int error, phy;
+
+ device_printf(sc->arge_dev, "finishing attachment, phymask %04x"
+ ", proxy %s \n", sc->arge_phymask, sc->arge_miiproxy == NULL ?
+ "null" : "set");
+ for (phy = 0; phy < ARGE_NPHY; phy++) {
+ if (((1 << phy) & sc->arge_phymask) != 0) {
+ error = mii_attach(sc->arge_miiproxy != NULL ?
+ sc->arge_miiproxy : sc->arge_dev,
+ &sc->arge_miibus, sc->arge_ifp,
+ arge_ifmedia_upd, arge_ifmedia_sts,
+ BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
+ if (error != 0) {
+ device_printf(sc->arge_dev, "unable to attach"
+ " PHY %d: %d\n", phy, error);
+ goto fail;
+ }
}
}
- else {
+ if (sc->arge_miibus == NULL) {
+ /* no PHY, so use hard-coded values */
ifmedia_init(&sc->arge_ifmedia, 0,
arge_multiphy_mediachange,
arge_multiphy_mediastatus);
@@ -494,24 +564,23 @@ arge_attach(device_t dev)
}
/* Call MI attach routine. */
- ether_ifattach(ifp, eaddr);
+ ether_ifattach(sc->arge_ifp, sc->arge_eaddr);
/* Hook interrupt last to avoid having to lock softc */
- error = bus_setup_intr(dev, sc->arge_irq, INTR_TYPE_NET | INTR_MPSAFE,
+ error = bus_setup_intr(sc->arge_dev, sc->arge_irq, INTR_TYPE_NET | INTR_MPSAFE,
arge_intr_filter, arge_intr, sc, &sc->arge_intrhand);
if (error) {
- device_printf(dev, "couldn't set up irq\n");
- ether_ifdetach(ifp);
+ device_printf(sc->arge_dev, "couldn't set up irq\n");
+ ether_ifdetach(sc->arge_ifp);
goto fail;
}
/* setup sysctl variables */
- arge_attach_sysctl(dev);
-
+ arge_attach_sysctl(sc->arge_dev);
fail:
if (error)
- arge_detach(dev);
+ arge_detach(sc->arge_dev);
return (error);
}
@@ -542,6 +611,9 @@ arge_detach(device_t dev)
if (sc->arge_miibus)
device_delete_child(dev, sc->arge_miibus);
+ if (sc->arge_miiproxy)
+ device_delete_child(dev, sc->arge_miiproxy);
+
bus_generic_detach(dev);
if (sc->arge_intrhand)
@@ -592,6 +664,13 @@ arge_shutdown(device_t dev)
return (0);
}
+static void
+arge_hinted_child(device_t bus, const char *dname, int dunit)
+{
+ BUS_ADD_CHILD(bus, 0, dname, dunit);
+ device_printf(bus, "hinted child %s%d\n", dname, dunit);
+}
+
static int
arge_miibus_readreg(device_t dev, int phy, int reg)
{
@@ -600,16 +679,13 @@ arge_miibus_readreg(device_t dev, int phy, int reg)
uint32_t addr = (phy << MAC_MII_PHY_ADDR_SHIFT)
| (reg & MAC_MII_REG_MASK);
- if ((sc->arge_phymask & (1 << phy)) == 0)
- return (0);
-
mtx_lock(&miibus_mtx);
- ARGE_MII_WRITE(AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE);
- ARGE_MII_WRITE(AR71XX_MAC_MII_ADDR, addr);
- ARGE_MII_WRITE(AR71XX_MAC_MII_CMD, MAC_MII_CMD_READ);
+ ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE);
+ ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_ADDR, addr);
+ ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_READ);
i = ARGE_MII_TIMEOUT;
- while ((ARGE_MII_READ(AR71XX_MAC_MII_INDICATOR) &
+ while ((ARGE_MDIO_READ(sc, AR71XX_MAC_MII_INDICATOR) &
MAC_MII_INDICATOR_BUSY) && (i--))
DELAY(5);
@@ -620,8 +696,8 @@ arge_miibus_readreg(device_t dev, int phy, int reg)
return (-1);
}
- result = ARGE_MII_READ(AR71XX_MAC_MII_STATUS) & MAC_MII_STATUS_MASK;
- ARGE_MII_WRITE(AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE);
+ result = ARGE_MDIO_READ(sc, AR71XX_MAC_MII_STATUS) & MAC_MII_STATUS_MASK;
+ ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE);
mtx_unlock(&miibus_mtx);
ARGEDEBUG(sc, ARGE_DBG_MII, "%s: phy=%d, reg=%02x, value[%08x]=%04x\n", __func__,
@@ -638,19 +714,15 @@ arge_miibus_writereg(device_t dev, int phy, int reg, int data)
uint32_t addr =
(phy << MAC_MII_PHY_ADDR_SHIFT) | (reg & MAC_MII_REG_MASK);
-
- if ((sc->arge_phymask & (1 << phy)) == 0)
- return (-1);
-
ARGEDEBUG(sc, ARGE_DBG_MII, "%s: phy=%d, reg=%02x, value=%04x\n", __func__,
phy, reg, data);
mtx_lock(&miibus_mtx);
- ARGE_MII_WRITE(AR71XX_MAC_MII_ADDR, addr);
- ARGE_MII_WRITE(AR71XX_MAC_MII_CONTROL, data);
+ ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_ADDR, addr);
+ ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CONTROL, data);
i = ARGE_MII_TIMEOUT;
- while ((ARGE_MII_READ(AR71XX_MAC_MII_INDICATOR) &
+ while ((ARGE_MDIO_READ(sc, AR71XX_MAC_MII_INDICATOR) &
MAC_MII_INDICATOR_BUSY) && (i--))
DELAY(5);
@@ -715,6 +787,8 @@ arge_set_pll(struct arge_softc *sc, int media, int duplex)
uint32_t fifo_tx;
int if_speed;
+ ARGEDEBUG(sc, ARGE_DBG_MII, "set_pll(%04x, %s)\n", media,
+ duplex == IFM_FDX ? "full" : "half");
cfg = ARGE_READ(sc, AR71XX_MAC_CFG2);
cfg &= ~(MAC_CFG2_IFACE_MODE_1000
| MAC_CFG2_IFACE_MODE_10_100
@@ -1923,3 +1997,47 @@ arge_multiphy_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
sc->arge_duplex_mode;
}
+#if defined(ARGE_MDIO)
+static int
+argemdio_probe(device_t dev)
+{
+ device_set_desc(dev, "Atheros AR71xx built-in ethernet interface, MDIO controller");
+ return (0);
+}
+
+static int
+argemdio_attach(device_t dev)
+{
+ struct arge_softc *sc;
+ int error = 0;
+
+ sc = device_get_softc(dev);
+ sc->arge_dev = dev;
+ sc->arge_mac_unit = device_get_unit(dev);
+ sc->arge_rid = 0;
+ sc->arge_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->arge_rid, RF_ACTIVE | RF_SHAREABLE);
+ if (sc->arge_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ error = ENXIO;
+ goto fail;
+ }
+ /* Reset MII bus */
+ ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_RESET);
+ DELAY(100);
+ ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_CLOCK_DIV_28);
+ DELAY(100);
+ bus_generic_probe(dev);
+ bus_enumerate_hinted_children(dev);
+ error = bus_generic_attach(dev);
+fail:
+ return (error);
+}
+
+static int
+argemdio_detach(device_t dev)
+{
+ return (0);
+}
+
+#endif
diff --git a/sys/mips/atheros/if_argevar.h b/sys/mips/atheros/if_argevar.h
index c1df678..dc3d931 100644
--- a/sys/mips/atheros/if_argevar.h
+++ b/sys/mips/atheros/if_argevar.h
@@ -67,15 +67,10 @@
#define ARGE_CLEAR_BITS(sc, reg, bits) \
ARGE_WRITE(sc, reg, ARGE_READ(sc, (reg)) & ~(bits))
-/*
- * MII registers access macros
- */
-#define ARGE_MII_READ(reg) \
- *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((AR71XX_MII_BASE + reg)))
-
-#define ARGE_MII_WRITE(reg, val) \
- *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((AR71XX_MII_BASE + reg))) = (val)
-
+#define ARGE_MDIO_WRITE(_sc, _reg, _val) \
+ ARGE_WRITE((_sc), (_reg), (_val))
+#define ARGE_MDIO_READ(_sc, _reg) \
+ ARGE_READ((_sc), (_reg))
#define ARGE_DESC_EMPTY (1 << 31)
#define ARGE_DESC_MORE (1 << 24)
@@ -132,11 +127,14 @@ struct arge_softc {
*/
uint32_t arge_media_type;
uint32_t arge_duplex_mode;
+ uint32_t arge_phymask;
+ uint8_t arge_eaddr[ETHER_ADDR_LEN];
struct resource *arge_res;
int arge_rid;
struct resource *arge_irq;
void *arge_intrhand;
device_t arge_miibus;
+ device_t arge_miiproxy;
bus_dma_tag_t arge_parent_tag;
bus_dma_tag_t arge_tag;
struct mtx arge_mtx;
@@ -148,7 +146,6 @@ struct arge_softc {
int arge_detach;
uint32_t arge_intr_status;
int arge_mac_unit;
- int arge_phymask;
int arge_if_flags;
uint32_t arge_debug;
struct {
--Apple-Mail=_213E4B8A-6009-4FF8-A23A-C6A4E1D4CE37--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?66DDA0A2-F878-43FF-8824-54868F493B18>
