Ndis网卡驱动是如何操控硬件的
- 在 DriverEntry 里设置一个_NDIS_MINIPORT_DRIVER_CHARACTERISTICS结构,初作为参数提供给 NdisMRegisterMiniportDriver 函数
NDIS_MINIPORT_DRIVER_CHARACTERISTICS MPChar;MPChar.InitializeHandlerEx = MPInitialize; // 初始化handle...// 注册小端口驱动 Status = NdisMRegisterMiniportDriver(DriverObject,RegistryPath,(PNDIS_HANDLE)MiniportDriverContext,&MPChar,&NdisMiniportDriverHandle);
- 系统会调用上面的初始化handle, 函数的模型如下
NDIS_STATUS MPInitialize( NDIS_HANDLE NdisMiniportHandle, NDIS_HANDLE MiniportDriverContext,PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters // 由系统传来的一个 _NDIS_MINIPORT_INIT_PARAMETERS 参数 )
其中 _NDIS_MINIPORT_INIT_PARAMETERS 结构里包含一项(PNDIS_RESOURCE_LIST AllocatedResources)
typedef struct _CM_PARTIAL_RESOURCE_LIST { // PNDIS_RESOURCE_LIST 结构USHORT Version;USHORT Revision;ULONG Count;CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]; //}
resList = MiniportInitParameters->AllocatedResources; // 取得参数里的resourcefor (index=0; index < resList->Count; index++) {pResDesc = &resList->PartialDescriptors[index]; // 取得resource里的PartialDescriptorsswitch(pResDesc->Type) {case CmResourceTypePort:Adapter->IoBaseAddress = pResDesc->u.Port.Start ; // 得到了一个IoBaseAddressAdapter->IoRange = pResDesc->u.Port.Length; //...}
硬件资源参考:https://blog.csdn.net/xiangbaohui/article/details/105179813
3 调用函数 NdisMRegisterIoPortRange 去注册一个I/O Port,以后通过返回的PortOffse去操控网卡
Status = NdisMRegisterIoPortRange( (PVOID *)&Adapter->PortOffset, // 返回一个portoffset,就是通过这个portoffset去操控硬件的,和以前的in out端口指令一样 Adapter->AdapterHandle,NdisGetPhysicalAddressLow ( Adapter->IoBaseAddress ) , // 上面我们得到的IoBaseAddress Adapter->IoRange); `
- 有了上面的portoffset,我们给网卡设置收包/发包的数据存放地址,通过写 PortOffset+reg 来给网卡下命令。 不同的reg对应不同的命令
enum RTL8169_registers { // 硬件网卡的reg命令表 ,/* PHY access */TxDescStartAddr = 0x20,RxDescStartAddr = 0xE4, ...};ULONG_PTR ioaddr = A->PortOffset; // PortOffset由上面调用 NdisMRegisterIoPortRange 函数得到的#define RTL_W32(reg, val32) WRITE_PORT_ULONG((PULONG)(ioaddr + reg),(ULONG)val32 ) // // 传递命令case SCB_RUC_LOAD_BASE : // 写入收包地址RTL_W32 ( RxDescStartAddr, NdisGetPhysicalAddressLow ( Adapter->HwRbdBasePa ) ); // Adapter->HwRbdBasePa 是收包数据地址RTL_W32 ( RxDescStartAddr + 4, NdisGetPhysicalAddressHigh ( Adapter->HwRbdBasePa )); // case SCB_TBD_LOAD_BASE : // 写入发包地址`RTL_W32 ( , NdisGetPhysicalAddressLow ( Adapter->HwTbdBasePa ) ); TxDescStartAddr // Adapter->HwTbdBasePa 是发包数据的存放地址`RTL_W32 ( TxDescStartAddr + 4, NdisGetPhysicalAddressHigh ( Adapter->HwTbdBasePa ) );//`
地址设置好了,当有数据要处理的时候,网卡会从 发包地址里读取要发送的数据 或 向收包地址里写入收到的数据。
收包 — 网卡写数据到收包地址,生成一个硬件中断通知中断处理函数,中断处理函数先关闭中断,然后取数据,通过NdisMIndicateReceiveNetBufferLists函数把数据传递到上层, 再打开中断,等待下一次中断( 数据传递路径:miniport驱动-> (filter) -> protocol驱动 -> 应用层recv(),驱动之间还可以有过滤驱动,如防火墙就是在底层驱动 之间装一个filter driver,这样数据包会在recv之前被抓到 )
发包 — 把上层传递下来的数据写到发包地址,通过portoffse+reg给网卡下指令,通知网卡去取数据 ( 路径很上面相反,send() -> protocol -> (filter) ->miniport )传给网卡的地址,参考 https://blog.csdn.net/hz5034/article/details/79794615 这篇文章,是一串的连续的描述符,addr —> [描述符][描述符][描述符]…[描述符]
把这个addr通过传给网卡,网卡/dma能够认识这个描述符的,他们会自动工作。【 这文章对这个描述符说的很好 https://www.cnblogs.com/CasonChan/p/5166239.html 】
数据在驱动中是以net_buffer_lists(NBL)结构存在的,一个NBL又有N个net_buffer(NB),一个NB下又有N个MDL,这Mdl存放的就是数据,
描述符描述的就是每个Mdl的地址。一连串的Mdl组成一个NB,一连串的NB组成一个NBL。
描述符的结构大概如下:
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 { // 收包的描述符UINT32 status;UINT32 vlan_tag;UINT32 buf_addr; // 网卡会把数据写到这个地址UINT32 buf_Haddr;} HW_RBD, *PHW_RBD;
6.参考资料 NDIS sample - 6.0 miniport driver for realtek 168/8169/8111/8110
https://www.codeproject.com/Articles/24384/NDIS-sample-miniport-driver-for-realtek
Ndis网卡驱动是如何操控硬件的相关推荐
- windows7以上平台NDIS6框架的NDIS协议驱动开发
by fanxiushu 2019-01-30 转载或引用请注明原始作者. 提到NDIS协议驱动,可能比较陌生,因为毕竟用得挺少的. 但是一提到WireShark或ethereal等抓包软件,大家就不 ...
- 《转》关于ath5k网卡驱动中beacon的发送过程(特别是timestamp字段)
转自:http://blog.csdn.net/liujihang88/article/details/39700385 ath5k网卡驱动中beacon 工作模式:ad-hoc 内核版本:3. ...
- 一文搞懂网卡驱动的原理与移植方法
1.网卡设备驱动原理 1.1 层次结构 Linux系统对网络设备驱动定义了4个层次, 这4个层次有到下分为: 1.网络协议接口层:实现统一的数据包收发的协议.该层主要负责调用dev_queue_xmi ...
- 基于NDIS(网络驱动接口标准)包拦截技术
看了很多提供数据包的拦截技术,其中最多的是编写IM DRIVER在NDIS中间层对MINIPORT(网卡驱动程序)和协议驱动程序之间的数据包进行拦截.但编写该过滤程序拦截程序非常的复杂,这里介绍一种更 ...
- 【转帖】基于NDIS(网络驱动接口标准)包拦截技术
通常用户都知道,NDIS协议驱动程序是通过填写一张NDIS_PROTOCOL_CHARACTERISTICS的表,并调用NDIS API函数NdisRegisterProtocol进行注册.现在我们来 ...
- 关闭Win8快速启动,解决网卡识别错误/网卡驱动安装不正确的问题
阴魂不散的问题 笔者安装的Windows 8是64位专业版,主板內建Intel 82597V千兆网络芯片.Windows 8系统的识别错误经常出现,尤其是当笔者上不了网时,一查看网络适配器,发现它被识 ...
- 字符设备驱动基础篇5——驱动如何操控硬件(动静态映射操作LED)
以下内容源于朱有鹏嵌入式课程的学习,,如有侵权,请告知删除. 参考资料:http://www.cnblogs.com/biaohc/p/6575074.html 这里的映射,是指物理地址和虚拟地址的对 ...
- intel x520网卡驱动_手工编译linux桌面内核(二)——硬件驱动的配置 下篇
前言: 前面的方法讲完了,接下来我们来看看实例(我自己电脑的配置). 这里我只打算列出几项重要的驱动配置来,其它的请自行查阅gentoo wiki! 再次强调,这是我自己电脑的硬件驱动配置,不可能完全 ...
- enc28j60 linux 驱动_linux enc28j60网卡驱动移植(硬件spi和模拟spi)
本来想移植DM9000网卡的驱动,无奈硬件出了点问题,通过杜邦线链接开发板和DM9000网卡模块,系统上电,还没加载网卡驱动就直接崩溃了,找不到原因...刚好手上有一个enc28j60的网卡模块,于是 ...
最新文章
- dis的前缀单词有哪些_英语单词词根.词缀II 5个最高频英语前缀 必背
- python是一种面向对象、直译式的脚本编程语言_什么是python编程语言
- jquery插件的写法
- 拼接路径优雅方式_章泽天“学生装”穿出高级感,缎面衬衫配小香风裙,温柔又优雅...
- 审计日志删除 oracle,oracle audit,怎么审计ORACLE日志
- c语言程序兔子反之问题,C语言解决兔子产子问题代码及解析
- cmake编译Debug和Release
- [bzoj] 2049 洞穴勘探 || LCT
- MyBatis第1天
- zookeeper 进入客户端_Zookeeper基础知识简单介绍
- 信息系统开发平台OpenExpressApp - ClickOnce智能部署
- c语言模拟试卷答案,C语言模拟试卷2(带答案)
- 如何注册CSDN博客
- WebService之CXF框架
- html视频播放卡顿,网页看视频卡怎么解决
- source insight使用2---设置全选为Ctrl+a
- 便利店卷疯了:便利蜂、罗森、易捷“激战”
- 项目需求的重要性和开发步骤
- 微信分享链接不显示缩略图
- 【软件测试】软件测试的方法
热门文章
- 2021-10-27【WGS】丨Pacbio三代甲基化修饰流程
- Linux设备模型(2)——Kobject
- 基于工业智能网关的PLC远程控制解决方案
- MSSQLSERVER 2019修改数据库文件存放路径的简单实现
- python爬虫利用线程池下载视频
- API调用,淘宝天猫、1688、京东、拼多多商品页面APP端原数据获取
- python文献知识图谱可视化_知识图谱可视化工具(知识图谱可视化python)
- 中止执行后超过2年_申请执行超过2年时效,法院还处理吗?
- 利用QProcess::finished信号(signal)来保持目标程序始终运行
- Synchronized详细介绍之锁升级过程