linux网络设备—mdio总线

一.结构体

[cpp]  view plain copy
  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. };  

二.初始化过程

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

[cpp]  view plain copy
  1. int __init mdio_bus_init(void)  
  2. {  
  3.     int ret;  
  4.     ret = class_register(&mdio_bus_class);  //注册设备类  
  5.     if (!ret) {  
  6.         ret = bus_register(&mdio_bus_type); //注册mdio总线  
  7.         if (ret)  
  8.             class_unregister(&mdio_bus_class);  
  9.     }  
  10.     return ret;  
  11. }  

设备类"/sys/class/mdio_bus"

[cpp]  view plain copy
  1. static struct class mdio_bus_class = {  
  2.     .name       = "mdio_bus",  
  3.     .dev_release    = mdiobus_release,  
  4. };  

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

[cpp]  view plain copy
  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);  

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

[cpp]  view plain copy
  1. struct mii_bus *mdiobus_alloc(void)  
  2. {  
  3.     struct mii_bus *bus;  
  4.     bus = kzalloc(sizeof(*bus), GFP_KERNEL);    //分配内存  
  5.     if (bus != NULL)  
  6.         bus->state = MDIOBUS_ALLOCATED;  
  7.     return bus;  
  8. }  
  9. EXPORT_SYMBOL(mdiobus_alloc);  

2.填充mii_bus的结构体成员

[cpp]  view plain copy
  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  = ;  

3.注册mii_bus

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

调用了mdiobus_scan函数

[cpp]  view plain copy
  1. struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)  
  2. {  
  3.     struct phy_device *phydev;  
  4.     int err;  
  5.     phydev = get_phy_device(bus, addr); //获取创建phy设备  
  6.     if (IS_ERR(phydev) || phydev == NULL)  
  7.         return phydev;  
  8.     err = phy_device_register(phydev);  //注册phy设备  
  9.     if (err) {  
  10.         phy_device_free(phydev);  
  11.         return NULL;  
  12.     }  
  13.     return phydev;  
  14. }  
  15. EXPORT_SYMBOL(mdiobus_scan);  

动态地创建了PHY设备

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

linux网络设备—mdio总线_第1张图片


http://blog.csdn.net/orz415678659/article/details/9370827

你可能感兴趣的:(linux网络设备—mdio总线)