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;

function _InBarX(hDevice: THandle; aBAR: Byte; ByteSize: Byte; Offset: LongWord; DataMask: LongWord): LongWord;
function _OutBarX(hDevice: THandle; aBAR: Byte; ByteSize: Byte; Offset: LongWord; Value: LongWord): LongWord;
function _InBar8  (hDevice: THandle; aBAR: Byte; Offset: LongWord): Byte;
function _InBar16 (hDevice: THandle; aBAR: Byte; Offset: LongWord): Word;
function _InBar32 (hDevice: THandle; aBAR: Byte; Offset: LongWord): LongWord;
function _OutBar8 (hDevice: THandle; aBAR: Byte; Offset: LongWord; Value: Byte): Byte;
function _OutBar16(hDevice: THandle; aBAR: Byte; Offset: LongWord; Value: Word): Word;
function _OutBar32(hDevice: THandle; aBAR: Byte; Offset: LongWord; Value: LongWord): LongWord;


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));
  IOCTL_InBAR      = LongWord((FILE_DEVICE_KRNLDRVR shl 16) or ($850 shl 2) or (METHOD_BUFFERED) or (FILE_READ_ACCESS  shl 14));
  IOCTL_OutBAR     = LongWord((FILE_DEVICE_KRNLDRVR shl 16) or ($851 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: Int64;
    Flags: Byte;
    Size: Byte;
    Data: LongWord;
  end;
  TPMemOp = ^TMemOp;

  TBarPortOp = packed record
    Addr: LongWord;
    BAR: Byte;
    Padding0: Byte;
    Flags: Byte;
    Size: Byte;
    Data: LongWord;
  end;
  TPBarPortOp = ^TBarPortOp;

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

begin
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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 _InBarX(hDevice: THandle; aBAR: Byte; ByteSize: Byte; Offset: LongWord; DataMask: LongWord): LongWord;
var
  DataBuffer: TBarPortOp;
  cbRet: LongWord;

begin
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  with DataBuffer do begin
    Addr := Offset;
    BAR := aBAR;
    Flags := pofRelative;
    Size := ByteSize;
  end;
  if DeviceIoControl(hDevice, IOCTL_InBAR, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := DataBuffer.Data and DataMask
  else
    Result := $AA55AA55
  ;
end;

function _OutBarX(hDevice: THandle; aBAR: Byte; ByteSize: Byte; Offset: LongWord; Value: LongWord): LongWord;
var
  DataBuffer: TBarPortOp;
  cbRet: LongWord;

begin
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  with DataBuffer do begin
    Addr := Offset;
    BAR := aBAR;
    Flags := pofRelative;
    Size := ByteSize;
    Data := Value;
  end;
  if DeviceIoControl(hDevice, IOCTL_OutBAR, @DataBuffer, sizeof(DataBuffer), @DataBuffer, sizeof(DataBuffer), cbRet, nil) then
    Result := 0
  else
    Result := GetLastError
  ;
end;

function _InBar8(hDevice: THandle; aBAR: Byte; Offset: LongWord): Byte;
begin
  Result := _InBarX(hDevice, aBAR, 1, Offset, $FF);
end;

function _InBar16(hDevice: THandle; aBAR: Byte; Offset: LongWord): Word;
begin
  Result := _InBarX(hDevice, aBAR, 2, Offset, $FFFF);
end;

function _InBar32(hDevice: THandle; aBAR: Byte; Offset: LongWord): LongWord;
begin
  Result := _InBarX(hDevice, aBAR, 4, Offset, $FFFFFFFF);
end;

function _OutBar8(hDevice: THandle; aBAR: Byte; Offset: LongWord; Value: Byte): Byte;
begin
  Result := _OutBarX(hDevice, aBAR, 1, Offset, Value);
end;

function _OutBar16(hDevice: THandle;  aBAR: Byte; Offset: LongWord; Value: Word): Word;
begin
  Result := _OutBarX(hDevice, aBAR, 2, Offset, Value);
end;

function _OutBar32(hDevice: THandle;  aBAR: Byte; Offset: LongWord; Value: LongWord): LongWord;
begin
  Result := _OutBarX(hDevice, aBAR, 4, Offset, Value);
end;



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

begin
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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 _OutPortX(hDevice: THandle; ByteSize: Byte; Address: LongWord; Value: LongWord): LongWord;
var
  DataBuffer: TPortOp;
  cbRet: LongWord;

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

function _OutPortB(hDevice: THandle; Address: LongWord; Value: Byte): Word;
begin
  Result := _OutPortX(hDevice, 1, Address, Value);
end;

function _OutPort(hDevice: THandle; Address: LongWord; Value: Word): Word;
begin
  Result := _OutPortX(hDevice, 2, Address, Value);
end;

function _OutPortL(hDevice: THandle; Address: LongWord; Value: LongWord): Word;
begin
  Result := _OutPortX(hDevice, 4, Address, Value);
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;

  ZeroMemory(pDataBuffer, SizeOf(pDataBuffer^));
  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
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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
  ZeroMemory(@DataBuffer, SizeOf(DataBuffer));
  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.
