;ISA-Port-Emulationstreiber für LPTISA-Adapter
.386 ;32bit-Segmente aktivieren
include tvmm2.inc ;Generelles
; include debug2.inc ;wegen Debugging
; include vpicd.inc ;Interrupt-Controller
LPTISA_Device_ID equ 4209h ;von Microsoft bestätigt:
;>You have been assigned a device ID of 4209h for your LPTISA.386 virtual
;>device. This number is uniquely assigned to this device.
LPTISA_Major_Ver equ 0
LPTISA_Minor_Ver equ 1
;=============================
ifdef DEBUG
%OUT !Assembliere Debugversion!
endif
locals @@
Declare_Virtual_Device LPTISA, LPTISA_Major_Ver, LPTISA_Minor_Ver,\
LPTISA_Control_Proc, LPTISA_Device_ID,\
3B800000h,LPTISA_API,LPTISA_API
;3C000000 ist die VPD_Init_Order des konkurrierenden VPD.VXD unter Windows95
;*********************************************************
;*** Obligatorischer VxD-Botschafts-Funktionsverteiler ***
;*********************************************************
VxD_Locked_Code_Seg
BeginProc LPTISA_Control_Proc
Control_Dispatch Sys_Critical_Init, LPTISA_Init
Control_Dispatch System_Exit, LPTISA_Exit
Control_Dispatch 1bh, LPTISA_Dynamic_Init
Control_Dispatch 1ch, LPTISA_Dynamic_Exit
clc
ret
EndProc LPTISA_Control_Proc
VxD_Locked_Code_ends
;********************************************************
;*** Residenter Datenbereich und Konstantendefinition ***
;********************************************************
MAXTRAP equ 64 ;Max. ISA-Zugriffsumlenkungen
TVxDData struc
;IrqHand dd ? ;IRQ-Griff (IRQ7) - wozu? Windows macht's!
LptBase dd 378h ;Portadresse der LPT-Schnittstelle
PatchAddr dd 0 ;Gepatchte Adresse im BIOS-Datenbereich
IsaAddr dw ? ;Merker für Adress-Flipflops (2x 74HC574)
LptData db ? ;Merker für Datenport (+0)
LptCtrl db ? ;Merker für Steuerport (+2)
Trapped dw MAXTRAP dup (?) ;"Angezapfte" Portadressen
TVxDData ends
VxD_Locked_Data_Seg
VxDData TVxDData <> ;in <struc> für relative Adressierung
TrappedEnd = $
VxD_Locked_Data_Ends
;*******************************************
;** Real-Mode und Protected-Mode-API **
;** (siehe Ralfbrownliste Int2F AX=1684h) **
;*******************************************
VxD_Locked_Code_Seg
BeginProc LPTISA_API
;Funktionen nur unter Win95+ verfügbar:
;* Portadresse hinzufügen (AH=2, DX=Adresse)
;* Portadresse löschen (AH=3, DX=Adresse)
;Funktionen in allen Windows verfügbar:
;* Liste der Portadressen abfragen (AH=1, AL=Nummer; PA: AX=Adresse, 0=frei)
;* Version von LPTISA.386 abfragen (AH=0)
lea edi,VxDData.Trapped
mov ecx,MAXTRAP
mov eax,[ebp.Client_EAX] ;AX laden
cmp ah,4
jnc @@err
cmp ah,2
jnc @@setres
or ah,ah
jz @@ver
cmp al,cl
jnc @@err
movzx eax,al
mov ax,[edi+eax*2]
jmp @@ax
@@ver: mov ax,LPTISA_Major_Ver*256+LPTISA_Minor_Ver
@@ax: mov [ebp.Client_AX],ax
jmp @@ok
@@setres:
movzx eax,[ebp.Client_DX]
jnz @@res
or eax,eax
jz @@err ;Null ist Fehler!
xchg edx,eax ;nach EDX schaffen
xor eax,eax
repne scasw ;Freie Stelle suchen
jnz @@err ;kein Platz
lea esi,IOHandler
VMMcall Install_IO_Handler ;Portzugriffe umlenken
jmp @@gem
@@res:
or eax,eax
jz @@err ;Null ist Fehler!
repne scasw ;Portadresse suchen
jne @@err ;nicht gefunden
xchg edx,eax ;nach EDX schaffen
VMMCall 00010116h ;Remove_IO_Handler (Win95+)
LD edx,0 ;Flags nicht verändern
@@gem: jc @@err ;ging schief
mov word ptr [edi-2],dx ;(ein- bzw.) austragen
@@ok: BRES [ebp.Client_Flags],CF_MASK
ret
@@err: BSET [ebp.Client_Flags],CF_MASK
ret
EndProc LPTISA_Api
;******************************************
;** Ein/Ausgabe-Anzapfung und -Umleitung **
;******************************************
;Steuerport-Bitbelegung
;Bit Name SubD Inv Verwendung Aktiv-Bit
;0 /STB 1 ja /IOWR 1
;1 /AF 14 ja IORD 0 (wird invertiert)
;2 /INIT 16 nein /RESET 0 (wird invertiert)
;3 /SEL 17 ja /ALE 1 (wird invertiert)
; 0->1 lädt Low-Teil der Adresse
; 1->0 lädt High-Teil -"-
;4 /INT - - - 1
;5 /INP - - - 0 (Ausgabe, nicht rücklesbar!)
;Ruhezustand des Steuerports: x11110b (x je nach letztem Befehl)
;Um unnötige lahme ISA-Buszyklen zu vermeiden, werden diese nur ausgeführt,
;wenn sich irgendein Bit ändert. Der Unterprogrammaufruf kostet dagegen
;fast nichts, könnte aber durch Makros ersetzt werden...
BeginProc Put_Ctrl,No_Log
cmp al,[edi.LptCtrl]
je @@e
Put_Ctrl_:
inc edx
inc edx
out dx,al
dec edx
dec edx
mov [edi.LptCtrl],al
@@e: ret
EndProc Put_Ctrl
BeginProc Put_Data,No_Log
cmp al,[edi.LptData]
je @@e
Put_Data_:
out dx,al
mov [edi.LptData],al
@@e: ret
EndProc Put_Data
BeginProc Put_Addr
;Gibt die Adresse auf die Latches, sofern sie sich geändert hat
;PE: DX=Adresse
;PA: EDX=LPT-Basisadresse
; CX=Adresse
;VR: ECX,EDX
push eax
mov ecx,edx ;Adresse retten
mov eax,[edi.LptBase]
xchg eax,edx
xchg [edi.IsaAddr],ax
cmp cx,ax
je @@e ;Keine Änderung!
mov al,011110b ;auf AUSGABE schalten
call Put_Ctrl
mov al,ch
call Put_Data ;High-Teil anlegen
mov al,010110b
call Put_Ctrl_ ;High-Teil übernehmen, ALE=low, Adr. ungültig
mov al,cl
call Put_Data ;Low-Teil anlegen
mov al,011110b
call Put_Ctrl_ ;Low-Teil übernehmen
@@e: pop eax
ret
EndProc Put_Addr
;Trapserviceroutine für Portzugriffe auf die geschützten Adressen
;PE: EDX=Portadresse, ECX=Zugriffsart, EBX=VM-Griff, EAX=EA-Daten
BeginProc IOHandler,No_Log
lea edi,VxDData
Dispatch_Byte_IO Fall_Through,@@o
call Put_Addr
mov al,111110b
call Put_Ctrl ;auf EINGABE schalten
mov al,111100b
call Put_Ctrl_ ;/IORD aktivieren
in al,dx ;InByte lesen
xchg ecx,eax ;InByte retten
mov al,111110b
call Put_Ctrl_ ;/IORD deaktivieren (EINGABE belassen)
xchg eax,ecx ;InByte liefern
ret
@@o:
call Put_Addr
xchg ecx,eax
mov al,011110b
call Put_Ctrl ;auf AUSGABE schalten
xchg eax,ecx
call Put_Data ;OutByte anlegen
mov al,011111b
call Put_Ctrl_ ;/IOWR aktivieren
mov al,011110b
call Put_Ctrl_ ;/IOWR deaktivieren (AUSGABE belassen)
ret
EndProc IOHandler
;*********************
;*** Exit-Funktion ***
;*********************
BeginProc LPTISA_Dynamic_Exit
lea edi,VxDData.Trapped
LD ecx,MAXTRAP
@@l: movzx edx,word ptr [edi]
or edi,edi
jz @@1
VMMCall 00010116h ;Remove_IO_Handler
@@1: inc edi
inc edi
loopd @@l
LPTISA_Exit:
lea edi,VxDData
mov eax,[edi.LptBase]
mov edi,[edi.PatchAddr]
or edi,edi
jz @@e
stosw ;zurückpatchen
@@e: ret
EndProc LPTISA_Dynamic_Exit
VxD_Locked_Code_Ends
;******************************
;*** Installations-Funktion ***
;******************************
VxD_IData_Seg
;IrqDesc VPICD_Irq_Descriptor <8,VPICD_Opt_Can_Share,OFFSET32 CmosIsr>
LPTISA$ db "LPTISA",0
LPT$ db "LPT",0
Ports$ db "Ports",0
VxD_IData_Ends
VxD_ICode_Seg
BeginProc LPTISA_Dynamic_Init
;Nur LPT-Initialisierung, (noch) keine Traps
lea edi,VxDData
mov edx,[edi.LptBase]
add dx,402h
mov al,00100000b ;ECP-Schnittstelle in PS/2-Modus (rück)schalten
out dx,al
LD edx,-1
call Put_Addr ;Adresslatch (und Daten) auf FFFFh setzen
mov al,001010b
call Put_Ctrl_ ;RESET und kein Interrupt
mov al,011110b
jmp Put_Ctrl_ ;Default-Zustand
EndProc LPTISA_Dynamic_Init
BeginProc GetEntry
;Lese SYSTEM.INI-Eintrag in Form LPTx oder als Hexzahl (aus VDONGLE.386)
;PE: EDI=Key-String, ESI=LPTISA$
;PA: EAX=Portadresse
; CY=1: kein oder ungültiger Eintrag
;VR: EAX,EDX
VMMCall Get_Profile_String
jc @@e ;Nicht gefunden? - Nicht auswerten!
mov eax,[edx]
and eax,00DFDFDFh ;Großbuchstaben!
cmp eax,'TPL' ;"LPT"?
je @@2 ;ja
VMMCall Convert_Hex_String
cmp byte ptr [edx],1 ;korrekt null-terminiert?
@@ecmc: cmc
ret
@@2:
mov al,[edx+3] ;Nummer...
sub al,'1'
cmp al,4
jnc @@ecmc
movzx eax,al
movzx eax,word ptr [408h+eax*2] ;LPT-Adresse...
cmp eax,1 ;Null? (Wäre ein Fehler!)
@@e: ret
EndProc GetEntry
BeginProc EditLpt
;entfernt LPT-Adresse aus BIOS-Datenbereich;
;vielleicht hält das Windows vom Direktzugriff ab?
mov edi,408h
LD ecx,3
repne scasw
jne @@e
dec edi
dec edi
mov [VxDData.PatchAddr],edi
mov word ptr [edi],0
@@e: ret
EndProc EditLpt
BeginProc LPTISA_Init
;* Portadressen aus SYSTEM.INI holen
;* Ports trappen
;* LPT rücksetzen
lea esi,LPTISA$ ;Sektion [LPTISA]
lea edi,LPT$ ;Schlüssel LPT
call GetEntry ;Aus SYSTEM.INI ein Wert lesen
jnc @@01
PUSHSTATE
IDEAL ;Der Folgebefehl geht in MASM nicht...
movzx eax,[word 408h] ;LPT1
POPSTATE
or eax,eax
jz @@00
@@01: mov [VxDData.LptBase],eax
call EditLpt
@@00: lea edi,Ports$
VMMCall Get_Profile_String ;Zeile lesen
jc @@x
lea edi,VxDData.Trapped
@@l1: cmp edi,OFFSET32 TrappedEnd
je @@x ;Liste voll!
VMMCall Convert_Hex_String
stosw ;Adresse in Liste eintragen
xchg ecx,eax ;retten
@@y: mov al,[edx] ;Folge-Zeichen betrachten
inc edx
or al,al
jz @@x ;Ende der Liste
cmp al,'-'
jnz @@l1 ;nächste IO-Adresse
VMMCall Convert_Hex_String
xchg ecx,eax ;ist eine Endadresse
@@l2: inc eax
cmp edi,OFFSET32 TrappedEnd
je @@x
stosw
cmp eax,ecx ;bis zum Ende des Bereiches
jb @@l2
inc ecx ;falls jemand wirklich "280-288-289" schreibt
jmp @@y
@@x:
call LPTISA_Dynamic_Init
add edi,Trapped
lea esi,IOHandler
LD ecx,MAXTRAP
@@l: movzx edx,word ptr [edi]
or edx,edx
jz @@1
VMMcall Install_IO_Handler ;folgende Portzugriffe umlenken
jnc @@1
mov word ptr [edi],0
@@1: inc edi
inc edi
loopd @@l
@@e:
ret
EndProc LPTISA_Init
VxD_ICode_Ends
END
Detected encoding: OEM (CP437) | 1
|
|