This is an old revision of the document!
A quick and dirty summary: miibus
(Robert Watson and Warner Losh)
Media Independent Interface (MII) is a standard interface connecting network interface MACs with PHYs, and carries information regarding device capabilities, link status, etc. MII is a simple bus protocol driven by the MAC, but exposed via PCI (or similar) to the operating system. Several devices may be present on an MII bus, typically one per PHY, each addressed using a 5-bit device ID. Further, each device can expose several registers, which may be set or retrieved, identified by a 5-bit register IDs. This allows addressing requests to specific devices, as well as enumeration through standard interpretations of registers. On a boring NIC, you might have one PHY (a 10Mbps/100Mbps/1Gbps RJ-45 UTP port), but on an embedded board, multiply PHYs might appear on the MII bux.
Because MII exists in most (all) network interface devices, and is functionally extremely similar, FreeBSD provides an abstraction, miibus(4), used by many device drivers. Device drivers implement MII get and set methods, mapping get and set operations into device driver-specific I/O, such as PCI reads and writes. As PHYs vary, different PHY drivers may attach, based on OUI's returned during enumeration. Device drivers can then map network ioctls, such as media requests, into MII operations, which miibus(4) will arrange to be handled appropriately.
Simplified world view: MAC, MII, and PHY
+-------+ +-------+
| | === MII DATA ===== | |
| | === MII CLOCK ==== | |
... ===PCI=== | MAC | | PHY | (real fibre and copper and stuff)
| | === PHY RECEIVE == | |
| | === PHY SEND ===== | |
+-------+ +-------+
Simplified world view: MII communication traces
Typical MII communications register read:
| T NIC PHY i --- start read/write ---------------> m --- 5-bit device, 5-bit register ---> e <-- register data ------------------- | V
Typical MII communications register write:
| T NIC PHY i --- start read/write ---------------> m --- 5-bit device, 5-bit register ---> e --- register data ------------------> | V
Device drivers
In FreeBSD, device drivers indicate that they support MII by implementing two device methods:
DEVMETHOD(miibus_readreg, foo_miibus_readreg), DEVMETHOD(miibus_writereg, foo_miibus_writereg),
In this case, foo_miibus_readreg and foo_miibus_writereg will implement the foo driver's device-specific methods for accessing the device's MII bus, such as PCI reads/writes.
In addition, a device driver might want to override certain methods, such as state change, that involve more complex NIC/driver logic:
DEVMETHOD(miibus_statchg, vr_miibus_statchg),
Finally, the device driver itself may need to use this MII information, such as when implementing the ifmedia ioctl()'s that allow the network stack to query link state and configuration. For example, this code comes from the if_vr driver:
/*
* Report current media status.
*/
static void
vr_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct vr_softc *sc;
struct mii_data *mii;
sc = ifp->if_softc;
mii = device_get_softc(sc->vr_miibus);
VR_LOCK(sc);
mii_pollstat(mii);
VR_UNLOCK(sc);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
}