前言
在上一文中,初步了解了一些协议与相关的一些知识,至少已经有了一些概念,OK,那么下面就是我们对于开发的深入了。
Linux以太网驱动架构
OSI 模型中将网络划分为七层,从下到上依次为:物理层(Physical)、数据链路层(Date Link)、网络层(Network)、传输层(Transport)、会话层(Session)、表示层(Presentation)和应用层(Application)。
Linux内核网络协议栈涉及其中三层,分别为数据链路层、网络层和传输层,不涉及物理层,应用层的任务也是由用户空间程序来实现的。
Linux网络驱动体系
网络驱动程序体系结构分为四层:
1.网络协议接口层
网络协议接口层向网络层协议提供统一的数据包收发接口,不论上层协议是ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过netif_rx()函数接收数据。这一层的存在使得上层协议独立于具体的设备。
2.网络设备接口层
网络设备接口层向协议接口层提供的用于描述具体网络设备属性和操作的结构体net_device,该结构体是设备驱动功能层各函数的容器。
3.设备驱动功能层
设备驱动功能层的各函数是网络设备接口层net_device数据结构的具体成员,是驱使网络设备硬件完成相应动作的程序,它通过nto_start_xmit()函数启动发送操作,并通过网络设备上的中断触发接收操作。
4.网络设备与媒介层
网络设备与媒介层完成数据包发送和接收的物理实体,包括网络适配器和具体的传输媒介,网络适配器被设备驱动功能层中的函数在物理上驱动。
这里我们以从驱动到最上层应用的方式来分析这个
linux的MDIO
基本上你只要看到相关的phy的spec,那么必然会先接触到一个协议,那就是MDIO协议,我们又称其为SMI。
一般每个跟SOC连接的phy必然有这个两个pin脚,用于控制phy的寄存器。
而起一般的芯片内部如下:
其基本的时序如下图:
一般通过该协议向phy访问相关的寄存器,然后进行相应的寄存器控制。
那么这个驱动又是如何实现的?
struct mii_bus *new_bus = NULL;
new_bus = mdiobus_alloc();//申请MDIO bus的内存
new_bus->name = "XXX_phy";
new_bus->read = XXX_mdio_read;
new_bus->write = XXX_mdio_write;
new_bus->reset = XXX_mdio_reset;
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", new_bus->name,
pdata->bus_id);
new_bus->priv = dev;
new_bus->phy_mask = 0;
new_bus->parent = &pdata->pdev->dev;
mdiobus_register(new_bus);//注册这个bus即可
而里面的XXX_mdio_read等,最终走向的是ioread等直接去读取SOC内部的寄存器,这个一般要soc的datasheet才能做相关的解析,在此就不过多的赘述了。
realtek的rtl900x的初始化流程
好了上文,我们已经完成了相关的MDIO的注册与使用,那么我们就直接找个phy来实现一番吧。
这里的硬件是采用RMII的方式去访问的。
大致上如上图所示
硬件方面此处就不再继续说了。
其相关的初始化启动,如下图:
那么在下一章节我将提供相关的驱动设计,提供作为开源库。
标签:bus,Linux,网络,接口,驱动,phy,初探,new,网络设备 From: https://www.cnblogs.com/samuelwnb/p/17641389.html