如何将以太网设备直接连接到linux中的交换机?

 透明的眼泪2502913707 发布于 2023-01-19 20:05

我们有一个嵌入式主板,其中以太网设备直接连接到交换机,两者之间没有phy.为了使事情变得更复杂,以太网设备的mdio总线连接到交换机的mdio进行控制.

我已设法使用固定的mdio/phy驱动程序启用以太网,并通过将交换机的默认配置与固定的phy匹配来工作.

我现在如何连接到mdio总线以更改开关设置?由于以太网设备附加的phy由固定的phy填充,我现在如何将真正的mdio总线连接到系统,以便我可以对其进行配置.似乎没有直接用户空间接口到mdio总线.我是否创建了一个假的以太网设备,其唯一目的是访问mdio总线或者以某种方式将它连接到以太网设备,然后将连接两个mdio总线?

PS:看起来物理mdio总线驱动程序找到了开关,但我该如何与它交谈?

1 个回答
  • 该补丁允许我读取和写入系统中检测到的mdio设备中的所有寄存器.

    diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
    index dc92097..668150e 100644
    --- a/drivers/net/phy/mdio_bus.c
    +++ b/drivers/net/phy/mdio_bus.c
    @@ -439,8 +439,85 @@ phy_id_show(struct device *dev, struct device_attribute *attr, char *buf)
        return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id);
     }
    
    +static ssize_t
    +mdio_reg_show(struct device *dev, struct device_attribute *attr, char *buf)
    +{
    +   struct phy_device *phydev = to_phy_device(dev);
    +   struct mii_bus* bus = phydev->bus;
    +   int regnum;
    +   int val;
    +
    +   if (sscanf(attr->attr.name, "%d", &regnum) != 1)
    +       return -EINVAL;
    +
    +   val = mdiobus_read(bus, phydev->addr, regnum);
    +   if (val < 0)
    +       return -EIO;
    +
    +   return sprintf(buf, "0x%.4x\n", val);
    +}
    +
    +static ssize_t
    +mdio_reg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
    +{
    +   struct phy_device *phydev = to_phy_device(dev);
    +   struct mii_bus* bus = phydev->bus;
    +   int regnum;
    +   int val;
    +   int err;
    +
    +   if (sscanf(attr->attr.name, "%d", &regnum) != 1)
    +       return -EINVAL;
    +
    +   if (sscanf(buf, "%d", &val) != 1)
    +       return -EINVAL;
    +
    +   if (val < 0 || val > 0xffff)
    +       return -EINVAL;
    +
    +   err = mdiobus_write(bus, phydev->addr, regnum, val);
    +   if (err < 0)
    +       return -EIO;
    +
    +   return size;
    +}
    +
    +#define MDIO_REG(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), mdio_reg_show, mdio_reg_store)
    +
     static struct device_attribute mdio_dev_attrs[] = {
        __ATTR_RO(phy_id),
    +   MDIO_REG(0),
    +   MDIO_REG(1),
    +   MDIO_REG(2),
    +   MDIO_REG(3),
    +   MDIO_REG(4),
    +   MDIO_REG(5),
    +   MDIO_REG(6),
    +   MDIO_REG(7),
    +   MDIO_REG(8),
    +   MDIO_REG(9),
    +   MDIO_REG(10),
    +   MDIO_REG(11),
    +   MDIO_REG(12),
    +   MDIO_REG(13),
    +   MDIO_REG(14),
    +   MDIO_REG(15),
    +   MDIO_REG(16),
    +   MDIO_REG(17),
    +   MDIO_REG(18),
    +   MDIO_REG(19),
    +   MDIO_REG(20),
    +   MDIO_REG(21),
    +   MDIO_REG(22),
    +   MDIO_REG(23),
    +   MDIO_REG(24),
    +   MDIO_REG(25),
    +   MDIO_REG(26),
    +   MDIO_REG(27),
    +   MDIO_REG(28),
    +   MDIO_REG(29),
    +   MDIO_REG(30),
    +   MDIO_REG(31),
        __ATTR_NULL
     };
    

    它扩展了已经存在的sysfs接口,每个mdio设备可以包含32个寄存器地址.由于mdio设备不是物理设备,因此它们不遵循phy标准,因此我不得不破解phy检测以允许所有设备出现:

    --- a/drivers/net/phy/phy_device.c
    +++ b/drivers/net/phy/phy_device.c
    @@ -339,9 +339,12 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
            if (r)
                    return ERR_PTR(r);
    
    +       /* BRM: this is patently not the case for our marvell switch */
    +#if 0
            /* If the phy_id is mostly Fs, there is no device there */
            if ((phy_id & 0x1fffffff) == 0x1fffffff)
                    return NULL;
    +#endif
    
    
        dev = phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);
    

    希望这对其他人有帮助.

    2023-01-19 20:10 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有