home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1990 / 03 / ldm / cache.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1989-12-17  |  11.4 KB  |  292 lines

  1. (*--------------------------------------------------------*)
  2. (*                    CACHE.PAS                           *)
  3. (* Ein Cache-Programm zum Beschleunigen des Festplatten-  *)
  4. (* zugriffs, NICHT für Disketten-Laufwerke brauchbar !    *)
  5. (*         (C) 1990 E.v.Pappenheim & toolbox              *)
  6. (*--------------------------------------------------------*)
  7. {$D-,I-,L-,R-,S-,V-}                     (* Alles aus ... *)
  8. {$M 1024,0,0}             (* Ein KByte Stack, kein Heap ! *)
  9.  
  10. PROGRAM CacheMe;  (* Hasch mich, ich bin der Frühling ... *)
  11.  
  12. USES Dos;
  13.  
  14. CONST min = 1;
  15.       max = 125;             (* Größe des Cache-Speichers *)
  16.       readsec = 2;           (* INT $13, Sektor lesen     *)
  17.       writesec = 3;          (* INT $13, Sektor schreiben *)
  18.          (* Max. Sektorzahl, die am Stück gespeichert wird *)
  19.       maxsecnum = 25;
  20.  
  21. TYPE sectortype = ARRAY[1..512] OF BYTE;
  22.      cachetype  = ARRAY[min..max] OF sectortype; (* Cache *)
  23.  
  24.      (* "Fingerabdruck" eines Sektors                     *)
  25.      datetype   = RECORD
  26.                         head     : BYTE;
  27.                         zylinder : WORD;
  28.                         sector   : BYTE;
  29.                   END;
  30.  
  31.      (* Indexarray für Fingerabdrücke                     *)
  32.      indextype = ARRAY[min..max] OF datetype;
  33.  
  34.      (* Rudiment des Bios-Parameter-Blocks                *)
  35.      bpbtype = RECORD
  36.                      fill            : ARRAY[0..20] OF BYTE;
  37.                      media_id        : BYTE;
  38.                      fat_sectors     : WORD;
  39.                      sec_p_track     : WORD;
  40.                      no_heads        : WORD;
  41.                END;
  42.  
  43. VAR firstpos,lastpos : BYTE;  (* Zeiger auf die Arrays    *)
  44.     f,l              : BYTE;
  45.     cache            : cachetype;
  46.     index            : indextype;
  47.     int13save        : POINTER;
  48.     workdate         : datetype;
  49.     numsecs          : BYTE;
  50.     maxhead          : BYTE;
  51.     maxsec           : BYTE;
  52.     i                : BYTE;
  53.     num              : BYTE;
  54.     func             : BYTE;
  55.     hdnum            : WORD;
  56.     bufseg,bufofs    : WORD;
  57.     Read             : BOOLEAN;
  58.     akku             : WORD;
  59.     st               : STRING[3];
  60.     c                : CHAR;
  61.  
  62.     (* Um Speicherplatz zu sparen, wird der Sektor 0, in  *)
  63.     (* dem der BPB steht, in den Cache geladen. Deshalb   *)
  64.     (* diese etwas wilde Deklaration ...                  *)
  65.     bpb              : bpbtype ABSOLUTE cache;
  66.  
  67.  
  68. (* Chainint restauriert die Register komplett, *)
  69. (* ruft die  alte Routine des INT $13 auf,     *)
  70. (* und speichert die Register wieder auf den   *)
  71. (* Stack, von wo sie Turbo wieder abräumt ...  *)
  72. (* Die Prozedur wird aufgerufen, wenn nicht    *)
  73. (* "gecachet" werden soll.                     *)
  74. PROCEDURE chainint;
  75. BEGIN
  76.   INLINE($89/$ec/     (* mov sp,bp                     *)
  77.          $5d/         (* pop bp     ; Stack auf int13  *)
  78.          $89/$ec/     (* mov sp,bp                     *)
  79.          $5d/         (* pop bp                        *)
  80.          $07/         (* pop es  ; alle Register vom   *)
  81.          $1f/         (* pop ds  ; Stack               *)
  82.          $5f/         (* pop di                        *)
  83.          $5e/         (* pop si                        *)
  84.          $5a/         (* pop dx                        *)
  85.          $59/         (* pop cx                        *)
  86.          $5b/         (* pop bx                        *)
  87.          $58/         (* pop ax ; Jetzt ist alles wie  *)
  88.                       (* vor dem Interrupt             *)
  89.          $ea/0/0/0/0);(* jmp far xxxx:yyyy ; Hier wird *)
  90.                       (* bei der Installation die      *)
  91.                       (* Adresse vom alten INT $13     *)
  92.                       (* eingesetzt                    *)
  93. END;
  94.  
  95.  
  96.  
  97. (* Folgende Prozedur macht ähnliches, nur *)
  98. (* werden ihr die Daten für die Register  *)
  99. (* per Parameter übergeben                *)
  100. PROCEDURE calloldint13(ax,bx,cx : WORD);
  101. INLINE($59/                        (* pop cx              *)
  102.        $5b/                        (* pop bx              *)
  103.        $58/                        (* pop ax              *)
  104.        $8b/$56/$0A/                (* mov dx,[bp+0A]      *)
  105.        $8e/$46/$02/                (* mov es,[bp+02]      *)
  106.        $9c/                        (* pushf               *)
  107.        $ff/$1e/int13save/          (* call far int13      *)
  108.        $89/$46/$10/                (* mov [bp+10],ax      *)
  109.        $9c/                        (* pushf               *)
  110.        $58/                        (* pop ax              *)
  111.        $89/$46/$16);               (* mov [bp+16],ax      *)
  112.  
  113. {$F+}
  114.  
  115. (* Die eigentliche Service-Routine ...  *)
  116. PROCEDURE int13(Flags,CS,IP,
  117.                 ax,bx,cx,DX,
  118.                 SI,DI,
  119.                 DS,ES,
  120.                 BP: WORD); INTERRUPT;
  121. BEGIN
  122.      func := Hi(ax);        (* Was wird gewünscht  ?      *)
  123.      numsecs := Lo(ax);     (* Wieviel Sektoren enblock ? *)
  124.      IF ((func = readsec) OR (func = writesec))
  125.         AND (Lo(DX) = hdnum) AND (numsecs < maxsecnum) THEN
  126.        (* Alles im Rahmen ? Dann los ...                    *)
  127.        WITH workdate DO BEGIN
  128.          (* Alle Variablen initialisieren                   *)
  129.          head := Hi(DX);
  130.          sector := Lo(cx) AND $1f;
  131.          zylinder := (Lo(cx) SHR 6) SHL 8 + (Hi(cx));
  132.          bufseg := ES;
  133.          bufofs := bx;
  134.          Read := func = readsec;
  135.          akku := func SHL 8 + 1;
  136.          FOR i := 1 TO numsecs DO BEGIN
  137.            f := firstpos;
  138.            l := lastpos;
  139.            (* Gewünschten Sektor im Cache suchen       *)
  140.            WHILE (l <> f) AND NOT
  141.                  (LONGINT(index[l]) = LONGINT(workdate)) DO
  142.               BEGIN
  143.                 IF l = max THEN
  144.                   l := min
  145.                 ELSE
  146.                   Inc(l);
  147.               END;
  148.               IF f = l THEN
  149.                 num := 0
  150.               ELSE
  151.                 num := l;
  152.               (* Wenn gefunden und er gelesen werden     *)
  153.               (* soll, dann dem rufenden Programm in     *)
  154.               (* den Puffer schreiben ...                *)
  155.               IF (num <> 0) AND Read THEN BEGIN
  156.                 Move(cache[num],Ptr(bufseg,bufofs)^,512);
  157.                 (* Alles O.K. signalisieren  *)
  158.                 Flags := Flags AND (NOT fcarry);
  159.                 ax := 0;
  160.               END
  161.               ELSE BEGIN
  162.                  (* ... ansonsten alten INT $13 EINEN  *)
  163.                  (* Sektor lesen oder schreiben lassen *)
  164.                  calloldint13(akku,bufofs,
  165.                       (Lo(zylinder) SHL 8) +
  166.                       (Hi(zylinder) SHL 6) + sector);
  167.                  (* Bei einem Fehler, signalisiert durch *)
  168.                  (* gesetzes Carry-Flag, Abbruch des     *)
  169.                  (* ganzen Vorgangs                      *)
  170.                  IF Flags AND fcarry <> 0 THEN Exit;
  171.                  IF Read THEN BEGIN
  172.                       (* Wenn gelesen wurde, dann in *)
  173.                       (* den Cache ...               *)
  174.                       index[firstpos] := workdate;
  175.                       cache[firstpos] :=
  176.                             sectortype(Ptr(bufseg,bufofs)^);
  177.                       IF firstpos = max THEN
  178.                         firstpos := min
  179.                       ELSE
  180.                         Inc(firstpos);
  181.                       IF firstpos = lastpos THEN
  182.                         IF lastpos = max THEN
  183.                           lastpos := min
  184.                          ELSE
  185.                            Inc(lastpos);
  186.                    END
  187.                    ELSE
  188.                      IF num <> 0 THEN
  189.                        (* ... sonst geschriebenen Sektor, *)
  190.                        (* falls er im Cache war, dort     *)
  191.                        (* ersetzen (KONSISTENZ !)         *)
  192.                         cache[num] :=
  193.                             sectortype(Ptr(bufseg,bufofs)^);
  194.               END;
  195.               (* Nächsten Sektor ansteuern *)
  196.               IF sector = maxsec THEN BEGIN
  197.                 sector := 1;
  198.                 IF head = maxhead THEN BEGIN
  199.                   head := 0;
  200.                   Inc(zylinder);
  201.                 END
  202.                 ELSE
  203.                   Inc(head);
  204.                 DX := head SHL 8 + Lo(DX);
  205.               END
  206.               ELSE
  207.                 Inc(sector);
  208.               (* Pufferzeiger auf nächsten Block *)
  209.               Inc(bufofs,512);
  210.           END;
  211.      END
  212.      ELSE
  213.        chainint;
  214. END;
  215. {$F-}
  216.  
  217. (* Liest mit INT $25 den nullten  *)
  218. (* Sektor der Festplatte          *)
  219. FUNCTION readbpb(lw : WORD;
  220.                  VAR buffer : sectortype) : BYTE;
  221. INLINE($5b/                     (* pop bx      ; ofs(buf) *)
  222.        $58/                     (* pop ax      ; seg(buf) *)
  223.        $59/                     (* pop cx      ; lwnum    *)
  224.        $1e/                     (* push ds     ; !        *)
  225.        $8e/$d8/                 (* mov ds,ax              *)
  226.        $89/$c8/                 (* mov ax,cx   ;lw => ax  *)
  227.        $b9/$01/$00/             (* mov cx,1    ; 1 Sektor *)
  228.        $ba/$00/$00/             (* mov dx,0    ; Sektor 0 *)
  229.        $cd/$25/                 (* int 25      ; read     *)
  230.        $9d/                     (* popf                   *)
  231.        $1f);                    (* pop ds      ; !        *)
  232.  
  233.  
  234. PROCEDURE errorhalt(msg : STRING);
  235. BEGIN
  236.   WriteLn(#7,msg);
  237.   WriteLn('Installation abgebrochen ...');
  238.   Halt(1);
  239. END;
  240.  
  241. BEGIN
  242.   firstpos := 1;
  243.   lastpos := 1;
  244.   WriteLn('Cache Ver. 5.5 (C) 1990 by ',
  245.           'E. v. Pappenheim & toolbox'   );
  246.   (* Laufwerk aus Kommandozeile holen und beim kleinsten *)
  247.   (* Fehler abbrechen (kleinlich, kleinlich ...)         *)
  248.   IF ParamCount = 0 THEN
  249.      errorhalt('Kein Laufwerk angegeben');
  250.      st := ParamStr(1);
  251.      IF Pos(':',st) = 0 THEN
  252.        errorhalt('Kein Laufwerk angegeben');
  253.        c := UpCase(st[Pred(Pos(':',st))]);
  254.        IF NOT (c IN ['A'..'Z']) THEN
  255.         errorhalt('Kein Laufwerk angegeben');
  256.         hdnum := Ord(c) - 65;  (* Für INT $25 *)
  257.         IF hdnum < 2 THEN
  258.           errorhalt('Das Programm funktioniert NICHT mit'+
  259.                     'Diskettenlaufwerken !');
  260.         (* Festplattendaten aus BPB holen und *)
  261.         (* Variablen initialisieren           *)
  262.         IF readbpb(hdnum,cache[1]) <> 0 THEN
  263.           errorhalt('Das Programm konnte ihre '+
  264.                     'Festplattendaten nicht ermitteln');
  265.          WITH bpb DO BEGIN
  266.            IF media_id <> $f8 THEN    (* $F8 = Festplatte *)
  267.              errorhalt('Das angegebene Laufwerk ist keine '+
  268.                        'Festplatte');
  269.           WriteLn;
  270.           WriteLn('Das Programm wird mit folgenden Daten '+
  271.                   'installiert : ');
  272.           WriteLn;
  273.           WriteLn('Sektoren pro Spur : ',sec_p_track);
  274.           WriteLn('Anzahl der Köpfe  : ',no_heads);
  275.           WriteLn;
  276.           maxhead := Pred(no_heads);
  277.           maxsec := sec_p_track;
  278.           Inc(hdnum,$7e);                  (* Für INT $13 *)
  279.           (* Routine einklinken *)
  280.           GetIntVec($13,int13save);
  281.           (* Chainint mit der Adresse des alten INT $13 patchen *)
  282.           Move(int13save,
  283.                Ptr(Seg(chainint),Ofs(chainint)+18)^,4);
  284.           SetIntVec($13,@int13);
  285.           (* Turbo-Vektoren zurück *)
  286.           swapvectors;
  287.           Keep(0);  (* Resident machen *)
  288.      END;
  289. END.
  290. (*-------------------------------------------------------*)
  291. (*                 Ende von CACHE.PAS                    *)
  292.