我的Linux网络之行3-rtl9000bx驱动设计与分析

发布时间 2023-10-07 10:44:16作者: King_Alex

MAC的简介

Linux的大致的以太网的驱动基本上已经在上一文中做了一些介绍了,那么本文就对相应的以太网做一些介绍。

以太网的MAC:Media Access Control,即媒体访问控制子层协议

以太网的PHY:(物理层)之间的MII(Media Independent Interface ,媒体独立接口

一般的框架是:

img

而CPU集成MAC,PHY采用独立芯片。比较常见

img

而MAC及PHY工作在OSI七层模型的数据链路层和物理层。

img

什么是MAC

MAC(Media Access Control)即媒体访问控制子层协议。

该部分有两个概念:MAC可以是一个硬件控制器 及 MAC通信以协议。该协议位于OSI七层协议中数据链路层的下半部分,主要负责控制与连接物理层的物理介质。MAC硬件大约就是下面的样子了:

img

在发送数据的时候,MAC协议可以事先判断是否可以发送数据,如果可以发送将给数据加上一些控制信息,最终将数据以及控制信息以规定的格式发送到物理层。

在接收数据的时候,MAC协议首先判断输入的信息并是否发生传输错误,如果没有错误,则去掉控制信息发送至LLC(逻辑链路控制)层。该层协议是以太网MAC由IEEE-802. 3以太网标准定义。

以太网数据链路层其实包含MAC(介质访问控制)子层和LLC(逻辑链路控制)子层。一块以太网卡MAC芯片的作用不但要实现MAC子层和LLC子层的功能,还要提供符合规范的PCI界面以实现和主机的数据交换。

MAC从PCI总线收到IP数据包(或者其他网络层协议的数据包)后,将之拆分并重新打包成最大1518Byte、最小64Byte的帧。

img

整个解包的过程类似于上面以上这个过程。

这个帧里面包括了目标MAC地址、自己的源MAC地址和数据包里面的协议类型(比如IP数据包的类型用80表示,最后还有一个DWORD(4Byte)的CRC码。

可是目标的MAC地址是哪里来的呢?

这牵扯到一个ARP协议(介乎于网络层和数据链路层的一个协议)。第一次传送某个目的IP地址的数据的时候,先会发出一个ARP包,其MAC的目标地址是广播地址,里面说到:“谁是xxx.xxx.xxx.xxx这个IP地址的主人?”

因为是广播包,所有这个局域网的主机都收到了这个ARP请求。收到请求的主机将这个IP地址和自己的相比较,如果不相同就不予理会,如果相同就发出ARP响应包。

这个IP地址的主机收到这个ARP请求包后回复的ARP响应里说到:“我是这个IP地址的主人”。这个包里面就包括了他的MAC地址。以后的给这个IP地址的帧的目标MAC地址就被确定了。(其它的协议如IPX/SPX也有相应的协议完成这些操作)。

IP地址和MAC地址之间的关联关系保存在主机系统里面,叫做ARP表。由驱动程序和操作系统完成。

在Microsoft的系统里面可以用arp-a 的命令查看ARP表。收到数据帧的时候也是一样,做完CRC校验以后,如果没有CRC效验错误,就把帧头去掉,把数据包拿出来通过标准的接口传递给驱动和上层的协议栈。最终正确的达到我们的应用程序。

还有一些控制帧,例如流控帧也需要MAC直接识别并执行相应的行为。

以太网MAC芯片的一端接计算机PCI总线,另外一端就接到PHY芯片上,它们之间是通过MII接口链接的。

img

SMI:串行管理接口(Serial Management Interface),通常直接被称为MDIO接口(Management Data Input/Output Interface)。MDIO最早在IEEE 802.3的第22卷定义,后来在第45卷又定义了增强版本的MDIO,其主要被应用于以太网的MAC和PHY层之间,用于MAC层器件通过读写寄存器来实现对PHY层器件的操作与管理。

MDIO主机(即产生MDC时钟的设备)通常被称为STA(Station Management Entity),而MDIO从机通常被称为MMD(MDIO Management Device)。通常STA都是MAC层器件的一部分,而MMD则是PHY层器件的一部分。

MDIO接口包括两条线,MDIO和MDC,其中MDIO是双向数据线,而MDC是由STA驱动的时钟线。MDC时钟的最高速率一般为2.5MHz,MDC也可以是非固定频率,甚至可以是非周期的。MDIO接口只是会在MDC时钟的上升沿进行采样,而并不在意MDC时钟的频率(类似于I2C接口)。如下图所示。

img

什么是PHY

PHY(英语:Physical),中文可称之为端口物理层,是一个对OSI模型物理层的共同简称。

一个以太网PHY是一个芯片,可以发送和接收以太网的数据帧(frame)。 也就是说,PHY是网络结构中的最底层,物理层。PHY芯片是实现物理层这一层功能的芯片。网络设备之间就是通过PHY芯片相互连接的(介质是网线或者光纤)。

img

其主要的作用就是:将数字信号转成模拟信号,然后在网线或者光纤传输。

实战支持RTL9000BX

基本的框架如下:

static struct phy_driver KingPhy_drvs[] = {
    {
	.phy_id		= 0x001ccb00 ,
	.name		= "rtl9000bx Ethernet",
	.phy_id_mask  = RTL9000BX_MASK,
               .features	    = PHY_GBIT_FEATURES | SUPPORTED_MII |SUPPORTED_AUI
 | SUPPORTED_FIBRE |SUPPORTED_BNC,
	 .flags		= PHY_HAS_INTERRUPT,
                .config_init    = rtl9000bx_config_init,
                .read_status    = rtl9000bx_read_status,
	.soft_reset     = rtl9000bx_soft_reset,
	.config_aneg    = rtl9000bx_config_aneg,
	.aneg_done      = rtl9000bx_aneg_done,
     },
};

module_phy_driver(KingPhy_drvs);
static struct mdio_device_id __maybe_unused KingPhy_tbl[] = {
	{ 0x001ccb00, 0x001fffff },
	{ }
};
MODULE_DEVICE_TABLE(mdio, KingPhy_tbl);


其主要工作实现均在rtl9000bx_config_init中:
居然如下:

img

这些代码均是来自上一文的最后一图。