The driver provides a wrapper for in/out cpu instructions.
- PortsIoRead:
ininstruction wrapper - PortsWrite:
outinstruction wrapper
For memory mapped i/o the driver provides mapping and read/write operations.
-
WARNING:
Be careful with the write operation for MMIO, you can access any address in memory and therefore you can accidentally damage the memory.
Also, don't forget to MANDATORY free up memory after using it via
Unmap
Before, you have to compile or install driver. See installation guide.
Driver registers device and link it to a file named ISA-IO.
You might open it and then can use IOCTL_* commands to get access to the I/O ports and MMIO.
Step-by-step:
-
Include
Windows.h. -
Copy and include header file
IO.hinto your userspace program. -
Open device handle like this:
HANDLE hDevice = CreateFileW( L"\\??\\ISA-IO", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
-
Ports I/O write (
IOCTL_PIO_WRITE):PortsIoRequestWrite request; request.port = ...; request.value = ...; request.size = ...; // Can be `IO_BYTE`, `IO_WORD`, `IO_DWORD`. DeviceIoControl(hDevice, IOCTL_PIO_WRITE, &request, sizeof(request), NULL, 0, NULL, NULL);
-
Ports I/O read (
IOCTL_PIO_READ):PortsIoRequestRead request; request.port = ...; request.size = ...; // Can be `IO_BYTE`, `IO_WORD`, `IO_DWORD`. PortsIoResponse response = { 0 }; DeviceIoControl(hDevice, IOCTL_PIO_READ, &request, sizeof(request), &response, sizeof(response), NULL, NULL); // Access result ... = response.value;
-
MMIO memory map (
IOCTL_MMAP_MMIO):IoRequestMmap request; IoResponseMmap response; request.phys = physical; request.size = size; DeviceIoControl( hDevice, IOCTL_MMAP_MMIO, &request, sizeof(request), &response, sizeof(response), NULL, NULL ) // Acces result ... = response.virt;
-
MMIO memory unmap (
IOCTL_UMAP_MMIO):IoRequestUnmap request; request.virt = virt; request.size = size; DeviceIoControl(hDevice, IOCTL_UMAP_MMIO, &request, sizeof(request), NULL, 0, NULL, NULL);
-
MMIO read (
IOCTL_MMIO_READ_32):IoRequestRead request; IoResponse response; request.virt = address; DeviceIoControl( hDevice, IOCTL_MMIO_READ_32, &request, sizeof(request), &response, sizeof(response), NULL, NULL ) // Access result ... = response.value;
-
MMIO write (
IOCTL_MMIO_WRITE_32) (unsafe):IoRequestWrite request; request.virt = address; request.value = value; DeviceIoControl(hDevice, IOCTL_MMIO_WRITE_32, &request, sizeof(request), NULL, 0, NULL, NULL);
These functions are provided in IO.h, their prototypes are provided here for a quick look.
-
unsigned int PortsIoRead(HANDLE hDevice, unsigned short port, IoSize size)
-
bool PortsIoWrite(HANDLE hDevice, unsigned short port, unsigned int value, IoSize size)
-
void* MmIoMmap(HANDLE hDevice, void* physical, unsigned int size)
-
bool MmIoUnmap(HANDLE hDevice, void* virt, unsigned int size)
-
unsigned int MmIoRead(HANDLE hDevice, void* address)
-
bool MmIoWrite(HANDLE hDevice, void* address, unsigned int value)