📄 hw_32.pas
字号:
CtlCode(_DRV_SET_POST_EVENT),
@fLocEvent, sizeof(fLocEvent),
NIL, 0, nByte, POverlapped(NIL));
dwIRQ := fIRQNumber;
DeviceIoControl(hDrv,
CtlCode(_DRV_SET_INT_VEC),
@dwIRQ, sizeof(dwIRQ),
NIL, 0, nByte, POverlapped(NIL));
fMasked := FALSE;
DeviceIoControl(hDrv,
CtlCode(_DRV_UNMASK_INT_VEC),
NIL, 0, NIL, 0,
nByte, POverlapped(NIL));
while (TRUE) do
begin
WaitForSingleObject(fLocEvent, INFINITE);
if (not fTerminated) then
begin
if (LPT_BASE_PORT<>0) and (L_BUF_LPT>0) then
begin
sel := N_SEL_LPT;
wrd := BUF_LPT[sel];
Inc(sel);
sel := sel and (MAX_BUF_LPT);
N_SEL_LPT := sel;
Dec(L_BUF_LPT);
end;
if Assigned(fOnHWInterrupt) then
OnHwInterrupt(HW32,Drv_IRQ_Counter,Hi(wrd),Lo(wrd),ScanCode);
end
else
break;
end;
DeviceIoControl(hDrv,
CtlCode(_DRV_STOP_INT_VEC),
NIL, 0, NIL, 0,
nByte, POverlapped(NIL));
CurrentProcess := GetCurrentProcess();
SetPriorityClass(CurrentProcess, NORMAL_PRIORITY_CLASS);
end;
end;
procedure IRQProc95(HW32 : TVicHw32); stdcall;
var nByte,Count,fHandled,dwIRQ : DWORD;
CurrentProcess : THandle;
pl : PLockedBuffer;
wrd,sel : Word;
begin
pl := PLockedBuffer(HW32.fpLockedMemory);
with HW32,pl^ do
begin
wrd := 0;
fHandled:=0;
CurrentProcess := GetCurrentProcess();
SetPriorityClass(CurrentProcess, REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
DeviceIoControl(hDrv,
CtlCode(_DRV_SET_POST_EVENT),
@hDrvEvent, sizeof(hDrvEvent),
NIL, 0, nByte, POverlapped(NIL));
dwIRQ := fIRQNumber;
DeviceIoControl(hDrv,
CtlCode(_DRV_SET_INT_VEC),
@dwIRQ, sizeof(dwIRQ),
NIL, 0, nByte, POverlapped(NIL));
fMasked := FALSE;
DeviceIoControl(hDrv,
CtlCode(_DRV_UNMASK_INT_VEC),
NIL, 0, NIL, 0,
nByte, POverlapped(NIL));
while (TRUE) do
begin
WaitForSingleObject(fLocEvent, INFINITE);
ResetEvent(fLocEvent);
if (not fTerminated) then
begin
Count := Drv_IRQ_Counter;
while (fHandled<Count) do
begin
Inc(fHandled);
if (fIRQNumber = 7) and (L_BUF_LPT>0) then
begin
sel := N_SEL_LPT;
wrd := BUF_LPT[sel];
Inc(sel);
sel := sel and (MAX_BUF_LPT);
N_SEL_LPT := sel;
Dec(L_BUF_LPT);
end;
if Assigned(fOnHWInterrupt) then
OnHwInterrupt(HW32,Drv_IRQ_Counter,Hi(wrd),Lo(wrd),ScanCode);
end;
end
else
break;
end;
DeviceIoControl(hDrv,
CtlCode(_DRV_STOP_INT_VEC),
NIL, 0, NIL, 0,
nByte, POverlapped(NIL));
CurrentProcess := GetCurrentProcess();
SetPriorityClass(CurrentProcess, NORMAL_PRIORITY_CLASS);
end;
end;
procedure TVicHW32.ClearFields;
begin
hDrv := INVALID_HANDLE_VALUE;
fRegistry := TRUE;
fStarted := TRUE;
fTerminated := FALSE;
fInterface := 0;
fBus := 0;
fPhysLoPart := 0;
fPhysHiPart := 0;
fTypeMem := 0;
fMemorySize := 0;
fDebugCode := 0;
FillChar(fMappedPointers,4*MaxMappedAreas,0);
FillChar(fMappedSizes,4*MaxMappedAreas,0);
FillChar(fMappedAddresses,4*MaxMappedAreas,0);
fMappedAreas := 0;
fHardAccess := TRUE;
fIsIRQSet := (fIRQNumber>0) and (fIRQNumber<16);
fMasked := TRUE;
fOpenDrive := FALSE;
end;
constructor TVicHW32.Create(Owner:TComponent); {==}
begin
inherited Create(Owner);
fWin95:= (GetVersion() and $80000000)<>0;
ClearFields();
fDriverName := {$ifdef DEMOVERSION} 'VICHW00' {$else} 'VICHW11' {$endif};
fSDriverName := StrPas(fDriverName);
if fWin95 then
begin
StrPCopy(fPathToDriver,'\\.\'+fSDriverName+'.VXD');
hDll := GetModuleHandle('kernel32');
OpenVxdHandle := TOpenVxdHandle(GetProcAddress(hDll,'OpenVxDHandle'));
fLocEvent := CreateEvent(NIL, TRUE, FALSE, NIL);
hDrvEvent := OpenVxDHandle(fLocEvent);
end
else
begin
GetWindowsDirectory(fPathToDriver,128);
StrCat(fPathToDriver,'\SYSTEM32\DRIVERS\');
StrCat(fPathToDriver,fDriverName);
StrCat(fPathToDriver,'.SYS');
StrPCopy(fShortPathToDriver,'\\.\'+fSDriverName);
fLocEvent := CreateSemaphore(NIL, 0, 1000, NIL);
end;
end;
destructor TVicHW32.Destroy; {==}
begin
CloseDriver();
ClearFields();
if fWin95 then
begin
CloseHandle(hDrvEvent);
CloseHandle(hDll);
end;
CloseHandle(fLocEvent);
inherited Destroy;
end;
procedure TVicHW32.SetIRQMasked(bNewValue : Boolean);
var nByte : DWORD;
begin
if (fOpenDrive and fIsIRQSet) then
begin
if (bNewValue) then
begin
if (not fMasked) then
begin
fMasked := TRUE;
DeviceIoControl(hDrv,
CtlCode(_DRV_MASK_INT_VEC),
NIL, 0, NIL, 0,
nByte, POverlapped(NIL));
fTerminated := true;
if fWin95 then SetEvent(fLocEvent)
else ReleaseSemaphore(fLocEvent, 1, NIL);
WaitForSingleObject(fThreadHandle,INFINITE);
CloseHandle(fThreadHandle);
end;
end
else begin
if fMasked then
begin
with PLockedBuffer(fpLockedMemory)^ do
begin
{$ifdef DEB_NOT_LPT}
LPT_BASE_PORT := $300;
{$ELSE}
LPT_BASE_PORT := fLPTBasePort;
{$ENDIF}
MAX_BUF_LPT := MAX_RING_BUFFER;
L_BUF_LPT := 0;
N_ADD_LPT := 0;
N_SEL_LPT := 0;
end;
fTerminated := FALSE;
if (fWin95) then
fThreadHandle := CreateThread(NIL,
0,
@IRQProc95,
self,
0,
fThreadId)
else
fThreadHandle := CreateThread(NIL,
0,
@IRQProcNT,
self,
0,
fThreadId);
end;
end;
end;
end;
procedure TVicHW32.SetIRQNumber(nNewValue : Byte);
begin
if (nNewValue>0) and (nNewValue<16) then
begin
if (not fMasked) and fOpenDrive then SetIRQMasked(TRUE);
fIRQNumber := nNewValue;
fIsIRQSet := TRUE;
end;
end;
procedure TVicHW32.CloseDriver;
var nByte : DWORD;
i : Byte;
begin
if fOpenDrive then
begin
SetHardAccess(TRUE);
if not fMasked then SetIRQMasked(TRUE);
fOpenDrive := FALSE;
DeviceIoControl(hDrv,
CtlCode(_DRV_UNMAP_LPT_AREA),
@fLPTAddresses,4,
@fLPTAddresses,4,
nByte,POverlapped(NIL));
DeviceIoControl(hDrv,
CtlCode(_DRV_UNLOCK_MEMORY),
@fMdl,4,
@fMdl,4,
nByte,POverlapped(NIL));
for i:=1 to fMappedAreas do
UnmapMemory(fMappedAddresses[i],fMappedSizes[i]);
CloseStopUnloadDriver();
end;
end;
function TVicHW32.OpenDriver : Boolean;
type TLocRec = record pBuf : Pointer; Sz : DWORD; end;
var Rec : TLocRec;
nByte : DWORD;
i : Byte;
begin
Result:=fOpenDrive;
if fOpenDrive then Exit;
ClearFields();
fLPTBasePort := $378;
fLPTNumber := 1;
InstallStartLoadDriver();
if (hDrv = INVALID_HANDLE_VALUE) then
begin
CloseStopUnloadDriver();
InstallStartLoadDriver();
if hDrv = INVALID_HANDLE_VALUE then Exit;
end;
fOpenDrive := TRUE;
Result := TRUE;
fPhysLoPart := $408;
fMemorySize := 6;
DeviceIoControl(hDrv,
CtlCode(_DRV_MAP_MEMORY),//LPT_AREA),
@fInterface,24,
@fLPTAddresses,4,
nByte,POverlapped(NIL));
if (fLPTAddresses<>NIL) then
begin
for i:=1 to 3 do
if fLPTAddresses^[i] <> 0 then Inc(fLPTs);
fLPTBasePort := fLPTAddresses^[1];
end
else begin
fLPTBasePort :=$378;
end;
fLPTNumber := 1;
fpLockedMemory := VirtualAlloc(NIL,4096,MEM_COMMIT,PAGE_READWRITE);
Rec.pBuf := fpLockedMemory;
Rec.Sz := 4096;
DeviceIoControl(hDrv,
CtlCode(_DRV_LOCK_MEMORY),
@Rec,8,@fMdl,4,
nByte,POverlapped(NIL));
with PLockedBuffer(fpLockedMemory)^ do
begin
{$ifdef DEB_NOT_LPT}
LPT_BASE_PORT := $300;
{$ELSE}
LPT_BASE_PORT := fLPTBasePort;
{$ENDIF}
MAX_BUF_LPT := MAX_RING_BUFFER;
L_BUF_LPT := 0;
N_ADD_LPT := 0;
N_SEL_LPT := 0;
end;
end;
function TVicHW32.GetPortB(PortAddr:Word):Byte;
var nByte,PortNumber,DataPort : DWORD;
begin
if not ActiveHW then begin Result:=$ff; Exit; end;
PortNumber:=PortAddr;
if HardAccess then
begin
DeviceIoControl(hDRV,
CtlCode(_DRV_HARD_READ_PORT),
@PortNumber,4,@DataPort,4,
nByte,pOverlapped(NIL))
end
else begin
asm
mov dx,word ptr PortNumber
in al,dx
mov byte ptr DataPort,al
end;
end;
Result:=Lo(LoWord(DataPort));
end;
function TVicHW32.GetPortW(PortAddr:Word):Word;
var nByte,PortNumber,DataPort : DWORD;
begin
if not ActiveHW then begin Result:=$ff; Exit; end;
PortNumber:=PortAddr;
if HardAccess then
begin
DeviceIoControl(hDRV,
CtlCode(_DRV_HARD_READ_PORTW),
@PortNumber,4,@DataPort,4,
nByte,pOverlapped(NIL));
end
else begin
asm
mov dx,word ptr PortNumber
in ax,dx
mov word ptr DataPort,ax
end;
end;
Result:=LoWord(DataPort);
end;
function TVicHW32.GetPortL(PortAddr:Word):DWORD;
var nByte,PortNumber,DataPort : DWORD;
begin
if not ActiveHW then begin Result:=$ff; Exit; end;
PortNumber:=PortAddr; DataPort:=0;
if HardAccess then
begin
DeviceIoControl(hDRV,
CtlCode(_DRV_HARD_READ_PORTL),
@PortNumber,4,@DataPort,4,
nByte,pOverlapped(NIL));
end
else begin
asm
mov dx,word ptr PortNumber
in eax,dx
mov DataPort,eax
end;
end;
Result:=DataPort;
end;
procedure TVicHW32.SetPortB(PortAddr : Word; nNewValue: Byte);
var nByte : DWORD;
Rec : record
PortNumber:DWORD;
DataPort :DWORD;
end;
begin
if not ActiveHW then Exit;
if HardAccess then
begin
Rec.PortNumber:=PortAddr; Rec.DataPort:=nNewValue;
DeviceIoControl(hDRV,
CtlCode(_DRV_HARD_WRITE_PORT),
@Rec,8,NIL,0,
nByte,pOverlapped(NIL));
end
else begin
asm
mov al,nNewValue
mov dx,PortAddr
out dx,al
end;
end;
end;
procedure TVicHW32.SetPortW(PortAddr : Word; nNewValue: Word);
var nByte : DWORD;
Rec : record
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -