home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1987 / 10 / dfreecpm.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-07-31  |  7.1 KB  |  139 lines

  1. (* ----------------------------------------------------------------------- *)
  2. (*                             DFREECPM.PAS                                *)
  3. (*  Ermittlung des freien Speicherplatzes einer Disk fuer CP/M 2.x & 3.x.  *)
  4.  
  5. TYPE            (* MS-DOS kompatible Ergebnis-Struktur der DFree-Funktion: *)
  6.   DSK_Info = RECORD
  7.                FreeCluster,         (* Anzahl freier Cluster der Disk      *)
  8.                TotalCluster,        (* Anzahl Cluster insgesamt            *)
  9.                SectorSize,          (* Groesse eines phys. Sektor in Bytes *)
  10.                ClusterSize  : REAL; (* Anzahl Sektoren pro Cluster         *)
  11.              END;
  12. (* Anm.: In den verfuegbaren Unterlagen (CP/M 2.2 Operating System Manual,
  13.    CP/M 3 System & Programmers Guide) konnte ich keinen Hinweis finden, ob
  14.    und wie die physikalische Sektorgroesse einer Disk bei CP/M 2.x ermit-
  15.    telt werden kann. Dieses Info gibt CP/M 3.x im Disk Parameter Block
  16.    (DPB). Aus diesem Grund wird in CP/M 2.x-Varianten einfach die logische
  17.    Sektor-(Record-)groesse von 128 Bytes zu Grunde gelegt.
  18.    Zur Ermittlung des freien Platzes unter CP/M 3.x ist das Verfahren fuer
  19.    die 2.x Versionen nicht generell anwendbar (nur "nonbanked version" mit
  20.    "single-Bit allocation vector"). Deshalb wird bei 3.x die entsprechende
  21.    BDos-Funktion benutzt (s.u.).                                      (MC) *)
  22. (* ----------------------------------------------------------------------- *)
  23. (*  MS-DOS/TOS kompatible Funktion zur Ermittlung freien Speicherplatzes:  *)
  24. (*    Drive = 0: aktuelles Laufwerk, 1: Laufwerk A, 2: Laufwerk B, usw.    *)
  25. PROCEDURE DFree(VAR Info: DSK_Info; Drive: INTEGER);
  26.  
  27. TYPE
  28.   DPB_Rec = RECORD               (* ein CP/M 2.x/3.x Disk Parameter Block: *)
  29.               RecsPerTrk   : INTEGER;   (* 128-Byte-Records pro Spur       *)
  30.               BlkShift,                 (* k.A.                            *)
  31.               RecsPerBlk,               (* 128-Byte-Records pro Block -1   *)
  32.               ExtMask     : BYTE;       (* max. 16K-Extents pro FCB        *)
  33.               BlksPerDrv,               (* Anzahl Bloecke - 1 der Disk     *)
  34.               DirEntrys,                (* Anzahl Directory-Eintraege -1   *)
  35.               DirBlkAlloc,              (* Block-Belegung durch Directory  *)
  36.               DirChkVector,             (* Groesse Dir.-Pruefvektors:
  37.                                                            (DirEntrys/4)+1 *)
  38.               ReservedTrks : INTEGER;   (* Anz. reservierter Spuren        *)
  39.                                         (* folgendes nur bei CP/M 3.x !!!! *)
  40.               SecShift,                 (* k.A.                            *)
  41.               RecsPerSec  : BYTE;       (* Anz. 128-Byte-Records p. Sektor *)
  42.             END;
  43.   DPB_Ptr = ^DPB_Rec;
  44.   (* Der "Disk Allocation Vector" gibt die Block/Cluster-Belegung der Disk
  45.      wieder. Bit gesetzt -> Cluster belegt, sonst frei. Seine Groesse in
  46.      Bytes haengt von der Gesamtanzahl der Cluster einer Disk ab (s.u.)    *)
  47.   DAlloc_Ptr = ^BYTE;
  48.   (* 3.x liefert Anz. freier 128-Rec. in den ersten 3 Bytes der akt. DTA:  *)
  49.   DFree_Inf = ARRAY[1..3] OF BYTE;
  50.   DTA_Ptr   = ^DFree_Inf;
  51.  
  52. VAR
  53.   CurDrv, AllocLen, FreeBlks, i: INTEGER;
  54.   j, mask, shift               : BYTE;
  55.   DPB                          : DPB_Ptr;
  56.   DAlloc                       : DAlloc_Ptr;
  57.  
  58. FUNCTION DGetDPB: DPB_Ptr; (* Adr. des DPB des aktiven Laufwerks ermitteln *)
  59. BEGIN  DGetDPB := Ptr(BDosHL($1F))  END;
  60.  
  61. FUNCTION DGetAlloc: DAlloc_Ptr;  (* Adr. des dazugehoerigen Alloc. Vectors *)
  62. BEGIN  DGetAlloc := Ptr(BDosHL($1B))  END;
  63.  
  64. FUNCTION DGetDrive: INTEGER;          (* gerade aktives Laufwerk ermitteln *)
  65. BEGIN  DGetDrive := BDos($19)  END;
  66.  
  67. PROCEDURE DSetDrive (Drive: INTEGER);        (* obiges als selbiges setzen *)
  68. BEGIN
  69.   BDos($0D);         (* Laufwerke zuruecksetzen, dadurch akt. Alloc. Vect. *)
  70.   BDos($0E, Drive)   (* und neues Laufwerk waeh|en...                      *)
  71. END;
  72.  
  73. FUNCTION DVersion: INTEGER;               (* CP/M Versionsnummer ermitteln *)
  74. BEGIN  DVersion := BDosHL($0C)  END;
  75.  
  76. FUNCTION FGetDTA: DTA_Ptr;             (* akt. DTA ermitteln, nur CP/M 3.x *)
  77. VAR scbpb: RECORD ofs,com: BYTE; value: INTEGER; END;
  78. BEGIN
  79.   scbpb.ofs := $3C; scbpb.com := 0; FGetDTA := Ptr(BDosHL($31,Addr(scbpb)));
  80. END;
  81.  
  82. FUNCTION DFree3x (drv: INTEGER): REAL;   (* Frei 128-Byte-Records ermit-   *)
  83. VAR DTA: DTA_Ptr;                        (* teln, nur CP/M 3.x             *)
  84. BEGIN
  85.   DTA := FGetDTA;  BDos($2E,drv);
  86.   DFree3x := DTA^[1] + 256.0*DTA^[2] + 65536.0*DTA^[3];
  87. END;
  88.  
  89. BEGIN (* DFree *)
  90.   CurDrv := DGetDrive;                        (* aktuelles Laufwerk merken *)
  91.   IF Drive IN [1..16] THEN Drive := Pred(Drive) ELSE Drive := CurDrv;
  92.   DSetDrive(Drive);  (* folgendes geht nur mit akt. Laufw., deshalb dieses *)
  93.   DPB := DGetDPB;           (* Adresse der Disk Parameter Blocks ermitteln *)
  94.   IF (DVersion AND $FF) IN [$20..$2F] THEN BEGIN             (* CP/M 2.x : *)
  95.                          (* Groesse des Alloc. Vectors in Bytes errechnen: *)
  96.     AllocLen := Succ(DPB^.BlksPerDrv DIV 8);
  97.     DAlloc := DGetAlloc;                        (* und seine Adresse holen *)
  98.     FreeBlks := 0;                              (* logo !?                 *)
  99.     shift := 8;  (* Anz. zu maskierender Bits im akt. Byte des Alloc.-Vec. *)
  100.     FOR i := 0 TO AllocLen DO BEGIN
  101.      (* im letzten Byte des Alloc.-Vec. nicht mehr unbedingt 8 Bits mask.: *)
  102.       IF i = Pred(AllocLen) THEN shift := DPB^.BlksPerDrv MOD 8;
  103.       mask := 1;                         (* wir fangen beim' ersten Bit an *)
  104.       FOR j := 1 TO shift DO BEGIN
  105.                                           (* entsprechendes Cluster frei ? *)
  106.         IF (DAlloc^ AND mask) = 0 THEN FreeBlks := Succ(FreeBlks);
  107.         mask := mask SHL 1;                   (* zum naechsten Bit im Byte *)
  108.       END;                     (* zum naechsten Byte im Allocation Vector: *)
  109.       DAlloc := Ptr(Ord(DAlloc)+SizeOf(BYTE));
  110.     END;
  111.     WITH Info,DPB^ DO BEGIN
  112.       FreeCluster := FreeBlks;  SectorSize := 1.0;
  113.     END;
  114.    END
  115.   ELSE IF (DVersion AND $FF) IN [$30..$3F] THEN              (* CP/M 3.x : *)
  116.     WITH Info,DPB^ DO BEGIN
  117.       FreeCluster := DFree3x(Drive) / Succ(RecsPerBlk);
  118.       SectorSize  := Succ(RecsPerSec);
  119.     END;
  120.   WITH Info,DPB^ DO BEGIN (* gesammeltes Material der Aussenwelt mitteilen *)
  121.     TotalCluster := Succ(BlksPerDrv);
  122.     ClusterSize := Succ(RecsPerBlk) / SectorSize;
  123.     SectorSize := SectorSize * 128.0;
  124.   END;
  125.   DSetDrive(CurDrv);         (* wieder zum vorher aktiven Laufwerk zurueck *)
  126. END;
  127. (* ----------------------------------------------------------------------- *)
  128. (* und dies hier gibt schliesslich den freien Platz der Disk ganz einfach  *)
  129. (* in Bytes aus. Wer kBytes moechte, teile den Ausdruck einfach durch 1024 *)
  130. FUNCTION DiskFree (Drive: CHAR): REAL;
  131. VAR Info: DSK_Info;
  132. BEGIN
  133.   DFree(Info, Succ(Ord(UpCase(Drive))-Ord('A')));
  134.   WITH Info DO
  135.     DiskFree := SectorSize * ClusterSize * FreeCluster (* / 1024.0 *);
  136. END;
  137. (* ----------------------------------------------------------------------- *)
  138. (*                             DFREECPM.PAS                                *)
  139.