Programming 版 (精华区)
发信人: zpw (zhao), 信区: Programming
标 题: How To Acess I/O Ports under Windows NT
发信站: 紫 丁 香 (Wed Jul 29 21:05:23 1998), 转信
How To Access I/O Ports under Windows NT
When an application is running on Windows NT, the operating system has set
the processor to a mode in which the instructions for accessing the I/O space
cause protection faults. This means that an application requires the assistance
of a device driver to perform I/O. Device drivers run in kernel mode, which
means (among other things) that the processor is running in a state that allows
execution of I/O instructions.
If your goal is to gain access to the I/O space for the purpose of a small
number of dedicated applications, as opposed to creating a driver that enables
generalized access to your hardware, then you should consider
Driver::Agent.This product enables to you access I/O ports without having to
write a device driver. It provides not only I/O access, but memory mapped
device access, interrupt management, DMA support, and a set of utility objects,
such as timers, events, and FIFOs. Driver::Agent works with applications
written in C/C++, VB, Delphi, and Java.
If you are writing a device driver, you'll find that doing simple I/O to ports
under Windows NT is not quite as simple as it is under Windows 95. Under
Windows 95, a driver simply called functions _inp and _outp, or used assembler
instructions IN and OUT. Because Windows 95 is designed solely for Intel
machines, no additional abstraction of the I/O is required.
Windows NT was designed to be portable to different machine architectures. The
system model requires the driver writer to take into account that a machine
may have multiple buses, and that it may be necessary to translate addresses
between buses.
Furthermore, the model distinguishes between I/O space and memory space.
In a machine with multiple buses, each bus may support both memory and I/O
cycles.
By definition, I/O registers, also called ports, are accessed with I/O cycles.
However, on some systems the I/O space of a peripheral bus can be mapped to the
processor memory space. The HAL makes this determination. To access an I/O
register, the driver writer must know on which bus the register resides, and
its I/O space address on that bus. A bus is specified by its interface type
(ISA, PCI, etc.) and its number (starting with zero).
Here is an example of I/O access for an imaginary device, which resides at
address 0xE700 of the ISA bus 0. The layout of the device is as follows:
Offset Size Usage
0
1
Command register
1
1
Status register
2
2
Word data register
4
4
Dword data register
With Vireo Driver::Works, a tool kit for developing NT/WDM device drivers,
you use the following steps to access the device:
First, construct an instance of KIoRange to map the device registers.
KIoRange DeviceIos;
status = DeviceIos.Initialize(
Isa, // Bus type
0, // Bus number
0xE700, // Bus address
8, // Device size
TRUE // Map to system space (if port is memory mapped)
);
if (NT_SUCCESS(status)) // all ok
You can use member functions of KIoRange to access the registers:
// register offsets
#define COMMAND 0
#define STATUS 1
#define WDATA 2
#define DDATA 3
// read status register
UCHAR DeviceStatus = DeviceIos.inb (STATUS);
// Write to command register
DeviceIos.outb (COMMAND, CMD_RESET);
// Write 20 words the word data port
DeviceIos.outw (WDATA, buffer, 20);
Alternatively, you can create instances of KIoRegister, and use them to access
the device:
KIoRegister CommandReg = DeviceIos[COMMAND];
KIoRegister StatusReg = DeviceIos[STATUS];
CommandReg = (UCHAR)RESET; // write RESET command
UCHAR status = StatusReg; // read STATUS register
There is a small performance benefit to using KIoRegister as opposed to member
functions of KIoRange if a register is accessed repeatedly in the same function.
However, it is crucial to type the data correctly (UCHAR, USHORT, ULONG),
because this determines the size of the access that actually goes out to the
bus.
--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: yaoyu.hit.edu.cn]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:4.426毫秒