linux网络设备—mdio总线

linux网络设备—mdio总线       
        分类:            linux设备驱动 2074人阅读 评论(2) 收藏 举报

一.结构体

  1. struct mii_bus { 
  2.     const char *name;   //总线名 
  3.     char id[MII_BUS_ID_SIZE];   //id 
  4.     void *priv; //私有数据 
  5.     int (*read)(struct mii_bus *bus, int phy_id, int regnum);   //读方法 
  6.     int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val); //写方法 
  7.     int (*reset)(struct mii_bus *bus);  //复位 
  8.     struct mutex mdio_lock; 
  9.     struct device *parent;  //父设备 
  10.     enum
  11.         MDIOBUS_ALLOCATED = 1, 
  12.         MDIOBUS_REGISTERED, 
  13.         MDIOBUS_UNREGISTERED, 
  14.         MDIOBUS_RELEASED, 
  15.     } state;    //总线状态 
  16.     struct device dev;  //设备文件 
  17.     struct phy_device *phy_map[PHY_MAX_ADDR];   //PHY设备数组 
  18.     u32 phy_mask; 
  19.     int *irq;   //中断 
  20. }; 
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总线

  1. int __init mdio_bus_init(void
  2.     int ret; 
  3.     ret = class_register(&mdio_bus_class);  //注册设备类 
  4.     if (!ret) { 
  5.         ret = bus_register(&mdio_bus_type); //注册mdio总线 
  6.         if (ret) 
  7.             class_unregister(&mdio_bus_class); 
  8.     } 
  9.     return ret; 
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"

  1. static struct class mdio_bus_class = { 
  2.     .name       = "mdio_bus"
  3.     .dev_release    = mdiobus_release, 
  4. }; 
static struct class mdio_bus_class = {
	.name		= "mdio_bus",
	.dev_release	= mdiobus_release,
};

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

  1. struct bus_type mdio_bus_type = { 
  2.     .name       = "mdio_bus"
  3.     .match      = mdio_bus_match,   //匹配方法 
  4.     .pm     = MDIO_BUS_PM_OPS, 
  5. }; 
  6. EXPORT_SYMBOL(mdio_bus_type); 
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函数分配内存

  1. struct mii_bus *mdiobus_alloc(void
  2.     struct mii_bus *bus; 
  3.     bus = kzalloc(sizeof(*bus), GFP_KERNEL);    //分配内存 
  4.     if (bus != NULL) 
  5.         bus->state = MDIOBUS_ALLOCATED; 
  6.     return bus; 
  7. EXPORT_SYMBOL(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的结构体成员

  1. mii_bus->name    = ; 
  2. mii_bus->read    = ; 
  3. mii_bus->write   = ; 
  4. mii_bus->reset   = ; 
  5. mii_bus->parent  = ; 
  6. mii_bus->priv    = ; 
  7. mii_bus->id  = ; 
mii_bus->name 	= ;
mii_bus->read 	= ;
mii_bus->write	= ;
mii_bus->reset	= ;
mii_bus->parent	= ;
mii_bus->priv 	= ;
mii_bus->id	= ;

3.注册mii_bus

  1. int mdiobus_register(struct mii_bus *bus) 
  2.     int i, err; 
  3.     if (NULL == bus || NULL == bus->name || NULL == bus->read ||NULL == bus->write) 
  4.         return -EINVAL; 
  5.     BUG_ON(bus->state != MDIOBUS_ALLOCATED &&bus->state != MDIOBUS_UNREGISTERED); 
  6.     bus->dev.parent = bus->parent; 
  7.     bus->dev.class = &mdio_bus_class;    //总线设备类"/sys/bus/mdio_bus" 
  8.     bus->dev.groups = NULL; 
  9.     dev_set_name(&bus->dev, "%s", bus->id);   //设置总线设备名 
  10.     err = device_register(&bus->dev);    //注册设备文件 
  11.     if (err) { 
  12.         printk(KERN_ERR "mii_bus %s failed to register\n", bus->id); 
  13.         return -EINVAL; 
  14.     } 
  15.     mutex_init(&bus->mdio_lock); 
  16.     if (bus->reset) 
  17.         bus->reset(bus); //总线复位 
  18.     for (i = 0; i < PHY_MAX_ADDR; i++) { 
  19.         if ((bus->phy_mask & (1 << i)) == 0) { 
  20.             struct phy_device *phydev; 
  21.             phydev = mdiobus_scan(bus, i);  //扫描phy设备 
  22.             if (IS_ERR(phydev)) { 
  23.                 err = PTR_ERR(phydev); 
  24.                 goto error; 
  25.             } 
  26.         } 
  27.     } 
  28.     bus->state = MDIOBUS_REGISTERED; //状态设置为已注册 
  29.     pr_info("%s: probed\n", bus->name); 
  30.     return 0; 
  31. error: 
  32.     while (--i >= 0) { 
  33.         if (bus->phy_map[i]) 
  34.             device_unregister(&bus->phy_map[i]->dev); 
  35.     } 
  36.     device_del(&bus->dev); 
  37.     return err; 
  38. EXPORT_SYMBOL(mdiobus_register); 
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\n", 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\n", 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函数

  1. struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) 
  2.     struct phy_device *phydev; 
  3.     int err; 
  4.     phydev = get_phy_device(bus, addr); //获取创建phy设备 
  5.     if (IS_ERR(phydev) || phydev == NULL) 
  6.         return phydev; 
  7.     err = phy_device_register(phydev);  //注册phy设备 
  8.     if (err) { 
  9.         phy_device_free(phydev); 
  10.         return NULL; 
  11.     } 
  12.     return phydev; 
  13. EXPORT_SYMBOL(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关系图

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值