linux网络设备—mdio总线

一.结构体

struct mii_bus {const char *name;//总线名char id[MII_BUS_ID_SIZE];//idvoid *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\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函数

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关系图

行动是治愈恐惧的良药,而犹豫、拖延将不断滋养恐惧。

linux网络设备—mdio总线

相关文章:

你感兴趣的文章:

标签云: