SIOCGMIIPHY 和 SIOCSMIIREG 命令

使用ioctl命令时,可以看到上述两个命令的存在,

在头文件 include/linux/sockios.h,定义如下:

#define SIOCETHTOOL    0x8946        /* Ethtool interface        */     ethtool 接口

#define SIOCGMIIPHY    0x8947        /* Get address of MII PHY in use. */    获取MII phy的地址
#define SIOCGMIIREG    0x8948        /* Read MII PHY register.    */     读取 MII phy 寄存器
#define SIOCSMIIREG    0x8949        /* Write MII PHY register.    */      写MII phy 寄存器

内核中对于上述两个命令的处理定义在文件  /drivers/net/phy/phy.c 的函数 phy_mii_ioctl中,

函数原型如下:

/**
 * phy_mii_ioctl - generic PHY MII ioctl interface
 * @phydev: the phy_device struct
 * @ifr: &struct ifreq for socket ioctl's
 * @cmd: ioctl cmd to execute
 *
 * Note that this function is currently incompatible with the
 * PHYCONTROL layer.  It changes registers without regard to
 * current state.  Use at own risk.
 */
int phy_mii_ioctl(struct phy_device *phydev,
        struct ifreq *ifr, int cmd)
{
    struct mii_ioctl_data *mii_data = if_mii(ifr);
    u16 val = mii_data->val_in;

switch (cmd) {
    case SIOCGMIIPHY:     // 获取phy的地址
        mii_data->phy_id = phydev->addr;
        /* fall through */

    case SIOCGMIIREG:
        mii_data->val_out = mdiobus_read(phydev->bus,  mii_data->phy_id, mii_data->reg_num);
        break;

    case SIOCSMIIREG:
        if (mii_data->phy_id == phydev->addr) {
            switch(mii_data->reg_num) {
                case MII_BMCR:
                    if ((val & (BMCR_RESET|BMCR_ANENABLE)) == 0)
                        phydev->autoneg = AUTONEG_DISABLE;
                    else
                        phydev->autoneg = AUTONEG_ENABLE;
                    if ((!phydev->autoneg) && (val & BMCR_FULLDPLX))
                        phydev->duplex = DUPLEX_FULL;
                    else
                        phydev->duplex = DUPLEX_HALF;
                    if ((!phydev->autoneg) &&
                            (val & BMCR_SPEED1000))
                        phydev->speed = SPEED_1000;
                    else if ((!phydev->autoneg) &&
                            (val & BMCR_SPEED100))
                        phydev->speed = SPEED_100;
                    break;
                case MII_ADVERTISE:
                    phydev->advertising = val;
                    break;
                default:
                    /* do nothing */
                    break;
            }
        }

mdiobus_write(phydev->bus, mii_data->phy_id,
                  mii_data->reg_num, val);

if (mii_data->reg_num == MII_BMCR &&
            val & BMCR_RESET &&
            phydev->drv->config_init) {
            phy_scan_fixups(phydev);
            phydev->drv->config_init(phydev);
        }
        break;

case SIOCSHWTSTAMP:
        if (phydev->drv->hwtstamp)
            return phydev->drv->hwtstamp(phydev, ifr);
        /* fall through */

default:
        return -EOPNOTSUPP;
    }

return 0;
}
EXPORT_SYMBOL(phy_mii_ioctl);

补充:

关于MII,百度内容如下:

MII即“媒体独立接口”,也叫“独立于介质的接口”。它是IEEE-802.3定义的以太网行业标准。它包括一个数据接口,以及一个MAC和PHY之间的管理接口

RMII全称为“简化的媒体独立接口”,是IEEE-802.3u标准中除MII接口之外的另一种实现。

独立于介质的接口(MII) 用于MAC与外接的PHY互联,支持10Mbit/s和100Mbit/s数据传输模式。

上一篇:docker 安装rabbitmq


下一篇:git安装配置