summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Brown2018-04-19 13:38:55 +0200
committerMichael Brown2018-04-19 13:43:06 +0200
commit6804a8c89b8c31c3ef4e7e8ab03b82ebee41dd45 (patch)
treeceb234f68817ac16268c97b55771c0e0d16c9e7c /src
parent[velocity] Fix usage of mii_read() and mii_write() (diff)
downloadipxe-6804a8c89b8c31c3ef4e7e8ab03b82ebee41dd45.tar.gz
ipxe-6804a8c89b8c31c3ef4e7e8ab03b82ebee41dd45.tar.xz
ipxe-6804a8c89b8c31c3ef4e7e8ab03b82ebee41dd45.zip
[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 <mcb30@ipxe.org>
Diffstat (limited to 'src')
-rw-r--r--src/drivers/net/mii.c14
-rw-r--r--src/drivers/net/realtek.c23
-rw-r--r--src/drivers/net/realtek.h4
-rw-r--r--src/drivers/net/rhine.c19
-rw-r--r--src/drivers/net/rhine.h4
-rw-r--r--src/drivers/net/smscusb.c16
-rw-r--r--src/drivers/net/smscusb.h7
-rw-r--r--src/drivers/net/velocity.c19
-rw-r--r--src/drivers/net/velocity.h4
-rw-r--r--src/include/ipxe/mii.h67
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 */