Port I/O from 32-BIT Applications
From EDM2
By Alger Pike
A frequently asked question on OS/2 programming is,"Is any way to access the IO ports from an application?". One way of doing this, one of the simplest but slowest ways, is outlined below. It works by using the TESTCFG.SYS device driver, which comes with OS/2, to do the actual port I/O for you. Functions are provided to open and close the driver, and to perform IO in bytes, words, and doublewords.
// Include all needed includes for the .DLL definitions #define INCL_DOS #include // TESTCFG driver command constants #define CFG_CATEGORY 0x80 #define CFG_IN_IO 0x41 #define CFG_OUT_IO 0x42 #define CFG_IO_BYTE 1 #define CFG_IO_WORD 2 #define CFG_IO_DWORD 4 // TESTCFG driver structures // IO packet structures typedef struct _IOPKT { USHORT io_address ; USHORT data_width ; union { UCHAR ucData ; USHORT usData ; ULONG ulData ; } d ; } IOPKT ; typedef IOPKT * PIOPKT ; typedef struct _IODATAPKT { union { UCHAR ucData ; USHORT usData ; ULONG ulData ; } d ; } IODATAPKT ; typedef IODATAPKT * PIODATAPKT ; // exported functions // open_ports - prepare the system I/O ports to be read/written HFILE _Export open_ports (void) { HFILE hfDevice ; ULONG action ; DosOpen ("TESTCFG$", &hfDevice, &action, 0, 0, FILE_OPEN, OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, NULL) ; return hfDevice ; } // close_ports - close the I/O port device driver APIRET _Export close_ports (HFILE hfDevice) { return DosClose (hfDevice) ; } // port i/o input functions APIRET _Export input_byte (HFILE hfDevice, USHORT port, PBYTE pb) { APIRET rc ; ULONG cbparm, cbdata ; IOPKT iopkt ; IODATAPKT iodatapkt ; iopkt.io_address = port ; iopkt.data_width = CFG_IO_BYTE ; cbparm = sizeof (iopkt) ; cbdata = sizeof (iodatapkt) ; rc = DosDevIOCtl (hfDevice, CFG_CATEGORY, CFG_IN_IO, &iopkt, sizeof (iopkt), &cbparm, &iodatapkt, sizeof (iodatapkt), &cbdata) ; *pb = iodatapkt.d.ucData ; return rc ; } APIRET _Export input_word (HFILE hfDevice, USHORT port, PUSHORT pw) { APIRET rc ; ULONG cbparm, cbdata ; IOPKT iopkt ; IODATAPKT iodatapkt ; iopkt.io_address = port ; iopkt.data_width = CFG_IO_WORD ; cbparm = sizeof (iopkt) ; cbdata = sizeof (iodatapkt) ; rc = DosDevIOCtl (hfDevice, CFG_CATEGORY, CFG_IN_IO, &iopkt, sizeof (iopkt), &cbparm, &iodatapkt, sizeof (iodatapkt), &cbdata) ; *pw = iodatapkt.d.usData ; return rc ; } APIRET _Export input_dword (HFILE hfDevice, USHORT port, PULONG pd) { APIRET rc ; ULONG cbparm, cbdata ; IOPKT iopkt ; IODATAPKT iodatapkt ; iopkt.io_address = port ; iopkt.data_width = CFG_IO_DWORD ; cbparm = sizeof (iopkt) ; cbdata = sizeof (iodatapkt) ; rc = DosDevIOCtl (hfDevice, CFG_CATEGORY, CFG_IN_IO, &iopkt, sizeof (iopkt), &cbparm, &iodatapkt, sizeof (iodatapkt), &cbdata) ; *pd = iodatapkt.d.ulData ; return rc ; } // port i/o output functions APIRET _Export output_byte (HFILE hfDevice, USHORT port, BYTE b) { APIRET rc ; ULONG cbparm, cbdata ; IOPKT iopkt ; iopkt.io_address = port ; iopkt.data_width = CFG_IO_BYTE ; iopkt.d.ucData = b ; cbparm = sizeof (iopkt) ; cbdata = 0 ; rc = DosDevIOCtl (hfDevice, CFG_CATEGORY, CFG_OUT_IO, &iopkt, sizeof (iopkt), &cbparm, NULL, 0, &cbdata) ; return rc ; } APIRET _Export output_word (HFILE hfDevice, USHORT port, USHORT w) { APIRET rc ; ULONG cbparm, cbdata ; IOPKT iopkt ; iopkt.io_address = port ; iopkt.data_width = CFG_IO_WORD ; iopkt.d.usData = w ; cbparm = sizeof (iopkt) ; cbdata = 0 ; rc = DosDevIOCtl (hfDevice, CFG_CATEGORY, CFG_OUT_IO, &iopkt, sizeof (iopkt), &cbparm, NULL, 0, &cbdata) ; return rc ; } APIRET _Export output_dword (HFILE hfDevice, USHORT port, ULONG d) { APIRET rc ; ULONG cbparm, cbdata ; IOPKT iopkt ; iopkt.io_address = port ; iopkt.data_width = CFG_IO_DWORD ; iopkt.d.ulData = d ; cbparm = sizeof (iopkt) ; cbdata = 0 ; rc = DosDevIOCtl (hfDevice, CFG_CATEGORY, CFG_OUT_IO, &iopkt, sizeof (iopkt), &cbparm, NULL, 0, &cbdata) ; return rc ; }