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),這些決定了到匯流排上資料的實際大小.