3. MAC控制器核心寄存器
MAC(Media Access Control)控制器是网络设备驱动中连接物理层(PHY)与上层协议栈的桥梁。其核心寄存器组直接决定了数据帧的收发行为、地址匹配逻辑以及链路状态监控。本章深入剖析四类关键寄存器:控制寄存器(CR)、状态寄存器(SR)、MAC地址寄存器和帧过滤寄存器,并结合驱动代码与硬件时序图,帮助开发者建立寄存器级编程的精确认知。
3.1 控制寄存器(CR)—— MAC 行为的总开关
控制寄存器(Control Register, CR)是驱动初始化阶段最先操作的寄存器,它决定了 MAC 核心的工作模式、数据流方向以及复位状态。不同厂商的 MAC 控制器(如 Synopsys DesignWare、Cadence、TI CPSW)在 CR 布局上略有差异,但核心位域高度相似。
3.1.1 典型 CR 位域定义
| 位域 | 名称 | 描述 | 驱动典型操作 |
|---|---|---|---|
| 31 | SWR | 软件复位,置 1 复位整个 MAC 内核,自清零 | 写 1 后轮询等待清零 |
| 30:11 | RSVD | 保留位,必须写 0 | 掩码清零 |
| 10 | RE | 接收使能,控制接收路径 DMA 与 FIFO | 初始化最后置 1 |
| 9 | TE | 发送使能,控制发送路径 DMA 与 FIFO | 初始化最后置 1 |
| 8:3 | FES | 接口速度选择(MII/RMII/RGMII 速率) | 根据 PHY 协商结果设置 |
| 2 | DM | 双工模式:0=半双工,1=全双工 | 与 PHY 链路状态同步 |
| 1 | LM | 环路模式:置 1 使 MAC 内部环回(调试用) | 仅调试阶段置位 |
| 0 | RA | 接收所有帧(Promiscuous 模式辅助位) | 与帧过滤寄存器配合 |
3.1.2 驱动初始化 CR 的标准流程
- 软件复位:向 SWR 位写 1,然后循环读取该位直到硬件自动清零(超时保护)。
- 配置接口模式:根据 PHY 接口类型(MII/GMII/RGMII)设置 FES 与 DM 位。
- 使能收发路径:在 DMA 初始化完成后,同时置位 RE 和 TE。
- 调试与环回:仅在自测阶段置位 LM,正常模式必须清零。
关键提示:RE 与 TE 必须在 DMA 通道和描述符环初始化完成后才能置位,否则 MAC 会立即尝试访问未就绪的 FIFO 或描述符,导致总线错误(Bus Error)或数据损坏。
3.1.3 CR 配置与数据流关系 SVG
3.2 状态寄存器(SR)—— 链路与数据路径的实时仪表盘
状态寄存器(Status Register, SR)为驱动提供了 MAC 内部状态的只读快照,包括链路状态、FIFO 水位、错误计数以及中断挂起标志。驱动中断服务程序(ISR)和链路监控任务(如 PHY 状态轮询)频繁读取 SR 以做出响应决策。
3.2.1 核心状态位域解读
| 位域 | 名称 | 含义 | 驱动处理方式 |
|---|---|---|---|
| 31 | TS | 发送状态机忙(正在发送帧) | 发送超时检测 |
| 30 | RS | 接收状态机忙(正在接收帧) | 接收溢出判断 |
| 29:20 | TXFIFO_LVL | 发送 FIFO 当前填充深度(以字为单位) | 流控或中断触发阈值 |
| 19:10 | RXFIFO_LVL | 接收 FIFO 当前填充深度 | DMA 突发长度调整 |
| 9 | LPI | 低功耗空闲指示(Energy-Efficient Ethernet) | 电源管理策略 |
| 8 | LINK | PHY 链路状态(0=down, 1=up) | 网络设备 up/down 事件 |
| 7:0 | MISC_ERR | 杂项错误累积(CRC、对齐、长度错误) | 统计计数清零或触发复位 |
3.2.2 中断驱动的状态读取模式
现代 MAC 控制器通常将 SR 中的关键位(如 LINK 变化、FIFO 溢出、帧接收完成)映射到独立的中断线。驱动 ISR 中典型的读取与清中断流程如下:
static irqreturn_t mac_isr(int irq, void *dev_id)
{
struct net_device *ndev = dev_id;
struct mac_private *priv = netdev_priv(ndev);
u32 sr_val;
/* 1. 读取状态寄存器,获取中断源 */
sr_val = readl(priv->base + MAC_SR);
/* 2. 检查链路状态变化 */
if (sr_val & SR_LINK_CHG) {
if (sr_val & SR_LINK_UP)
netif_carrier_on(ndev);
else
netif_carrier_off(ndev);
}
/* 3. 检查接收 FIFO 溢出 */
if (sr_val & SR_RX_OVERFLOW) {
priv->stats.rx_over_errors++;
/* 触发 DMA 接收通道软复位 */
mac_reset_rx_dma(priv);
}
/* 4. 清除中断状态(写 1 清零) */
writel(sr_val & SR_INT_MASK, priv->base + MAC_SR);
return IRQ_HANDLED;
}
常见陷阱:SR 中的 LINK 位反映的是 MAC 侧检测到的 PHY 链路状态,并非 PHY 内部寄存器(如 BMSR)的直接映射。驱动应同时读取 PHY 的 BMSR 寄存器进行交叉验证,避免因 MAC 侧信号抖动导致误判。
3.3 MAC 地址寄存器 —— 设备身份的核心标识
MAC 地址寄存器存储了网络设备的唯一硬件地址(通常为 6 字节)。MAC 控制器在接收帧时,将帧头中的目的 MAC 地址与这些寄存器中的值进行比较,以决定是否接收该帧。大多数 MAC 控制器支持多个 MAC 地址寄存器(如 4 个或更多),用于实现 VLAN 接口、多播过滤或虚拟化场景。
3.3.1 寄存器布局与字节序
以 32 位 MAC 控制器为例,一个 6 字节的 MAC 地址通常占用两个 32 位寄存器:
- MAC_ADDR_HIGH(偏移 0x04):存放地址高 16 位(字节 4-5),位 31:16 保留或用于地址有效标志。
- MAC_ADDR_LOW(偏移 0x00):存放地址低 32 位(字节 0-3)。
字节序遵循网络序(Big-Endian),即寄存器中字节 0 对应 MAC 地址的第一个字节(如 00:1A:2B:3C:4D:5E 中的 0x00)。
3.3.2 驱动写入 MAC 地址的标准例程
void mac_set_address(struct mac_private *priv, const u8 *addr)
{
u32 high, low;
/* 将 6 字节 MAC 地址拆分为两个 32 位值 */
low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
high = addr[4] | (addr[5] << 8);
/* 写入寄存器,注意字节序与硬件对齐 */
writel(low, priv->base + MAC_ADDR_LOW);
writel(high | MAC_ADDR_ENABLE, priv->base + MAC_ADDR_HIGH);
}
性能要点:MAC 地址寄存器通常在初始化阶段写入一次,但支持热插拔或虚拟功能的驱动需要在运行时动态更新。每次更新后,建议读取回验证(Read-Back Check),防止总线写缓冲导致地址未生效。
3.4 帧过滤寄存器 —— 接收判决的规则引擎
帧过滤寄存器(Frame Filter Register, FFR)决定了 MAC 控制器如何根据帧头信息决定接收或丢弃。它实现了硬件级别的地址过滤、类型过滤和 VLAN 过滤,大幅减轻 CPU 的软件过滤负担。
3.4.1 过滤模式与位域配置
| 位域 | 名称 | 功能 | 典型应用场景 |
|---|---|---|---|
| 0 | PR | 混杂模式(Promiscuous):接收所有帧 | 网络嗅探、桥接设备 |
| 1 | HUC | 哈希单播过滤:使用哈希表匹配单播地址 | 大规模多播环境 |
| 2 | HMC | 哈希多播过滤:使用哈希表匹配多播地址 | IGMP Snooping 场景 |
| 3 | DAIF | 目的地址反向过滤:接收非匹配地址帧 | 特殊监控需求 |
| 4 | PM | 通过所有多播帧(Pass All Multicast) | 多播路由器端口 |
| 5 | DBF | 禁用广播帧过滤(接收所有广播) | 始终置 1 除非特殊安全策略 |
| 6 | VTFE | VLAN 标签过滤使能 | 802.1Q VLAN 感知桥接 |
| 7 | IPFE | IP 层过滤使能(检查 IPv4/IPv6 头) | 硬件 TCP/IP 卸载引擎 |
3.4.2 哈希过滤的工作原理
当 HUC 或 HMC 置位时,MAC 控制器使用一个 64 位哈希表(Hash Table Register, HTHR)对目的 MAC 地址进行哈希计算,取哈希值的低 6 位作为索引,查询哈希表中对应位是否为 1。若为 1,则接收该帧;否则丢弃。
哈希算法(CRC-6)的驱动实现片段:
u64 mac_hash_calc(const u8 *addr)
{
u32 crc = 0xFFFFFFFF;
int i, j;
for (i = 0; i < 6; i++) {
crc ^= addr[i];
for (j = 0; j < 8; j++) {
if (crc & 1)
crc = (crc >> 1) ^ 0xEDB88320;
else
crc >>= 1;
}
}
/* 取 CRC 高 6 位作为哈希索引 */
return (crc >> 26) & 0x3F;
}
3.4.3 帧过滤决策流程 SVG
3.5 寄存器配置的典型陷阱与调试建议
陷阱 1:CR 中 RE/TE 与 DMA 启动顺序 —— 部分 MAC 控制器要求在使能 RE/TE 之前,DMA 通道必须处于停止状态且描述符环已就绪。违反顺序可能导致 MAC 立即尝试读取无效的描述符指针,引发总线挂起。
调试建议:在驱动 probe 函数中,每次写入 CR 或 FFR 后,立即回读寄存器值并与预期值比较。使用 dev_dbg() 打印寄存器快照,配合示波器或逻辑分析仪观察 MII/RGMII 总线信号,可快速定位配置错误。
性能优化:帧过滤寄存器中的 VTFE 和 IPFE 位虽然能卸载 CPU 的过滤负担,但会引入额外的硬件查找延迟(通常 2-4 个时钟周期)。在低延迟场景(如工业实时以太网)中,建议关闭这些高级过滤功能,改用软件过滤。
3.6 本章小结
MAC 控制器的核心寄存器组构成了驱动与硬件交互的契约基础:
- 控制寄存器(CR) 是 MAC 行为的全局开关,驱动必须严格遵循复位→配置→使能的三步流程。
- 状态寄存器(SR) 提供了链路与数据路径的实时快照,中断驱动的读取模式是高效响应的关键。
- MAC 地址寄存器 定义了设备的网络身份,字节序和回读验证是常见出错点。
- 帧过滤寄存器(FFR) 实现了硬件级的接收判决,哈希过滤和 VLAN 过滤能显著降低 CPU 占用。
掌握这些寄存器的位域语义与配置时序,是后续理解 DMA 引擎协同工作和网络协议栈数据流的基础。