How to access MII management bus from userspace?

I'm trying to write a user-space app to access devices on an MII management bus (MDIO/MDC) associated with an Ethernet controller.

I'm using code copied from mii-tool, but the method used by mii-tool to override the PHY id doesn't seem to work.

After calling an ioctl() to fill in the mii/phy details in the interface request structure, mii-tool then overrides the phy_id field like this:

static struct ifreq ifr;

ioctl(skfd, SIOCGMIIPHY, &ifr); // load ifr with mii/phy details

struct mii_ioctl_data *mii = (struct mii_ioctl_data*)&ifr.ifr_data; mii->phy_id = phyid; // override phy mii bus address But that doesn't actually seem to work. No matter what value is written to mii->phy_id, the id that ends up passed to the ethernet driver's mdio_read/write() functions is always 0.

How do I control what MII bus address is read/written by the SIOCGMIIREG and SIOCSMIIREG?

--
Grant Edwards               grant.b.edwards        Yow! What GOOD is a
                                  at               CARDBOARD suitcase ANYWAY?
                              gmail.com
Reply to
Grant Edwards
Loading thread data ...

I've traced the calls through the kernel, and that field in the request structure is never even passed to the phy_read() or phy_write() routines by phy_mii_ioclt(). phy_read() and phy_write() always use a phy_id that's taken from a different structure.

However that field _is_ checked by phy_mii_ioclt() and there are certain side effects if the phy id you're attempting to write to matches the phy id that actually gets written to. Oddly, the write happens (not to the id you specified) even if they don't match, but there are extra side effects if the request matches the id that's forced during the write.

Doesn't make much sense to me...

AFAICT you can't, and mii-tool is deluding itself.

--
Grant Edwards               grant.b.edwards        Yow! I'll show you MY
                                  at               telex number if you show me
                              gmail.com            YOURS ...
Reply to
Grant Edwards

a;

Yow! I'll show you MY

=A0 =A0 =A0 =A0 =A0 =A0 =A0 telex number if you show me

=A0 =A0 =A0 =A0 =A0YOURS ...

Hi Grant,

Here's the code I used to read MII regs.

ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, "eth0"); //set to whatever your ethernet device is mii_ioctl_data* mii =3D (mii_ioctl_data*)(&ifr.ifr_data); mii->phy_id =3D phyId; //set to your phy's ID mii->reg_num =3D reg; //the register you want to read mii->val_in =3D 0; mii->val_out =3D 0;

int fd =3D socket(AF_INET, SOCK_DGRAM, 0); int err =3D ioctl(fd, SIOCGMIIREG, &ifr);

Assuming your working an embedded platform, you may have a custom ethernet driver. Make sure you should have static int mdio_read(struct net_device *dev, int phy_id, int location) static void mdio_write(struct net_device *dev, int phy_id, int location, int value) in your driver. Try putting a printk here to see the phy_id.

If your ioctl calls don't get as far as mdio_read/write, check your ioctl function in your driver. It should call generic_mii_ioctl(). Also, check that your (driver's private data)->mii.phy_id_mask isn't set to 0!

What driver are you using / can you post your driver's ioctl function?

Good luck, Jeremy

Reply to
Jeremy

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.