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),這些決定了到總線上數據的實際大小.