3.5 * Directory Device Handler
Was für die Einrichtung der einfachen Device Handler gilt, ist hier mit geringfügigen Abweichungen vorauszusetzen. Zusätzlich sind Angaben zur Verwaltung von Directories erforderlich.Eine wesentliche Ergänzung besteht in den "slave blocks", einer überaus nützlichen, aber auch ganz besonders verletzlichen Zwischenspeicherung, die den gesamten "freien" Ram-Bereich umfaßt. Nach der Darstellung dessen, was in Form der Files die Handler zu bearbeiten haben, soll deren Arbeitsweise beschrieben werden.
3.5.1 File-Struktur
Die Files für den QL setzen sich aus Blöcken zu 512 Bytes Daten zusammen. So wird ein Byte innerhalb eines File vom IOSS durch eine Blocknummer und die Nummer des Byte innerhalb dieses Blocks Adressiert. Diese Anordnung kann durchaus auch abgeändert werden, doch wird die Stellung der physischen zur logischen Struktur dann ungünstiger sein. Der folgenden Beschreibung wird die allgemein benutzte Einteilung in 512 Bytes lange Blöcke zugrundegelegt. Weiter setzt das FSS einen File Header voraus, beim TK2 auch in Form entsprechender Eintragungen in einem besonderen Directory-File, der der diese Angaben enthält:
HFLEN 00 .l File-Länge in Bytes HACCS 04 .b Null, frei für einen Zugriffsschlüssel HTYPE 05 .b File-Typ (s.u.) HDATA 06 .l Bei Typ 1 Datenbereich, wie er für einen Job zu reservieren ist HXTRA 10 .l Null oder Startadresse bei MINERVA(?), sonst frei verwendbar;
bei einem Wert =/= 0 darf LRESPR oder CALL nicht benutzt werden.HNAME 14 .w/.b Länge und max. 36 Bytes für den File-Namen HDATE 52 .l TK: DATE des jüngsten Schreibvorganges HVERS 56 .w LV: File-"Version" HFLID 58 .w LV: File-ID, bei QXL.WIN Index in die Sector-"Map" HBKUP 60 .l LV: DATE des jüngsten Copiervorganges (?)
Die Angabe DATE entspricht dem, was mit dem Basic-Befehl zu erhalten ist, nur das erweiterte System bedient diese Daten.Standardisierte File-Typen sind:
0 gewöhnliche Daten, alles was nicht zu den anderen Typen zählt 1 als Job ausführbare Programme 2 Relocatible Object Files, wie z.B. vom GST-Assembler benutzt 255 LV: Directory-File 3 Thor: Directory-File
3.5.2 Handler-Aufbau
Drei Speicherbereiche sind einzurichten:Zu 1. Directory Handler Linkage
- Directory Handler Linkage Block - Handler-Verkettung
- Pysical Definition Block (pdb) - Physische Daten
- Channel Definition Block - Definitonsblock
Der Handler-Einbau entspricht dem schon Bekannten. Die Art der Tabelle ist unverändert, die Angaben wurden erweitert. Der Definitionsblock ist nun mindestens 64 Bytes lang.
So wird die Liste der Link-Blöcke angelegt:
Label Link Basis Funktion CH.LXINT -24 00 Link auf nächsten Ext. Interrupt CH.AXINT -20 04 hier gültiger Aufruf CH.LPOLL -16 08 Link auf nächsten Poll-Int. CH.APOLL -12 12 hier gültiger Aufruf CH.LSCHD -08 16 Link auf nächsten Scheduled Interrupt CH.ASCHD -04 20 hier gültiger Aufruf CH.LNEXT 00 24 Ptr auf nächsten Device Handler CH.AIO 04 28 Ptr auf I/O-Bearbeitung CH.AOPEN 08 32 dto., zum Öffnen eines Kanals CH.ACLOS 12 36 dto., zum Schließen eines Kanals CH.SLAVE 16 40 dto., zur Slave-Block-Bedienung CH.RENAM 20 44 dto., ggf. für RENAME-Routine 24 48 reserviert CH.FORMT 28 52 Ptr, Formatieren des Datenträgers CH.DFLEN 32 56 Länge Physischer Definitionsblock CH.DRNAM 36 60 w/b Länge & Name d. Gerätebezeichnung ++ ++ Arbeitsspeicher nach Bedarf
In CH.DRNAM steht der Anteil des Devicenamen im Filenamen, z.B. 3, 'FLP' für 'flp1_probe', ggf. mit 0 aufgefüllt.Die zusätzlichen Posten müssen nicht unbedingt auch benutzt werden. Solche markiert man mit Null statt einer Adresse und verzichtet ggf. auf das Einfügen in die Sytemliste.
Bei der Installation ist in bekannter Weise erst der nötige Speicherbereich für die Listen des Handlers zu reservieren. Erforderlich sind wenigstens die erweiterten Angaben für den Device Handler mit dessen Routinen der Access Layer, der Länge der Physischen Definitionsblöcke für die Laufwerke und dem Laufwerksnamen. Der Speicherblock kann im Bereich residenter Proceduren liegen und ist auf diese Weise besonders geschützt. Für gewöhnlich wird er jedoch im Common Heap angelegt.
Wichtig zu beachten, daß das System mit Sicherheit zusammenbricht, falls der Link-Block überschrieben wird, bevor der Handler aus der Liste genommen worden ist. Was im Übrigen für alle Programmteile gilt, die mit Hilfe einer der vom System abzuarbeitenden Listen aufgerufen werden.
Nun erst sind nach Bedarf die Qdos-Traps (1) aufzurufen:
MT.LXINT 26 $1A Externen Interrupt einfügen MT.LPOLL 28 $1C dto., Abfrage-Interrupt (polled) MT.LSCHD 30 $1E dto., Scheduler-Aufruf MT.LDD 31 $1F Abschließend die Aufnahme in das System
Die in den Handler übergebenen Register enthaltenD0 Code der Qdos-Trap bei I/O-Operationen (Trap #3)
A0 Basisadresse des Kanal-Definitionsblocks
A1 dto., pysischer Definitionsblock
A3 dto., Directory Handler Link-Block (CH.LXINT)
A6 dto., Systemvariable
A7 Supervisor StackptrRückkehr mit Fehlercode in D0.
D1 - D7 und A1 - A5 sind frei verwendbar.OPEN-Routine
Zusätzlich bestimmt hier der Schlüsselcode in D3, wenn er negativ aus IO.DELET (2/4) ankommt, daß das File mit dem angegebenen Namen zu löschen ist.Abweichend von den einfachen Handlern wird der Name selbst durch das IOSS decodiert. Im Handler erfolgt Prüfung auf Übereinstimmung in den ersten Zeichen, wie sie in CH.DRNAM angegeben sind. Als Laufwerksname werden sie gültig, wenn dann erwartungsgemäß eine Ziffer im Bereich 1 bis 8 folgt, danach der Unterstrich als Trennzeichen.
Das System sucht diesen Namen in den Physischen Definitionsblöcken. Ist er noch nicht verzeichnet, wird dort automatisch ein neuer Block eingerichtet. Es wird nicht geprüft, ob das betreffende Laufwerk auch tatsächlich angeschlossen ist. Hier geht der Computer vom überragenden Verstand seines Menschen aus.Alle Zeichen, die dem ersten Unterstrich folgen, gelten als Filename. Nach diesem wird erst einmal in den bereits vorhandenen Kanaltabellen gesucht. Gibt es ihn schon, und ist der geteilte Zugriff erlaubt, baut das IOSS eine Copie davon auf. Ist aber der Name an einen als "ausschließlich" markierten Kanal gebunden, erfolgt Fehlermeldung. Andernfalls hat die OPEN-Routine nun einen neuen Kanal mit eigenem Definitionsblock für den angegebenen Filenamen auf das zuvor decodierte Device einzurichten.
Mindestens 160 Bytes sind für die Tabelle erforderlich. Ergänzend zu den in bekannter Weise vom IOSS bestimmten Daten erhält die Kanaltabelle weitere zur File-Betreuung geeignete Angaben. Die unten mit "X" markierten Posten trägt das IOSS ein. Außer an den markierten Stellen werden die Blöcke anfangs mit Null aufgemacht.
Bei geteilten Kanälen übernimmt das IOSS den Aufbau der ganzen Tabelle. Dann wird $40 auf FS.NBYTE eingetragen und der Rest aus dem zuerst geöffneten Kanal copiert.
FS.NEXT $18 .b X Link zum nächsten FSS-Kanal FS.ACCES $1C .b X Zugriffsart nach D3 des OPEN-Aufrufs FS.DRIVE $1D .w X Laufwerks-Kennzahl (drive ID) FS.FILNR $1E .w Anzahl Files im selben Laufwerk FS.NBLOK $20 .w Block mit dem nächsten Byte FS.NBYTE $22 .w Nummer des nächsten Byte darin FS.EBLOK $24 .w Block mit dem Byte nach EOF FS.EBYTE $26 .w Nummer dieses Byte FS.CBLOK $28 .l Ptr auf aktuelle Slaveblock-Tabelle FS.FNAME $2C .w+.b X Länge und Zeichen des Filenamen FS.SPARE $58 72 .b 72 Bytes Arbeitsspeicher
Die Zahl in FS.DRIVE zeigt als Index in eine Tabelle, die in den Systemvariablen ab SV.FSDEF(sb) mit 16 Langworten zu finden ist. Dort sind die Pysischen Definitionsblöcke aller Laufwerke verzeichnet. Das bedeutet zugleich, daß im QDOS insgesamt bis zu 16 solcher Laufwerke verwaltet werden können.
Bei auswechselbaren Datenträgern ist der Filename im Physischen Definitionsblock bei FS.MNAME einzutragen. Soll ein File nur gelöscht werden, kann das nun geschehen. Unmittelbar anschließend erfolgt die Rückkehr.
In diesem Falle gibt das IOSS die zugehörigen Speicherblöcke frei. Ansonsten wird man jetzt die restlichen Angaben in die Kanal-Definitionstabelle eintragen, insbesondere FS.FILNR, FS.EBLOK, FS.EBYTE, FS.NBLOK und FS.NBYTE.
FS.CBLOK ist ein Ptr auf die Tabelle der Slave Blöcke. Er dient als Hinweis an die I/O-Routinen und zeigt an, daß der betreffende Block dort aufgezeichnet sein könnte. Die Routine selbst hat dann die Chance, nach Durchsuchen der Tabelle den zwischengespeicherten Block zu finden. Angaben zum entsprechenden Verfahren folgen weiter unten.
CLOSE-RoutineDas IOSS betreffend gibt es hier keinen Unterschied zum einfachen Handler. Die Filestruktur bedarf jedoch noch der Beachtung. So sind weitere Vorkehrungen erforderlich, etwa in Gestalt abschließenden Sicherns noch nicht übertragener Slave-Blöcke. Ein Prozess ist einzuleiten, der in den zugehörigen noch verbliebenen Slave Blöcken aufräumt.
Dabei ist es nicht nötig, die sofortige Ausführung zu erzwingen. Es ist bei Fälligkeit jedoch Sorge zu tragen, daß das Zurückcopieren ungestört durch irgendeinen anderen Vorgang, insbesondere des rufenden Programms, abläuft. Alles, was zum Schließen des Kanals nötig ist, wird solange zurückgestellt. Hier werden dann die "true" markierten Slave Blöcke (s. dort) auf den eigentlichen Datenträger übertragen.Schließich wird der Kanal aus der Liste offener Files herausgenommen und die Zahl in FS.FILES angepaßt.
SV.FSDEF $100(sb) max. 16 Ptr physische Definitionsblöcke FS.DRIVE .b FS.DRIVE hält den Index dorthin (s. o.) SV.FSLST $140(sb) Ptr auf die offenen Filekanäle
Ein Beispiel nach {2} zum Schließen solch eines Kanals:
(pdb - Physischer Definitionsblock)I/O-Routinen
moveq #0,d0 register freimachen move.b $1d(a0),d0 fs.drive lsl.b #2,d0 ID wird Platz in pdb-Tabelle lea $100(a6),a2 sv.fsdef ist die Basis move.l 0(a2,d0.w),a2 zur id gehöriger pdb subq.b #1,$22(a2) darin Zähler fs.files anpassen lea $18(a0),a0 Adresse des Link-Ptr in fs.next lea $140(a6),a1 sv.flst mit Ptr auf Fileliste move.w $00d4,a2 mit ut.unlk jsr (a2) File herausnehmen lea $-18(a0),a0 wieder der Definitionsblock move.w $00c2,a2 mm.rechp löst den Block auf jmp (a2) und verläßt die CLOSE-Routine Diese Teilprogramme erscheinen zunächst einmal wie bei den einfachen Devices. Die nicht vom IOSS verwalteten Posten der Kanaltabelle sind immer auf aktuellem Stand zu halten. Die Möglichkeit, auf Files frei adressiert zuzugreifen, bedarf der besonderen Beachtung. In alle Operationen sind also auch die zugehörigen Positionsangaben einzubeziehen. Einfach nur fortlaufendes Zählen genügt nicht, weil der Filepointer auch außer der Reihe mit einem Trap-Aufruf verstellt worden sein könnte.
Zusätzlich sind in Trap #3 mit Programmen zu versorgen:
FS.CHECK 64 $40 Prüfung laufender Fileoperationen FS.FLUSH 65 $41 schließt die File-Pufferung ab FS.POSAB 66 $42 Fileposition aufsuchen FS.POSRE 67 $43 im File vor- oder zurückgehen FS.MDINF 69 $45 Liefert die Angaben zum Datenträger FS.HEADS 70 $46 Fileheader neu besetzen FS.HEADR 71 $47 Fileheader lesen FS.LOAD 72 $48 ganzes File in den Speicher holen FS.SAVE 73 $49 Speicherbereich als File sichern IOF.DATE 76 $4C TK File-Datum lesen oder eintragen IOF.MKDR 77 $4D TK File zum Directory machen IOF.VERS 78 $4E LV File-Version lesen oder eintragen IOF.XINF 79 $4F LV Erweiterten Informationsblock holen
Zu 2. Physical Definition Block - pdbDieser Datenblock ist neu.
Hier wird für jedes Laufwerk die Nummer abgelegt, dann Angaben zur Art des Datenträgers und der Anzahl offener Files darin. Das geschieht mit dem ersten Aufruf automatisch und für jedes Laufwerk einzeln.
In der Tabelle sind die ersten 16 Bytes zur Verwaltung durch das IOSS reserviert. Weiter werden mit der Basisadresse A1 an die Access Layer übergeben:
FS.DRIVR 16 Ptr auf Access Layer Link des Handlers FS.DRIVN 20 .b Nummer des Laufwerks FS.MNAME 22 .w/.b Länge & max. 10 Bytes Name des Geräts FS.FILES 34 .b Anzahl offener Files darin
CH.DFLEN im Access Layer gibt die Länge dieses mindestens 36 Bytes langen Blocks an. Angelegt wird er durch das IOSS. Die Handlerroutinen müssen die Eintragungen FS.MNAME und FS.FILES besorgen. Zu 3. Channel Definition Block Der Aufbau dieses Datenblocks ist bei der OPEN-Routine beschrieben worden. Hier stehen wie gewohnt alle einem Kanal eigenen Daten, die mit seinem Verschwinden nutzlos werden. Der Block wird darum dann auch aufgelöst. Wesentliche Unterstützung gibt diese Tabelle dem zumeist im Hintergrund ablaufenden Austausch zwischen Files und den Slave Blöcken, gelegentlich kontrolliert durch Aufrufe der Access Layer.
FORMAT
Zum Formatieren wird die Adresse aus CH.FORMT auf $34 im Handler aufgerufen. Zusätzlich zu den bereits genannten Angaben kommen in
D1 LaufwerksnummerBei Rückkehr sind zu übergeben
A1 Ptr auf den Namen des MediumsD0 FehlercodeRegister D3 - D7 und A0 - A5 sind frei verwendbar.
ERR.OM -3 Speicherüberlauf
ERR.NF -7 Laufwerk nicht gefunden
ERR.IU -9 Laufwerk wird benutzt
ERR.FF -14 Formatierungsfehler
D0 = 0 wenn alles richtig abgeschlossen wurde, dann auch
D1 Anzahl brauchbarer Sectoren
D2 Gesamtzahl aller SectorenNach {5} wird in jedem Falle, auch wenn das Formatieren nicht gelingt, der Name ab FS.MNAME ($16) des physischen Definitionsblocks eingetragen.
3.5.3 * Slave Blocks - Forced Slaving
Dies sind zunächst einmal Zwischenspeicher, die im freien Ram angeordnet wurden und unabhängig von der sonstigen Speicherverwaltung dort verweilen. Dabei immer nur in der stillen Hoffnung, daß sie nicht durch vorrangige Daten überschrieben werden.Übergeordnet ist hierbei alles. Nur andere Slave Blöcke nicht. Und Hoffnung heißt, daß das Vorhandensein eines solchen Blocks immer erst bestätigt werden muß. Er kann nämlich jederzeit vom Betriebssystem zurückgeschickt und aufgelöst worden sein. Wird dieser Vorgang erzwungen, etwa um einer anderen Speicheranforderung Raum zu geben, heißt er "forced slaving".
Bei einem Filezugriff werden zunächst einige Sectoren in den Speicher geholt. Zuvor kann man prüfen, ob diese dort schon vorhanden sind. Ist dies der Fall, und sind die Blöcke bereits als "true copy" markiert, kann der Zugriff auf das Laufwerk entfallen.
Das Laden wird im Übrigen von den Anforderungen der Anwendung abhängig ausgelöst. Die Markierung drückt aus, daß der betreffende Slave Block "true" ein gültiger Teil des im Speicher stehenden Datenblocks ist, eines File zumeist.
Bei einer neuen Definition ist ggf. die Arbeitsweise vollkommen freigestellt. Lediglich die Anforderungen des "forced slaving" müssen erfüllt werden. Das PRT-Device des TK2 ist ein Beispiel dafür.
Für die Zuweisung als Puffer sind nur leere Blöcke einzeln auszuwählen, "true" markiert sind sie gleichermaßen brauchbar. Letztere wurden vom "forced slaving" notfalls vorher gesichert. Ist eine geeignete Stelle gefunden, wird SV.BTPNT auf $54(sb) aktualisiert. Dabei darf das wie jede Speicherreservierung nur aus einer Scheduler-Routine oder einem Access-Layer-Aufruf heraus geschehen.
SV.BTPNT $54(sb) Ptr auf den Tabellenplatz des jüngsten Slave Blocks SV.BTBAS $58(sb) Ptr auf die Tabellenbasis SV.BTTOP $5C(sb) Ptr auf das Tabellenende
Eine Eintragung besteht aus acht Bytes.
Die Verwendung für Microdrives sieht folgendermaßen aus:
BT.STAT 0 .b Laufwerks-ID und Zugriffscode BT.PRIOR 1 .b frei für besondere Algorithmen BT.SECTR 2 .w pysischer Sector im Datenträger ( * 2 ) BT.FILNR 4 .w Filenummer BT.BLOCK 6 .w Nummer des Blocks mit dem betr. Sector
Darin wird nur BT.STAT vom System tatsächlich und nicht nur für die Microdrives benutzt. Ein Zugriffscode steht in den niederwertigen 4 Bits und die Laufwerks-Kennzahl im höherwertigen Teil.Die Codes für den (Block-)Status bedeuten:
00 Nicht für das FSS verfügbar 01 leerer Block des FSS x3 "true block" - repräsentiert gültige Daten der wirklichen Datei x7 Block aktualisiert, steht zum Schreiben an x9 Leseoperation wird erwartet $xB Verifikation (Kontrolle auf Richtigkeit) wird erwartet
Für den ursprünglichen FLP-Handler im QL gilt {15}:
BT.STAT 0 .b Block-Status BT.PRIOR 1 .b Priorität BT.SECTR 2 .w FS-Sector-Nummer BT.FILNR 4 .w Filenummer BT.BLOCK 6 .w Nummer des FS-Blocks mit dem betr. Sector
mit den Statusbits:
0 Block des FSS 1 Block gültig 2 Schreibanforderung 3 Leseanforderung
und im erweiterten (LV2) Handler {15}:
BT.STAT 0 .b Block-Status BT.PRIOR 1 .b Nummer des physischen FS-Sectors BT.SECTR 2 .w Nummer des physischen FS-Blocks BT.FILNR 4 .w Filenummer BT.BLOCK 6 .w Nummer des FS-Blocks mit dem betr. Sector
Beim Sichern der Filedaten muß der Inhalt der Slave Blöcke nicht sofort gesendet werden. Das kann bei der nächsten Gelegenheit erfolgen, wird darum einer Task übertragen, die bei Bedarf die eigentliche Datenübertragung nach Maßgabe der verfügbaren Zeit abwickelt. Spätestens aber dann ist das umgehend zu erledigen, wenn der zugehörige Speicher anderweitig reklamiert wird. Das "forced slaving" wird aufgerufen und veranlaßt die Umwandlung sonst noch markierter Blöcke in "true" Typen. Von der Speicherverwaltung kommt die entsprechende Anforderung, solange wiederholt, bis alle Blöcke gesichert sind.Besonders zum "forced slaving" müssen passende Teile im Handler definiert worden sein. Deren Adresse steht für den bedarfsweise automatisch erfolgenden Aufruf an der Stelle CH.SLAVE im Link Block.
Die betreffende Routine erhält in
A1 Ptr auf den auslösenden Slave BlockFrei verwendbar sind nur D0 - D3 und A0 - A2.
A2 Physischer Definitionsblock
A3 Basisadresse des Handlers
A6 Basis der Systemvariablen
Fehlercodes brauchen nicht zurückgegeben zu werden.Die relevanten Adressen sind
SV.BTPNT $54(sb) Ptr auf den Tabellenplatz des jüngsten Slave Blocks SV.BTBAS $58(sb) Ptr auf die Tabellenbasis SV.BTTOP $5C(sb) Ptr auf Tabellenende SV.FREE $0C(sb) Untergrenze des "freien" Speichers SV.BASIC $10(sb) Beginn des Basic-Bereiches
Zwische SV.FREE und SV.BASIC werden die Slave Blöcke eingerichtet.
So kann etwa die Adresse des jüngsten Slave Blocks ermittelt werden:Nun steht die Adresse des Slave Blocks in D0.
move.l $54(sb),d0 sv.btpnt Tabellenplatz sub.l $58(sb),d0 sv.btbas damit Index aus Tabellenbasis lsl.l #6,d0 daraus Stufung zu 512 Bytes add.l a6,d0 Offset und Systemvariablenbasis
3.5.4 * Standard-Definitionen
Die in System vordefinierten Directory Device Handler sindAlle I/O-Traps und die zur Steuerung des Datenverkehrs mit Files eingerichteten Aufrufe sind verfügbar. Ausgenommen ist IO.EDLIN.
- MDV bis zu acht Laufwerke
- FLP TK je nach Version bis zu vier Laufwerke physisch adressierbar.
- RAM TK bis zu 8 Laufwerke.
Speziell und nur für die Microdrives gibt es dazu noch einige Vectoren, alle mit Offset $4000 aufzurufen:
MD.READ $0124 Einen Sector lesen MD.WRITE $0126 Einen Sector schreiben MD.VERIN $0128 Einen Sector vergleichen MD.SECTR $012A Sector-Header lesen
Adressierung erfolgt in der Art
move.w $0124,a2 jsr $4000(a2) Die besonderen Modalitäten für MDV und FLP stehen bei den Übertragungsprotokollen.