阅读:3049回复:0
DriverNetwork miniport驱动学习(4)
访问I/O端口
DriverNetworks 提供了一组类来访问NIC的I/O 和内存映射寄存器: • KNdisIoRange / KNdisIoRegister / KNdisIoRegisterSafe<T> • KNdisMemoryRange / KNdisMemoryRegister / KNdisMemoryRegisterSafe<T> 这些类都是基类KNdisPeripheralAddress的派生类。 NDIS Miniport驱动必须考虑以下问题: • Registering向系统注册I/O端口和内存区。 • Accessing访问单个I/O或内存映射端口。 • De-registering注销I/O端口和内存区 1. 注册I/O端口和内存区 1)在adapter类中包括KNdisIoRange和/或KNdisMemoryRange数据成员。例如: class MyAdapter : public KNdisMiniAdapter { . . . KNdisIoRange		m_Ports; KNdisMemoryRange	m_Memory; . . . }; 2)在adapter类的Initialize()处理程序中,采用KNdisXxxResource类查询中断资源分配情况。 3)根据第二步返回的资源属性对KNdisIoRange和/或KNdisMemoryRange数据成员初始化。例如: NDIS_STATUS MyAdapter::Initialize (KNdisMedium& Medium, IN KNdisConfig& Config) { . . . // get h/w resources KNdisPnpResourceRequest request(Config); KNdisResource<CmResourceTypePort> Port(request); // Make sure the resources are available if (!Port.IsValid()) KNDIS_RETURN_ERROR (NDIS_STATUS_NOT_ACCEPTED); // Register i/o port range system object: m_Ports.Initialize(this, Port); if (!m_Ports.IsValid()) KNDIS_RETURN_ERROR (NDIS_STATUS_RESOURCES); . . . } 2. 访问单个I/O或内存映射端口 代表IO或内存区的系统对象一旦创建,DriverNetworks提供四种方法访问硬件: 1)KNdisIoRange和KNdisMemoryRange直接读in(ULONG offset),直接写out(ULONG offset,data) 下面给一个更新偏移地址为4的I/O寄存器的例子: UCHAR reg = m_Ports.inb (4); if (reg | 1) m_Ports.outb(4, reg | 1); else m_Ports.outb(4, 0); 2)KNdisIoRegister和KNdisMemoryRegister提供内部寄存器。 KNdisIoRegister reg = m_Ports[4]; // 创建一个偏移地址为4的寄存器对象 if (UCHAR(reg) | 1) reg |= UCHAR(reg) | 1; else reg = 0; 3)使用KNdisIoRegister和KNdisMemoryRegister的安全版本KNdisIoRegisterSafe<T>和KNdisMemoryRegisterSafe<T>。上面两个方法不提供读写数据宽度和寄存器实际宽度的检测。例如,使用m_Ports.outd(4, 1)向一个8位寄存器写入一个ULONG类型数据。虽然编译和链接都通过,但是可能会导致NIC的出错。寄存器类的安全版本是参数都是寄存器类型(例如,ULONG, USHORT和UCHAR)的模块。读写一个组正确的类型都导致编译错误。例如: ULONG new val = 0; KNdisIoRegisterSafe<UCHAR> reg = m_Ports[4]; if (UCHAR(reg) | 1) reg |= UCHAR(reg) | 1; else reg = val; // error: wrong type 4)基于NdisImmediateXxx函数,通过immediate I/O原语访问I/O。在硬件资源查询和IO或内存注册之前immediate I/O使驱动就能访问NIC硬件。由于系统要执行硬件资源翻译并对每个IO请求映射,过程很慢。Immediate I/O仅在驱动初始化过程使用,例如,在资源分配之前,驱动读取卡上的EEPROM来检测板的类型。一般来说,在PnP环境下不建议这样做。 DriverNetworks通过KNdisConfig类提供immediate I/O支持。这种方法与第一种方法类似。例如: UCHAR reg = Config.inb(4); if (reg | 1) Config.outb(4, reg | 1); else Config.outb(4, 0); 3. 注销I/O端口和内存区 一般地,NDIS Miniport驱动在MyAdapter::Halt()处理程序中注销端口和内存域。另外,也可以在MyAdapter destructor析构函数中完成,DriverNetworks在完成Halt()处理程序之后立即调用析构函数。 m_Ports.Invalidate(); m_Memory.Invalidate(); |
|
最新喜欢:tempte... |