PACKET setup eumel partitionierung (* Copyright (C) 1985 *) (* Martin Schönbeck, Spenge *) DEFINES tracks, (* Lutz Prechelt, Karlsruhe *) sectors, (* Änderungen: Ley ms *) heads, (* Stand: 07.04.89 *) first track, last track, partition start, partition type, partition active, partition size, partition word 0, get boot block, put boot block, clear partition, (*get bad track table,*) get bad sector table, clear partition table, setup channel, start of partition: LET bst size = 1024; (* nr of bad sector table entrys *) ROW 256 INT VAR boot block; INT VAR boot block session := session - 1; INT VAR fd channel := 28; (* Festplatten-Setupkanal *) INT PROC setup channel: fd channel END PROC setup channel; PROC setup channel (INT CONST new channel): enable stop; teste kanal typ; boot block session DECR 1; wirf altes pac raus; fd channel := new channel; sorge dafuer dass kanal uptodate ist. teste kanal typ: IF (get value (1, new channel) AND 12) <> 12 THEN errorstop ("Hier gibt es leider keine Platte") FI. wirf altes pac raus: IF new channel <> fd channel THEN INT VAR raus := get value (-13, fd channel); FI. sorge dafuer dass kanal uptodate ist: INT VAR old channel := channel; ROW 256 INT VAR dummy; INT VAR i; continue (new channel); disable stop; blockin (dummy, -1, -1, i); break (quiet); continue (old channel). END PROC setup channel; PROC get bad sector table (ROW bst size REAL VAR bb tab, INT VAR bad sect, INT CONST eumel type): initialisiere tabelle; suche schlechte sectoren. initialisiere tabelle: INT VAR i; FOR i FROM 1 UPTO bst size REP bb tab [i] := -1.0; PER. suche schlechte sectoren: INT VAR my channel := channel; REAL VAR sector := start of partition (eumel type), end := sector + partition size (partition number (eumel type)), track mode restart :: 0.0; INT VAR akt track := 0, fehler code; bad sect := 1; (* Eintragsnr. des NÄCHSTEN schlechten Sektors *) continue (fd channel); disable stop; DATASPACE VAR ds := nilspace; REAL CONST cylinder size :: real (sectors * heads), track size :: real (sectors); track mode restart := sector + track size - (sector MOD track size); (* wenn sector nicht erster der spur, dann die erste einzeln *) WHILE sector < end REP IF sector MOD cylinder size = 0.0 THEN melde naechste spur FI; IF sector >= track mode restart THEN check track ELSE check sector FI UNTIL bad sect > bst size OR is error PER; continue (my channel); forget (ds); enable stop; IF bad sect > bst size THEN errorstop ("Zu viele schlechte Sektoren"); FI; lass nicht zu dass ein ersatzsektor ein schlechter ist; bad sect DECR 1. (* ANZAHL schlechter Sektoren *) melde naechste spur: break (quiet); continue (my channel); akt track INCR 1; cout (akt track); continue (fd channel). check track : verify track (ds, 2, sector, fehler code); IF schlechten sektor gefunden THEN track mode restart := sector + tracksize ELSE sector INCR track size FI. check sector : read block (ds, 2, sector, fehler code); IF schlechten sektor gefunden THEN eintragen FI; sector INCR 1.0. schlechten sektor gefunden: SELECT fehler code OF CASE 0: FALSE CASE 1: error stop ("Platte kann nicht gelesen werden"); FALSE CASE 2: TRUE CASE 3: error stop ("Versorgungsfehler beim Plattentest"); FALSE OTHERWISE error stop ("unbekannter Fehler auf Platte"); FALSE END SELECT. eintragen: bb tab [bad sect] := sector; bad sect INCR 1. lass nicht zu dass ein ersatzsektor ein schlechter ist: REAL VAR aktueller ersatz := end - real (bad sect - 1); INT VAR akt b sect; FOR akt b sect FROM 1 UPTO bad sect - 1 REP IF aktueller ersatz ist in tabelle THEN vertausche aktuell zu ersetzenden mit ihm FI; PER. aktueller ersatz ist in tabelle: INT VAR such index; FOR such index FROM 1 UPTO bad sect REP IF aktueller ersatz = bb tab (such index) THEN LEAVE aktueller ersatz ist in tabelle WITH TRUE FI; PER; FALSE. vertausche aktuell zu ersetzenden mit ihm: bb tab ( such index ) := bb tab ( akt b sect ); bb tab (akt b sect) := aktueller ersatz. END PROC get bad sector table; INT PROC cyl and head (REAL CONST sector): cylinder code (int (sector / real (sectors)) DIV heads) OR head. head : (int (sector / real (sectors)) MOD heads). END PROC cyl and head; PROC get boot block: IF boot block session <> session THEN hole aktuellen boot block FI. hole aktuellen bootblock : disable stop; DATASPACE VAR dummy ds := nilspace; BOUND STRUCT (ALIGN dummy, ROW 256 INT block) VAR partition table := dummy ds; get external block (dummy ds, 2, 0, fd channel); IF NOT is error THEN transfer data to boot block FI; forget (dummy ds). transfer data to boot block: IF not valid boot block THEN try to get valid boot block from file FI; boot block := partition table. block; boot block session := session. not valid boot block: partition table. block [256] <> boot indicator OR it is an old boot block of eumel. boot indicator: -21931. it is an old boot block of eumel: partition table. block [1] = 1514. try to get valid boot block from file: forget (dummy ds); partition table := old ("bootblock"); IF is error THEN LEAVE transfer data to boot block FI. END PROC get boot block; PROC clear partition table (INT CONST sicherung): IF sicherung = -3475 THEN neuen boot block; put boot block FI. neuen boot block: enable stop; BOUND STRUCT (ALIGN dummy, ROW 256 INT block) VAR partition table; partition table := old ("bootblock"); boot block := partition table. block; boot block session := session. END PROC clear partition table; PROC put boot block: IF boot block ist uptodate THEN schreibe block auf platte ELSE errorstop ("boot block nicht uptodate") FI. boot block ist uptodate: boot block session = session. schreibe block auf platte: disable stop; DATASPACE VAR dummy ds := nilspace; BOUND STRUCT (ALIGN dummy, ROW 256 INT block) VAR partition table := dummy ds; transfer data to dataspace; put external block (dummy ds, 2, 0, fd channel); forget (dummy ds). transfer data to dataspace: partition table. block := boot block. END PROC put boot block; INT PROC partition number (INT CONST part type): INT VAR partition; FOR partition FROM 1 UPTO 4 REP IF partition type (partition) = part type THEN LEAVE partition number WITH partition FI PER; errorstop ("Partitiontyp gibt es nicht"); 7. END PROC partition number; INT PROC partition word 0 (INT CONST partition): boot block (entry (partition)) END PROC partition word 0; PROC partition word 0 (INT CONST partition, word): boot block (entry (partition)) := word END PROC partition word 0; REAL PROC start of partition (INT CONST partition type): partition start (partition number (partition type)) END PROC start of partition; INT PROC first track (INT CONST partition): high byte (boot block [entry (partition) + 1]) + 4 * (low byte (boot block [entry (partition) + 1]) AND (128 + 64)) END PROC first track; INT PROC last track (INT CONST partition): high byte (boot block [entry (partition) + 3]) + 4 * (low byte (boot block [entry (partition) + 3]) AND (128 + 64)) END PROC last track; INT PROC partition type (INT CONST partition): low byte (boot block [entry (partition) + 2]) END PROC partition type; BOOL PROC partition active (INT CONST partition): low byte (boot block [entry (partition)]) = 128 END PROC partition active; (****************** neu eingefügt ******************************) PROC partition active (INT CONST partition, BOOL CONST active): IF active THEN activate this partition ELSE deactivate this partition FI. deactivate this partition: set bit (boot block [entry (partition)], 7); (* first setting needed, because reset bit does xor *) reset bit (boot block [entry (partition)], 7). activate this partition: set bit (boot block [entry (partition)], 7). END PROC partition active; (****************** neu eingefügt ******************************) PROC first track (INT CONST partition, cylinder): boot block [entry (partition) + 1] := cylinder code (cylinder) OR start sector. start sector: IF cylinder = 0 THEN 2 ELSE 1 FI. END PROC first track; PROC last track (INT CONST partition, cylinder): boot block [entry (partition) + 3] := cylinder code (cylinder). END PROC last track; PROC partition type (INT CONST partition, type): boot block [entry (partition) + 2] := type. END PROC partition type; REAL PROC partition start (INT CONST partition): unsigned low word + high word. unsigned low word: real (low byte (boot block [entry (partition) + 4])) + real (high byte (boot block [entry (partition) + 4])) * 256.0. high word: real (boot block [entry (partition) + 5]) * 65536.0. END PROC partition start; PROC partition start (INT CONST partition, REAL CONST sector offset): boot block [entry (partition) + 4] := low word (sector offset); boot block [entry (partition) + 5] := high word (sector offset) END PROC partition start; REAL PROC partition size (INT CONST partition): unsigned low word + high word. unsigned low word: real (low byte (boot block [entry (partition) + 6])) + real (high byte (boot block [entry (partition) + 6])) * 256.0. high word: real (boot block [entry (partition) + 7]) * 65536.0. END PROC partition size; PROC partition size (INT CONST partition, REAL CONST number of blocks): boot block [entry (partition) + 6] := low word (number of blocks); boot block [entry (partition) + 7] := high word (number of blocks) END PROC partition size; PROC clear partition (INT CONST partition): INT VAR i; FOR i FROM 0 UPTO 7 REP boot block [entry (partition) + i] := 0 PER END PROC clear partition; INT PROC entry (INT CONST partition): get boot block; 256 - 5 * 8 + (partition * 8) END PROC entry; INT PROC cylinder code (INT CONST cylinder): cylinder text ISUB 1. cylinder text: high cylinder bits + low cylinder bits. high cylinder bits: code ((cylinder AND (256 + 512)) DIV 4). low cylinder bits: code (cylinder AND (128 + 64 + 32 + 16 + 8 + 4 + 2 + 1)). END PROC cylinder code; INT PROC tracks: get value (-10, fd channel) END PROC tracks; INT PROC sectors: get value (-11, fd channel) END PROC sectors; INT PROC heads: get value (-12, fd channel) END PROC heads; INT PROC get value (INT CONST control code, channel for value): enable stop; INT VAR old channel := channel; IF channel for value <> old channel THEN continue (channel for value) FI; INT VAR value; control (control code, 0, 0, value); IF channel for value <> old channel THEN continue (old channel) FI; value END PROC get value; PROC get external block (DATASPACE VAR ds, INT CONST ds page, archive block, get channel): INT VAR old channel := channel; continue (get channel); disable stop; read block (ds, ds page, archive block, error); INT VAR error; SELECT error OF CASE 0: CASE 1: error stop ("Platte kann nicht gelesen werden"); CASE 2: error stop ("Lesefehler bei Block "+ text (archive block)); CASE 3: error stop ("Versorgungsfehler Archiv"); OTHERWISE error stop ("unbekannter Fehler auf Platte"); END SELECT; continue (old channel). END PROC get external block; PROC put external block (DATASPACE CONST ds, INT CONST ds page, archive block, get channel): INT VAR old channel := channel; continue (get channel); disable stop; write block (ds, ds page, archive block, error); INT VAR error; SELECT error OF CASE 0: CASE 1: error stop ("Platte kann nicht geschrieben werden"); CASE 2: error stop ("Schreibfehler bei Block "+ text (archive block)); CASE 3: error stop ("Versorgungsfehler Archiv"); OTHERWISE error stop ("unbekannter Fehler auf Platte"); END SELECT; continue (old channel). END PROC put external block; END PACKET setup eumel partitionierung;