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 的标准流程

  1. 软件复位:向 SWR 位写 1,然后循环读取该位直到硬件自动清零(超时保护)。
  2. 配置接口模式:根据 PHY 接口类型(MII/GMII/RGMII)设置 FES 与 DM 位。
  3. 使能收发路径:在 DMA 初始化完成后,同时置位 RE 和 TE。
  4. 调试与环回:仅在自测阶段置位 LM,正常模式必须清零。

关键提示:RE 与 TE 必须在 DMA 通道和描述符环初始化完成后才能置位,否则 MAC 会立即尝试访问未就绪的 FIFO 或描述符,导致总线错误(Bus Error)或数据损坏。

3.1.3 CR 配置与数据流关系 SVG

控制寄存器(CR)位域与数据流关系 控制寄存器 CR SWR 复位 RE 接收使能 TE 发送使能 DM/FES 模式 复位逻辑 接收 DMA 发送 DMA PHY 接口 注意:RE/TE 必须在 DMA 初始化完成后置位,SWR 置位后需轮询等待硬件自清零

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

帧过滤寄存器(FFR)接收判决流程 接收帧到达 MAC 广播帧? 多播帧? 单播帧? DBF=1 则接收 PM/HMC 检查 PR/HUC 检查 接收:送入 DMA 丢弃:帧被硬件丢弃 说明:PR 位置位时跳过所有单播/多播过滤,直接接收所有帧; VTFE 使能后,帧还需通过 VLAN ID 匹配才能进入接收路径。

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 引擎协同工作和网络协议栈数据流的基础。