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关系图
linux网络设备—mdio总线的更多相关文章
- Linux下smi/mdio总线驱动
Linux下smi/mdio总线驱动 韩大卫@吉林师范大学 MII(媒体独立接口), 是IEEE802.3定义的以太网行业标准接口, smi是mii中的标准管理接口, 有两跟管脚, mdio 和mdc ...
- Linux 下smi/mdio总线通信
Linux 下smi/mdio总线通信 韩大卫@吉林师范大学 下面代码描述了在用户层访问smi/mdio总线, 读写phy芯片寄存器的通用代码.Linux内核2.6以上通用. 将下面代码编译后,将可执 ...
- linux网络设备—PHY
一.结构体 1.PHY设备 struct phy_device { struct phy_driver *drv; //PHY设备驱动 struct mii_bus *bus; //对应的MII总线 ...
- linux网络设备驱动程序
4.linux网络设备驱动程序体系结构 -------------------------------------- | 数据包发送 | 数据包接收 | ----->网络协议接口层 | dev_ ...
- linux内核SPI总线驱动分析(一)(转)
linux内核SPI总线驱动分析(一)(转) 下面有两个大的模块: 一个是SPI总线驱动的分析 (研究了具体实现的过程) 另一个是SPI总线驱动的编写(不用研究具体的实现过程) ...
- Linux网络设备驱动架構學習(三)
Linux网络设备驱动架構學習(三) 接下來會從以下幾個方面介紹網絡設備驅動的編寫流程: 1.網絡設備的註冊與註銷 2.網絡設備的初始化 3.網絡設備的打開與釋放 4.網絡數據發送流程 5.網絡數據接 ...
- Linux网络设备驱动架构
Linux网络设备驱动程序体系结构分为四层:网络协议接口层.网络设备接口层.提供实际功能的设备驱动层以及网络设备与媒介层. (1)网络协议接口层向网络层协议提供统一的数据包收发接口,不论上层协议是AR ...
- linux网络设备驱动
Linux网络设备驱动 Linux网络驱动程序的体系结构可划分为4个层次.Linux内核源代码中提供了网络设备接口及以网络子系统的上层的代码,移植特定网络硬件的驱动程序的主要工作就是完成设备驱动功能层 ...
- Linux网络设备驱动架構學習(二)
Linux网络设备驱动架構學習(二) 接下來會從以下幾個方面介紹網絡設備驅動的編寫流程: 1.網絡設備的註冊與註銷 2.網絡設備的初始化 3.網絡設備的打開與釋放 4.網絡數據發送流程 5.網絡數據接 ...
随机推荐
- Python decorator
1.编写无参数的decorator Python的 decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数. 使用 decorator 用Python提供的 @ 语法 ...
- 《剑指offer》-链表找环入口
题目描述 一个链表中包含环,请找出该链表的环的入口结点. 初步想法是每个节点做几个标记,表示是否被访问过,那么遍历链表的时候就知道哪个被访问到了.但是不会实现. 另一个直觉是判断链表有环的算法中出现过 ...
- BZOJ1295 [SCOI2009]最长距离 最短路 SPFA
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1295 题意概括 有一块矩形土地,被分为 N*M 块 1*1 的小格子. 有的格子含有障碍物. 如果 ...
- 015 在Spark中关于groupByKey与reduceByKey的区别
1.groupByKey的源代码 2.groupByKey的使用缺点 不使用groupByKey的主要原因:在大规模的数据下,数据分布不均匀的情况下,可能导致OOM 3.reduceByKey的源代码 ...
- 科技界、IT届的外号
牙膏厂 = Intel 挤牙膏来形容缓慢的升级速度 农企(推土机,打桩机,压路机).阿曼达.按摩店 = AMD 两弹元勋.老黄 = 黄仁勋, 核弹.英伟达 = NVIDIA 大法 = ...
- python dictionay(字典 )基本用法
dict(dictionary)是一系列无序对象的集合,由键-值对构成,通过读取键来取得对应的值,具有可变,无序,异构,可嵌套的属性. dict初始化1.直接采用字典格式 2.利用dict(),[注] ...
- 洛谷P2982 [USACO10FEB]慢下来Slowing down(线段树 DFS序 区间增减 单点查询)
To 洛谷.2982 慢下来Slowing down 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows con ...
- POJ.1704.Georgia and Bob(博弈论 Nim)
题目链接 \(Description\) 一个1~INF的坐标轴上有n个棋子,给定坐标Pi.棋子只能向左走,不能跨越棋子,且不能越界(<1).两人每次可以将任意一个可移动的棋子向左移动一个单位. ...
- php 字符串翻转
字符串翻转 <?php$s = 'strlen,substr,count';$o = '';$i = 0;while(isset($s[$i]) && $s[$i] != nul ...
- BZOJ4714 : 旋转排列
对于每个$k$,问题等价于求有多少置换满足: 1.存在一个循环长度为$k$ 2.任意一个循环长度$\geq 2$ 枚举这种环的个数$t$: 设$g_t$表示至少有$kt$个人分成$t$个长度为$k$的 ...