ndis网卡驱动收发包
Posted asmalleyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ndis网卡驱动收发包相关的知识,希望对你有一定的参考价值。
尝试描述ndis网卡驱动的收发包过程
- 设置一个_NDIS_MINIPORT_DRIVER_CHARACTERISTICS结构,包含初始化,处理中断,发包等很多自己写的handle,初作为参数提供给MRegisterMiniportDriver函数
- MRegisterMiniportDriver会首先调用其中初始化handle模型如下
NDIS_STATUS MiniportInitialize(
...NDIS_HANDLE NdisMiniportHandle,
...NDIS_HANDLE MiniportDriverContext,
...PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters // 系统给我们提供的_NDIS_MINIPORT_INIT_PARAMETERS结构
)
其中_NDIS_MINIPORT_INIT_PARAMETERS结构里包含一项 PNDIS_RESOURCE_LIST AllocatedResources, 这个AllocatedResources包含下面数据;
switch (resource->Type)
【参考https://blog.csdn.net/xiangbaohui/article/details/105179813】
{
... case CmResourceTypePort:
......Adapter->IoBaseAddress = resource->u.Port.Start ; // 得到了一个IoBaseAddress
......Adapter->IoRange = resource->u.Port.Length; //
...
}
- 调用函数 NdisMRegisterIoPortRange去得到一个操控网卡的IO Port
Status = NdisMRegisterIoPortRange(
... (PVOID *)&Adapter->PortOffset, // 返回一个portoffset,就是通过这个portoffset去操控硬件的,和以前的in out端口指令一样
... Adapter->AdapterHandle,
... NdisGetPhysicalAddressLow ( Adapter->IoBaseAddress ) , // 上面我们得到的IoBaseAddress
... Adapter->IoRange);
- 有了上面的portoffset,我们可以给硬件下命令,设置收发包的地址,RxDescStartAddr和TxDescStartAddr都是【portoffset+寄存器偏移】,操作相应地址等于下相应的命令
case SCB_RUC_LOAD_BASE : // 设置收包地址,为我们要收包的地址
... RTL_W32 ( RxDescStartAddr, NdisGetPhysicalAddressLow ( Adapter->HwRbdBasePa ) ); // 地址是自己分配的
... RTL_W32 ( RxDescStartAddr + 4, NdisGetPhysicalAddressHigh ( Adapter->HwRbdBasePa ));
case SCB_TBD_LOAD_BASE : // 设置发包地址,写地址【portoffset+寄存器偏移】为我们要发包的地址
... RTL_W32 ( TxDescStartAddr, NdisGetPhysicalAddressLow ( Adapter->HwTbdBasePa ) ); // 地址是自己分配的
... RTL_W32 ( TxDescStartAddr + 4, NdisGetPhysicalAddressHigh ( Adapter->HwTbdBasePa ) );
- 地址设置好了,以后
【 收包 - 网卡写数据到收包地址,生成一个中断,通知驱动程序的中断处理函数去取数据 】
【 发包 - 我们把数据写到发包地址,通过portoffset通知网卡去取数据 】
=================================================================================================================
大概流程如此,从系统得到一个portoffset,通过给portoffset下相应的命令,来完成对应的工作 (以前都是通过cpu的In out指令下的命令)。
-- 设置收发包地址(所谓的地址其实是一连串的地址描述符,下面)
-- 收包 - 数据写入后,产生硬件中断,通知我们去取
-- 发包 - 数据写好后,给portoffset下对应指令,让网卡去发
传给网卡的地址,参考 https://blog.csdn.net/hz5034/article/details/79794615这篇文章
设定的收发包地址,是一串的连续的描述符,addr->[描述符][描述符][描述符].N个.[描述符],把这个addr通过portoffset下命令传给网卡,网卡或是dma能够认识这个描述符的,他们会自动工作。
描述符的结构大概如下:
typedef struct _TBD_STRUC { // 发包的描述符, 一个包一个描述符
... UINT16 FrameLength ;
... UINT16 status;
... UINT32 notused;
... UINT32 TbdBufferAddress; // 网卡会去这个地址取发包的数据
... UINT32 TbdBufferAddressHigh ;
} TBD_STRUC, *PTBD_STRUC;
typedef struct _RTK_RECEIVE_BUFFER_DESCRIPOR_STRUC { // 收包的描述符,网卡会挨个往里面的buf_addr地址写数据
... UINT32 status;
... UINT32 vlan_tag;
... UINT32 buf_addr; // 网卡会把数据写到这个地址
... UINT32 buf_Haddr;
} HW_RBD, *PHW_RBD;
参考:NDIS 6.0的miniport设备驱动 ---- http://www.codesoso.com/code/NDIS-miniport-driver.aspx
以上是关于ndis网卡驱动收发包的主要内容,如果未能解决你的问题,请参考以下文章