ReactOS Intel PRO/1000 (e1000.sys) 网卡驱动程序分析
2026/7/24 23:14:34 网站建设 项目流程

ReactOS Intel PRO/1000 (e1000.sys) 网卡驱动程序分析

目录

  1. 项目概述
  2. 源码文件结构
  3. NDIS Miniport 框架结构
  4. 核心数据结构
  5. 功能实现详解
  6. 运行流程图
  7. 数据流图
  8. TODO / FIXME 清单

1. 项目概述

项目内容
驱动名称e1000.sys
功能Intel PRO/1000 系列千兆以太网 NDIS Miniport 驱动
硬件厂商 ID0x8086 (Intel)
支持芯片8254x 系列 (82542 ~ 82546, 82541, 82547 等 ~50 种 Device ID)
驱动类型NDIS 5.1 传统 Miniport (Legacy Miniport)
NDIS 版本NDIS 5.0/5.1
总线类型PCI (NdisInterfacePci)
DMA总线主控 (Bus Master), 32-bit (禁用 64-bit)
介质类型802.3 以太网 (NdisMedium802_3)
最大帧大小1522 字节
接收缓冲区2048 字节/条目
传输描述符128 个 (环形缓冲区)
接收描述符128 个 (环形缓冲区)
多播地址最多 16 个
许可证GPL-2.0+

2. 源码文件结构

d:\reactos\drivers\network\dd\e1000\ ├── CMakeLists.txt # 构建配置 ├── ndis.c # 驱动入口 + MiniportInitialize / MiniportHalt / MiniportReset ├── hardware.c # 硬件初始化、寄存器操作、资源分配、Tx/Rx 启用/禁用 ├── send.c # 数据包发送 (MiniportSend) ├── interrupt.c # 中断处理 (MiniportISR / MiniportHandleInterrupt) ├── info.c # OID 查询/设置 (MiniportQueryInformation / MiniportSetInformation) ├── debug.c # OID-to-string 调试转换 ├── nic.h # 适配器上下文结构体 + 函数声明 + 内联寄存器 I/O ├── e1000hw.h # 硬件寄存器定义 + 描述符格式 + 常量 ├── debug.h # 调试宏 (NDIS_DbgPrint / UNIMPLEMENTED_DBGBREAK) ├── nete1000.inf # 驱动安装 INF 文件 └── e1000.rc # 版本资源

编译配置 (CMakeLists.txt)

add_definitions(-DNDIS50_MINIPORT -DNDIS_MINIPORT_DRIVER -DNDIS_LEGACY_MINIPORT=1) add_library(e1000 MODULE ${SOURCE} e1000.rc) add_pch(e1000 nic.h SOURCE) set_module_type(e1000 kernelmodedriver) add_importlibs(e1000 ndis ntoskrnl hal)
  • 定义为内核模块驱动(kernelmodedriver)
  • 预编译头:nic.h
  • 链接库:ndis.lib+ntoskrnl.lib+hal.lib
  • 编译宏:NDIS50_MINIPORT(NDIS 5.0 API) +NDIS_MINIPORT_DRIVER+NDIS_LEGACY_MINIPORT

3. NDIS Miniport 框架结构

3.1 NDIS Miniport 驱动模型

NDIS (Network Driver Interface Specification) 是 Windows 网络驱动标准。e1000 驱动属于传统 Miniport 驱动(Legacy Miniport),位于网络栈最底层,直接管理硬件。

┌─────────────────────────────────────┐ │ 上层协议驱动 (TCP/IP) │ ├─────────────────────────────────────┤ │ NDIS 库 (ndis.sys) │ ├─────────────────────────────────────┤ │ e1000.sys (Miniport 驱动) │ ├─────────────────────────────────────┤ │ Intel PRO/1000 硬件 (PCI) │ └─────────────────────────────────────┘

3.2 NDIS 回调注册表

DriverEntry中注册的 Miniport 回调:

回调函数注册项状态
MiniportInitialize.InitializeHandler✅ 已实现
MiniportHalt.HaltHandler✅ 已实现
MiniportSend.SendHandler✅ 已实现
MiniportISR.ISRHandler✅ 已实现
MiniportHandleInterrupt.HandleInterruptHandler✅ 已实现
MiniportQueryInformation.QueryInformationHandler✅ 已实现
MiniportSetInformation.SetInformationHandler✅ 已实现
MiniportReset.ResetHandler⚠️ 存根 (UNIMPLEMENTED)
CheckForHangHandler❌ NULL
DisableInterruptHandler❌ NULL
EnableInterruptHandler❌ NULL
TransferDataHandler❌ NULL
ReturnPacketHandler❌ NULL
SendPacketsHandler❌ NULL

3.3 NDIS 版本常量

// 来自 ndis.h#defineNDIS_MINIPORT_MAJOR_VERSION5#defineNDIS_MINIPORT_MINOR_VERSION0

4. 核心数据结构

4.1 适配器上下文E1000_ADAPTER(nic.h:27-93)

typedefstruct_E1000_ADAPTER{/* ── PCI 内存映射 I/O ── */volatilePUCHAR IoBase;// MMIO 基地址 (NdisMMapIoSpace)NDIS_PHYSICAL_ADDRESS IoAddress;// MMIO 物理地址ULONG IoLength;// MMIO 长度 (128KB)/* ── NDIS 句柄 ── */NDIS_HANDLE AdapterHandle;// NDIS 适配器句柄/* ── 硬件标识 ── */USHORT VendorID;// PCI Vendor IDUSHORT DeviceID;// PCI Device IDUSHORT SubsystemID;USHORT SubsystemVendorID;/* ── MAC 地址 ── */UCHAR PermanentMacAddress[6];// 出厂 MAC (从 EEPROM 读取)struct{UCHAR MacAddress[6];}MulticastList[16];// 多播地址表ULONG MulticastListSize;// 当前多播地址数量/* ── 链路状态 ── */ULONG LinkSpeedMbps;// 当前链路速度 (10/100/1000)ULONG MediaState;// 连接状态 (Connected/Disconnected)ULONG PacketFilter;// 当前包过滤掩码/* ── I/O 端口 (备用访问路径) ── */ULONG IoPortAddress;ULONG IoPortLength;volatilePUCHAR IoPort;/* ── 中断 ── */ULONG InterruptVector;ULONG InterruptLevel;BOOLEAN InterruptShared;ULONG InterruptFlags;NDIS_MINIPORT_INTERRUPT Interrupt;// NDIS 中断对象BOOLEAN InterruptRegistered;LONG InterruptMask;// 中断掩码 (写入 E1000_REG_IMS)volatileLONG InterruptPending;// 待处理中断位图 (_InterlockedOr)/* ── 发送 (TX) ── */PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptors;// TX 描述符环形缓冲区NDIS_PHYSICAL_ADDRESS TransmitDescriptorsPa;// TX 描述符物理地址PNDIS_PACKET TransmitPackets[NUM_TRANSMIT_DESCRIPTORS];// 待 ACK 的 NDIS 包ULONG CurrentTxDesc;// 当前可用的 TX 描述符索引 (Tail)ULONG LastTxDesc;// 最后一个待完成的 TX 描述符索引 (Head)BOOLEAN TxFull;// TX 描述符是否已满/* ── 接收 (RX) ── */PE1000_RECEIVE_DESCRIPTOR ReceiveDescriptors;// RX 描述符环形缓冲区NDIS_PHYSICAL_ADDRESS ReceiveDescriptorsPa;// RX 描述符物理地址E1000_RCVBUF_SIZE ReceiveBufferType;// 接收缓冲区大小类型 (默认 2048)volatilePUCHAR ReceiveBuffer;// 接收数据缓冲区 (共享内存)NDIS_PHYSICAL_ADDRESS ReceiveBufferPa;// 接收缓冲区物理地址ULONG ReceiveBufferEntrySize;// 每个条目大小}E1000_ADAPTER,*PE1000_ADAPTER;

4.2 发送描述符E1000_TRANSMIT_DESCRIPTOR(e1000hw.h:86-97)

typedefstruct_E1000_TRANSMIT_DESCRIPTOR{UINT64 Address;// 数据缓冲区物理地址 (PCI DMA)USHORT Length;// 数据长度UCHAR ChecksumOffset;// 校验和偏移UCHAR Command;// 命令标志UCHAR Status;// 完成状态 (由硬件写入)UCHAR ChecksumStartField;// 校验和起始域USHORT Special;// 特殊字段}E1000_TRANSMIT_DESCRIPTOR;// C_ASSERT(sizeof == 16)

4.3 接收描述符E1000_RECEIVE_DESCRIPTOR(e1000hw.h:64-74)

typedefstruct_E1000_RECEIVE_DESCRIPTOR{UINT64 Address;// 接收缓冲区物理地址USHORT Length;// 接收数据长度 (由硬件写入)USHORT Checksum;// 校验和UCHAR Status;// 完成状态 (由硬件写入)UCHAR Errors;// 错误标志USHORT Special;}E1000_RECEIVE_DESCRIPTOR;// C_ASSERT(sizeof == 16)

4.4 以太网帧头ETH_HEADER(e1000hw.h:27-31)

typedefstruct_ETH_HEADER{UCHAR Destination[6];// 目的 MACUCHAR Source[6];// 源 MACUSHORT PayloadType;// 以太类型 (如 0x0800 = IPv4)}ETH_HEADER;// sizeof = 14

4.5 中断标志位

标志含义
E1000_IMS_TXDW0x0001发送描述符写回
E1000_IMS_TXQE0x0002发送队列空
E1000_IMS_LSC0x0004链路状态变化
E1000_IMS_RXDMT00x0010接收描述符达到最小阈值
E1000_IMS_RXT00x0080接收定时器中断
E1000_IMS_TXD_LOW0x8000发送描述符低阈值

默认中断掩码:(LSC | TXDW | TXQE | RXDMT0 | RXT0 | TXD_LOW)


5. 功能实现详解

5.1 驱动入口与初始化 (ndis.c)

DriverEntry(ndis.c:252-295)

驱动入口点,被ntoskrnl在加载驱动时调用。

流程:

  1. 初始化NDIS_MINIPORT_CHARACTERISTICS结构体,注册所有回调
  2. 调用NdisMInitializeWrapper获取 NDIS 包装句柄
  3. 调用NdisMRegisterMiniport向 NDIS 注册此 Miniport
  4. 注册成功后返回NDIS_STATUS_SUCCESS
MiniportInitialize(ndis.c:48-250)

NDIS 发现匹配硬件后调用此函数进行初始化。

详细步骤:

  1. 介质检查— 确认MediumArray包含NdisMedium802_3
  2. 分配适配器上下文NdisAllocateMemoryWithTag(sizeof(E1000_ADAPTER), '001e')
  3. 设置属性NdisMSetAttributesEx(BusMaster, NdisInterfacePci)
  4. 读取 PCI 配置NdisReadPciSlotInformation获取 VendorID/DeviceID/SubsystemID
  5. 硬件识别NICRecognizeHardware检查 Vendor=0x8086 且 Device 在支持列表
  6. 获取 PCI 资源NdisMQueryAdapterResources获取 MMIO/Port/IRQ
  7. 初始化硬件资源NICInitializeAdapterResources解析 MMIO/Port/IRQ 资源
  8. 分配 IO 资源NICAllocateIoResources:
    • 映射 MMIO 空间 (NdisMMapIoSpace)
    • 注册 I/O 端口 (NdisMRegisterIoPortRange)
    • 分配 TX 描述符共享内存 (128 × 16 = 2048 字节)
    • 分配 RX 描述符共享内存 (128 × 16 = 2048 字节)
    • 分配 RX 数据缓冲区 (2048 × 128 = 256KB)
  9. 初始化 DMANdisMInitializeScatterGatherDma(maxFrame=1522, 32-bit)
  10. 上电NICPowerOn→ 软复位 + 验证 EEPROM 校验和
  11. 软复位NICSoftReset→ 写 CTRL.RST, 等待复位完成
  12. 读取 MACNICGetPermanentMacAddress→ 从 EEPROM 读取 MAC
  13. 更新多播列表NICUpdateMulticastList→ 初始化 RAH/RAL 寄存器
  14. 更新链路状态NICUpdateLinkStatus→ 读取 STATUS 寄存器
  15. 注册中断NICRegisterInterruptsNdisMRegisterInterrupt
  16. 启用中断— 写E1000_REG_IMS设置中断掩码
  17. 启用 Tx/RxNICEnableTxRx→ 配置 TX/RX 控制寄存器

5.2 硬件操作 (hardware.c)

NICSoftReset(hardware.c:529-570)
  1. 禁用中断 (NICDisableInterrupts)
  2. 清除 RCTL/TCTL (禁用接收/发送)
  3. 写 CTRL.RST 启动硬件复位
  4. 循环等待复位完成 (最多 10 次, 每次 1μs)
  5. 复位完成后重新禁用中断
  6. 清除 ICR (读取即清除)
  7. 配置 CTRL: 清除 LRST/VME, 设置 ASDE/SLU (自动速度/链路向上)
NICEnableTxRx(hardware.c:572-637)

发送配置:

  1. 写 TDBAH/TDBAL — 设置 TX 描述符基地址
  2. 写 TDLEN — 设置 TX 描述符环形缓冲区长度
  3. 写 TDH/TDT = 0 — 初始化 Head/Tail 指针
  4. 写 TADV=96, TIDV=16 — 中断延迟定时器
  5. 写 TCTL = EN | PSP — 启用发送 + 填充短包
  6. 写 TIPG — 设置帧间距 (IPGT=10, IPGR1=10, IPGR2=10)

接收配置:

  1. 写 RDBAH/RDBAL — 设置 RX 描述符基地址
  2. 写 RDLEN — 设置 RX 描述符环形缓冲区长度
  3. 写 RDH=0, RDT=NUM_RX_DESC-1 — 初始化 Head/Tail
  4. 写 RADV=96, RDTR=16 — 中断延迟定时器
  5. 写 RCTL = EN | SECRC | BSIZE | FilterMask — 启用接收 + 剥离 CRC + 缓冲区大小 + 包过滤
NICGetPermanentMacAddress(hardware.c:659-689)

通过 EEPROM 读取 MAC 地址:

  • 读取 EEPROM 字 0~2 (6 字节)
  • 每个字高/低字节组合成 MAC 地址
E1000ReadEeprom(hardware.c:162-185)
  1. 写 EERD: START | (Address << ADDR_SHIFT)
  2. 循环等待 DONE 标志 (最多 10000 次, 每次 5μs)
  3. 读取 EERD.DATA 字段返回
NICUpdateMulticastList(hardware.c:691-719)

遍历 16 个多播地址槽, 写入 RAL[n]/RAH[n]:

  • 非零地址: 写入 RAL + (RAH | AV)
  • 零地址: 写 0 清除

5.3 数据包发送 (send.c)

MiniportSend(send.c:47-85)

NDIS 上层协议调用此函数发送一个网络包。

流程:

  1. 从 NDIS 包获取 Scatter/Gather List (NDIS_PER_PACKET_INFO_FROM_PACKET)
  2. 断言: sgList->NumberOfElements == 1 (单一缓冲区)
  3. 检查 TxFull 标志 — 如果 TX 描述符已满则返回 NDIS_STATUS_RESOURCES
  4. 保存 NDIS 包指针到TransmitPackets[CurrentTxDesc]
  5. 调用NICTransmitPacket写入 TX 描述符并通知硬件
  6. 返回NDIS_STATUS_PENDING(异步发送)
NICTransmitPacket(send.c:14-45)
  1. 获取当前 TX 描述符 (TransmitDescriptors + CurrentTxDesc)
  2. 设置描述符字段:
    • Address= 数据缓冲区的物理地址
    • Length= 数据长度
    • Command= RS | IFCS | EOP | IDE (报告状态/插入FCS/包结束/延迟中断)
  3. 写 TDT 寄存器 = CurrentTxDesc (通知硬件有新的发送请求)
  4. 更新 CurrentTxDesc (环形推进)
  5. 如果 CurrentTxDesc == LastTxDesc, 设置 TxFull = TRUE

5.4 中断处理 (interrupt.c)

MiniportISR(interrupt.c:14-42)

运行于 DIRQL (设备中断请求级别)。

流程:

  1. 读取 ICR (Interrupt Cause Read) — 该操作同时确认中断
  2. 将读取的值与 InterruptMask 取与
  3. 使用_InterlockedOr原子写入 InterruptPending
  4. 如果值为非零 →InterruptRecognized = TRUE, QueueMiniportHandleInterrupt = TRUE
  5. 如果值为零 → 不是我们的中断
MiniportHandleInterrupt(interrupt.c:44-197)

运行于 DISPATCH_LEVEL, 处理所有待处理中断。

链路状态变化 (LSC):

  1. 读取 STATUS 寄存器更新链路状态
  2. 调用NdisMIndicateStatus+NdisMIndicateStatusComplete通知 NDIS

接收中断 (RXDMT0 | RXT0):

  1. 读取 RDH/RDT 获取当前硬件位置
  2. 遍历 RDT→RDH 之间的描述符:
    • 检查Status & DD(Descriptor Done, 硬件已写回数据)
    • 忽略IXSM | PIF标志
    • 检查Status == (EOP | DD)
    • 如果PacketFilter == 0, 跳过 (不指示数据)
    • 调用NdisMEthIndicateReceive向上层指示接收数据
  3. 写回Status = 0归还描述符给硬件
  4. 更新 RDT 寄存器
  5. 如果有数据收到, 调用NdisMEthIndicateReceiveComplete

发送完成中断 (TXD_LOW | TXDW | TXQE):

  1. 遍历 LastTxDesc→CurrentTxDesc:
    • 检查Status & DD(发送完成)
    • 收集对应的 NDIS 包到 AckPackets 数组
    • 清除描述符 Status
    • 更新 LastTxDesc, 清除 TxFull
  2. 调用NdisMSendComplete通知 NDIS 发送完成

5.5 OID 查询与设置 (info.c)

MiniportQueryInformation(info.c:72-279)

支持的 OID (Object IDentifier) 列表:

OID返回数据说明
OID_GEN_SUPPORTED_LISTSupportedOidList支持的 OID 列表
OID_GEN_CURRENT_PACKET_FILTERAdapter->PacketFilter当前包过滤掩码
OID_GEN_HARDWARE_STATUSNdisHardwareStatusReady硬件状态 (存根)
OID_GEN_MEDIA_SUPPORTEDNdisMedium802_3支持的介质
OID_GEN_MEDIA_IN_USENdisMedium802_3使用的介质
OID_GEN_RECEIVE_BLOCK_SIZEMAX_FRAME - 14接收块大小 (1508)
OID_GEN_LINK_SPEEDSpeedMbps × 10000链路速度
OID_GEN_VENDOR_IDMAC 前 3 字节厂商 ID
OID_GEN_VENDOR_DESCRIPTION“ReactOS Team”厂商描述
OID_802_3_PERMANENT_ADDRESSPermanentMacAddress出厂 MAC
OID_802_3_CURRENT_ADDRESSMulticastList[0]当前 MAC
OID_GEN_MEDIA_CONNECT_STATUSMediaState介质连接状态
OID_GEN_PHYSICAL_MEDIUMNdisPhysicalMedium802_3物理介质类型
统计类 OIDNICQueryStatisticCounter (返回 0)统计计数器 (TODO)
OID_PNP_CAPABILITIESNICFillPowerManagementCapabilities电源管理 (不支持)
MiniportSetInformation(info.c:281-400)
OID行为
OID_GEN_CURRENT_PACKET_FILTER验证过滤位, 更新 Adapter->PacketFilter, 调用 NICApplyPacketFilter
OID_GEN_CURRENT_LOOKAHEAD验证大小, 忽略设置
OID_802_3_MULTICAST_LIST验证地址列表, 复制到 Adapter->MulticastList, 调用 NICUpdateMulticastList

5.6 停止与销毁 (ndis.c)

MiniportHalt(ndis.c:26-46)

NDIS 卸载驱动或移除设备时调用。

  1. NICDisableTxRx— 清除 TCTL.EN / RCTL.EN 禁用接收和发送
  2. NICUnregisterInterruptsNdisMDeregisterInterrupt注销中断
  3. NICReleaseIoResources— 释放所有共享内存 + 取消 MMIO/Port 映射
  4. NdisFreeMemory(Adapter)— 释放适配器上下文
MiniportReset(ndis.c:15-24)

未实现的存根。返回NDIS_STATUS_FAILURE


6. 运行流程图

6.1 驱动初始化流程

DriverEntry() │ ├─ 填充 NDIS_MINIPORT_CHARACTERISTICS ├─ NdisMInitializeWrapper() └─ NdisMRegisterMiniport() │ ▼ (NDIS 检测到匹配 PCI 设备后调用) MiniportInitialize() │ ├─ 检查介质 (NdisMedium802_3) ├─ NdisAllocateMemoryWithTag → Adapter ├─ NdisMSetAttributesEx (BusMaster) ├─ NdisReadPciSlotInformation → PciConfig ├─ NICRecognizeHardware (Vendor=0x8086, Device in list) ├─ NdisMQueryAdapterResources → 获取 MMIO/IRQ/Port ├─ NICInitializeAdapterResources (解析资源) ├─ NICAllocateIoResources │ ├─ NdisMRegisterIoPortRange │ ├─ NdisMMapIoSpace │ ├─ 分配 TX 描述符 (NdisMAllocateSharedMemory) │ ├─ 分配 RX 描述符 (NdisMAllocateSharedMemory) │ └─ 分配 RX 缓冲区 (NdisMAllocateSharedMemory) ├─ NdisMInitializeScatterGatherDma ├─ NICPowerOn │ ├─ NICSoftReset │ └─ E1000ValidateNvmChecksum ├─ NICGetPermanentMacAddress (从 EEPROM) ├─ NICUpdateMulticastList (写 RAH/RAL) ├─ NICUpdateLinkStatus (读 STATUS 寄存器) ├─ NICRegisterInterrupts (NdisMRegisterInterrupt) ├─ 设置 InterruptMask, NICApplyInterruptMask └─ NICEnableTxRx ├─ 配置 TDBAH/TDBAL/TDLEN/TDH/TDT ├─ 配置 TCTL/TIPG ├─ 配置 RDBAH/RDBAL/RDLEN/RDH/RDT └─ 配置 RCTL 成功 → NDIS_STATUS_SUCCESS 失败 → Cleanup → MiniportHalt → 返回值

6.2 数据包发送流程

上层协议 (TCP/IP) │ │ NdisSend() ▼ NDIS 库 │ │ MiniportSend(AdapterHandle, Packet, Flags) ▼ MiniportSend() │ ├─ 从 Packet 获取 Scatter/Gather List ├─ 检查 TxFull? → NDIS_STATUS_RESOURCES ├─ TransmitPackets[CurrentTxDesc] = Packet (保存包引用) └─ NICTransmitPacket(Adapter, PhysicalAddress, Length) │ ├─ 填充 TX 描述符: │ Address = DataPA │ Length = DataLength │ Command = RS | IFCS | EOP | IDE ├─ 更新 CurrentTxDesc (环形 +1) ├─ E1000WriteUlong(TDT, CurrentTxDesc) ← 通知硬件 └─ 如果描述符满 → TxFull = TRUE │ └─ 返回 NDIS_STATUS_PENDING (异步) │ ▼ (稍后, 硬件发送完成产生中断) MiniportHandleInterrupt() │ ├─ 检测 TXD_LOW | TXDW | TXQE ├─ 遍历 LastTxDesc→CurrentTxDesc │ ├─ 检查 TDESC.Status.DD │ ├─ 收集 TransmitPackets[LastTxDesc] │ └─ 清除描述符, 更新 LastTxDesc └─ NdisMSendComplete(Packet, NDIS_STATUS_SUCCESS) ← 通知上层

6.3 数据包接收流程

硬件收到网络包 │ ├─ DMA 写入接收缓冲区 (ReceiveBuffer + Offset) ├─ 写回接收描述符 (Status.DD = 1, Length = 实际长度) └─ 触发中断 │ ▼ MiniportISR() │ ├─ E1000ReadUlong(ICR) → 获取中断原因 └─ InterruptPending |= Value │ ▼ NDIS 调度 MiniportHandleInterrupt() │ ├─ 检测 RXDMT0 | RXT0 ├─ 读取 RDH/RDT ├─ 循环遍历 RDT→RDH: │ ├─ 检查 Status.DD (硬件已写回) │ ├─ 检查 Status.EOP (包结束) │ ├─ 检查 PacketFilter (非 0 才指示) │ ├─ 构造 ETH_HEADER 指针 │ └─ NdisMEthIndicateReceive( │ AdapterHandle, │ NULL, // 无上层绑定句柄 │ EthHeader, // 以太头 │ sizeof(ETH_HEADER), // 14 字节 │ Payload, // 负载 │ Length - sizeof(header), // 负载长度 │ Length - sizeof(header)) // 全包长度 ├─ 归还描述符 (Status = 0, 更新 RDT) └─ NdisMEthIndicateReceiveComplete() │ ▼ 上层协议 (TCP/IP) 处理接收数据

6.4 中断处理总流程

硬件触发中断 │ ▼ (DIRQL) MiniportISR() │ ├─ 读取 ICR (确认中断) ├─ InterruptPending = ICR & InterruptMask ├─ Value != 0? → InterruptRecognized=TRUE, QueueInterrupt=TRUE └─ Value == 0? → InterruptRecognized=FALSE (不是我们的设备) │ ▼ (DISPATCH_LEVEL) MiniportHandleInterrupt() │ ├─ InterruptPending = InterlockedExchange(&Adapter->InterruptPending, 0) │ ├─ if (LSC) → NICUpdateLinkStatus → NdisMIndicateStatus │ ├─ if (RXDMT0 | RXT0) → 接收处理循环 → NdisMEthIndicateReceive │ └─ if (TXD_LOW | TXDW | TXQE) → 发送完成处理 → NdisMSendComplete

6.5 停止流程

MiniportHalt() │ ├─ NICDisableTxRx() │ ├─ 清除 TCTL.EN │ └─ 清除 RCTL.EN │ ├─ NICUnregisterInterrupts() │ └─ NdisMDeregisterInterrupt() │ └─ NICReleaseIoResources() ├─ 写 TDH=0, TDT=0 (解除硬件关联) ├─ NdisMFreeSharedMemory(RX 描述符) ├─ NdisMFreeSharedMemory(RX 缓冲区) ├─ NdisMFreeSharedMemory(TX 描述符) ├─ NdisMDeregisterIoPortRange() └─ NdisMUnmapIoSpace() │ └─ NdisFreeMemory(Adapter)

7. 数据流图

7.1 发送数据流

┌──────────┐ ┌──────────┐ ┌──────────┐ │ 上层协议 │ Send │ NDIS │ Miniport │ e1000 │ │ (TCP/IP) │────────►│ 库 │────────►│ 驱动 │ └──────────┘ └──────────┘ └────┬─────┘ │ ┌─────────────────────────────┤ │ │ ▼ ▼ ┌────────────────┐ ┌────────────────┐ │ TransmitPackets│ │ TX Descriptor │ │ [TDT]=Packet │ │ Ring Buffer │ └────────────────┘ │ (128 entries) │ │ │ TDH ▲ TDT │ │ └─────┼─────────┘ │ │ │ ▼ DMA │ ┌────────────────┐ │ │ Packet Data │ │ │ (Shared Memory)│ │ └────────────────┘ │ │ │ ▼ │ ┌────────────────┐ │ │ NIC Hardware │ │ │ (PRO/1000) │ │ └────────┬───────┘ │ │ │ 发送完成中断 │ │ ▼ └──────────────────┬────────┘ │ ▼ ┌────────────────┐ │ NdisMSendComp- │ │ lete(Packet) │ └────────────────┘

7.2 接收数据流

┌────────────────┐ │ NIC Hardware │ │ (PRO/1000) │ └───────┬────────┘ │ DMA ▼ ┌──────────────────┐ │ Receive Buffer │ │ (256KB Shared) │ ├──────────────────┤ │ RxDesc[0].Addr │──► Buffer[0] (2KB) │ RxDesc[1].Addr │──► Buffer[1] (2KB) │ ... │ │ RxDesc[127].Addr │──► Buffer[127] (2KB) └──────────────────┘ │ Status.DD=1 + 中断 │ ▼ ┌──────────────────┐ │ MiniportISR() │ │ MiniportHandle- │ │ Interrupt() │ └───────┬──────────┘ │ ▼ ┌──────────────────┐ │ NdisMEthIndicate-│ │ Receive( │ │ EthHeader, │ │ Payload) │ └───────┬──────────┘ │ ▼ ┌──────────────────┐ │ NDIS 库 │ └───────┬──────────┘ │ ▼ ┌──────────────────┐ │ 上层协议 (TCP/IP) │ └──────────────────┘

7.3 描述符环形缓冲区操作

发送 (TX) 环形缓冲区: ┌────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 1 │ 2 │ ...│ N │ ...│127 │ └────┴────┴────┴────┴────┴────┴────┘ ▲ ▲ │ │ LastTxDesc (Head) CurrentTxDesc (Tail) └─ 硬件已完成的 └─ 下一个可用的 描述符 (待 ACK) 描述符 推进规则: MiniportSend 时: CurrentTxDesc++ 中断处理完成时: LastTxDesc++ 当 Current == Last → TxFull = TRUE 接收 (RX) 环形缓冲区: ┌────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 1 │ 2 │ ...│ N │ ...│127 │ └────┴────┴────┴────┴────┴────┴────┘ ▲ ▲ │ │ RDH (硬件读取) RDT (驱动写入) └─ 硬件正在处理的 └─ 驱动已归还的 推进规则: 硬件写完数据后自动推进 RDH 驱动处理完成后写 RDT 归还描述符 初始: RDH=0, RDT=127 硬件写入数据 → RDH 推进 驱动处理完成 → RDT 推进 (RDT+1) % 128 == RDH → 无待处理数据

7.4 数据缓冲区的物理/虚拟地址映射

NDIS 内存管理 │ NdisMAllocateSharedMemory() │ ┌─────────┴─────────┐ ▼ ▼ 虚拟地址 物理地址 (CPU 可访问) (DMA 可访问) │ │ │ │ ┌────┴────┐ ┌────┴────┐ │ TX Desc │ │ TX Desc │ │ (虚拟) │◄────────│ (物理) │ │ RX Desc │ │ RX Desc │ │ RX Buf │ │ RX Buf │ └─────────┘ └─────────┘ │ │ 写入 TX Desc.Address │ 写入 RDBAH/RDBAL ▼ ┌────────────────┐ │ NIC Hardware │ │ (DMA Engine) │ └────────────────┘

8. TODO / FIXME 清单

位置问题影响
hardware.cNICUpdateMulticastList// FIXME: Use 'Adapter->MulticastListSize'?当前固定写 16 个地址,未使用MulticastListSize低 — 不影响基本功能
info.cMiniportQueryInformationUNIMPLEMENTED_DBGBREAK()(OID_GEN_HARDWARE_STATUS)硬编码为NdisHardwareStatusReady低 — 仅用于查询
info.cNICQueryStatisticCounter/* TODO */ return 0统计计数器未实现 (XMIT_OK, RCV_OK 等全部返回 0)低 — 不影响网络通信
info.cNICFillPowerManagementCapabilitiesreturn NDIS_STATUS_NOT_SUPPORTED电源管理能力未实现低 — 不影响基本功能
interrupt.c`ReceiveDescriptor->Status &= ~IXSMPIF` 忽略校验和标志未利用硬件校验和卸载
ndis.cMiniportResetUNIMPLEMENTED_DBGBREAK() return NDIS_STATUS_FAILURE复位处理未实现中 — 某些错误恢复场景可能失败
hardware.cE1000ReadMdic#if 0禁用PHY 寄存器读取未启用低 — 当前通过 STATUS 寄存器读取链路状态
hardware.cNdisMInitializeScatterGatherDma 禁用 64-bit DMA强行禁用了 64-bit DMA 支持中 — 32-bit 也能工作,但限制性能
interrupt.cASSERT(InterruptPending == 0)如果出现未处理的中断位会导致断言失败低 — 仅 DBG 构建
info.cSupportedOidList 缺少OID_802_3_MAC_OPTIONS未声明支持的 MAC 选项
info.cOID_GEN_MAXIMUM_SEND_PACKETS 返回 1每次只能发送一个包中 — 限制发送并发性
info.cOID_802_3_CURRENT_ADDRESS 返回MulticastList[0].MacAddress理论上应是当前 MAC,但结构上 MulticastList[0] 被初始化为 PermanentMacAddress低 — 通常是正确的

附录 A: 关键寄存器地址

寄存器地址类型描述
CTRL0x0000R/WDevice Control
STATUS0x0008RDevice Status
EERD0x0014R/WEEPROM Read
MDIC0x0020R/WMDI Control
ICR0x00C0R/clrInterrupt Cause Read
IMS0x00D0R/WInterrupt Mask Set
IMC0x00D8WInterrupt Mask Clear
RCTL0x0100R/WReceive Control
TCTL0x0400R/WTransmit Control
TIPG0x0410R/WTransmit IPG
RDBAL0x2800R/WRX Desc Base Low
RDBAH0x2804R/WRX Desc Base High
RDLEN0x2808R/WRX Desc Length
RDH0x2810R/WRX Desc Head
RDT0x2818R/WRX Desc Tail
TDBAL0x3800R/WTX Desc Base Low
TDBAH0x3804R/WTX Desc Base High
TDLEN0x3808R/WTX Desc Length
TDH0x3810R/WTX Desc Head
TDT0x3818R/WTX Desc Tail
RAL0x5400R/WReceive Address Low (每 8 字节递增)
RAH0x5404R/WReceive Address High (每 8 字节递增)

附录 B: 支持的设备 ID 列表

0x1000(82542),0x1001(82543GC Fiber),0x1004(82543GC Copper),0x1008(82544EI Copper),0x1009(82544EI Fiber),0x100A(82540EM),0x100C(82544GC Copper),0x100D(82544GC LOM),0x100E(82540EM),0x100F(82545EM Copper),0x1010(82546EB Copper),0x1011(82545EM Fiber),0x1012(82546EB Fiber),0x1013(82541EI),0x1014(82541EI LOM),0x1015(82540EM LOM),0x1016(82540EP LOM),0x1017(82540EP),0x1018(82541EI Mobile),0x1019(82547EI),0x101A(82547EI Mobile),0x101D(82546EB Quad),0x101E(82540EP LP),0x1026(82545GM Copper),0x1027(82545GM Fiber),0x1028(82545GM SerDes),0x1075(82547GI),0x1076(82541GI),0x1077(82541GI Mobile),0x1078(82541ER),0x1079(82546GB Copper),0x107A(82546GB Fiber),0x107B(82546GB SerDes),0x107C(82541PI),0x108A(82546GB PCI-E),0x1099(82546GB Quad),0x10B5(82546GB Quad KSP3)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询