mdio 驱动

linux网络设备—mdio总线

2013年09月17日  ⁄ 综合 ⁄ 共 2575字 ⁄ 字号  小 中 大  ⁄ 评论关闭
id="iframeu1788635_0" src="http://pos.baidu.com/acom?rdid=1788635&dc=2&di=u1788635&dri=0&dis=0&dai=2&ps=236x1165&dcb=BAIDU_UNION_define&dtm=BAIDU_DUP_SETJSONADSLOT&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1455863629875&ti=linux%E7%BD%91%E7%BB%9C%E8%AE%BE%E5%A4%87%E2%80%94mdio%E6%80%BB%E7%BA%BF%20%7C%20%E5%AD%A6%E6%AD%A5%E5%9B%AD&ari=1&dbv=2&drs=1&pcs=1879x891&pss=1879x256&cfv=17&cpl=18&chi=1&cce=true&cec=UTF-8&tlm=1455834829&ltu=http%3A%2F%2Fwww.xuebuyuan.com%2F1722839.html&ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DXj4k2CEgYRC13eeGTTCNGffhPsDvLGk-XMmMLBQEDdKw8UiKBEV6B2O4cUtaA82C%26wd%3D%26eqid%3De9ea931e000230b90000000356c6b6a9&ecd=1&psr=1920x1080&par=1920x1040&pis=-1x-1&ccd=32&cja=true&cmi=42&col=zh-CN&cdo=-1&tcn=1455863630&qn=90a9d0aa836d9116&tt=1455863629859.109.3245.3245" width="336" height="280" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="margin: 0px; padding: 0px; border-width: 0px; background-color: transparent; vertical-align: bottom;">

一.结构体

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值