home *** CD-ROM | disk | FTP | other *** search
- Unit DrvLib; { Bibliothek der Treiberfunktionen }
- {$A-}
- Interface
- uses Dos, DosUtils;
-
- Type
- DriverPointer = ^DriverHead;
- DriverHead = Record { Gerätetreiber-Kopf }
- DNext: DriverPointer; { Zeiger auf den nächsten Treiber }
- DAttr: Word; { Geräteattribut, <> Func $4400! }
- DStrat: Word; { Offset-Adresse der "Strategy"-Routine }
- DIntr: Word; { Offset-Adresse der "Interrupt"-Routine }
- case Integer of
- 0: (Name: Array[1..8] of Char);
- 1: (Drives: Byte);
- end;
-
- Function GetFirstHeader: DriverPointer; { liefert die Adresse von NUL }
- Function LocateDriver(DriverName: String): DriverPointer; { Treiberadresse }
- Procedure ShowDriver(p: DriverPointer); { Ausgabe Daten Treiberkopf }
- Procedure CallStrategy(Driver: DriverPointer; ParmBlock: Pointer);
- Procedure CallInterrupt(Driver: DriverPointer);
-
- Implementation
-
- Function GetFirstHeader: DriverPointer; { liefert die Adresse von NUL }
- var Regs: Registers;
- begin
- with Regs do
- begin
- AH := $52; Intr($21,Regs);
- if Lo(DosVersion) < 3 then GetFirstHeader := Ptr(ES,BX+$18)
- else if DosVersion = $3 then GetFirstHeader := Ptr(ES,BX+$28)
- else GetFirstHeader := Ptr(ES,BX+$22);
- end;
- end;
-
- { Sucht die Treiber-Kette von DOS ab und ermittelt das Attribut
- sowie die Aufrufadressen der Strategie- und Interrupt-Routinen.
- Bei Aufruf mit einem Nullstring wird der zuletzt eingebaute
- Blocktreiber lokalisiert, ansonsten gehts um Zeichentreiber.
- }
- Function LocateDriver(DriverName: String): DriverPointer;
- var Regs: Registers;
- DHead: DriverPointer; { Zeiger auf den aktuellen Treiberkopf }
- DosV: Word; { Dos-Versionsnummer, umgedreht }
- SearchBlock: Boolean;
- begin
- if Length(DriverName) = 0 then SearchBlock := True
- else
- begin { Treibernamen auf volle Länge bringen, soweit notwendig }
- while Length(DriverName) < 8 do DriverName := DriverName + ' ';
- SearchBlock := False;
- end;
-
- { DOS-Datenbereich ermitteln. Je nach Version steht der Kopf der
- Treiberkette (Gerät NUL) hier ab dem Offset $17, $28 oder $22:
- }
- Regs.AH := $52; Intr($21,Regs); { DOS-Datenbereich }
- DosV := Swap(DosVersion); { $1403 (20.3) -> $0314 (3.20) }
- if DosV < $0300 then DHead := Ptr(Regs.ES,Regs.BX+$17)
- else if DosV < $030A then DHead := Ptr(Regs.ES,Regs.BX+$28)
- else DHead := Ptr(Regs.ES,Regs.BX+$22); { Version 4.x, 5.0 }
-
- { Hat die Sache geklappt? }
- if DHead^.Name <> 'NUL ' then { 'NUL'+ 5 Leerzeichen }
- begin
- Writeln('Kopf der Treiberkette (NUL) nicht gefunden!');
- Writeln('Welches Betriebssystem ist das?');
- Halt;
- end;
-
- { Absuchen der Kette nach dem entsprechenden Gerät oder dem
- zuletzt eingebauten Blocktreiber }
- while (not SearchBlock and (DHead^.Name <> DriverName)) or
- (SearchBlock and ((DHead^.DAttr and $8000) <> 0)) do
- begin
- DHead := DHead^.DNext; { nächster Treiberkopf }
- if Ofs(DHead^) = $FFFF then { Kettenende? }
- begin
- LocateDriver := NIL; Exit;
- end;
- end;
- LocateDriver := DHead;
- end;
-
- { Ausgabe der Daten eines Treiberkopfes }
- Procedure ShowDriver(p: DriverPointer);
- var x: Integer;
- begin
- if p = NIL then
- begin
- Writeln('Treiber nicht lokalisierbar!');
- Halt;
- end;
- with p^ do
- begin
- if (DAttr and $8000) <> 0 then
- begin
- Write('Gerät ');
- for x:= 1 to 8 do Write(Name[x]);
- end
- else Write('Block, (',Drives,' Lw.)');
- Writeln(' - Attr: $',HexW(DAttr),
- ', Strat: $', HexP(Ptr(Seg(p^),DStrat)),
- ', Intr: $', HexP(Ptr(Seg(p^),DIntr)));
- end;
- end;
-
- { Aufruf der Strategie-Routine, d.h. Übergabe Parameterblock }
- Procedure CallStrategy(Driver: DriverPointer; ParmBlock: Pointer);
- var DStrategy: Pointer; { Adresse der "Strategie"-Routine }
- begin
- DStrategy := Ptr(Seg(Driver^),Driver^.DStrat);
- inline($C4/$5E/<ParmBlock/ { asm les bx,[ParmBlock] }
- $FF/$9E/DStrategy { call [DStrategy] }
- ); { end; }
- end;
-
- { Aufruf der Interrupt-Routine, d.h. Ausführung der Funktion }
- Procedure CallInterrupt(Driver: DriverPointer);
- var DInterrupt: Pointer; { Adresse der "Interrupt"-Routine }
- begin
- DInterrupt := Ptr(Seg(Driver^),Driver^.DIntr);
- inline($55/ { asm push bp ; nur für DR-DOS }
- $1E/ { push ds }
- $FF/$9E/DInterrupt/ { call [DInterrupt] }
- $1F/ { pop ds }
- $5D { pop bp ; dito }
- ); { end; }
- end;
-
- end.
-