From 6804a8c89b8c31c3ef4e7e8ab03b82ebee41dd45 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Apr 2018 12:38:55 +0100 Subject: [mii] Separate concepts of MII interface and MII device We currently have no generic concept of a PHY address, since all existing implementations simply hardcode the PHY address within the MII access methods. A bit-bashing MII interface will need to be provided with an explicit PHY address in order to generate the correct waveform. Allow for this by separating out the concept of a MII device (i.e. a specific PHY address attached to a particular MII interface). Signed-off-by: Michael Brown --- src/drivers/net/mii.c | 14 +++++----- src/drivers/net/realtek.c | 23 ++++++++++------ src/drivers/net/realtek.h | 4 ++- src/drivers/net/rhine.c | 19 ++++++++----- src/drivers/net/rhine.h | 4 ++- src/drivers/net/smscusb.c | 16 ++++++----- src/drivers/net/smscusb.h | 7 +++-- src/drivers/net/velocity.c | 19 ++++++++----- src/drivers/net/velocity.h | 4 ++- src/include/ipxe/mii.h | 67 +++++++++++++++++++++++++++++++++------------- 10 files changed, 118 insertions(+), 59 deletions(-) diff --git a/src/drivers/net/mii.c b/src/drivers/net/mii.c index 9b297029..f6db3074 100644 --- a/src/drivers/net/mii.c +++ b/src/drivers/net/mii.c @@ -37,10 +37,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * Restart autonegotiation * - * @v mii MII interface + * @v mii MII device * @ret rc Return status code */ -int mii_restart ( struct mii_interface *mii ) { +int mii_restart ( struct mii_device *mii ) { int bmcr; int rc; @@ -66,12 +66,12 @@ int mii_restart ( struct mii_interface *mii ) { } /** - * Reset MII interface + * Reset MII device * - * @v mii MII interface + * @v mii MII device * @ret rc Return status code */ -int mii_reset ( struct mii_interface *mii ) { +int mii_reset ( struct mii_device *mii ) { unsigned int i; int bmcr; int rc; @@ -119,11 +119,11 @@ int mii_reset ( struct mii_interface *mii ) { /** * Update link status via MII * - * @v mii MII interface + * @v mii MII device * @v netdev Network device * @ret rc Return status code */ -int mii_check_link ( struct mii_interface *mii, struct net_device *netdev ) { +int mii_check_link ( struct mii_device *mii, struct net_device *netdev ) { int bmsr; int link; int rc; diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 022b5932..310b9f96 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -242,12 +242,15 @@ static int realtek_init_eeprom ( struct net_device *netdev ) { /** * Read from MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @ret value Data read, or negative error */ -static int realtek_mii_read ( struct mii_interface *mii, unsigned int reg ) { - struct realtek_nic *rtl = container_of ( mii, struct realtek_nic, mii ); +static int realtek_mii_read ( struct mii_interface *mdio, + unsigned int phy __unused, unsigned int reg ) { + struct realtek_nic *rtl = + container_of ( mdio, struct realtek_nic, mdio ); unsigned int i; uint32_t value; @@ -279,14 +282,17 @@ static int realtek_mii_read ( struct mii_interface *mii, unsigned int reg ) { /** * Write to MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @v data Data to write * @ret rc Return status code */ -static int realtek_mii_write ( struct mii_interface *mii, unsigned int reg, - unsigned int data) { - struct realtek_nic *rtl = container_of ( mii, struct realtek_nic, mii ); +static int realtek_mii_write ( struct mii_interface *mdio, + unsigned int phy __unused, unsigned int reg, + unsigned int data ) { + struct realtek_nic *rtl = + container_of ( mdio, struct realtek_nic, mdio ); unsigned int i; /* Fail if PHYAR register is not present */ @@ -1158,7 +1164,8 @@ static int realtek_probe ( struct pci_device *pci ) { } /* Initialise and reset MII interface */ - mii_init ( &rtl->mii, &realtek_mii_operations ); + mdio_init ( &rtl->mdio, &realtek_mii_operations ); + mii_init ( &rtl->mii, &rtl->mdio, 0 ); if ( ( rc = realtek_phy_reset ( rtl ) ) != 0 ) goto err_phy_reset; diff --git a/src/drivers/net/realtek.h b/src/drivers/net/realtek.h index b1ce7f98..4d13784c 100644 --- a/src/drivers/net/realtek.h +++ b/src/drivers/net/realtek.h @@ -283,7 +283,9 @@ struct realtek_nic { /** Non-volatile options */ struct nvo_block nvo; /** MII interface */ - struct mii_interface mii; + struct mii_interface mdio; + /** MII device */ + struct mii_device mii; /** Legacy datapath mode */ int legacy; diff --git a/src/drivers/net/rhine.c b/src/drivers/net/rhine.c index 3d8f696d..a1dc5872 100644 --- a/src/drivers/net/rhine.c +++ b/src/drivers/net/rhine.c @@ -49,12 +49,14 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** * Read from MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @ret value Data read, or negative error */ -static int rhine_mii_read ( struct mii_interface *mii, unsigned int reg ) { - struct rhine_nic *rhn = container_of ( mii, struct rhine_nic, mii ); +static int rhine_mii_read ( struct mii_interface *mdio, + unsigned int phy __unused, unsigned int reg ) { + struct rhine_nic *rhn = container_of ( mdio, struct rhine_nic, mdio ); unsigned int timeout = RHINE_TIMEOUT_US; uint8_t cr; @@ -80,14 +82,16 @@ static int rhine_mii_read ( struct mii_interface *mii, unsigned int reg ) { /** * Write to MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @v data Data to write * @ret rc Return status code */ -static int rhine_mii_write ( struct mii_interface *mii, unsigned int reg, +static int rhine_mii_write ( struct mii_interface *mdio, + unsigned int phy __unused, unsigned int reg, unsigned int data ) { - struct rhine_nic *rhn = container_of ( mii, struct rhine_nic, mii ); + struct rhine_nic *rhn = container_of ( mdio, struct rhine_nic, mdio ); unsigned int timeout = RHINE_TIMEOUT_US; uint8_t cr; @@ -719,7 +723,8 @@ static int rhine_probe ( struct pci_device *pci ) { netdev->hw_addr[i] = readb ( rhn->regs + RHINE_MAC + i ); /* Initialise and reset MII interface */ - mii_init ( &rhn->mii, &rhine_mii_operations ); + mdio_init ( &rhn->mdio, &rhine_mii_operations ); + mii_init ( &rhn->mii, &rhn->mdio, 0 ); if ( ( rc = mii_reset ( &rhn->mii ) ) != 0 ) { DBGC ( rhn, "RHINE %p could not reset MII: %s\n", rhn, strerror ( rc ) ); diff --git a/src/drivers/net/rhine.h b/src/drivers/net/rhine.h index b26f9ae7..eef49ec9 100644 --- a/src/drivers/net/rhine.h +++ b/src/drivers/net/rhine.h @@ -237,7 +237,9 @@ struct rhine_nic { uint8_t cr1; /** MII interface */ - struct mii_interface mii; + struct mii_interface mdio; + /** MII device */ + struct mii_device mii; /** Transmit descriptor ring */ struct rhine_ring tx; diff --git a/src/drivers/net/smscusb.c b/src/drivers/net/smscusb.c index 60390ce3..538d338c 100644 --- a/src/drivers/net/smscusb.c +++ b/src/drivers/net/smscusb.c @@ -481,13 +481,15 @@ static int smscusb_mii_wait ( struct smscusb_device *smscusb ) { /** * Read from MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @ret value Data read, or negative error */ -static int smscusb_mii_read ( struct mii_interface *mii, unsigned int reg ) { +static int smscusb_mii_read ( struct mii_interface *mdio, + unsigned int phy __unused, unsigned int reg ) { struct smscusb_device *smscusb = - container_of ( mii, struct smscusb_device, mii ); + container_of ( mdio, struct smscusb_device, mdio ); unsigned int base = smscusb->mii_base; uint32_t mii_access; uint32_t mii_data; @@ -520,15 +522,17 @@ static int smscusb_mii_read ( struct mii_interface *mii, unsigned int reg ) { /** * Write to MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @v data Data to write * @ret rc Return status code */ -static int smscusb_mii_write ( struct mii_interface *mii, unsigned int reg, +static int smscusb_mii_write ( struct mii_interface *mdio, + unsigned int phy __unused, unsigned int reg, unsigned int data ) { struct smscusb_device *smscusb = - container_of ( mii, struct smscusb_device, mii ); + container_of ( mdio, struct smscusb_device, mdio ); unsigned int base = smscusb->mii_base; uint32_t mii_access; uint32_t mii_data; diff --git a/src/drivers/net/smscusb.h b/src/drivers/net/smscusb.h index 5e4440ea..b5d9ad3f 100644 --- a/src/drivers/net/smscusb.h +++ b/src/drivers/net/smscusb.h @@ -151,7 +151,9 @@ struct smscusb_device { /** USB network device */ struct usbnet_device usbnet; /** MII interface */ - struct mii_interface mii; + struct mii_interface mdio; + /** MII device */ + struct mii_device mii; /** MII register base */ uint16_t mii_base; /** PHY interrupt source register */ @@ -275,7 +277,8 @@ static inline __attribute__ (( always_inline )) void smscusb_mii_init ( struct smscusb_device *smscusb, unsigned int mii_base, unsigned int phy_source ) { - mii_init ( &smscusb->mii, &smscusb_mii_operations ); + mdio_init ( &smscusb->mdio, &smscusb_mii_operations ); + mii_init ( &smscusb->mii, &smscusb->mdio, 0 ); smscusb->mii_base = mii_base; smscusb->phy_source = phy_source; } diff --git a/src/drivers/net/velocity.c b/src/drivers/net/velocity.c index 129fc136..0a2a3ac1 100644 --- a/src/drivers/net/velocity.c +++ b/src/drivers/net/velocity.c @@ -100,13 +100,15 @@ static int velocity_autopoll_start ( struct velocity_nic *vlc ) { /** * Read from MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @ret value Data read, or negative error */ -static int velocity_mii_read ( struct mii_interface *mii, unsigned int reg ) { +static int velocity_mii_read ( struct mii_interface *mdio, + unsigned int phy __unused, unsigned int reg ) { struct velocity_nic *vlc = - container_of ( mii, struct velocity_nic, mii ); + container_of ( mdio, struct velocity_nic, mdio ); int timeout = VELOCITY_TIMEOUT_US; int result; @@ -140,15 +142,17 @@ static int velocity_mii_read ( struct mii_interface *mii, unsigned int reg ) { /** * Write to MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @v data Data to write * @ret rc Return status code */ -static int velocity_mii_write ( struct mii_interface *mii, unsigned int reg, +static int velocity_mii_write ( struct mii_interface *mdio, + unsigned int phy __unused, unsigned int reg, unsigned int data) { struct velocity_nic *vlc = - container_of ( mii, struct velocity_nic, mii ); + container_of ( mdio, struct velocity_nic, mdio ); int timeout = VELOCITY_TIMEOUT_US; DBGC2 ( vlc, "VELOCITY %p MII write reg %d data 0x%04x\n", @@ -747,7 +751,8 @@ static int velocity_probe ( struct pci_device *pci ) { netdev->hw_addr[5] = readb ( vlc->regs + VELOCITY_MAC5 ); /* Initialise and reset MII interface */ - mii_init ( &vlc->mii, &velocity_mii_operations ); + mdio_init ( &vlc->mdio, &velocity_mii_operations ); + mii_init ( &vlc->mii, &vlc->mdio, 0 ); if ( ( rc = mii_reset ( &vlc->mii ) ) != 0 ) { DBGC ( vlc, "VELOCITY %p could not reset MII: %s\n", vlc, strerror ( rc ) ); diff --git a/src/drivers/net/velocity.h b/src/drivers/net/velocity.h index 04e6a146..84817d1b 100644 --- a/src/drivers/net/velocity.h +++ b/src/drivers/net/velocity.h @@ -326,7 +326,9 @@ struct velocity_nic { /** Registers */ void *regs; /** MII interface */ - struct mii_interface mii; + struct mii_interface mdio; + /** MII device */ + struct mii_device mii; /** Netdev */ struct net_device *netdev; diff --git a/src/include/ipxe/mii.h b/src/include/ipxe/mii.h index c2245b49..154f69cf 100644 --- a/src/include/ipxe/mii.h +++ b/src/include/ipxe/mii.h @@ -19,21 +19,24 @@ struct mii_operations { /** * Read from MII register * - * @v mii MII interface + * @v mdio MII interface + * @v phy PHY address * @v reg Register address * @ret data Data read, or negative error */ - int ( * read ) ( struct mii_interface *mii, unsigned int reg ); + int ( * read ) ( struct mii_interface *mdio, unsigned int phy, + unsigned int reg ); /** * Write to MII register * - * @v mii MII interface + * @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 *mii, unsigned int reg, - unsigned int data ); + int ( * write ) ( struct mii_interface *mdio, unsigned int phy, + unsigned int reg, unsigned int data ); }; /** An MII interface */ @@ -42,49 +45,75 @@ struct mii_interface { 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 mii MII interface + * @v mdio MII interface * @v op MII interface operations */ static inline __attribute__ (( always_inline )) void -mii_init ( struct mii_interface *mii, struct mii_operations *op ) { - mii->op = op; +mdio_init ( struct mii_interface *mdio, struct mii_operations *op ) { + mdio->op = op; } /** - * Read from MII register + * Initialise MII device * + * @v mii MII device * @v mii 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_interface *mii, unsigned int reg ) { - return mii->op->read ( mii, reg ); +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 interface + * @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_interface *mii, unsigned int reg, unsigned int data ) { - return mii->op->write ( mii, reg, data ); +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 interface + * @v mii MII device */ static inline void -mii_dump ( struct mii_interface *mii ) { +mii_dump ( struct mii_device *mii ) { unsigned int i; int data; @@ -112,9 +141,9 @@ mii_dump ( struct mii_interface *mii ) { /** Maximum time to wait for a reset, in milliseconds */ #define MII_RESET_MAX_WAIT_MS 500 -extern int mii_restart ( struct mii_interface *mii ); -extern int mii_reset ( struct mii_interface *mii ); -extern int mii_check_link ( struct mii_interface *mii, +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 */ -- cgit v1.2.3-55-g7522