{ -----------------------------------------------------------------------------}
{ Copyright 2000-2001, Zloba Alexander. All Rights Reserved. }
{ This unit can be freely used and distributed in commercial and private }
{ environments, provided this notice is not modified in any way. }
{ -----------------------------------------------------------------------------}
{ Feel free to contact me if you have any questions, comments or suggestions at}
{ zal@specosoft.com (Zloba Alexander) }
{ You can always find the latest version of this unit at: }
{ http://www.specosoft.com }
{ -----------------------------------------------------------------------------}
{ Date last modified: 08/10/2001 }
{ -----------------------------------------------------------------------------}
{ ZLPortIO driver interface unit v1.20 }
{ -----------------------------------------------------------------------------}
{ Description: }
{ This unit allow your application direct access port input and output under }
{ all versions of Microsoft Windows� }
{ Depends: }
{ zlportio.sys ddkint.pas }
{ You must distribute zlportio.sys with your application }
{ Procedures and functions: }
{ procedure zlioportread( const Port,DataType:dword ):dword; }
{ procedure zlioportwrite( const Port,DataType,Data:dword ); }
{ }
{ function portreadb( const Port:dword ):byte; }
{ function portreadw( const Port:dword ):word; }
{ function portreadl( const Port:dword ):dword; }
{ }
{ procedure portwriteb( const Port:Dword;const Data:byte ); }
{ procedure portwritew( const Port:dword;const Data:word ); }
{ procedure portwritel( const Port,Data:dword ); }
{ }
{ Examples: }
{ // get data bits from LPT port }
{ databits := portreadb( $378 ) }
{ // set data bits from LPT port }
{ portwriteb( $378, databits ) }
{ // The second parameter determine the databus length for operation }
{ -----------------------------------------------------------------------------}
{ Revision History: }
{ 1.00: + First public release }
{ 1.10: + Added new functions (portreadX,portwriteX) for convenience of usage }
{ 1.20: + Added new function (zliosetiopm) for enabling direct access to ports}
{ 1.30: + added compiler directives for correct compilation }
{ 1.40: + added opportunity to run multiply instances client to driver }
{ 1.50: - fixed bug with work under win98 }
{------------------------------------------------------------------------------}
{$A-,H-}
unit zlportio;
interface
uses windows,sysutils,ddkint;
Const
ZLIO_BYTE = 0;
ZLIO_WORD = 1;
ZLIO_DWORD = 2;
var
// if TRUE then driver was started
// in other case something wrong
// We start driver in initialization section of unit.
ZlIOStarted:boolean = false;
// if TRUE then we can use asm IN,OUT under NT/2000
// see zliosetiopm for more details
ZlIODirect:boolean = false;
// handle to opened driver
HZLIO:THandle;
function portreadb( const Port:dword ):byte;
function portreadw( const Port:dword ):word;
function portreadl( const Port:dword ):dword;
procedure portwriteb( const Port:Dword;const Data:byte );
procedure portwritew( const Port:dword;const Data:word );
procedure portwritel( const Port,Data:dword );
procedure zlioportwrite( const Port,DataType,Data:dword );
function zlioportread( const Port,DataType:dword ):dword;
// if you need the best perfomance for your IO operations
// call zliosetiopm(TRUE). This allow your application
// to use asm command IN,OUT directly in your code.
procedure zliosetiopm( const Direct:boolean );
// internal
function zliostart:boolean;
procedure zliostop;
implementation
const
ZLIODriverName='zlportio';
var
IOCTL_ZLUNI_PORT_READ:cardinal;
IOCTL_ZLUNI_PORT_WRITE:cardinal;
IOCTL_ZLUNI_IOPM_ON:cardinal;
IOCTL_ZLUNI_IOPM_OFF:cardinal;
type
TzlIOData = record
Port,DataType,Data:dword;
end;
procedure zlioportwrite( const Port,DataType,Data:dword );
var resdata:TZLIOData;
cBR:cardinal;
begin
if (not ZLIODirect) then begin
resdata.Port := Port;
resdata.Data := Data;
resdata.DataType := DataType;
if ZLIOStarted then
DeviceIoControl(HZLIO,IOCTL_ZLUNI_PORT_WRITE,@resdata,sizeof(resdata),nil,0,cBR,nil );
end
else begin
Case DataType of
ZLIO_BYTE : asm mov edx,Port;mov eax,data;out dx,al; end;
ZLIO_WORD : asm mov edx,Port;mov eax,data;out dx,ax; end;
ZLIO_DWORD: asm mov edx,Port;mov eax,data;out dx,eax; end;
end;
end;
end;
function zlioportread(const Port,DataType:dword):dword;
var resdata:TZLIOData;
cBR:cardinal;i:dword;
begin
if (not ZLIODirect) then begin
resdata.Port := Port;
resdata.DataType := DataType;
if ZLIOStarted then
DeviceIoControl(HZLIO,IOCTL_ZLUNI_PORT_READ,@resdata,sizeof(resdata),@i,sizeof(dword),cBR,nil );
end
else begin
Case DataType of
ZLIO_BYTE : asm mov edx,Port;xor eax,eax;in al,dx;mov i,eax; end;
ZLIO_WORD : asm mov edx,Port;xor eax,eax;in ax,dx;mov i,eax; end;
ZLIO_DWORD: asm mov edx,Port;xor eax,eax;in eax,dx;mov i,eax end;
end;
end;
result := i;
end;
function portreadb( const Port:dword ):byte;
begin
Result := zlioportread(Port,ZLIO_BYTE);
end;
function portreadw( const Port:dword ):word;
begin
Result := zlioportread(Port,ZLIO_WORD);
end;
function portreadl( const Port:dword ):dword;
begin
Result := zlioportread(Port,ZLIO_DWORD);
end;
procedure portwriteb( const Port:Dword;const Data:byte );
begin
zlioportwrite(Port,ZLIO_BYTE,Data);
end;
procedure portwritew( const Port:dword;const Data:word );
begin
zlioportwrite(Port,ZLIO_WORD,Data);
end;
procedure portwritel( const Port,Data:dword );
begin
zlioportwrite(Port,ZLIO_DWORD,Data);
end;
procedure zliosetiopm( const Direct:boolean );
var cBR:cardinal;
begin
if Win32Platform=VER_PLATFORM_WIN32_NT then
if ZLIOStarted then begin
if Direct then
DeviceIoControl(HZLIO,IOCTL_ZLUNI_IOPM_ON,nil,0,nil,0,cBR,nil )
else
DeviceIoControl(HZLIO,IOCTL_ZLUNI_IOPM_OFF,nil,0,nil,0,cBR,nil );
ZLIODirect := Direct;
end
end;
function zliostart;
var dir:shortstring;
begin
if Win32Platform<>VER_PLATFORM_WIN32_NT then begin
result := true;
exit;
end;
// Result := false;
zliostop;
dir := ExtractFileDir(ParamStr(0))+'\'+ZLIODriverName+'.sys'#0;
driverinstall(pchar(@dir[1]),ZLIODriverName+#0);
Result := driverstart(ZLIODriverName) = 0;
end;
procedure zliostop;
begin
if Win32Platform<>VER_PLATFORM_WIN32_NT then
exit;
driverstop(ZLIODriverName);
driverremove(ZLIODriverName);
end;
function zlioopen( var Handle:thandle):boolean;
var cERR:integer;
s:string;
begin
if Win32Platform<>VER_PLATFORM_WIN32_NT then begin
result := true;
exit;
end;
Result := false;
Handle := THandle(-1);
Handle := createFile('\\.\ZLPORTIO',
GENERIC_READ or GENERIC_WRITE,
0,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0 );
cERR := getlasterror;
s := messagestring( cerr);
if (cERR = ERROR_ALREADY_EXISTS)or(cERR = ERROR_SUCCESS) then Result := True;
end;
procedure zlioclose( const Handle:thandle);
begin
if (Win32Platform=VER_PLATFORM_WIN32_NT) then
closehandle(Handle);
end;
initialization
IOCTL_ZLUNI_PORT_READ := CTL_CODE(FILE_DEVICE_KRNLDRVR, 1, METHOD_BUFFERED, FILE_ANY_ACCESS);
IOCTL_ZLUNI_PORT_WRITE := CTL_CODE(FILE_DEVICE_KRNLDRVR, 2, METHOD_BUFFERED, FILE_ANY_ACCESS);
IOCTL_ZLUNI_IOPM_ON := CTL_CODE(FILE_DEVICE_KRNLDRVR, 3, METHOD_BUFFERED, FILE_ANY_ACCESS);
IOCTL_ZLUNI_IOPM_OFF := CTL_CODE(FILE_DEVICE_KRNLDRVR, 4, METHOD_BUFFERED, FILE_ANY_ACCESS);
if Win32Platform<>VER_PLATFORM_WIN32_NT then begin
zliostarted := true;
zliodirect := true;
end
else begin
if not zlioopen(HZLIO) then begin
if zliostart then
ZLIOStarted := zlioopen(HZLIO) or (Win32Platform<>VER_PLATFORM_WIN32_NT);
end
else
ZLIOStarted := true;
end;
finalization
if ZLIOStarted then
zliostop;
end.