#ifndef _IPXE_MII_H #define _IPXE_MII_H /** @file * * Media Independent Interface * */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include struct mii_interface; /** MII interface operations */ struct mii_operations { /** * Read from MII register * * @v mdio MII interface * @v phy PHY address * @v reg Register address * @ret data Data read, or negative error */ int ( * read ) ( struct mii_interface *mdio, unsigned int phy, unsigned int reg ); /** * Write to MII register * * @v mdio MII interface * @v phy PHY address * @v reg Register address * @v data Data to write * @ret rc Return status code */ int ( * write ) ( struct mii_interface *mdio, unsigned int phy, unsigned int reg, unsigned int data ); }; /** An MII interface */ struct mii_interface { /** Interface operations */ struct mii_operations *op; }; /** An MII device */ struct mii_device { /** MII interface */ struct mii_interface *mdio; /** PHY address */ unsigned int address; }; /** * Initialise MII interface * * @v mdio MII interface * @v op MII interface operations */ static inline __attribute__ (( always_inline )) void mdio_init ( struct mii_interface *mdio, struct mii_operations *op ) { mdio->op = op; } /** * Initialise MII device * * @v mii MII device * @v mdio MII interface * @v address PHY address */ static inline __attribute__ (( always_inline )) void mii_init ( struct mii_device *mii, struct mii_interface *mdio, unsigned int address ) { mii->mdio = mdio; mii->address = address; } /** * Read from MII register * * @v mii MII device * @v reg Register address * @ret data Data read, or negative error */ static inline __attribute__ (( always_inline )) int mii_read ( struct mii_device *mii, unsigned int reg ) { struct mii_interface *mdio = mii->mdio; return mdio->op->read ( mdio, mii->address, reg ); } /** * Write to MII register * * @v mii MII device * @v reg Register address * @v data Data to write * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int mii_write ( struct mii_device *mii, unsigned int reg, unsigned int data ) { struct mii_interface *mdio = mii->mdio; return mdio->op->write ( mdio, mii->address, reg, data ); } /** * Dump MII registers (for debugging) * * @v mii MII device */ static inline void mii_dump ( struct mii_device *mii ) { unsigned int i; int data; /* Do nothing unless debug output is enabled */ if ( ! DBG_LOG ) return; /* Dump basic MII register set */ for ( i = 0 ; i < 16 ; i++ ) { if ( ( i % 8 ) == 0 ) { DBGC ( mii, "MII %p registers %02x-%02x:", mii, i, ( i + 7 ) ); } data = mii_read ( mii, i ); if ( data >= 0 ) { DBGC ( mii, " %04x", data ); } else { DBGC ( mii, " XXXX" ); } if ( ( i % 8 ) == 7 ) DBGC ( mii, "\n" ); } } /** Maximum time to wait for a reset, in milliseconds */ #define MII_RESET_MAX_WAIT_MS 500 extern int mii_restart ( struct mii_device *mii ); extern int mii_reset ( struct mii_device *mii ); extern int mii_check_link ( struct mii_device *mii, struct net_device *netdev ); #endif /* _IPXE_MII_H */