unit WDMIO;

interface

function _InPortB(hDevice: THandle; Address: LongWord): Word;
function _InPort(hDevice: THandle; Address: LongWord): Word;
function _InPortL(hDevice: THandle; Address: LongWord): LongWord;
function _INS(hDevice: THandle; Address, Count, Wide: LongWord; pBuf: Pointer): LongWord;
function _OutPortB(hDevice: THandle; Address: LongWord; Value: Byte): Word;
function _OutPort(hDevice: THandle; Address: LongWord; Value: Word): Word;
function _OutPortL(hDevice: THandle; Address: LongWord; Value: LongWord): Word;

function _OutPortMB(hDevice: THandle; Address: LongWord; Count: Byte; pValue: PByte): Word;

function _InMemB(hDevice: THandle; Address: LongWord): Word;
function _InMem(hDevice: THandle; Address: LongWord): Word;
function _InMemL(hDevice: THandle; Address: LongWord): LongWord;
function _OutMemB(hDevice: THandle; Address: LongWord; Value: Byte): Word;
function _OutMem(hDevice: THandle; Address: LongWord; Value: Word): Word;
function _OutMemL(hDevice: THandle; Address: LongWord; Value: LongWord): Word;

implementation

uses
  Windows;

const
  METHOD_BUFFERED = 0;
  FILE_READ_ACCESS = 1;
  FILE_WRITE_ACCESS = 2;
  FILE_DEVICE_KRNLDRVR = $80FF;

  IOCTL_PORT_IN    = LongWord((FILE_DEVICE_KRNLDRVR shl 16) or ($820 shl 2) or (METHOD_BUFFERED) or (FILE_READ_ACCESS  shl 14));
  IOCTL_PORT_INSTR = LongWord((FILE_DEVICE_KRNLDRVR shl 16) or ($821 shl 2) or (METHOD_BUFFERED) or (FILE_READ_ACCESS  shl 14));
  IOCTL_PORT_OUT   = LongWord((FILE_DEVICE_KRNLDRVR shl 16) or ($822 shl 2) or (METHOD_BUFFERED) or (FILE_WRITE_ACCESS shl 14));
  IOCTL_MEM_IN     = LongWord((FILE_DEVICE_KRNLDRVR shl 16) or ($824 shl 2) or (METHOD_BUFFERED) or (FILE_READ_ACCESS  shl 14));
  IOCTL_MEM_OUT    = LongWord((FILE_DEVICE_KRNLDRVR shl 16) or ($826 shl 2) or (METHOD_BUFFERED) or (FILE_WRITE_ACCESS shl 14));
  IOCTL_PORTMB_OUT = LongWord((FILE_DEVICE_KRNLDRVR shl 16) or ($82A shl 2) or (METHOD_BUFFERED) or (FILE_WRITE_ACCESS shl 14));

  pofRelative = $01;

type
  TPortOp = packed record
    Addr: Word;
    Flags: Byte;
    Size: Byte;
    Data: LongWord;
  end;
  TPPortOp = ^TPortOp;

  TMemOp = packed record
    Addr: LongWord;
    Padding0: Word;
    Flags: Byte;
    Size: Byte;
    Data: LongWord;
  end;
  TPMemOp = ^TMemOp;

function _InPortB(hDevice: THandle; Address: LongWord): Word;
var
  DataBuffer: TPortOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := pofRelative;
    Size := 1;
  end;
  if DeviceIoControl(hDevice, IOCTL_PORT_IN, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := DataBuffer.Data and $FF
  else
    Result := $AA55
  ;
end;

function _InPort(hDevice: THandle; Address: LongWord): Word;
var
  DataBuffer: TPortOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := pofRelative;
    Size := 2;
  end;
  if DeviceIoControl(hDevice, IOCTL_PORT_IN, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := DataBuffer.Data and $FFFF
  else
    Result := $AA55
  ;
end;

function _InPortL(hDevice: THandle; Address: LongWord): LongWord;
var
  DataBuffer: TPortOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := pofRelative;
    Size := 4;
  end;
  if DeviceIoControl(hDevice, IOCTL_PORT_IN, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := DataBuffer.Data
  else
    Result := $AA55
  ;
end;

function _INS(hDevice: THandle; Address, Count, Wide: LongWord; pBuf: Pointer): LongWord;
var
  DataBuffer: TPortOp;
  cbRet: LongWord;

begin
  DataBuffer.Addr := Address;
  DataBuffer.Flags := pofRelative;
  DataBuffer.Size := Wide;
  if DeviceIoControl(hDevice, IOCTL_PORT_INSTR, @DataBuffer, sizeof(DataBuffer), pBuf, Wide*Count, cbRet, nil) then
    Result := 0
  else
    Result := $AA55
  ;
end;

function _OutPortB(hDevice: THandle; Address: LongWord; Value: BYTE): Word;
var
  DataBuffer: TPortOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := pofRelative;
    Size := 1;
    Data := Value;
  end;
  if DeviceIoControl(hDevice, IOCTL_PORT_OUT, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := 0
  else
    Result := $AA55
  ;
end;

function _OutPort(hDevice: THandle; Address: LongWord; Value: Word): Word;
var
  DataBuffer: TPortOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := pofRelative;
    Size := 2;
    Data := Value;
  end;
  if DeviceIoControl(hDevice, IOCTL_PORT_OUT, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := 0
  else
    Result := $AA55
  ;
end;

function _OutPortL(hDevice: THandle; Address: LongWord; Value: LongWord): Word;
var
  DataBuffer: TPortOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := pofRelative;
    Size := 4;
    Data := Value;
  end;
  if DeviceIoControl(hDevice, IOCTL_PORT_OUT, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := 0
  else
    Result := $AA55
  ;
end;

function _OutPortMB(hDevice: THandle; Address: LongWord; Count: Byte; pValue: PByte): Word;
var
  DataStr: AnsiString;
  pDataBuffer: TPPortOp;
  cbRet, L: LongWord;

begin
  try
    L := SizeOf(pDataBuffer^) - SizeOf(pDataBuffer.Data) + Count;
    SetString(DataStr, nil, L);
    pDataBuffer := TPPortOp(PAnsiChar(DataStr));
    Move(pValue^, pDataBuffer.Data, Count);
  except
    Result := $AA55;
    Exit;
  end;

  with pDataBuffer^ do begin
    Addr := Address;
    Flags := pofRelative;
    Size := Count;
  end;

  if DeviceIoControl(hDevice, IOCTL_PORTMB_OUT, pDataBuffer, L, pDataBuffer, L, cbRet, nil) then
    Result := 0
  else
    Result := $AA55
  ;
end;

function _InMemB(hDevice: THandle; Address: LongWord): Word;
var
  DataBuffer: TMemOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := 0;
    Size := 1;
  end;
  if DeviceIoControl(hDevice, IOCTL_MEM_IN, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := DataBuffer.Data and $FF
  else
    Result := $AA55
  ;
end;

function _InMem(hDevice: THandle; Address: LongWord): Word;
var
  DataBuffer: TMemOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := 0;
    Size := 2;
  end;
  if DeviceIoControl(hDevice, IOCTL_MEM_IN, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := DataBuffer.Data and $FFFF
  else
    Result := $AA55
  ;
end;

function _InMemL(hDevice: THandle; Address: LongWord): LongWord;
var
  DataBuffer: TMemOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := 0;
    Size := 4;
  end;
  if DeviceIoControl(hDevice, IOCTL_MEM_IN, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := DataBuffer.Data
  else
    Result := $AA55
  ;
end;

function _OutMemB(hDevice: THandle; Address: LongWord; Value: BYTE): Word;
var
  DataBuffer: TMemOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := 0;
    Size := 1;
    Data := Value;
  end;
  if DeviceIoControl(hDevice, IOCTL_MEM_OUT, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := 0
  else
    Result := $AA55
  ;
end;

function _OutMem(hDevice: THandle; Address: LongWord; Value: Word): Word;
var
  DataBuffer: TMemOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := 0;
    Size := 2;
    Data := Value;
  end;
  if DeviceIoControl(hDevice, IOCTL_MEM_OUT, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := 0
  else
    Result := $AA55
  ;
end;

function _OutMemL(hDevice: THandle; Address: LongWord; Value: LongWord): Word;
var
  DataBuffer: TMemOp;
  cbRet: LongWord;

begin
  with DataBuffer do begin
    Addr := Address;
    Flags := 0;
    Size := 4;
    Data := Value;
  end;
  if DeviceIoControl(hDevice, IOCTL_MEM_OUT, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := 0
  else
    Result := $AA55
  ;
end;

end.
