home *** CD-ROM | disk | FTP | other *** search
- (*--------------------------------------------------------*)
- (* CACHE.PAS *)
- (* Ein Cache-Programm zum Beschleunigen des Festplatten- *)
- (* zugriffs, NICHT für Disketten-Laufwerke brauchbar ! *)
- (* (C) 1990 E.v.Pappenheim & toolbox *)
- (*--------------------------------------------------------*)
- {$D-,I-,L-,R-,S-,V-} (* Alles aus ... *)
- {$M 1024,0,0} (* Ein KByte Stack, kein Heap ! *)
-
- PROGRAM CacheMe; (* Hasch mich, ich bin der Frühling ... *)
-
- USES Dos;
-
- CONST min = 1;
- max = 125; (* Größe des Cache-Speichers *)
- readsec = 2; (* INT $13, Sektor lesen *)
- writesec = 3; (* INT $13, Sektor schreiben *)
- (* Max. Sektorzahl, die am Stück gespeichert wird *)
- maxsecnum = 25;
-
- TYPE sectortype = ARRAY[1..512] OF BYTE;
- cachetype = ARRAY[min..max] OF sectortype; (* Cache *)
-
- (* "Fingerabdruck" eines Sektors *)
- datetype = RECORD
- head : BYTE;
- zylinder : WORD;
- sector : BYTE;
- END;
-
- (* Indexarray für Fingerabdrücke *)
- indextype = ARRAY[min..max] OF datetype;
-
- (* Rudiment des Bios-Parameter-Blocks *)
- bpbtype = RECORD
- fill : ARRAY[0..20] OF BYTE;
- media_id : BYTE;
- fat_sectors : WORD;
- sec_p_track : WORD;
- no_heads : WORD;
- END;
-
- VAR firstpos,lastpos : BYTE; (* Zeiger auf die Arrays *)
- f,l : BYTE;
- cache : cachetype;
- index : indextype;
- int13save : POINTER;
- workdate : datetype;
- numsecs : BYTE;
- maxhead : BYTE;
- maxsec : BYTE;
- i : BYTE;
- num : BYTE;
- func : BYTE;
- hdnum : WORD;
- bufseg,bufofs : WORD;
- Read : BOOLEAN;
- akku : WORD;
- st : STRING[3];
- c : CHAR;
-
- (* Um Speicherplatz zu sparen, wird der Sektor 0, in *)
- (* dem der BPB steht, in den Cache geladen. Deshalb *)
- (* diese etwas wilde Deklaration ... *)
- bpb : bpbtype ABSOLUTE cache;
-
-
- (* Chainint restauriert die Register komplett, *)
- (* ruft die alte Routine des INT $13 auf, *)
- (* und speichert die Register wieder auf den *)
- (* Stack, von wo sie Turbo wieder abräumt ... *)
- (* Die Prozedur wird aufgerufen, wenn nicht *)
- (* "gecachet" werden soll. *)
- PROCEDURE chainint;
- BEGIN
- INLINE($89/$ec/ (* mov sp,bp *)
- $5d/ (* pop bp ; Stack auf int13 *)
- $89/$ec/ (* mov sp,bp *)
- $5d/ (* pop bp *)
- $07/ (* pop es ; alle Register vom *)
- $1f/ (* pop ds ; Stack *)
- $5f/ (* pop di *)
- $5e/ (* pop si *)
- $5a/ (* pop dx *)
- $59/ (* pop cx *)
- $5b/ (* pop bx *)
- $58/ (* pop ax ; Jetzt ist alles wie *)
- (* vor dem Interrupt *)
- $ea/0/0/0/0);(* jmp far xxxx:yyyy ; Hier wird *)
- (* bei der Installation die *)
- (* Adresse vom alten INT $13 *)
- (* eingesetzt *)
- END;
-
-
-
- (* Folgende Prozedur macht ähnliches, nur *)
- (* werden ihr die Daten für die Register *)
- (* per Parameter übergeben *)
- PROCEDURE calloldint13(ax,bx,cx : WORD);
- INLINE($59/ (* pop cx *)
- $5b/ (* pop bx *)
- $58/ (* pop ax *)
- $8b/$56/$0A/ (* mov dx,[bp+0A] *)
- $8e/$46/$02/ (* mov es,[bp+02] *)
- $9c/ (* pushf *)
- $ff/$1e/int13save/ (* call far int13 *)
- $89/$46/$10/ (* mov [bp+10],ax *)
- $9c/ (* pushf *)
- $58/ (* pop ax *)
- $89/$46/$16); (* mov [bp+16],ax *)
-
- {$F+}
-
- (* Die eigentliche Service-Routine ... *)
- PROCEDURE int13(Flags,CS,IP,
- ax,bx,cx,DX,
- SI,DI,
- DS,ES,
- BP: WORD); INTERRUPT;
- BEGIN
- func := Hi(ax); (* Was wird gewünscht ? *)
- numsecs := Lo(ax); (* Wieviel Sektoren enblock ? *)
- IF ((func = readsec) OR (func = writesec))
- AND (Lo(DX) = hdnum) AND (numsecs < maxsecnum) THEN
- (* Alles im Rahmen ? Dann los ... *)
- WITH workdate DO BEGIN
- (* Alle Variablen initialisieren *)
- head := Hi(DX);
- sector := Lo(cx) AND $1f;
- zylinder := (Lo(cx) SHR 6) SHL 8 + (Hi(cx));
- bufseg := ES;
- bufofs := bx;
- Read := func = readsec;
- akku := func SHL 8 + 1;
- FOR i := 1 TO numsecs DO BEGIN
- f := firstpos;
- l := lastpos;
- (* Gewünschten Sektor im Cache suchen *)
- WHILE (l <> f) AND NOT
- (LONGINT(index[l]) = LONGINT(workdate)) DO
- BEGIN
- IF l = max THEN
- l := min
- ELSE
- Inc(l);
- END;
- IF f = l THEN
- num := 0
- ELSE
- num := l;
- (* Wenn gefunden und er gelesen werden *)
- (* soll, dann dem rufenden Programm in *)
- (* den Puffer schreiben ... *)
- IF (num <> 0) AND Read THEN BEGIN
- Move(cache[num],Ptr(bufseg,bufofs)^,512);
- (* Alles O.K. signalisieren *)
- Flags := Flags AND (NOT fcarry);
- ax := 0;
- END
- ELSE BEGIN
- (* ... ansonsten alten INT $13 EINEN *)
- (* Sektor lesen oder schreiben lassen *)
- calloldint13(akku,bufofs,
- (Lo(zylinder) SHL 8) +
- (Hi(zylinder) SHL 6) + sector);
- (* Bei einem Fehler, signalisiert durch *)
- (* gesetzes Carry-Flag, Abbruch des *)
- (* ganzen Vorgangs *)
- IF Flags AND fcarry <> 0 THEN Exit;
- IF Read THEN BEGIN
- (* Wenn gelesen wurde, dann in *)
- (* den Cache ... *)
- index[firstpos] := workdate;
- cache[firstpos] :=
- sectortype(Ptr(bufseg,bufofs)^);
- IF firstpos = max THEN
- firstpos := min
- ELSE
- Inc(firstpos);
- IF firstpos = lastpos THEN
- IF lastpos = max THEN
- lastpos := min
- ELSE
- Inc(lastpos);
- END
- ELSE
- IF num <> 0 THEN
- (* ... sonst geschriebenen Sektor, *)
- (* falls er im Cache war, dort *)
- (* ersetzen (KONSISTENZ !) *)
- cache[num] :=
- sectortype(Ptr(bufseg,bufofs)^);
- END;
- (* Nächsten Sektor ansteuern *)
- IF sector = maxsec THEN BEGIN
- sector := 1;
- IF head = maxhead THEN BEGIN
- head := 0;
- Inc(zylinder);
- END
- ELSE
- Inc(head);
- DX := head SHL 8 + Lo(DX);
- END
- ELSE
- Inc(sector);
- (* Pufferzeiger auf nächsten Block *)
- Inc(bufofs,512);
- END;
- END
- ELSE
- chainint;
- END;
- {$F-}
-
- (* Liest mit INT $25 den nullten *)
- (* Sektor der Festplatte *)
- FUNCTION readbpb(lw : WORD;
- VAR buffer : sectortype) : BYTE;
- INLINE($5b/ (* pop bx ; ofs(buf) *)
- $58/ (* pop ax ; seg(buf) *)
- $59/ (* pop cx ; lwnum *)
- $1e/ (* push ds ; ! *)
- $8e/$d8/ (* mov ds,ax *)
- $89/$c8/ (* mov ax,cx ;lw => ax *)
- $b9/$01/$00/ (* mov cx,1 ; 1 Sektor *)
- $ba/$00/$00/ (* mov dx,0 ; Sektor 0 *)
- $cd/$25/ (* int 25 ; read *)
- $9d/ (* popf *)
- $1f); (* pop ds ; ! *)
-
-
- PROCEDURE errorhalt(msg : STRING);
- BEGIN
- WriteLn(#7,msg);
- WriteLn('Installation abgebrochen ...');
- Halt(1);
- END;
-
- BEGIN
- firstpos := 1;
- lastpos := 1;
- WriteLn('Cache Ver. 5.5 (C) 1990 by ',
- 'E. v. Pappenheim & toolbox' );
- (* Laufwerk aus Kommandozeile holen und beim kleinsten *)
- (* Fehler abbrechen (kleinlich, kleinlich ...) *)
- IF ParamCount = 0 THEN
- errorhalt('Kein Laufwerk angegeben');
- st := ParamStr(1);
- IF Pos(':',st) = 0 THEN
- errorhalt('Kein Laufwerk angegeben');
- c := UpCase(st[Pred(Pos(':',st))]);
- IF NOT (c IN ['A'..'Z']) THEN
- errorhalt('Kein Laufwerk angegeben');
- hdnum := Ord(c) - 65; (* Für INT $25 *)
- IF hdnum < 2 THEN
- errorhalt('Das Programm funktioniert NICHT mit'+
- 'Diskettenlaufwerken !');
- (* Festplattendaten aus BPB holen und *)
- (* Variablen initialisieren *)
- IF readbpb(hdnum,cache[1]) <> 0 THEN
- errorhalt('Das Programm konnte ihre '+
- 'Festplattendaten nicht ermitteln');
- WITH bpb DO BEGIN
- IF media_id <> $f8 THEN (* $F8 = Festplatte *)
- errorhalt('Das angegebene Laufwerk ist keine '+
- 'Festplatte');
- WriteLn;
- WriteLn('Das Programm wird mit folgenden Daten '+
- 'installiert : ');
- WriteLn;
- WriteLn('Sektoren pro Spur : ',sec_p_track);
- WriteLn('Anzahl der Köpfe : ',no_heads);
- WriteLn;
- maxhead := Pred(no_heads);
- maxsec := sec_p_track;
- Inc(hdnum,$7e); (* Für INT $13 *)
- (* Routine einklinken *)
- GetIntVec($13,int13save);
- (* Chainint mit der Adresse des alten INT $13 patchen *)
- Move(int13save,
- Ptr(Seg(chainint),Ofs(chainint)+18)^,4);
- SetIntVec($13,@int13);
- (* Turbo-Vektoren zurück *)
- swapvectors;
- Keep(0); (* Resident machen *)
- END;
- END.
- (*-------------------------------------------------------*)
- (* Ende von CACHE.PAS *)
-