]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[mii] Separate concepts of MII interface and MII device
authorMichael Brown <mcb30@ipxe.org>
Thu, 19 Apr 2018 11:38:55 +0000 (12:38 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 19 Apr 2018 11:43:06 +0000 (12:43 +0100)
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>
src/drivers/net/mii.c
src/drivers/net/realtek.c
src/drivers/net/realtek.h
src/drivers/net/rhine.c
src/drivers/net/rhine.h
src/drivers/net/smscusb.c
src/drivers/net/smscusb.h
src/drivers/net/velocity.c
src/drivers/net/velocity.h
src/include/ipxe/mii.h

index 9b297029ad04562edc78f633eb4a75ef81eebdeb..f6db307409a1be5afd1efadf63f42aee9306c465 100644 (file)
@@ -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;
index 022b59324c1421e97a9d0fec5ba10d999ba21d01..310b9f96a8349bde35ac4e48feac7c1f64851071 100644 (file)
@@ -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;
 
index b1ce7f98f77bb3c29eb9558c4056a265402a0745..4d13784c4d28e93615032b832d8c9e9d9b9aef09 100644 (file)
@@ -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;
index 3d8f696db7ca20646fd6380a8eab5707e9346115..a1dc5872520d41fd43d5739d94bbac1ee56df501 100644 (file)
@@ -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 ) );
index b26f9ae78278496851b7694030d60a991da5881c..eef49ec98be171e99f13bff8c85242b8453070c5 100644 (file)
@@ -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;
index 60390ce31c564e0f4e3f7d529e2a6b293e9c96f0..538d338c49a5672a4288a7fc086cbb96f7bf9cb2 100644 (file)
@@ -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;
index 5e4440ea60fa28963a9baa53a0b6db815ecea41c..b5d9ad3fcc323a3d5b76f4fcc51dbb1874c2c6ae 100644 (file)
@@ -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;
 }
index 129fc136adeebcde16101e182215c492e5576e91..0a2a3ac1083ec9df454cabfab06358388f0d3889 100644 (file)
@@ -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 ) );
index 04e6a14605fb9818d70a670be53964b1d1342dde..84817d1bbb8bbf4810292bbd80fb53e2b61dd352 100644 (file)
@@ -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;
 
index c2245b49e08e60401af06d30189ee0d429376e8b..154f69cf74ccb379909c3ff91655dd5136769a87 100644 (file)
@@ -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 */