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;