32-bit port I/O using the TESTCFG.SYS device driver

Written by Stefan Zollner

A frequently asked question on OS/2 programming is if there is any way to access the IO ports from an application. One way of doing this, one of the simplest 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 // TESTCFG driver command constants // 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 ; }
 * 1) define INCL_DOS
 * 2) include
 * 1) define  CFG_CATEGORY        0x80
 * 1) define  CFG_IN_IO           0x41
 * 2) define  CFG_OUT_IO          0x42
 * 1) define  CFG_IO_BYTE         1
 * 2) define  CFG_IO_WORD         2
 * 3) define  CFG_IO_DWORD        4

// 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 ; } Note: This was copied verbatim from Alistair Young's Web page.