• linux网络设备—mdio总线


    一.结构体

    struct mii_bus {
    	const char *name;	//总线名
    	char id[MII_BUS_ID_SIZE];	//id
    	void *priv;	//私有数据
    	int (*read)(struct mii_bus *bus, int phy_id, int regnum);	//读方法
    	int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);	//写方法
    	int (*reset)(struct mii_bus *bus);	//复位
    	struct mutex mdio_lock;
    	struct device *parent;	//父设备
    	enum {
    		MDIOBUS_ALLOCATED = 1,
    		MDIOBUS_REGISTERED,
    		MDIOBUS_UNREGISTERED,
    		MDIOBUS_RELEASED,
    	} state;	//总线状态
    	struct device dev;	//设备文件
    	struct phy_device *phy_map[PHY_MAX_ADDR];	//PHY设备数组
    	u32 phy_mask;
    	int *irq;	//中断
    };

    二.初始化过程

    在phy_init函数中调用了mdio_bus_init初始化mdio总线

    int __init mdio_bus_init(void)
    {
    	int ret;
    	ret = class_register(&mdio_bus_class);	//注册设备类
    	if (!ret) {
    		ret = bus_register(&mdio_bus_type);	//注册mdio总线
    		if (ret)
    			class_unregister(&mdio_bus_class);
    	}
    	return ret;
    }

    设备类"/sys/class/mdio_bus"

    static struct class mdio_bus_class = {
    	.name		= "mdio_bus",
    	.dev_release	= mdiobus_release,
    };

    总线类型"/sys/bus/mdio"

    struct bus_type mdio_bus_type = {
    	.name		= "mdio_bus",
    	.match		= mdio_bus_match,	//匹配方法
    	.pm		= MDIO_BUS_PM_OPS,
    };
    EXPORT_SYMBOL(mdio_bus_type);

    三.mdio总线注册
    1.调用mdiobus_alloc函数分配内存

    struct mii_bus *mdiobus_alloc(void)
    {
    	struct mii_bus *bus;
    	bus = kzalloc(sizeof(*bus), GFP_KERNEL);	//分配内存
    	if (bus != NULL)
    		bus->state = MDIOBUS_ALLOCATED;
    	return bus;
    }
    EXPORT_SYMBOL(mdiobus_alloc);

    2.填充mii_bus的结构体成员

    mii_bus->name 	= ;
    mii_bus->read 	= ;
    mii_bus->write	= ;
    mii_bus->reset	= ;
    mii_bus->parent	= ;
    mii_bus->priv 	= ;
    mii_bus->id	= ;

    3.注册mii_bus

    int mdiobus_register(struct mii_bus *bus)
    {
    	int i, err;
    	if (NULL == bus || NULL == bus->name || NULL == bus->read ||NULL == bus->write)
    		return -EINVAL;
    	BUG_ON(bus->state != MDIOBUS_ALLOCATED &&bus->state != MDIOBUS_UNREGISTERED);
    	bus->dev.parent = bus->parent;
    	bus->dev.class = &mdio_bus_class;	//总线设备类"/sys/bus/mdio_bus"
    	bus->dev.groups = NULL;
    	dev_set_name(&bus->dev, "%s", bus->id);	//设置总线设备名
    	err = device_register(&bus->dev);	//注册设备文件
    	if (err) {
    		printk(KERN_ERR "mii_bus %s failed to register
    ", bus->id);
    		return -EINVAL;
    	}
    	mutex_init(&bus->mdio_lock);
    	if (bus->reset)
    		bus->reset(bus);	//总线复位
    	for (i = 0; i < PHY_MAX_ADDR; i++) {
    		if ((bus->phy_mask & (1 << i)) == 0) {
    			struct phy_device *phydev;
    			phydev = mdiobus_scan(bus, i);	//扫描phy设备
    			if (IS_ERR(phydev)) {
    				err = PTR_ERR(phydev);
    				goto error;
    			}
    		}
    	}
    	bus->state = MDIOBUS_REGISTERED;	//状态设置为已注册
    	pr_info("%s: probed
    ", bus->name);
    	return 0;
    error:
    	while (--i >= 0) {
    		if (bus->phy_map[i])
    			device_unregister(&bus->phy_map[i]->dev);
    	}
    	device_del(&bus->dev);
    	return err;
    }
    EXPORT_SYMBOL(mdiobus_register);

    调用了mdiobus_scan函数

    struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
    {
    	struct phy_device *phydev;
    	int err;
    	phydev = get_phy_device(bus, addr);	//获取创建phy设备
    	if (IS_ERR(phydev) || phydev == NULL)
    		return phydev;
    	err = phy_device_register(phydev);	//注册phy设备
    	if (err) {
    		phy_device_free(phydev);
    		return NULL;
    	}
    	return phydev;
    }
    EXPORT_SYMBOL(mdiobus_scan);

    动态地创建了PHY设备

    四.mii、mdio、phy、mac关系图

  • 相关阅读:
    BZOJ 3156 防御准备
    codevs 1033 蚯蚓的游戏问题
    BZOJ 3669 【NOI2014】 魔法森林
    分享知识-快乐自己:全面解析 java注解实战指南
    分享知识-快乐自己:MySQL中的约束,添加约束,删除约束,以及一些其他修饰
    分享知识-快乐自己:Oracle基本语法(创建:表空间、用户、授权、约束等)使用指南
    分享知识-快乐自己: Oracle数据库实例、用户、表、表空间之间关系
    分享知识-快乐自己:oracle12c创建用户提示ORA-65096:公用用户名或角色无效
    分享知识-快乐自己:论 Mybatis中的关联关系(一对多,多对一,多对多)
    分享知识-快乐自己:JAVA中的 Iterator 和 Iterable 区别
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3424152.html
Copyright © 2020-2023  润新知