Windows 版 (精华区)

发信人: wugang (◆◆King◆◆), 信区: OS
标  题: 在Windows NT 下实现对I/O地址的访问
发信站: 紫 丁 香 (Tue Oct 12 23:02:00 1999), 转信

南京师范大学物理系
                                               单学民
                    ---- Windows NT 操作系统设置的进程模式会使运行在其中的应
                    用程序访问I/O地址的指令引起保护性的失败。这使得应用程序
                    需要附以一个设备驱动程序进行I/O操作。设备驱动程序运行在
                    内核模式,这使得在这种状态的中运行的进程可以执行I/O操
                    作。
                    ---- Windows 95/98 是仅为 Intel 类型机器设计的,没有额外
                    复杂的I/O需求,而Windows NT 被设计成可以在不同机器机构上
                    进行移植。这使得Windows NT 的系统模式要求驱动程序的编写
                    者要考虑一台机器可能有多种类型的总线,这可能需要在总线之
                    间传递地址。这种模式还要区别I/O空间和内存空间。在多总线
                    的机器中每一总线可以既支持内存又支持I/O循环。
                    ---- 根据定义,I/O寄存器或者端口访问是通过I/O循环实现
                    的。然而,在一些系统中外部总线的I/O空间可以被映像到进程
                    内存空间。硬件抽象层(Hardware Abstract Layer)决定这
                    些。要访问I/O寄存器,驱动程序编写者必须知道寄存器在那一
                    总线,它的I/O 空间地址在那条总线。一条总线是由其接口类行
                    (如 ISA 、PCI 等)和编号(从零开始)决定的。
                    ---- 下面是一个假象设备访问I/O的例子,接口类型:ISA 编号
                    0 地址 0xE700。设备描述如下:
                    Offset        Size        Usage
                      0          1          Command register
                      1          1      Status register
                      2          2      Word data register
                      4          4      Dword data register
                    ---- 用开发NT 设备驱动程序的工具包DriverDorks 可以用以下
                    步骤访问设备:
                    ---- 建立一个KIoRange的对象映像设备寄存器。
                                    KIoRange  DeviceIos;
                            Status = DevceIos.Initialize(
                       Isa,        // 总线类型
                       0,         //  总线号
                       0xE700,    // 总线地址
                       8,         // 设备数
                       TRUE     // 映像到系统空间(如果端口是内存映像的)
                                    );
                            if(NT_SUCCESS(status))  //建立成功
                    ---- 可以用KIoRange 的成员函数访问寄存器:
                    //寄存器偏移量
                    #define COMMAND   0
                    #define STATUS  1
                    #define WDATA  2
                    #define DDATA   3
                    //读状态寄存器
                    UCHAR DeviceStatus = DeviceIos.inb(STATUS);
                    //写命令寄存器
                    DeviceIos.outb(COMMAND,CMD_RESET);
                    //写20个字到端口
                    DeviceIos.outw(WDATA,buffer,20);
                    ---- 另外也可以建立KIoRegister 的对象来访问设备:
                    KIoRegister CommandReg = DeviceIos[COMMAND];
                    KIoRegister StatusReg = DeviceIos[STATUS];
                    CommandRge=(UCHAR)RESET;   //写 RESET命令
                    UCHAR status=StatusReg; //读状态寄存器
                    如果在同一函数中频繁访问寄存器用KioRegiser 比用KIoRange
                    的成员函数的性能好一些 。无论如何,数据类型必须正确
                    (UCHAR,USHORT,ULONG),这些决定了到总线上数据的实际大
                    小。 
--
                       _______
      伞              ノ____ノ\           ★       伞     ┌───────┐
     伞伞             | ∩  ▓                   伞伞    │ ◆◆KING◆◆ │
    伞伞伞            ˉˉˉˉˉ -_              伞伞伞   │ Icq:10689743 │
      ‖             ▇▇▇▇▇▇   -__--          ‖     └───────┘ 
_._.-*'"'*-._,_.-*'"'*-._,_.-*'"'*-._,_.-*'"'*-._,_.-*'"'*-._,_.-*'"'*-._,_.-* 

※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: rainy.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.528毫秒