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

From EDM2
Jump to: navigation, search

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.

Note: This was copied verbatim from Alistair Young's Web page.

// 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 ;
}

Note: This was copied verbatim from Alistair Young's Web page.