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\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關系圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM