lsshao
驱动牛犊
驱动牛犊
  • 注册日期2004-02-03
  • 最后登录2007-10-29
  • 粉丝0
  • 关注0
  • 积分33分
  • 威望5点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
阅读:3049回复:0

DriverNetwork miniport驱动学习(4)

楼主#
更多 发布于:2004-03-18 11:35
访问I/O端口
DriverNetworks 提供了一组类来访问NIC的I/O 和内存映射寄存器:
&#8226; KNdisIoRange / KNdisIoRegister / KNdisIoRegisterSafe<T>
&#8226; KNdisMemoryRange / KNdisMemoryRegister / KNdisMemoryRegisterSafe<T>
这些类都是基类KNdisPeripheralAddress的派生类。
NDIS Miniport驱动必须考虑以下问题:
&#8226; Registering向系统注册I/O端口和内存区。
&#8226; Accessing访问单个I/O或内存映射端口。
&#8226; De-registering注销I/O端口和内存区
1. 注册I/O端口和内存区
1)在adapter类中包括KNdisIoRange和/或KNdisMemoryRange数据成员。例如:
class MyAdapter : public KNdisMiniAdapter {
. . .
  KNdisIoRange&#9;&#9;m_Ports;
  KNdisMemoryRange&#9;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();

最新喜欢:

temptemptempte...
游客

返回顶部