dos/fat.dos

Raw file
Back to index

PACKET dos fat DEFINES                      (* Copyright (C) 1985, 86, 87 *)
                                            (* Frank Klapper              *)
                                            (* 11.09.87                   *)
  read fat,
  write fat,
  first fat block ok,
  clear fat ds,
  format fat,

  fat entry,
  last fat chain entry,
  is last fat chain entry,
  erase fat chain,
  available fat entry:

  (* Referenz: 4. *)

LET fat size                = 16 384, (* maximal 64 Sektoren a 512 Byte (256 Worte) *)
    max anzahl fat sektoren = 64;

LET FAT = BOUND STRUCT (ALIGN dummy,
                        ROW 256 INT block row,      (* für Kopie des 1. Fatsektors *)
                        ROW fat size INT fat row); 

DATASPACE VAR fat ds;
INITFLAG  VAR fat ds used := FALSE;
FAT       VAR fat struktur;

.fat: fat struktur.fat row.

REAL VAR erster moeglicher freier eintrag;

BOOL VAR kleines fat format;

PROC read fat:
  fat ds initialisieren;
  fat bloecke lesen;
  fat format bestimmen;
  erster moeglicher freier eintrag := 2.0.

fat ds initialisieren:
  clear fat ds;
  fat struktur := fat ds.

fat bloecke lesen:
  LET kein testblock = FALSE;
  INT VAR block no;
  FOR block no FROM 0 UPTO fat sectors - 1 REP
     fat block lesen (block no, kein testblock)
  PER.

fat format bestimmen:
  IF fat entrys <= 4086
    THEN kleines fat format := TRUE
    ELSE kleines fat format := FALSE
  FI.

END PROC read fat;

PROC write fat:
  disable stop;
  INT VAR block nr;
  FOR block nr FROM 0 UPTO fat sectors - 1 REP
    fat block schreiben (block nr)
  PER.

END PROC write fat;

BOOL PROC first fat block ok:
  (* überprüft, ob der erste Block der Fat auf Diskette und im Speicher
     gleich ist                                                        *)
  enable stop;
  LET testblock = TRUE;
  fat block lesen (0, testblock);
  INT VAR i;
  FOR i FROM 1 UPTO 256 REP
    vergleiche woerter
  PER; 
  TRUE.

vergleiche woerter:
  IF fat [i] <> fat struktur.block row [i] 
    THEN LEAVE first fat block ok WITH FALSE
  FI. 

END PROC first fat block ok;

PROC clear fat ds:
  IF initialized (fat ds used)
    THEN forget (fat ds)
  FI;
  fat ds := nilspace.

END PROC clear fat ds;

PROC format fat:
  fat ds initialisieren;
  fat format bestimmen;
  erster moeglicher freier eintrag := 2.0;
  write first four fat bytes;
  write other fat bytes;
  vermerke schreibzugriffe;
  write fat.

fat ds initialisieren:
  clear fat ds;
  fat struktur := fat ds.

fat format bestimmen:
  IF fat entrys <= 4086
    THEN kleines fat format := TRUE
    ELSE kleines fat format := FALSE
  FI.

write first four fat bytes:
  fat [1] := word (media descriptor, 255);
  IF kleines fat format
    THEN fat [2] := word (255, 0)
    ELSE fat [2] := word (255, 255)
  FI.

write other fat bytes:
  INT VAR i;
  FOR i FROM 3 UPTO 256 * fat sectors REP
    fat [i] := 0
  PER.

vermerke schreibzugriffe:
  FOR i FROM 0 UPTO fat sectors - 1 REP
    schreibzugriff (i)
  PER.

END PROC format fat;

(*-------------------------------------------------------------------------*)

REAL PROC fat entry (REAL CONST real entry no):
  (* 0 <= entry no <= 22 000 *)
  INT CONST entry no :: int (real entry no);
  IF kleines fat format
    THEN construct 12 bit value
    ELSE dint (fat [entry no + 1], 0)
  FI.

construct 12 bit value:
  INT CONST first byte no := entry no + entry no DIV 2;
  IF entry no MOD 2 = 0
    THEN real ((right byte MOD 16) * 256 + left byte)
    ELSE real (right byte * 16 + left byte DIV 16)
  FI.

left byte:
  fat byte (first byte no).

right byte:
  fat byte (first byte no + 1).

END PROC fat entry;

TEXT VAR convert buffer := "12";

INT PROC fat byte (INT CONST no): 
  replace (convert buffer, 1, word); 
  IF even byte no
    THEN code (convert buffer SUB 1)
    ELSE code (convert buffer SUB 2)
  FI. 
 
even byte no:
  no MOD 2 = 0.

word: 
  fat [no DIV 2 + 1]. 

END PROC fat byte; 
 
PROC fat entry (REAL CONST real entry no, real value):
  (* 0 <= entry no <= 22 000 *)
  INT CONST entry no :: int (real entry no),
            value    :: low word (real value);
  IF kleines fat format
    THEN write 12 bit value
    ELSE fat [entry no + 1] := value;
         schreibzugriff (entry no DIV 256)
  FI;
  update first possible available entry.

write 12 bit value:
  INT CONST first byte no :: entry no + entry no DIV 2;
  schreibzugriff (fat block of first  byte);
  schreibzugriff (fat block of second byte);
  write value.

fat block of first byte:
  first byte no DIV 512.

fat block of second byte:
  second byte no DIV 512.

write value:
  IF even entry no
    THEN write fat byte (first  byte no, value MOD 256);
         write fat byte (second byte no,
                        (right byte DIV 16) * 16 + value DIV 256)
    ELSE write fat byte (first byte no,
                         (left byte MOD 16) + 16 * (value MOD 16));
         write fat byte (second byte no, value DIV 16)
  FI.

even entry no:
  entry no MOD 2 = 0.

second byte no:
  first byte no + 1.

left byte:
  fat byte (first byte no).

right byte:
  fat byte (second byte no).

update first possible available entry:
  IF value = 0
    THEN erster moeglicher freier eintrag :=
         min (erster moeglicher freier eintrag, real entry no)
  FI.

END PROC fat entry; 

PROC write fat byte (INT CONST byte no, new value):
  read old word;
  change byte;
  write new word.

read old word: 
  replace (convert buffer, 1, word).

write new word:
  word := convert buffer ISUB 1.

word:
  fat [byte no DIV 2 + 1].

change byte:
  replace (convert buffer, byte pos, code (new value)).

byte pos:
  byte no MOD 2 + 1.

END PROC write fat byte;

REAL PROC last fat chain entry:
  IF kleines fat format
    THEN  4 088.0
    ELSE 65 528.0
  FI.

END PROC last fat chain entry;

BOOL PROC is last fat chain entry (REAL CONST value):
  value >= last fat chain entry

END PROC is last fat chain entry;

PROC erase fat chain (REAL CONST first entry no):
  REAL VAR next entry no := first entry no,
           act  entry no := 0.0;
  WHILE next entry exists REP
    act entry no  := next entry no;
    next entry no := fat entry (act entry no);
    fat entry (act entry no, 0.0)
  PER.

next entry exists:
  NOT is last fat chain entry (next entry no).

END PROC erase fat chain; 

REAL PROC available fat entry:
  (* da die fat weniger als 22 000 Einträge umfaßt, kann ich diese als
     INTEGER berechnen                                                   *)
  INT VAR i;
  REAL VAR real i := erster moeglicher freier eintrag;
  FOR i FROM int (erster moeglicher freier eintrag) UPTO fat entrys - 1 REP
    IF fat entry (real i) = 0.0
      THEN erster moeglicher freier eintrag := real i;
           LEAVE available fat entry WITH erster moeglicher freier eintrag
    FI;
    real i INCR 1.0
  PER;
  close work;
  error stop ("MS-DOS Datentraeger voll");
  1.0e99.

END PROC available fat entry;

(*-------------------------------------------------------------------------*)

PROC fat block lesen (INT CONST block nr, BOOL CONST test block):
  (* 0 <= block nr <= fat sectors - 1 *)
  disable stop;
  IF NOT test block
    THEN kein schreibzugriff (block nr)
  FI;
  INT VAR kopie nr;
  FOR kopie nr FROM 0 UPTO fat copies - 1 REP
    clear error;
    read disk block (fat ds, ds seiten nr, disk block nr)
    UNTIL NOT is error
  PER;
  IF is error
    THEN close work
  FI.

ds seiten nr:
  IF test block
    THEN 2
    ELSE block nr + 2 + 1
  FI.

disk block nr:
  begin of fat (kopie nr) + block nr.

END PROC fat block lesen;

PROC fat block schreiben (INT CONST block nr):
  IF war schreibzugriff (block nr)
    THEN wirklich schreiben
  FI.

wirklich schreiben:
  disable stop;
  INT VAR kopie nr;
  FOR kopie nr FROM 0 UPTO fat copies - 1 REP
    write disk block and close work if error (fat ds, ds seiten nr, disk block nr)
  PER;
  kein schreibzugriff (block nr).

ds seiten nr:
  block nr + 2 + 1.

disk block nr:
  begin of fat (kopie nr) + block nr.

END PROC fat block schreiben;

(*-------------------------------------------------------------------------*)

ROW max anzahl fat sektoren BOOL VAR schreib zugriff tabelle;

PROC schreibzugriff (INT CONST fat sektor):
  schreibzugriff tabelle [fat sektor + 1] := TRUE

END PROC schreibzugriff;

PROC kein schreibzugriff (INT CONST fat sektor):
  schreibzugriff tabelle [fat sektor + 1] := FALSE

END PROC kein schreibzugriff;

BOOL PROC war schreibzugriff (INT CONST fat sektor):
  schreibzugriff tabelle [fat sektor + 1]

END PROC war schreibzugriff;

(*-------------------------------------------------------------------------*)

END PACKET dos fat;