zurück : weiter : inhalt =

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:
  1. Directory Handler Linkage Block - Handler-Verkettung
  2. Pysical Definition Block (pdb) - Physische Daten
  3. Channel Definition Block - Definitonsblock
Zu 1. Directory Handler Linkage

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 enthalten

D0 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 Stackptr

Rü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-Routine

Das 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)

 
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
 
I/O-Routinen

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 - pdb

Dieser 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 Laufwerksnummer
A1 Ptr auf den Namen des Mediums
Bei Rückkehr sind zu übergeben
D0 Fehlercode
    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 Sectoren
Register D3 - D7 und A0 - A5 sind frei verwendbar.

Nach {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 .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 .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 .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 Block
A2 Physischer Definitionsblock
A3 Basisadresse des Handlers
A6 Basis der Systemvariablen
Frei verwendbar sind nur D0 - D3 und A0 - A2.
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:

 
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
 
Nun steht die Adresse des Slave Blocks in D0.
 

3.5.4 * Standard-Definitionen

Die in System vordefinierten Directory Device Handler sind Alle I/O-Traps und die zur Steuerung des Datenverkehrs mit Files eingerichteten Aufrufe sind verfügbar. Ausgenommen ist IO.EDLIN.

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.
 

  

oben : zurück : weiter : inhalt 

(count)