PCIE网卡驱动DMA初始化配置

发布于:2025-04-17 ⋅ 阅读:(98) ⋅ 点赞:(0)

1. DMA 启用的时机

e1000e 驱动在 设备初始化阶段 启用 DMA,具体步骤如下:

(1) PCIe 设备初始化
  • 调用路径
    e1000_probe() → e1000_sw_init() → e1000_init_hw() → e1000_configure()

  • 关键操作

    1. 启用 PCIe 设备的 DMA 主控模式(通过设置 PCI Command Register 的 PCI_COMMAND_MASTER 位)。

    2. 分配 DMA 缓冲区(如描述符环和数据缓冲区)。

(2) DMA 引擎启动
  • 调用路径
    e1000_open() → e1000_configure_tx() / e1000_configure_rx()

  • 关键操作

    1. 配置发送(TX)和接收(RX)描述符环的 DMA 地址(通过 MMIO 寄存器写入)。

    2. 启动 DMA 引擎(通过设置控制寄存器 TCTL 和 RCTL)。


2. 配置 MMIO 寄存器

 e1000e 通过 MMIO 寄存器控制 DMA 行为,关键寄存器包括:

寄存器名 地址偏移 作用
TCTL 0x0400 发送控制寄存器,启用 TX DMA(设置 TCTL.EN 位)。
RCTL 0x0100 接收控制寄存器,启用 RX DMA(设置 RCTL.EN 位)。
TDBAL/TDBAH 0x3800 TX 描述符环基地址(低32位/高32位),指向 DMA 缓冲区。
RDBAL/RDBAH 0x2800 RX 描述符环基地址(低32位/高32位),指向 DMA 缓冲区。
TDH/TDT 0x3810 TX 描述符头/尾指针,用于 DMA 环形队列管理。
RDH/RDT 0x2810 RX 描述符头/尾指针,用于 DMA 环形队列管理。

3. 代码示例:DMA 启用流程

(1) 启用 PCIe DMA 主控模式
// drivers/net/ethernet/intel/e1000e/netdev.c
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) {
    pci_enable_device_mem(pdev); // 启用设备内存和 DMA
    pci_set_master(pdev);       // 设置 PCI_COMMAND_MASTER 位
}
(2) 配置 TX/RX 描述符环的 DMA 地址
// drivers/net/ethernet/intel/e1000e/netdev.c
static void e1000_configure_tx(struct e1000_adapter *adapter) {
    struct e1000_hw *hw = &adapter->hw;
    // 写入 TX 描述符环的 DMA 地址
    ew32(TDBAL, (u32)(adapter->tx_ring->dma));
    ew32(TDBAH, (u32)((u64)adapter->tx_ring->dma >> 32));
    // 启用 TX DMA
    ew32(TCTL, adapter->tx_ring->tctl | E1000_TCTL_EN);
}
(3) 启动 RX DMA
static void e1000_configure_rx(struct e1000_adapter *adapter) {
    struct e1000_hw *hw = &adapter->hw;
    // 写入 RX 描述符环的 DMA 地址
    ew32(RDBAL, (u32)(adapter->rx_ring->dma));
    ew32(RDBAH, (u32)((u64)adapter->rx_ring->dma >> 32));
    // 启用 RX DMA
    ew32(RCTL, adapter->rx_ring->rctl | E1000_RCTL_EN);
}

(注:ew32() 是 e1000e 驱动中用于写 MMIO 寄存器的宏)


4. DMA 数据传输流程

  1. 发送数据

    • 驱动将数据包存入内存缓冲区,更新 TX 描述符环。

    • 网卡通过 DMA 从内存读取数据并发送。

  2. 接收数据

    • 网卡通过 DMA 将数据写入内存缓冲区,触发中断通知驱动。

    • 驱动从 RX 描述符环读取数据。


5. 关键点总结

步骤 操作
PCIe DMA 启用 调用 pci_set_master() 设置 PCI_COMMAND_MASTER
MMIO 配置 通过 TCTL/RCTL 寄存器启用 DMA,通过 TDBAL/RDBAL 设置缓冲区。
缓冲区分配 使用 dma_alloc_coherent() 分配 DMA 内存。
数据传输 描述符环管理 DMA 的起始/结束位置。

6. 调试技巧

  • 查看寄存器状态
    通过 ethtool -d ethX 可以 dump e1000e 的寄存器值,确认 TCTL.EN 和 RCTL.EN 是否已置位。

  • DMA 地址验证
    在驱动代码中打印 adapter->tx_ring->dma 和 adapter->rx_ring->dma,确保地址有效。


网站公告

今日签到

点亮在社区的每一天
去签到