HomeMagiCDas DFS-Konzept von MagiCVFAT-XFS in MagiC

11.21 Das XFS-Konzept von MagiC

MagiC ermöglicht wie MultiTOS die Einbindung alternativer Dateisysteme, und damit prinzipiell die Verwendung langer Dateinamen. Aus verschiedenen Gründen wurde in MagiC jedoch ein anderer Ansatz gewählt, als in Atari's Lösung. Dies hat leider zur Folge, daß die für MultiTOS vorhandenen XFS's (Minix-XFS, CD-ROM-XFS, ...) unter MagiC nicht eingesetzt werden können. Dieses Kapitel beschreibt die folgenden Punkte:

Querverweis: VFAT-XFS in MagiC   DFS-Konzept in MagiC

11.21.1 Allgemeines zum XFS-Konzept von MagiC

Das GEMDOS war bisher der konservativste Teil des Betriebssystems MagiC. Für Netzwerktreiber mußten praktisch sämtliche DOS-Aufrufe einschließlich Pexec nachgebildet werden, ohne auf einer tieferen Ebene eingreifen zu können. In MagiC 1.x (wie in TOS) war das DOS nicht einmal reentrant, da ein statisch angelegter Stack verwendet wurde.

In MultiTOS/MiNT wird das Problem dermaßen umgangen, daß gewissermaßen über das GEMDOS ein System gelegt wird, das alle höheren Verwaltungsaufgaben erledigt, andere Dateisysteme einbinden kann und das GEMDOS nur noch als dummen Dateisystemtreiber verwendet. Vorteil dieses Systems ist seine große Flexibilität und Erweiterbarkeit, ein entscheidender Nachteil aber der gewaltive Overhead bei der Verwendung von 'normalen' DOS-Dateisystemen. Dies sind aber gerade diejenigen, die mit Abstand am häufigsten eingesetzt werden. Hinzu kommt, daß das GEMDOS-Dateisystem mit dem Einsatz von MiNT nichts an Funktionalität, Komfort oder Geschwindigkeit gewinnen kann, da ja die alten Routinen nur mit zusätzlichem Overhead ablaufen. Die Dateisystemzugriffe unter MiNT sind also i.a. nicht reentrant, d.h. jeder Diskettenzugriff legt wie unter MS-Windows den gesamten Rechner lahm.

Eine weitere Eigenschaft von MiNT ist das Bemühen, die Funktionen, die alle Dateisysteme gemeinsam haben, in den Kernel zu übernehmen. Dabei bleiben zwar die Dateisystemtreiber (MiNT-XFSs) kompakt, aber durch den Inode-orientierten Aufbau der Kernelfunktionen wird den Dateitreibern eine unter Umständen ungünstige Struktur aufgezwungen, außerdem sind i.a. viele Aufrufe des Dateisystemtreibers für einen DOS-Aufruf notwendig. Schließlich ist der MiNT-Kernel selbst sehr lang, liegt aber zum großen Teil brach, solange keine anderen Dateisysteme als DOS eingesetzt werden.

Unter MagiC wurde ein anderer Ansatz gewählt, der darin bestand, das gesamte GEMDOS einschließlich der Lowlevel-Funktionen für die Sektorpufferung von Grund auf neu zu schreiben und in insgesamt drei, vier oder fünf Schichten zu zerlegen, in die von außen (durch nachgeladene Treiber) eingegriffen werden kann. Als Nebeneffekt kam eine Erweiterung der Funktionalität des DOS-Dateisystems und ein zusätzliches Dateisystem auf dem logischen Laufwerk U: heraus.

Das gesamte Konzept einschließlich der Zugriffe auf DOS-Dateisysteme ist reentrant und läuft im Hintergrund ab. So ist es möglich, auf Laufwerk A: Dateien zu bearbeiten, ohne den Rechner bei den Diskettenzugriffen merklich zu bremsen. Dabei ist MagiC bisher nur um 10k länger geworden. Im Vergleich zu MiNT wurden aber mehr Funktionen in die Dateisystemtreiber ausgelagert, was diese zwar länger macht, aber ihnen die Möglichkeit gibt, die Funktionen wesentlich effizienter auszuführen. Das DOS-Dateisystem ist eher noch etwas schneller als langsamer geworden.

Obwohl vollständig in Assembler realisiert, handelt es sich um ein objektorientiertes System mit virtuellen Funktionen und mehrstufigen Vererbungen. Ein Dateideskriptor, wie ihn der Kernel verwendet und das XFS zur Verfügung stellt, ist ein Objekt mit speziellen Daten und Funktionen. Das XFS realisiert aber ein abgeleitetes Objekt mit weiteren Datenfeldern und Funktionen. Der DFS-Untertreiber des DOS_XFS schließlich muß wiederum weitere Funktionen und Daten im FD unterbringen und leitet die Klasse weiter ab. Genauso sieht es mit dem DMD (drive medium descriptor) aus. Der Kernel benötigt nur wenige Angaben, die unteren Schichten jedoch wesentlich mehr, aber immer wieder verschiedene.

Die Schichten im einzelnen:

  1. Der DOS-Kernel. Er liegt in MagiC selbst und wird direkt von den Anwenderprogrammen über Trap #1 aufgerufen. Er enthält Module für die Speicherverwaltung, für die Prozeßverwaltung und für die Dateiverwaltung. Letztere hat die folgenden Unterschichten.
  2. Das Dateisystem (XFS = eXtended File System). Sein Aufbau ist grundsätzlich verschieden von einem MiNT-XFS, erfüllt aber denselben Zweck. MagiC für Ataris enthält nur ein einziges XFS, das sogenannte DOS_XFS, andere können eingebunden werden. Die Macintosh-Version (MagiC Mac) enthält zusätzlich ein Mac-XFS. Speziell dieses Dateisystem greift wieder auf Untertreiber zu:
    1. Ein DOS- Dateisystem (DFS) wird vom DOS_XFS aufgerufen. Hier stehen nur die Dateifunktionen, während die Verzeichnisverwaltung im wesentlichen vom DOS_XFS übernommen wird. MagiC direkt enthält zwei DFSs. Eines für Laufwerk U:, ein zweites für FAT-Dateisysteme, die auf BIOS Laufwerken liegen. Weitere DFSs können eingebunden werden. Der Aufwand für ein DFS ist wesentlich geringer als für ein XFS, da viele Funktionen vom DOS_XFS bereits ausgeführt werden. Die wesentliche Voraussetzung ist eine DOS-konforme Verzeichnisstruktur (mit 32-Byte Einträgen und Dateinamen des Formats 8+3). Der Kernel selbst kommt mit dem DFS nicht in Berührung, sondern steuert ihn transparent über das DOS-XFS an.
  3. Die Dateitreiber (MX_DEV), die im wesentlichen das Lesen und Schreiben einer Datei erledigen. Sie werden vom XFS angelegt und verwaltet, aber bei Funktionen wie Fread() und Fwrite() direkt vom Kernel aufgerufen, wodurch extrem wenig Overhead entsteht. Das DOS_XFS enthält tatsächlich nur einen Dateitreiber. Dieser erledigt z.B. bei Schreibzugriffen die Aktualisierung des Verzeichnisses und ruft wieder Untertreiber (MX_DDEV) auf.
    1. Der Untertreiber MX_DDEV wird nur vom DOS-Dateitreiber des Dateisystems DOS_XFS aufgerufen. Der Benutzer kann eigene MX_DDEVs über das Verzeichnis U:\\DEV einbinden. Der Kernel selbst kommt mit den Untertreibern übrigens nicht in Berührung.

Bemerkungen:

Querverweis: XFS-Konzept in MagiC   Test auf Pipes

11.21.2 Der Aufbau eines XFS

Da die Implementation eines XFS nur in Assembler erfolgen kann, wird dessen Beschreibung in Assembler-Syntax angegeben:

xfs_name:       DS.B      8    /* Name des Dateisystems               */
xfs_next:       DS.L      1    /* nächster Treiber                    */
xfs_flags:      DS.L      1    /* Flags analog zu MiNT                */
xfs_init:       DS.L      1    /* Initialisierung                     */
xfs_sync:       DS.L      1    /* Synchronisation des Dateisystems    */
xfs_pterm:      DS.L      1    /* teilt ein Programmende mit          */
xfs_garbcoll:   DS.L      1    /* Garbage-Collection oder NULL        */
xfs_freeDD:     DS.L      1    /* DD freigeben                        */
xfs_drv_open:   DS.L      1    /* DMD (Mediach) testen/initialisieren */
xfs_drv_close:  DS.L      1    /* erzwingt einen Disk-Wechsel         */
xfs_path2DD:    DS.L      1    /* gibt einen DD zum Pfadnamen zurück  */
xfs_sfirst:     DS.L      1    /* sucht die erste passende Datei      */
xfs_snext:      DS.L      1    /* sucht die nächste passende Datei    */
xfs_fopen:      DS.L      1    /* öffnet oder erstellt eine Datei     */
xfs_fdelete:    DS.L      1    /* löscht eine Datei                   */
xfs_link:       DS.L      1    /* für Frename und Flink benötigt      */
xfs_xattr:      DS.L      1    /* für Fxattr benötigt                 */
xfs_attrib:     DS.L      1    /* für Fattrib benötigt                */
xfs_chown:      DS.L      1    /* für Fchown benötigt                 */
xfs_chmod:      DS.L      1    /* für Fchmod benötigt                 */
xfs_dcreate:    DS.L      1    /* erstellt ein Verzeichnis            */
xfs_ddelete:    DS.L      1    /* löscht ein Verzeichnis              */
xfs_DD2name:    DS.L      1    /* gibt den absoluten Pfadnamen zurück */
xfs_dopendir:   DS.L      1    /* öffnet ein Verzeichnis              */
xfs_dreaddir:   DS.L      1    /* liest nächsten Verzeichnis-Eintrag  */
xfs_drewinddir: DS.L      1    /* setzt das dirhandle auf 1. Eintrag  */
xfs_dclosedir:  DS.L      1    /* schließt das dirhandle              */
xfs_dpathconf:  DS.L      1    /* ermittelt verschiedene Limits       */
xfs_dfree:      DS.L      1    /* Anzahl freier Blöcke etc. ermitteln */
xfs_wlabel:     DS.L      1    /* schreibt den Disk-Namen             */
xfs_rlabel:     DS.L      1    /* liest den Disk-Namen                */
xfs_symlink:    DS.L      1    /* erstellt einen symbolischen Link    */
xfs_readlink:   DS.L      1    /* liest einen symbolischen Link       */
xfs_dcntl:      DS.L      1    /* für Dcntl benötigt                  */

Querverweis: Aufbau eines DFS   XFS-Konzept in MagiC

11.21.2.1 xfs_attrib

Name: »xfs_attrib« - für Fattrib notwendig
Parameter:
a0 = DD *
a1 = char *name
d0 = int rwflag
d1 = int attrib
-> d0 = char attr oder long errcode
-> a0 = SYMLINK *
Beschreibung: Im Gegensatz zu MiNT führt MagiC diese Funktion nicht auf Fxattr zurück, weil dies u.U. einen gewaltigen Overhead bedeutet. Hierbei müssen symbolische Links verfolgt werden, d.h. die Rückgabe von ELINK ist zulässig.

Diese Funktion wird vom XFS_DOS noch nicht ordentlich durchführt, es werden keine symbolischen Links erkannt.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Fattrib   Fxattr

11.21.2.2 xfs_chmod

Name: »xfs_chmod« - für Fchmod notwendig
Parameter:
a0 = DD *
a1 = char *name
d0 = int mode
-> d0 = long errcode
Beschreibung: Ändert die Zugriffsrechte einer Datei. Die Parameter entsprechen denen von Fchmod. Symbolische Links werden nicht verfolgt.

Wird vom XFS_DOS nicht unterstützt.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Fchmod

11.21.2.3 xfs_chown

Name: »xfs_chown« - für Fchown notwendig.
Parameter:
a0 = DD *
a1 = char *name
d0 = uid
d1 = gid
-> d0 = long errcode
Beschreibung: Ändert den Eigner (User-ID und Group-ID) einer Datei. Die Parameter entsprechen denen von Fchown. Symbolische Links werden nicht verfolgt, d.h. Eigner und Gruppe des symbolischen Links werden modifiziert.

Wird vom XFS_DOS nicht unterstützt.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Fchown

11.21.2.4 xfs_dclosedir

Name: »xfs_dclosedir« - schließt ein Verzeichnis
Parameter:
a0 = DHD *dhd
-> d0 = long errcode
Beschreibung: Analog zu MiNT.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Dclosedir

11.21.2.5 xfs_dcntl

Name: »xfs_dcntl« - für Dcntl notwendig.
Parameter:
a0 = DD *
a1 = char *name
d0 = int cmd
d1 = long arg
-> d0 = long errcode
Beschreibung: Für Dcntl. Jedes XFS sollte FUTIME unterstützen.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.6 xfs_dcreate

Name: »xfs_dcreate« - erstellt ein Verzeichnis
Parameter:
a0 = DD *
a1 = char *name (ohne Pfad)
-> d0 = long errcode
Beschreibung: Für Dcreate benötigt.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Dcreate

11.21.2.7 xfs_ddelete

Name: »xfs_ddelete« - löscht ein Verzeichnis
Parameter:
a0 = DD *
-> d0 = long errcode
Beschreibung: Diese Funktion musste ab MagiC Version 4.01 geändert werden. Für MagiC < 4.01 (Kernelversion < 3) gilt:

Beim Löschen ist darauf zu achten, daß kein Verzeichnis durch den Kernel referenziert sein darf außer durch den Aufruf selbst (d.h. es muß dd_refcnt == 1 sein). Außerdem ist darauf zu achten, daß keine Dateien im Verzeichnis liegen. ELINK darf nicht zurückgegeben werden, symbolische Links dürfen nicht behandelt werden. Die Zugriffsberechtigung muß (falls eine existiert) vom XFS geprüft werden.

Für MagiC < 4.01 (Kernelversion >= 3) gilt:

Wegen Reentranzproblematiken ergeben sich einigen Änderungen, wobei der Kernel dem XFS Zugriffskontrollen abnimmt und weiterhin der Kernel den DD freigibt, nicht das XFS: Der Kernel öffnet zunächst mit xfs_path2DD den Parent des zu löschenden Verzeichnisses, dann testet er mit xfs_xattr, ob es sich um einen Symlink handelt, und löscht ihn ggf. per xfs_fdelete.

Handelt es sich um ein Verzeichnis, öffnet der Kernel dieses wieder per xfs_path2DD (Modus 1) und gibt den Parent wieder per xfs_freeDD frei. Die Überprüfung von dd_refcnt wird vom Kernel durchgeführt, der Zähler kann und muß daher vom XFS ignoriert werden. Das XFS muß nun sicherstellen, daß das zu löschende Verzeichnis bzw. der DD nicht anderweitig geöffnet oder benutzt werden können (wichtig für reentrante XFSs). Das XFS löscht dann das Verzeichnis, gibt aber den DD nicht (!) frei, damit der Kernel im Erfolgsfall (Rückgabe E_OK) vorher seine Standardpfade freigeben kann. Der Kernel ruft dann xfs_freeDD auf. Wie gehabt, muß das XFS prüfen, ob das Verzeichnis leer ist, bzw. Zugriffsberechtigungen existieren.

Nochmal im Zusammenhang:
  • Kernel ermittelt zu löschenden DD, prüft Referenzzähler.

  • xfs_ddelete sperrt den DD. Wenn das nicht geht, wird EACCDN geliefert.

  • xfs_ddelete löscht das Verzeichnis, wenn es leer ist. Der DD wirkt dabei als Sperre für parallel laufende Versuche, das gerade gelöschte Verzeichnis zu benutzen.

  • xfs_ddelete läßt den jetzt ungültigen, aber noch als Sperre dienenden DD weiterhin gültig (im Gegensatz zum alten Konzept).

  • Der Kernel macht bei Erfolg seine Standardpfade ungültig.

  • Der Kernel gibt den DD frei.

Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Ddelete

11.21.2.8 xfs_dfree

Name: »xfs_dfree« - Anzahl freier Blöcke ermitteln.
Parameter:
a0 = DD *
a1 = long[4]
-> d0 = long errcode
Beschreibung: Für Dfree. XFS_DOS ruft direkt den zuständigen DFS-Treiber auf.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Dfree

11.21.2.9 xfs_DD2name

Name: »xfs_DD2name« - gibt den absoluten Pfadnamen zurück.
Parameter:
a0 = DD *
a1 = char *name
d0 = int bufsize
-> d0 = long errcode
Beschreibung: Für Dgetpath und Dgetcwd. Nach wird der Pfad kopiert der zum übergebenen Verzeichnis gehört. Der Pfad muß ohne folgenden '\' zurückgegeben werden, d.h. ein Leerstring für das Wurzelverzeichnis. versteht sich, wie überall, inklusive abschließendes Nullbyte. Wenn der Puffer zu klein ist (bufsize kleiner als der Pfad), muß wie in MiNT ERANGE zurückgegeben werden.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.10 xfs_dopendir

Name: »xfs_dopendir« - öffnet ein Verzeichnis
Parameter:
a0 = DD *
d0 = int tosflag
-> d0 = DHD *dhd oder Fehlercode
Beschreibung: Für Dopendir. Als sind z.Zt. nur 0 und 1 erlaubt. Ist == 0, werden Dateinamen nicht abgeschnitten, und die ersten 4 Bytes, die von D(x)readdir zurückgegeben werden, enthalten den Datei-Index.

Ist == 1, muß dreaddir die Dateinamen auf 8+3 und Großschrift kürzen und darf keine Dateikennung zurückgeben.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Dopendir   Dreaddir   Dxreaddir

11.21.2.11 xfs_dpathconf

Name: »xfs_dpathconf« - ermittelt verschiedene Limits
Parameter:
a0 = DD *
d0 = int which
-> d0 = long value
Beschreibung: Wie in MiNT. XFS_DOS ruft direkt den zuständigen DFS-Treiber auf. kann folgende Werte annehmen:
DP_MAXREQ (-1) ermittle max. gültigen Wert für
DP_IOPEN (0) internes Limit für Anzahl offener Dateien
DP_MAXLINKS (1) maximale Anzahl Links für eine Datei
DP_PATHMAX (2) maximale Länge für vollen Pfadnamen
DP_NAMEMAX (3) maximale Länge für Dateinamen
DP_ATOMIC (4) Blockgröße
DP_TRUNC (5) Dateinamen-Verkürzung liefert:
DP_NOTRUNC (0) nie kürzen, ggf. ERANGE
DP_AUTOTRUNC (1) auf max. Länge gekürzt
DP_DOSTRUNC (2) Verkürzung auf 8+3
DP_CASE (6) Groß-/Kleinschreibung liefert:
DP_CASESENS (0) unterschieden
DP_CASECONV (1) in Großschrift gewandelt
DP_CASEINSENS (2) nicht unterschieden und nicht gewandelt


Ab der MagiC Version vom 21.5.95 wird weiterhin unterstützt:
DP_MODEATTR (7) (vgl. Dpathconf)
DP_XATTRFIELDS (8) (vgl. Dpathconf)
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Dpathconf

11.21.2.12 xfs_dreaddir

Name: »xfs_dreaddir« - liest nächsten Verzeichniseintrag
Parameter:
a0 = DHD *dhd
d0 = int size
a1 = char *buf
d1 = XATTR *xattr oder NULL
d2 = long *xr (wenn xattr != NULL)
-> d0 = long errcode
Beschreibung: Wie in MiNT. Übernimmt sowohl Dreaddir als auch Dxreaddir.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.13 xfs_drewinddir

Name: »xfs_drewinddir« - Directory Handle auf 1. Eintrag setzen.
Parameter:
a0 = DHD * dhd
-> d0 = long errcode
Beschreibung:Wie in MiNT.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC   Drewinddir

11.21.2.14 xfs_drv_close

Name: »xfs_drv_close« - erzwingt einen Diskwechsel.
Parameter:
a0 = DMD *
d0 = int mode
-> d0 = long errcode
Beschreibung: Auch diese Funktion erfüllt, abhängig vom , zwei Aufgaben:

  1. mode = 0:
    Der Kernel bittet das XFS, das Laufwerk, wenn möglich, zu schließen. Wenn dies nicht erlaubt ist, muß EACCDN geliefert werden, sonst sind alle Strukturen freizugeben bzw. Caches zurückzuschreiben und E_OK als Rückgabewert zu liefern.

    Geöffnete Dateien werden bereits vom Kernel erkannt und das Schließen verhindert. Dabei können aber nur solche Dateien erkannt werden, die ein Handle haben und dem Kernel bekannt sind. Der Kernel ruft sicherheitshalber vor Aufruf dieser Funktion xfs_sync auf, falls ein Write-Back-Cache verwendet wird. Diese Vorgehensweise wird auch dann durchgeführt, wenn einmal ein Mechanismus eingebaut wird, der den Auswurfknopf von Wechselplattenlaufwerken oder CD-ROM abfragt und ggf. den Auswurf verweigert.

  2. mode = 1:
    Der Kernel erzwingt das Schließen, das XFS muß E_OK liefern. Es dürfen keine Caches zurückgeschrieben werden, da das Laufwerk bereits ungültig ist (nachdem ein Diskwechsel bereits gemeldet wurde). DDs und FDs brauchen nicht freigegeben zu werden, soweit sie vom Kernel noch referenziert werden, d.h. der Kernel führt auch nach dem Diskwechsel noch xfs_freeDD bzw. dev_close aus.



Das interne DOS_XFS leitet den Aufruf an die gleichnamige Funktion des DFS weiter, außerdem werden ggf. XFS-Strukturen freigegeben.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.15 xfs_drv_open

Name: »xfs_drv_open« - DMD (Mediach) testen/initialisieren.
Parameter:
a0 = DMD *
-> d0 = long errcode
Beschreibung: MagiC unterstützt genau 26 gleichzeitig aktive Dateisysteme denen die Buchstaben 'A'..'Z' zugeordnet sind. Dieser Eintrag hat zwei Aufgaben:

  1. Beim ersten Zugriff auf ein Laufwerk (etwa D:) legt der Kernel einen DMD (drive media descriptor) an und "bietet" diesen den XFSs an. Der Eintrag d_xfs ist noch ein Nullzeiger, d_drive ist initialisiert (zwischen 0 und 25, entsprechend 'A'..'Z').

    Die XFS-Treiber versuchen nun, auf dem Laufwerk "ihr" Dateisystem zu erkennen. Falls dies gelingt, müssen d_xfs und d_root initialisiert werden, der Rückgabewert ist dann E_OK. Andernfalls wird EDRIVE gemeldet, und der Kernel probiert das nächste XFS.

    Achtung: Die root darf während der Lebensdauer eines gemounteten Dateisystems nicht freigegeben werden. Der Referenzzähler der root sollte mit 1 vorbesetzt werden, um zu verhindern, daß er per free_DD freigegeben wird. In den Versionen vor MagiC 4.01 war dies nicht notwendig, weil der Referenzzähler (in unsauberer Weise) vor dem Aufruf von path2DD nicht inkrementiert und nachher dekrementier wurde.

  2. Beim wiederholten Zugriff ist d_xfs bereits initialisiert, und das XFS hat die Gelegenheit, auf Mediumwechsel zu testen. Ist alles in Ordnung, muß E_OK zurückgegeben werden. Ansonsten muß die Diskwechselroutine des Kernels aufgerufen und E_CHNG zurückgegeben werden. Den Zeiger auf die Diskwechselroutine des Kernels erhält man bei der Installation des XFS.



Das interne DOS_XFS leitet den Aufruf an die gleichnamige Funktion des DFS weiter, d.h. alle DFS-Treiber werden durchprobiert.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.16 xfs_fdelete

Name: »xfs_fdelete« - löscht eine Datei.
Parameter:
a0 = DD *
a1 = char *name (ohne Pfad)
-> d0 = long errcode
Beschreibung: Für Fdelete. Beim Löschen eines Symlinks darf nur dieser gelöscht werden, nicht etwa eine referenzierte Datei. D.h. der Rückgabewert ELINK ist hier _UNZULÄSSIG_.

Zugriffsrecht-Überprüfungen obliegen vollständig dem XFS. Beim Löschen ist darauf zu achten, daß keine Datei durch den Kernel referenziert sein darf (d.h. fd_refcnt != 0).
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.17 xfs_flags

Name: »xfs_flags« - Flags analog zu MiNT
Parameter:
Beschreibung: Reserviert. Sollte eigentlich Flags enthalten. Wird jedoch vom MagiC Kernel nicht verwendet. Also bitte nicht verwenden!
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.18 xfs_fopen

Name: »xfs_fopen« - öffnet oder erstellt eine Datei.
Parameter:
a0 = DD *
a1 = char *name (ohne Pfad)
d0 = int omode (fürs Öffnen)
d1 = int attrib (fürs Erstellen)
-> d0 = FD * oder Fehlercode
-> a0 = SYMLINK *
Beschreibung: Wird für die Funktionen Fopen und Fcreate verwendet. Der Open-Modus ist im niederwertigen Byte anders als in MiNT, weil die MiNT-Modi für die Implementierung der Abfragen ungünstig sind. Beim Aufrufen von Fopen über Trap #1 werden die MiNT-Modi vom Kernel in die internen Modi konvertiert. Hier die internen Modi, die vom XFS-Treiber bearbeitet werden müssen (NOINHERIT wird nicht unterstützt, weil nach TOS-Konvention nur die Handles 0..5 vererbt werden). Ansonsten entspricht das HiByte den MiNT-Konventionen:
OM_RPERM   EQU  1   // Datei ist zum Lesen geöffnet
OM_WPERM   EQU  2   // Datei ist zum Schreiben geöffnet
OM_EXEC    EQU  4   // Datei ist zum Ausführen geöffnet
OM_APPEND  EQU  8   // Schreibzugriffe ans Ende (Kernel!)
OM_RDENY   EQU  16  // andere dürfen nicht gleichz. lesen
OM_WDENY   EQU  32  // "" "" nicht gleichz. schreiben
OM_NOCHECK EQU  64  // KEINE Überprüfung durch den Kernel


Das Bit OM_APPEND wird vom Kernel bei Aufruf von Fwrite() automatisch beachtet, der Kernel führt vor jedem Schreibzugriff ein Fseek() aus.

OM_NOCHECK wird vom Kernel gesetzt, wenn eine Datei als Device, d.h. als Handle -1,-2,-3 oder -4 geöffnet bzw. auf ein solches Handle umgelenkt (Fforce) wird. Ist dieses Bit gesetzt, sollte das XFS keine Prüfung auf mehrfaches Öffnen der Datei machen (siehe auch unten bei fd_mode), sondern dies dem Gerätetreiber überlassen.

Hier die Bits, die wie im MiNT verwendet werden:
O_CREAT EQU  $200 // Datei erstellen, falls nicht existiert
O_TRUNC EQU  $400 // Datei leeren, falls existiert
O_EXCL  EQU  $800 // nicht öffnen, falls existiert


Der Kernel führt Fcreate aus als Fopen (O_CREAT +O_RDWR + O_TRUNC). O_COMPAT (d.h. nur der TOS-Modus 0,1 oder 2 angegeben, ist in MagiC immer gleichbedeutend mit O_WDENY.

Die Überprüfung der Zugriffsrechte obliegt vollständig dem XFS, der Kernel tut nichts. Das wäre auch wenig sinnvoll, da jedes Dateisystem seine eigenen Mechanismen und Rechte hat. Zurückgegeben wird dem Kernel ein Zeiger auf einen geöffneten FD, d.h. das Öffnen des Dateitreibers muß vom XFS durchgeführt werden. Der Referenzzähler des zurückgegebenen FDs ist vom XFS zu erhöhen bzw. beim ersten Öffnen auf 1 zu initialisieren. Für symbolische Links und Diskwechsel gilt dasselbe wie bei xfs_sfirst.

Fopen wird unter MiNT folgendermaßen zurückgeführt:
  1. per Konvertierung pathname->fcookie
  2. per Ermittlung der Zugriffsrechte
  3. Test der Zugriffsrechte durch den Kernel
  4. per Ermittlung des Dateitreibers
  5. per open> Öffnen der Datei


Dieses Verfahren ist sehr langwierig. DOS gibt beim Suchen der Datei bereits einen Zeiger auf den 32-Byte-Verzeichniseintrag zurück, der direkt zum Überprüfen des Attributs und damit der Zugriffsrechte und auch zum Öffnen der Datei dient. MagiC erwartet daher direkt die Implementation des Fopen-Befehls mit allen Überprüfungen der Zugriffsrechte. Zurückgeliefert wird eine FD-Struktur, in die der Dateitreiber eingetragen und geöffnet wurde.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.19 xfs_freeDD

Name: »xfs_freeDD« - gibt einen DD frei.
Parameter:
a0 = DD *
-> void
Beschreibung: Der Kernel hat den Referenzzähler eines DD auf 0 dekrementiert, der DD wird also vom Kernel nicht mehr referenziert. Die Funktion wird z.B. aufgerufen, wenn der Kernel nach dem Fopen() den Pfad, in dem die geöffnete Datei liegt und der an xfs_fopen übergeben worden war, nicht mehr benötigt. XFSs, die keine garbage collection machen, können über diese Funktion ihre DDs freigeben.

Es muss sichergestellt werden, daß die root nie freigegeben wird. Entweder baut man hier eine spezielle Abfrage ein, oder (eleganter) setzt den Referenzzähler der root bei drv_open bereits auf 1.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.20 xfs_garbcoll

Name: »xfs_garbcoll« - Garbage Collection.
Parameter:
a0 = DMD *d
-> d0 = 1L oder 0L
Beschreibung: Der Kernel benötigt dringend internen GEMDOS-Speicher und macht eine Müllsammlung (garbage collection). Ein XFS, das die interne Speicherverwaltung des Kernels nicht verwendet, kann hier einen Nullpointer als Funktion eintragen.

Achtung: Es sollten möglichst soviele Blöcke wie möglich freigegeben werden, Rückgabe ist 1, wenn (mindestens) ein Block freigegeben werden konnte. Bei einer garbage collection durchläuft der Kernel die gesamte Liste aller angemeldeten logischen Laufwerke. Das XFS wird also so oft um eine garbage collect ersucht, wie es zu diesem Zeitpunkt Laufwerke verwaltet.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.21 xfs_init

Name: »xfs_init« - Initialisierung.
Parameter:
Beschreibung: Reserviert. Enthält im Fall MagiC interner XFSs deren Initialisierung. Wird bei nachgeladenen XFSs nicht verwendet.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.22 xfs_link

Name: »xfs_link« - für Frename und Flink notwendig.
Parameter:
a0 = DD *olddir
a1 = DD *newdir
d0 = char *oldname
d1 = char *newname
d2 = int flag_link
-> d0 = long errcode
Beschreibung: Wird sowohl für Frename (d2 = 0) als auch für Flink (d2 = 1) verwendet. Im Fall Frename ist ein neuer Verzeichniseintrag zu erstellen und der alte Eintrag (Verweis auf die Datei) zu löschen oder zu überschreiben.

Im Fall Flink wird ein weiterer Verweis auf dieselbe Datei angelegt und der alte Eintrag nicht gelöscht. Beide DDs liegen immer auf demselben Dateisystem, haben also denselben DMD. Wie bei Fdelete ist im Fall eines symbolischen Links dieser umzubenennen bzw. ein weiterer Link zu erstellen. D.h. der Rückgabewert ELINK ist hier (wie bei xfs_fdelete) _UNZULÄSSIG_.

Flinkwird vom DOS_XFS nicht unterstützt.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.23 xfs_name

Name: »xfs_name« - Name des Dateisystems
Parameter:
Beschreibung: Der Name ist bisher nur Kommentar; er soll irgendwann auch einmal die Möglichkeit bieten, festzustellen, welche Treiber installiert sind und wie z.B. der für Laufwerk A: zuständige Treiber heißt (d.h. was für ein Dateisystem die Diskette enthält).

Der Name des integrierten XFS lautet "DOS_XFS " (auf 8 Zeichen per Leerstellen erweitert).
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.24 xfs_next

Name: »xfs_next« - nächster Treiber.
Parameter:
Beschreibung: Ist einfach ein Verkettungszeiger auf den nächsten Treiber. Ein neuer Treiber wird vorn eingebunden, hat also immer höchste Priorität. Damit ist es z.B. möglich, den integrierten DOS-Treiber zu überladen.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.25 xfs_path2DD

Name: »xfs_path2DD« - gibt einen DD zum Pfadnamen zurück.
Parameter:
mode = 0: name ist Datei
= 1: name ist selbst Verzeichnis
d0 = int mode
a0 = DD *reldir akt. Verzeichnis
a1 = char *pathname
-> d0 = DD *
d1 = char *restpfad
oder  
-> d0 = ELINK
d1 = Restpfad ohne beginnenden '\'
a0 = FD des Pfades, in dem der symbolische Link liegt. Dies ist wichtig bei relativen Pfadangaben im Link.
a1 = NULL, Der Pfad stellt den Parent des Wurzelverzeichnisses dar.
oder  
a1 = Pfad des symbolischen Links
Beschreibung: Der Kernel unterscheidet zwischen zwei Typen von Deskriptoren, Dateideskriptoren FD, file descriptor) und Verzeichnisdeskriptoren (DD, directory descriptor), die aber im Aufbau identisch sein können. Diese Funktion liefert zu einem Pfad einen Deskriptor zurück. Der Referenzzähler des DD muß jedesmal, wenn er als Funktionswert zurückgeliefert wird, um 1 erhöht werden, weil er vom Kernel referenziert wird. Die Funktion path2DD entspricht einem "Öffnen" des Pfades, es wird eine Art "Dateihandle" dem Kernel zurückgegeben, das der Kernel wieder schließen muß. Das Parsen des Pfades muß immer vom XFS erledigt werden.

Eingabeparameter:
Legt fest, ob das letzte Pfadelement selbst ein Verzeichnis ist (mode == 1), oder ob der Pfad ermittelt werden soll, in dem diese Datei liegt.
Verzeichnis, von dem aus gesucht werden soll.
Der Pfadname, ohne Laufwerkbuchstaben und ohne führendes '\'.


Ausgabeparameter:

1. Fall: Es ist ein Fehler aufgetreten

enthält den Fehlercode

2. Fall: Ein Verzeichnisdeskriptor (DD) konnte ermittelt werden.
Zeiger auf den DD. Der Referenzzähler des DD wurde vom XFS um 1 erhöht.
Zeiger auf den restlichen Dateinamen ohne beginnenden '\' bzw. '/'. Wenn das Ende des Pfades erreicht wurde, zeigt dieser Zeiger auf das abschliessende Nullbyte.


3. Fall: Das XFS ist bei der Pfadauswertung auf einen symbolischen Link gestoßen
enthält den internen MagiC Fehlercode ELINK
Zeiger auf den restlichen Pfad ohne beginnenden '\' bzw. '/'
enthält den DD des Pfades, in dem der symbolische Link liegt. Der Referenzzähler des DD wurde vom XFS um 1 erhöht.
ist der Zeiger auf den Link selbst. Ein Link beginnt mit einem Wort (16 Bit) für die Länge des Pfads, gefolgt vom Pfad selbst.


Achtung: Die Länge muß INKLUSIVE abschließendes Nullbyte und außerdem gerade sein. Der Link muß auf einer geraden Speicheradresse liegen.

Der Puffer für den Link kann statisch oder auch flüchtig sein, da der Kernel die Daten sofort umkopiert, ohne daß zwischendurch ein Kontextwechsel stattfinden kann.

Wird a1 == NULL übergeben, wird dem Kernel signalisiert, daß der Parent des Wurzelverzeichnisses angewählt wurde. Befindet sich der Pfad etwa auf U:\A, kann der Kernel auf U:\ zurückgehen. Der Wert des Rückgaberegisters a0 wird vom Kernel ignoriert, es darf daher kein Referenzzähler erhöht werden.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.26 xfs_pterm

Name: »xfs_pterm« - teilt ein Programmende mit.
Parameter:
a0 = PD *
-> void
Beschreibung: Diese Funktion wird bei jedem Programmende aufgerufen und gibt dem XFS Gelegenheit, internen Strukturen freizugeben oder Locks zu entfernen. Die für den Kernel sichtbaren Dateien (d.h. die, denen ein Handle zugeordnet ist), werden vorher vom Kernel geschlossen. Die Referenzzähler für Standardverzeichnisse werden ebenfalls vorher durch den Kernel dekrementiert. Übergeben wird in a0 ein Zeiger auf einen Prozeß-Deskriptor.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.27 xfs_readlink

Name: »xfs_readlink« - liest einen symbolischen Link.
Parameter:
a0 = DD *
a1 = char *name
d0 = char *buf
d1 = int size
-> d0 = long errcode
Beschreibung: Für Freadlink. Wird vom DOS_XFS unterstützt.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.28 xfs_rlabel

Name: »xfs_rlabel« - liest den Disknamen.
Parameter:
a0 = DD *
a1 = char *name
d0 = char *buf
d1 = int len
-> d0 = long errcode
Beschreibung: Zum Lesen des Medien-Namens. Wird vom Kernel dann aufgerufen, wenn Fsfirst mit (Attribut == 8) durchgeführt wird. ist i.a. "*.*" und kann ignoriert werden. ist die Länge des Puffers , bei Überschreitung muß ERANGE geliefert werden. Wird auch für Dreadlabel() aufgerufen. In diesem Fall ist name == NULL.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.29 xfs_sfirst

Name: »xfs_sfirst« - sucht die erste passende Datei.
Parameter:
a0 = DD * srchdir
a1 = char *name (ohne Pfad)
d0 = DTA *
d1 = int attrib
-> d0 = long errcode
-> a0 = SYMLINK * (ggf. Symlink)
Beschreibung: Wird für Fsfirst benötigt. MiNT verwendet statt dieser Funktion eine Kombination von Dreaddir und Fxattr, wozu aber sehr viele Aufrufe des XFS-Treibers notwendig sind. Der reservierte Bereich der DTA kann vom XFS frei verwendet werden, falls dieser zu klein ist, muß mit ähnlichen heuristischen Methoden wie in MiNT vorgegangen werden, d.h. Zeiger in die DTA eingetragen werden, die auf fest angelegte Deskriptoren zeigen.

Diese Deskriptoren können aber nur nach heuristischen Methoden freigegeben werden, weil man nie weiß, ob noch ein Fsnext kommt oder nicht. Der Kernel ermittelt über path2DD bereits den vollständigen Pfad, so daß nur noch der reine Dateiname in a1 übergeben wird. Wie bei allen DOS-Aufrufen, die einen Pfad verarbeiten, muß das XFS darauf achten, daß der DD für die Dauer der Bearbeitung geschützt wird. Das ist besonders dann kritisch, wenn das Dateisystem reentrant ist.

Ist eine gesuchte Datei ein symbolischer Link, muß als Fehlercode in d0 ELINK und in a0 der Zeiger auf den Link übergeben werden. Der Kernel ruft dann einfach Fxattr auf, um die DTA zu füllen. Trat ein Diskwechsel auf, ist E_CHNG zurückzugeben, der Kernel wiederholt dann automatisch die Funktion. Das gilt auch für alle anderen Funktionen.

In jedem Fall muß dta_drive korrekt initialisiert werden, z.B. per: dta.dta_drive = srchdir->dd_dmd->d_drive. Wird E_OK oder ELINK zurückgegeben, ohne daß dta_drive initialisiert wurde, ist das Resultat unvorhersehbar!
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.30 xfs_snext

Name: »xfs_snext« - sucht die nächste passende Datei.
Parameter:
a0 = DTA *
a1 = DMD *
-> d0 = long errcode,
-> a0 = SYMLINK * (Symlink)
Beschreibung: Wird für Fsnext benötigt. Der Kernel hat aus der DTA bereits das zugehörige Dateisystem ermittelt, dessen DMD in a1 übergeben wird. Auch hier kann ein symbolischer Link auftreten.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.31 xfs_symlink

Name: »xfs_symlink« - erstellt einen symbolischen Link.
Parameter:
a0 = DD * dir
a1 = char *name
d0 = char *to
-> d0 = long errcode
Beschreibung: Für Fsymlink. Es muß unter dem neuen Namen eine Datei im Verzeichnis erstellt werden, die auf die Datei zeigt. Wird vom DOS_XFS unterstützt.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.32 xfs_sync

Name: »xfs_sync« - synchronisiert das Dateisystem.
Parameter:
a0 = DMD *d
-> long errcode
Beschreibung: Der Kernel teilt dem XFS mit, daß auf Laufwerk alle Puffer zurückzuschreiben sind. Übergeben wird in Register a0 ein Zeiger auf einen DMD (drive media descriptor). Dieser wird vom Kernel angelegt.

Zurückgeliefert wird ein Fehlercode. Wenn das XFS keine Pufferverwaltung hat (z.B. eine RAMDisk), muß eine 0 geliefert werden. Das interne DOS_XFS ruft einfach die gleichlautende DFS- Funktion auf.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.33 xfs_wlabel

Name: »xfs_wlabel« - schreibt den Disknamen.
Parameter:
a0 = DD *
a1 = char *name
-> d0 = long errcode
Beschreibung: Zum (Um-)Benennen von Medien. Wird vom Kernel dann aufgerufen, wenn Fcreate mit Attribut 8 durchgeführt werden. Wird der Diskname, wie beim DOS-Dateisystem, als spezielle Datei abgelegt, müssen alle anderen pfadbasierten XFS-Funktionen den Disknamen ignorieren.

Ein leerer Name oder ein aus "\xe5" bestehender (Kompatibilität zu TOS) muß den Disknamen löschen (falls Medien ohne Namen zulässig sind). Wird auch für Dwritelabel() aufgerufen.
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.2.34 xfs_xattr

Name: »xfs_xattr« - für Fxattr notwendig.
Parameter:
a0 = DD *
a1 = char *name
d0 = XATTR *
d1 = int mode
-> d0 = long errcode
-> a0 = SYMLINK *
Beschreibung: Wird für Fxattr verwendet. Im Fall mode == 0 (d.h. folge symbolischen Links) kann in d0 ELINK und in a0 ein Link zurückgegeben werden, andernfalls ist ELINK unzulässig.
mode == 0: folge symbolischen Links (gib ggf. ELINK zurück)
== 1: folge nicht (d.h. erstelle XATTR für den Link)
Gruppe: Aufbau eines XFS
Querverweis: XFS-Konzept in MagiC

11.21.3 Datenstrukturen für ein XFS

Bei der Arbeit mit einem XFS sind die folgenden Datenstrukturen wichtig:

DD (Verzeichnis-Deskriptor)
DHD (Directory-Handle-Deskriptor)
DMD (Medium-Deskriptor)
DTA (Disk-Transfer-Area)
FD (Datei-Deskriptor)
MX_DEV (Gerätetreiber)

Querverweis: DFS-Strukturen   XFS-Konzept in MagiC

11.21.3.1 Der Verzeichnis-Deskriptor (DD)

Die Verzeichnisdeskriptoren müssen vom XFS angelegt und verwaltet werden. Alle Deskriptoren, die dem Kernel bekannt sind (d.h. diejenigen, die für einen Prozeß als Standardpfad verwendet werden) haben Referenzzähler ungleich Null. Eine Ausnahme bildet nur der DD für das Wurzelverzeichnis eines Laufwerks; hier ist der Referenzzähler immer 0, egal ob ein Prozeß das Wurzelverzeichnis als Standardverzeichnis hat oder nicht.

Für den Kernel sieht ein DD folgendermaßen aus, diese Einträge müssen vom XFS angelegt werden:

dd_dmd:      DS.L      1    /* 0x00: Zeiger auf DMD               */
dd_refcnt:   DS.W      1    /* 0x04: Ref.zähler für Standardpfade */

Querverweis: XFS-Konzept in MagiC

11.21.3.1.1 dd_dmd

Hier steht das zugehörige Dateisystem.

11.21.3.1.2 dd_refcnt

Der Referenzzähler. Dieser Eintrag wird nur vom Kernel verwendet, muß vom XFS beim Erstellen eines DD auf 0 initialiert (bei der root am besten auf 1, s.o. bei xfs_drv_open) und bei jeder Übergabe an den Kernel (-> xfs_path2DD) um 1 inkrementiert werden.

D.h. daß xfs_path2DD beim Zurückgeben eines neuen DD (der also vom Kernel sonst nicht referenziert wird) den Referenzzähler auf 1 setzen muß.

Wenn der Referenzzähler ungleich 0 ist, hat der Kernel Zeiger auf diesen DD, und er darf keinesfalls vom XFS freigegeben werden. Der Kernel zählt den Referenzzähler jedesmal um 1 herunter, wenn er einen DD nicht mehr benötigt. Erreicht der Zähler dabei Null, wird xfs_freeDD aufgerufen. Das XFS kann dann den DD freigeben oder ansonsten erst beim Aufruf von xfs_garbcoll (der "garbage collection") oder bei xfs_drv_close.

Achtung: Die root darf während der Lebensdauer eines gemounteten Dateisystems nicht freigegeben werden. Der Referenzzähler der root sollte mit 1 vorbesetzt werden, um zu verhindern, daß er per free_DD freigegeben wird.

Querverweis: XFS-Konzept in MagiC   Datenstrukturen für ein XFS

11.21.3.2 Der Directory-Handle-Deskriptor (DHD)

Die Directory-Handles werden für Dopendir/Dclosedir/Drewinddir benötigt. Im Gegensatz zu den Dateideskriptoren (FD) hält der Kernel keine Liste der geöffneten DHs. Wenn ein Prozeß terminiert, wird das XFS über die Funktion xfs_pterm aufgerufen und muß alle für den Prozeß angelegten DHs freigeben.

Den Eigner eines DH kann das XFS über den Kernel-Zeiger ermitteln. Für den Kernel sieht ein DH folgendermaßen aus, diese Einträge müssen vom XFS angelegt werden:

dhd_dmd:  DS.L   1   /* 0x00: Zeiger auf DMD  */

Querverweis: XFS-Konzept in MagiC   DMD

11.21.3.2.1 dhd_dmd

Hier steht das zugehörige Dateisystem.

11.21.3.3 Der Drive-Medium-Deskriptor (DMD)

Der DMD wird vom Kernel (!) für jedes geöffnete Laufwerk angelegt und auch ggf. wieder freigegeben. Hier legt der XFS alle Daten an, die er sich für das Laufwerk merken muß. Die folgenden Felder sind diejenigen, die der Kernel benötigt (Das Ur- Objekt, von dem der XFS seinen XFS-DMD ableitet):

d_xfs:      DS.L   1    /* 0x00: Der Dateisystemtreiber           */
d_drive:    DS.W   1    /* 0x04: Laufwerknummer 0..25             */
d_root:     DS.L   1    /* 0x06: Zeiger auf DD der Root           */
d_biosdev:  DS.W   1    /* 0x0a: BIOS-Laufwerk oder -1            */
d_driver:   DS.L   1    /* 0x0c: def. zus. mit devcode das Medium */
d_devcode:  DS.L   1    /* 0x10: z.B. SCSI Target & Laufwerk      */
d_dfs:      DS.L   1    /* 0x14: DOS-spez. Dateisystem-Treiber    */

Andere XFSs oder DFSs tragen weitere Daten in den DMD ein. Man kann sich den DMD als eine Objektklasse vorstellen. Ein für das DOS_XFS abgeleiteter DMD hat nur den zusätzlichen Eintrag d_dfs. Der FAT-DFS trägt zusätzlich Daten wie die Clustergröße und die Anzahl der Sektoren ein.

Querverweis: XFS-Konzept in MagiC   DD

11.21.3.3.1 d_xfs

Hier steht der zugehörige Dateisystemtreiber (XFS). Er wird von xfs_drv_open eingetragen.

11.21.3.3.2 d_drive

Hier steht, welchem logischen Laufwerk ('A' .. 'Z') das Dateisystem zugeordnet ist. Das braucht nicht immer einem BIOS-Laufwerk zu entsprechen. Dieser Wert wird immer (!) vom Kernel eingetragen, wenn ein Laufwerk geöffnet wird, bevor ein XFS eingetragen wird.

11.21.3.3.3 d_root

Hier steht ein Zeiger auf den DD des Wurzelverzeichnisses.

11.21.3.3.4 d_biosdev

Wenn es sich um eine Partition handelt, die mit BIOS Rwabs behandelt wird, steht hier die BIOS-Gerätenummer. Ansonsten muß -1 eingetragen werden (z.B. bei Laufwerk U: oder einer Macintosh-Partition).

11.21.3.3.5 d_driver

Bestimmt zusammen mit d_devcode das Medium. D.h. wenn d_driver und d_devcode identisch sind, liegen beide Laufwerke auf demselben Medium. D.h. wenn das Medium ausgeworfen werden soll, müssen beide Dateisysteme gesperrt werden. Bei einer Harddisk-Partion ist d_biosdev das BIOS-Laufwerk, d_driver ist beliebig (z.B. Zeiger auf die XHDI-Struktur), d_devcode ist der XHDI-Code eines Mediums, d.h. SCSI-Target und Gerätenummer (jew. ein WORD).

11.21.3.3.6 d_devcode

Bestimmt zusammen mit d_driver das Medium. D.h. wenn d_driver und d_devcode identisch sind, liegen beide Laufwerke auf demselben Medium. D.h. wenn das Medium ausgeworfen werden soll, müssen beide Dateisysteme gesperrt werden. Bei einer Harddisk-Partion ist d_biosdev das BIOS-Laufwerk, d_driver ist beliebig (z.B. Zeiger auf die XHDI-Struktur), d_devcode ist der XHDI-Code eines Mediums, d.h. SCSI-Target und Gerätenummer (jew. ein WORD).

11.21.3.3.7 d_dfs

Dieser Eintrag existiert zwingend nur für DOS-Dateisysteme (also bereits für ein abgeleitetes Objekt) und enthält einen Zeiger auf den DFS-Untertreiber.

11.21.3.4 Die Disk-Transfer-Area DTA

Die DTA wird von den alten DOS-Funktionen Fsfirst und Fsnext verwendet, deren ungeschickte Konzeption durch die MSDOS-Schöpfer immer noch wie ein Fluch auf dem System lastet. Für den Kernel sieht die Struktur folgendermaßen aus:

dta_res1:        DS.B    20    /* 0x00: vom Kernel nicht benutzt */
dta_drive:       DS.B     1    /* 0x14: logisches Laufwerk       */
dta_attribute:   DS.B     1    /* 0x15: gefundenes Attribut      */
dta_time:        DS.W     1    /* 0x16: gefundene Zeit           */
dta_date:        DS.W     1    /* 0x18: gefundenes Datum         */
dta_len:         DS.L     1    /* 0x1a: gefundene Länge          */
dta_name:        DS.B    14    /* 0x1e: gefundener Dateiname     */

Hinweis: Die Komponenten dta_attribute bis dta_name stellen den dokumentierten User-Bereich dar; dieser muss nach GEMDOS-Spezifikation behandelt werden.

Querverweis: XFS-Konzept in MagiC

11.21.3.4.1 xfs_dta_res1

Wird vom Kernel nicht verwendet. Hier darf sich das XFS tummeln.

11.21.3.4.2 xfs_dta_drive

Hier steht das zugehörige logische Laufwerk (0 entspricht Laufwerk-A etc). Hierdurch kann der Kernel beim Fsnext entscheiden, welches XFS die Anforderung ausführen muss.

11.21.3.5 Der Datei-Deskriptor (FD)

Die Dateideskriptoren müssen vom XFS angelegt und verwaltet werden. Alle Deskriptoren, die dem Kernel bekannt sind, haben Referenzzähler ungleich Null. Für den Kernel sieht ein FD genauso aus wie ein DD, weshalb im DOS_XFS die gleiche Datenstruktur verwendet wird.

Für den Kernel sieht ein FD folgendermaßen aus, diese Einträge müssen vom XFS angelegt werden:

fd_dmd:      DS.L    1   /* 0x00: Zeiger auf DMD                       */
fd_refcnt:   DS.W    1   /* 0x04: Ref.zähler fürs Schließen oder -1    */
fd_mode:     DS.W    1   /* 0x06: Open- Modus und flags                */
fd_dev:      DS.L    1   /* 0x08: Zeiger auf MX_DEV                    */

Die vom DOS_XFS abgeleitete Klasse (ein "DOS-FD") hat darüber hinaus noch die zusätzlichen Felder:

fd_ddev:     DS.L    1    /* 0x0c: Zeiger auf MX_DDEV                  */
fd_name:     DS.B   11    /* 0x10: DD_FD: Name im internen Format      */
fd_attr:     DS.B    1    /* 0x1b: Attribut                            */
fd_owner:    DS.L    1    /* 0x1c: DD_FD: Eigner eines FD oder NULL    */
fd_parent:   DS.L    1    /* 0x20: Zeiger auf den Parent-DD_FD         */
fd_children: DS.L    1    /* 0x24: DD_FD: Liste aller Kinder           */
fd_next:     DS.L    1    /* 0x28: Zeiger auf FDs im selben Verzeichn. */
fd_multi:    DS.L    1    /* 0x2c: Zeiger auf FD derselben Datei       */
fd_multi1:   DS.L    1    /* 0x30: Zeiger auf erstes Listenelement     */
fd_fpos:     DS.L    1    /* 0x34: Position des Dateizeigers           */
fd_dirch:    DS.B    1    /* 0x38: Bit0: "dirty"                       */
fd_unused:   DS.B    1    /* 0x39:                                     */
fd_time:     DS.W    1    /* 0x3a: Zeit  (8086)                        */
fd_date:     DS.W    1    /* 0x3c: Datum (8086)                        */
fd_stcl:     DS.W    1    /* 0x3e: Start- Cluster                      */
fd_len:      DS.L    1    /* 0x40: Dateilänge in Bytes                 */
fd_dirpos:   DS.L    1    /* 0x44: Pos. des zug. Eintrags im Directory */
fd_user1:    DS.L    1    /* 0x48: zur freien Verfügung                */
fd_user2:    DS.L    1    /* 0x4c: zur freien Verfügung                */

Querverweis: XFS-Konzept in MagiC   DMD   MX_DDEV   MX_DEV

11.21.3.5.1 fd_dmd

Hier steht das zugehörige Dateisystem.

11.21.3.5.2 fd_refcnt

Der Referenzzähler. Dieser Eintrag wird nur vom Kernel verwendet, muß beim Aufruf von dev_close dekrementiert und durch xfs_fopen initialisiert werden (mit 1).

Ein Referenzzähler von -1 signalisiert, daß der FD nie freigegeben werden darf. Dies ist z.B. für die Gerätedateien U:\DEV\CON, U:\DEV\AUX usw. notwendig, die immer zur Verfügung stehen.

11.21.3.5.3 fd_mode

Hier steht der Modus, wie bei xfs_fopen beschrieben. Zeigen zwei FDs auf dieselbe Datei, müssen die Modi kompatibel sein. Durch die einfache MagiC interne Modusdarstellung ist ein einfaches Rotieren und verUNDen der Bits ausreichend, z.B:

  move.w   fd_mode(a0),d1
  btst     #BOM_NOCHECK,d1  ; kein Check durch das XFS?
  bne.b    _opf_nxt         ; ja, ddev_open prüft
  ror.b    #4,d1
  and.b    d0,d1
  bne      opd_eaccdn       ; Konflikt: return(EACCDN)
11.21.3.5.4 fd_dev

Dies ist der Zeiger auf den Gerätetreiber.

11.21.3.5.5 fd_ddev

Hier muß das DFS beim Aufruf von dir2FD den MX_DDEV eintragen, also den Gerätetreiber.

11.21.3.5.6 fd_name

Hier wird der Name (8+3) im internen Format abgelegt. Der Name ist nur gültig, wenn es sich um ein Unterverzeichnis handelt. Der Name ist nur im Prototyp-FD, d.h. in fd->multi1 gültig. Der Name der Root ist eine leere Zeichenkette.

11.21.3.5.7 fd_attr

Hier wird das Datei-Attribut abgelegt. Dieses ist nur im Prototyp-FD, d.h. in fd->multi1 gültig. Am Attribut kann man erkennen, ob der FD ein Verzeichnis repräsentiert.

11.21.3.5.8 fd_owner

Hier wird ein Zeiger auf den Eigner eines FD abgelegt (d.h. ein Zeiger auf die Basepage). Ein Wert von NULL bedeutet, daß der FD z.Zt. nicht belegt ist.

11.21.3.5.9 fd_parent

Verkettungszeiger auf den Parent, d.h. auf das Verzeichnis, in dem die Datei liegt bzw. das Elterverzeichnis eines Unterverzeichnisses. fd_parent ist nur für den Prototyp-FD gültig.

11.21.3.5.10 fd_children

Liste aller geöffneten Dateien und geöffneten Unterverzeichnisse. fd_children ist nur für den Prototyp-FD gültig.

11.21.3.5.11 fd_next

Zeiger auf den nächsten FD im selben Verzeichnis, d.h. auf das nächste Geschwist, dieses kann eine geöffnete Datei oder ein Unterverzeichnis sein, prinzipiell werden keine Unterschiede gemacht. fd_next ist nur für den Prototyp-FD gültig.

11.21.3.5.12 fd_multi

Wenn eine Datei mehrmals geöffnet wird, wird ein 'Clone' des Prototyp-FD angelegt. Für diesen Clone sind die meisten Felder des FD ungültig, im wesentlichen sind nur Treiber, Modus und Dateiposition gültig. fd_multi ist eine verkettete Liste, die mit NULL abgeschlossen ist.

11.21.3.5.13 fd_multi1

Der zugehörige Prototyp-FD, der die gültigen Dateiangaben enthält. Wenn eine Datei nur einmal geöffnet ist, gilt: fd->fd_multi == fd

11.21.3.5.14 fd_fpos

Die Position des Dateizeigers, ist 0L bei einem Gerät.

11.21.3.5.15 fd_dirch

Bit 0 zeigt an, ob eine Datei verändert wurde und daher beim Schließen der Datei das Verzeichnis (fd_parent) aktualisiert werden muß (passiert nicht, wenn es sich um einen Ordner handelt). Die anderen Bits sind reserviert und werden teilweise vom DOS_XFS verwendet.

11.21.3.5.16 fd_unused

Unbenutzt und reserviert.

11.21.3.5.17 fd_time

Uhrzeit aus dem Verzeichniseintrag im Intel-Format.

11.21.3.5.18 fd_date

Datum aus dem Verzeichniseintrag im Intel-Format.

11.21.3.5.19 fd_stcl

Start-Cluster im Motorola-Format.

11.21.3.5.20 fd_len

Dateilänge in Bytes im Motorola-Format.

11.21.3.5.21 fd_dirpos

Position des zugehörigen Eintrags im Parent. Ist nur für den Prototyp-FD gültig.

11.21.3.5.22 fd_user1

Zusammen mit fd_user2 2 Langworte zur freien Verfügung. Das FAT_DFS speichert hier zusätzliche Informationen zu fd_fpos ab, und zwar den aktuellen Cluster. Andere DFSs können andere Daten ablegen. Diese Felder sind zunächst auch nur für den Prototyp-FD gültig, es sei denn, beim Öffnen (ddev_open) werden die Daten explizit aus dem Prototyp-FD in den Clone kopiert.

11.21.3.5.23 fd_user2

Zusammen mit fd_user1 2 Langworte zur freien Verfügung. Das FAT_DFS speichert hier zusätzliche Informationen zu fd_fpos ab, und zwar den aktuellen Cluster. Andere DFSs können andere Daten ablegen. Diese Felder sind zunächst auch nur für den Prototyp-FD gültig, es sei denn, beim Öffnen (ddev_open) werden die Daten explizit aus dem Prototyp-FD in den Clone kopiert.

11.21.3.6 Der Gerätetreiber (MX_DEV)

Der Gerätetreiber wird beim Öffnen einer Datei vom XFS in den Dateideskriptor eingesetzt und vom Kernel direkt aufgerufen. Der Gerätetreiber muß die folgenden Funktionen bereitstellen:

typedef struct _mx_dev
{
  LONG  (*dev_close)();
  LONG  (*dev_read)();
  LONG  (*dev_write)();
  LONG  (*dev_stat)();
  LONG  (*dev_seek)();
  LONG  (*dev_datime)();
  LONG  (*dev_ioctl)();
  LONG  (*dev_getc)();
  LONG  (*dev_getline)();
  LONG  (*dev_putc)();
} MX_DEV;

Querverweis: XFS-Konzept in MagiC

11.21.3.6.1 dev_close
Name: »dev_close«
Parameter:
a0 = FD *file
-> d0 = long errcode
Beschreibung: Wenn fd_refcnt nicht schon 0 ist, muß fd_refcnt dekrementiert werden (dies muß vom MX_DEV erledigt werden). Bei dieser Gelegenheit sollten auch möglicherweise vorhandene Puffer zurückgeschrieben bzw. Verzeichniseinträge aktualisiert werden. Wenn fd_refcnt 0 ist, kann der FD freigegeben werden. Beim Diskwechsel ist fd_refcnt bereits beim Aufruf von dev_close 0, d.h. der FD muß einfach nur freigegeben werden.

Der vom DOS_XFS installierte Dateitreiber schreibt die Verzeichnisdaten zurück und ruft dann den MX_DDEV-Untertreiber auf.
Gruppe: Gerätetreiber
Querverweis:
11.21.3.6.2 dev_datime

Für Fdatime. Der vom DOS_XFS installierte Dateitreiber leitet den Aufruf an den MX_DDEV-Untertreiber weiter, wenn die Funktion im MX_DDEV-Treiber unterstützt wird (Zeiger != NULL), ansonsten wird die Funktion automatisch mit Hilfe der Daten des FD ausgeführt.

Parameter-Übergabe:

a0 = FD *file
a1 = int d[2]
d0 = int setflag
-> d0 = long errcode
11.21.3.6.3 dev_getc
Name: »dev_getc«
Parameter:
a0 = FD *file
d0 = int mode
-> d0 = unsigned long c
Beschreibung: Wird vom Kernel für Fgetchar() und die zeichenorientierten Funktionen (Cconin, Cconout, Cauxin usw.) verwendet. Im Fall eines Geräts kann der Rückgabewert ein Langwort sein (so bei CON im Hiword der Scancode der Taste), ansonsten ein Byte (immer als "unsigned" erweitert). Bei EOF muß 0x0000FF1A geliefert werden.

bedeutet:
CMODE_COOKED (1) Bit 0 gesetzt: Steuerzeichen ^C, ^S, ^Q werden verarbeitet.
CMODE_RAW (0) Bit 0 nicht gesetzt: "raw" Modus
CMODE_ECHO (2) Bit 1 gesetzt: Eingabe wird ge-echo-t


Der vom DOS_XFS installierte Dateitreiber leitet den Aufruf an den MX_DDEV-Untertreiber weiter, wenn die Funktion im MX_DDEV-Treiber unterstützt wird (Zeiger != NULL), ansonsten wird die Funktion automatisch auf dev_fread zurückgeführt.
Gruppe: Gerätetreiber
Querverweis:
11.21.3.6.4 dev_getline

Für zeilenorientierte Eingabe. wie in dev_getc. Zurückgegeben wird die Anzahl der eingegebenen Zeichen ohne Endezeichen o.ä. Der vom DOS_XFS installierte Dateitreiber leitet den Aufruf an den MX_DDEV-Untertreiber weiter, wenn die Funktion im MX_DDEV-Treiber unterstützt wird (Zeiger != NULL), ansonsten wird die Funktion automatisch auf dev_fread zurückgeführt, die Zeile wird dann mit CR und LF beendet, Steuerzeichen (BS oder Del) nicht ausgewertet.

Parameter-Übergabe:

a0 = FD *file
a1 = char *buf
d1 = long size
d0 = int mode
-> d0 = long amount
11.21.3.6.5 dev_ioctl

Für Fcntl. Der vom DOS_XFS installierte Dateitreiber leitet den Aufruf direkt an den MX_DDEV-Untertreiber weiter. Bearbeitet werden jedoch vorher folgende Funktionen: FSTAT und FUTIME. Diese sollten auch von anderen XFSs ausgeführt werden. Jeder Dateitreiber sollte FIONREAD und FIONWRITE unterstützen.

Parameter-Übergabe:

a0 = FD *file
d0 = int cmd
a1 = void *buf
-> d0 = long errcode
11.21.3.6.6 dev_putc
Name: »dev_putc«
Parameter:
a0 = FD *file
d0 = int mode
d1 = long value
-> d0 = unsigned long count
Beschreibung: Wird vom Kernel für Fgetchar() und die zeichenorientierten Funktionen (Cconout, Cauxout usw.) verwendet. Im Fall eines Terminals muß der Rückgabewert 4L sein (d.h. 4 Bytes geschrieben, ansonsten 1L, falls erfolgreich geschrieben wurde.

bedeutet:
CMODE_COOKED (1) Bit 0 gesetzt: Steuerzeichen ^C, ^S, ^Q werden verarbeitet.
CMODE_RAW (0) Bit 0 nicht gesetzt: "raw" Modus


Der vom DOS_XFS installierte Dateitreiber leitet den Aufruf an den MX_DDEV-Untertreiber weiter, wenn die Funktion im MX_DDEV-Treiber unterstützt wird (Zeiger != NULL), ansonsten wird die Funktion automatisch auf dev_fwrite zurückgeführt.
Gruppe: Gerätetreiber
Querverweis:
11.21.3.6.7 dev_read

Von Datei werden Bytes in den Puffer gelesen. Die Anzahl der tatsächlich gelesenen Zeichen wird zurückgegeben. Der vom DOS_XFS installierte Dateitreiber leitet den Aufruf direkt an den MX_DDEV-Untertreiber weiter.

Parameter-Übergabe:

a0 = FD *file
d0 = long count
a1 = char *buffer
-> d0 = long amount
11.21.3.6.8 dev_seek

Für Fseek. ist, wie im TOS, 0, 1 oder 2. Zurückgegeben wird die aktuelle Position des Schreib-/Lesezeigers, Gerätetreiber müssen hier immer eine 0L zurückgeben. Der vom DOS_XFS installierte Dateitreiber leitet den Aufruf direkt an den MX_DDEV-Untertreiber weiter.

Parameter-übergabe:

a0 = FD *file
d0 = long where
d1 = int mode
-> d0 = long position
11.21.3.6.9 dev_stat
Name: »dev_stat«
Parameter:
a0 = FD *file
a1 = MAGX_UNSEL *unselect oder NULL
d0 = int rwflag
d1 = long apcode
-> d0 = long status
Beschreibung: Gibt den Lese-/Schreibstatus der Datei an. Wird z.B. bei Fselect() aufgerufen (oder bei Cconos()/Cconis() usw.). Im Gegensatz zu MiNT wird hier dem Treiber überlassen, ob er interruptfähig ist oder nicht, d.h. ob er in der Lage ist, eine wartende Applikation im Interrupt wieder aufzurufen oder nicht. rwflag gibt an, ob Schreib- oder Lesestatus abgefragt wird.

ist entweder NULL oder ein Zeiger auf folgende Struktur:
typedef struct
{
   union
   {
      void (*unsel) (MAGX_UNSEL *un);
      long status;
   }
   long param;
} MAGX_UNSEL;


Vorgehensweise:

Allgemein gilt: Wenn ungleich Null ist, muß der Rückgabewert nicht nur als Funktionsergebnis (in d0.l), sondern auch in unselect->status zurückgegeben werden. Das gilt für alle Arten von Rückgabewerten. In unsel->param kann optional ein Parameter abgelegt werden.

Wenn == NULL ist, wird gepollt, d.h. die Applikation wird nicht schlafengelegt. Also Rückgabe:

0 = nicht bereit, 1 = bereit, <0 = Fehler.

Wenn != NULL ist (dann ist auch != NULL) wird zurückgegeben:
<0 Fehler
0 nicht bereit, Gerät kann nur polling
1 bereit
>0 etwa Zeiger auf eine Funktion, die den Aufweckinterrupt wieder deinstalliert (entspricht in etwa dem unselect in MiNT).


Falls das Gerät nicht bereit ist und interruptfähig ist, geht man folgendermaßen vor:
  1. unselect mit der Adresse der Aufräumroutine und einem optionalen Parameter initialisieren, Prototyp etwa:
    void unselect( a0 = MAGX_UNSEL *un,a1 = void *ap_code );
    
  2. Interrupt zum Aufwecken installieren, diesem unselect (und damit auch den optionalen Parameter) und appl mitteilen.
  3. Zeiger auf Aufräumroutine in d0 zurückgeben.


Die Interruptroutine macht folgendes:
  1. Der Interrupt trifft ein.
  2. unselect->status wird mit 1 (ok) oder < 0 (nicht ok) beschrieben und der Interrupt deaktiviert! Die Applikation wird aufgeweckt mit
    kernel->appl_IOcomplete( a0 = APPL *ap );
    


Die Aufräumroutine macht folgendes:
  1. Der Interrupt wird deaktiviert.
  2. in unsel->status wird, falls noch nicht geschehen, eine 1 (eingetroffen) oder 0 (nicht eingetroffen) oder < 0 (Fehler) eingetragen. Es muß sichergestellt werden, daß kein IOcomplete und kein Schreibzugriff auf unsel anschließend noch erfolgen kann. Ein Wert ungleich 1, aber größer als Null wird immer als Adresse der Aufräumroutine interpretiert, diese muß noch aufgerufen werden, wenn der Interrupt nicht eingetroffen ist. Falls der Interrupt z.B. einen Wert von 2L eintrüge, ginge der Kernel davon aus, daß der Interrupt nicht eingetreten ist und immer noch die Adresse der Aufräumroutine in der MAGX_UNSEL-Struktur steht. Ein Sprung nach Adresse 2 ist dann aber schnell ziemlich tödlich.


Die DOS-Funktionen Finstat() und Foutstat() versuchen zunächst, den Aufruf auf Fcntl (FIONREAD bzw. FIONWRITE) zurückzuführen. Wenn diese Subfunktion von dev_ioctl nicht existiert (der Dateitreiber muß EINVFN liefern!), wird dev_stat aufgerufen. In diesem Fall kann die Aussage getroffen werden "Zeichen liegt an" (Wert == 1) bzw. "kein Zeichen liegt an" (Wert == 0).

Der vom DOS_XFS installierte Dateitreiber leitet den Aufruf direkt an den MX_DDEV-Untertreiber weiter.
Gruppe: Gerätetreiber
Querverweis:
11.21.3.6.10 dev_write

Auf Datei werden Bytes aus dem Puffer geschrieben. Die Anzahl der tatsächlich geschriebenen Zeichen wird zurückgegeben. Der vom DOS_XFS installierte Dateitreiber aktualisiert Zeit und Datum der Datei und leitet dann den Aufruf an den MX_DDEV-Untertreiber weiter.

Parameter-Übergabe:

a0 = FD *file
d0 = long count
a1 = char *buffer
-> d0 = long amount

11.21.4 Installation eines XFS

Ein XFS ist einfach ein Programm, das den Treiber installiert und sich resident beendet. Die Installation erfolgt per kernel = Dcntl (KER_INSTXFS, NULL, &myxfs).

Man erhält einen Zeiger auf wichtige Kernelfunktionen oder einen Fehlercode zurück. Die Kernelfunktionen kann man auch unabhängig von der Installation eines XFS erfragen, und zwar per kernel = Dcntl(KER_GETINFO, NULL, NULL).

Die Deinstallation eines XFS ist nicht vorgesehen.

11.21.5 Kernelfunktionen für ein XFS

MagiCstellt den installierten XFSs, DFSs oder Gerätetreibern einige Kernelinformationen sowie -funktionen zur Verfügung. Bei den Kernelfunktionen gilt dieselbe Registerkonvention wie für die XFS-Funktionen, d.h. d0-d2 und a0-a2 können zerstört werden. Einen Zeiger auf die Struktur, die die Kernelfunktionen enthält, bekommt man über

     kernel = Dcntl (KER_INSTXFS, NULL, &myxfs);   oder
     kernel = Dcntl (KER_GETINFO, NULL, NULL);

Im ersten Fall wird ein XFS installiert, im zweiten Fall bekommt man nur die Kernelstruktur (etwa für ein DFS oder einen Gerätetreiber). Der Aufbau der Kernelstruktur im einzelnen:

typedef struct
{
  WORD   mxk_version;
  VOID (*mxk_fast_clrmem)      ( void *von, void *bis );
  BYTE (*mxk_toupper)          ( char c );
  VOID (*mxk__sprintf)         ( char *dest, char *source, LONG *p );
  VOID  *mxk_mxk_act_pd;
  APPL  *mxk_act_appl;
  APPL  *mxk_keyb_app;
  WORD  *mxk_pe_slice;
  WORD  *mxk_pe_timer;
  VOID (*mxk_appl_yield)       ( void );
  VOID (*mxk_appl_suspend)     ( void );
  VOID (*mxk_appl_begcritic)   ( void );
  VOID (*mxk_appl_endcritic)   ( void );
  LONG (*mxk_evnt_IO)          ( LONG ticks_50hz, void *unsel );
  VOID (*mxk_evnt_mIO)         ( LONG ticks_50hz, void *unsel, WORD cnt );
  VOID (*mxk_evnt_emIO)        ( APPL *ap );
  VOID (*mxk_appl_IOcomplete)  ( APPL *ap );
  LONG (*mxk_evnt_sem)         ( WORD mode, void *sem, LONG timeout );
  VOID (*mxk_Pfree)            ( void *pd );
  WORD   mxk_int_msize;
  VOID  *mxk_int_malloc        ( void );
  VOID   mxk_int_mfree         ( void *memblk );
  VOID   mxk_resv_intmem       ( void *mem, LONG bytes );
  LONG   mxk_diskchange        ( WORD drv );
  LONG   mxk_DMD_rdevinit      ( DMD *dmd );
  LONG   mxk_proc_info         ( WORD code, PD *pd );
  LONG   mxk_mxalloc           ( d0 = LONG amount, d1 = WORD mode, a0 = PD *pd );
  LONG   mxk_mfree             ( a0 = void *block );
  LONG   mxk_mshrink           ( d0 = LONG newlen, a0 = void *block );
} MX_KERNEL;

Querverweis: XFS-Konzept in MagiC

11.21.5.1 mxk_version

Das ist die Versionsnummer, die z.Zt. einfach 3 ist. Bei jeder Änderung der Kernelstruktur wird die Versionsnummer hochgesetzt, so daß sich Programme entsprechend anpassen können.

11.21.5.2 mxk_fast_clrmem

Eine schnelle Speicherlöschroutine, die den Speicher von bis (ausschließlich) auf 0 setzt.

Dabei gilt:

a0 = void *von
a1 = void *bis

11.21.5.3 mxk_toupper

Wandelt das Zeichen unter Berücksichtigung der nationalen Sonderzeichen in Großschrift um.

Dabei gilt:

d0 = char c

11.21.5.4 mxk__sprintf

Eine Funktion, die ihre Argumente auf dem Stack erwartet. Übergeben wird die Ziel-Zeichenkette , die Schablone und die einzutragenden Werte p[]. Die Langworte werden je nach Formatieranweisung als "unsigned int" (%W), "signed long" (%L) oder Zeichenkette (%S) interpretiert.

Bei %W wird das weiter unten im Speicher liegende Wort verwendet, die Folge %% fügt ein Prozentzeichen ein.

11.21.5.5 mxk_act_pd

Der Zeiger auf die aktuelle Basepage, die Adresse läßt sich auch über den Systemheader oder die DOS-Variablen ermitteln.

11.21.5.6 mxk_act_appl

Der Zeiger auf die aktuelle Applikation (d.h. die laufende Task). Der Aufbau der Struktur ist nicht dokumentiert, der Zeiger wird wegen des schnelleren Zugriffs anstelle der ap_id als Deskriptor verwendet.

11.21.5.7 mxk_keyb_app

Die Applikation, die z.Zt. die Tastatur besitzt. Der Zeiger kann z.B. von Gerätetreibern verwendet werden, die die tastaturbesitzende Applikation anders behandeln müssen.

11.21.5.8 mxk_pe_slice

Für das präemptive Multitasking. Wenn <*pe_slice> == -1 ist, ist das präemptive Multitasking abgeschaltet, und Diskzugriffe werden nicht unterbrochen.

11.21.5.9 mxk_pe_timer

Für das präemptive Multitasking. Wenn <*pe_slice> == -1 ist, ist das präemptive Multitasking abgeschaltet, und Diskzugriffe werden nicht unterbrochen.

11.21.5.10 mxk_appl_yield

Gibt Rechenzeit ans System. Wichtig für Treiber, die nicht auf einen Interrupt warten können und verhindern müssen, daß ihr "busy waiting" das System lahmlegt.

11.21.5.11 mxk_appl_suspend

Arbeitet wie appl_yield(), gibt jedoch der Applikation eine geringere Priorität, etwa als Hintergrundprozeß.

11.21.5.12 mxk_appl_begcritic

Die aktuelle Applikation tritt in eine kritische Phase und darf nicht terminiert werden.

11.21.5.13 mxk_appl_endcritic

Ende der kritischen Phase. Falls zwischenzeitlich der Befehl zur Terminierung eingegangen ist, wird das Programm terminiert.

11.21.5.14 mxk_evnt_IO

Name: »evnt_IO«
Parameter:
d0 = long ticks_50hz
a0 = void *unsel
Beschreibung: evnt_IO ermöglicht es, auf EIN externes Ereignis zu warten. Als externes Ereignis kommt entweder ein Interrupt oder eine andere Applikation (die etwa zum Aufwecken in eine Pipe schreibt) in Frage. Die Funktion wird zum Erstellen von Gerätetreibern verwendet:

Vorgehensweise (siehe DEV_LPT1 als Beispiel):
  1. Interrupts sperren
  2. Abfrage, ob das Ereignis (im Fall DEV_LPT1 lautet das Ereignis: "centronics busy off" eingetroffen ist.
  3. Wenn ja, Interrupts freigeben und Aktion durchführen (im Fall DEV_LPT1: Zeichen drucken)
  4. Wenn nein, Interruptroutine aufsetzen (im Fall DEV_LPT1: MFP-I0, d.h. Centronics Busy Interrupt aktivieren) und diesem die aktuelle Applikation (act_appl) sowie eine Langwortadresse zugänglich machen, in die die Interruptroutine Rückmeldungen schreiben kann. Diese Adresse ist mit der Adresse einer Routine zu beschreiben, die den Interrupt wieder abmeldet, dahinter können nach eigenen Anforderungen z.B. noch weitere Daten folgen. Die Unselect-Routine bekommt später einen Zeiger auf alle diese Daten und kann z.B. die optionalen Parameter auswerten. Der ganze Mechanismus ist notwendig, um ein korrektes Deinitialisieren des Interrupts in jedem Fall zu garantieren.
  5. Interrupts freigeben
  6. evnt_IO aufrufen. In d0.w die Anzahl der 50Hz- Ticks für den Timeout angeben, 0 heißt "kein Timeout". In a0 die Adresse des Langworts angeben, in dem die Adresse der Aufräumroutine steht, die den Interrupt wieder abmeldet (dahinter folgen optional weitere Parameter, falls die Unselect-Routine diese versteht). Im Fall des Einbindens von Gerätetreibern für Fselect() ist nur ein optionales Langwort möglich.
    Die Interruptroutine schreibt bei Eintreffen des Interrupts einen Status < 0L (Fehler) oder 1L (OK) statt der Deinitialisierungsroutine in das Statuslangwort (in dem vorher ihre eigene Startadresse stand). Anschließend deinstalliert sich die Routine selbst bzw. stellt sicher daß bei folgenden Interrupts keine Aktionen ausgeführt werden. Schließlich weckt die Interruptroutine die dem Interrupt zugeordnete Applikation auf, und zwar über den Aufruf appl_IOcomplete() mit der Applikation als Parameter.
  7. evnt_IO() liefert als Rückgabewert 0L (Timeout, der Interrupt ist nicht eingetroffen) oder < 0 (der Interrupt hat Fehlermcode ins Statuslangwort geschrieben) oder 1L (der Interrupt hat eine 1L ins Statuslangwort geschrieben). Eine Deinstallierung des Interrupts ist nicht mehr notwendig, dies hat der Kernel erledigt, falls die Interruptroutine dies nicht selbst beim Eintreffen des Interrupts getan hat.
Gruppe: Kernelfunktionen
Querverweis:

11.21.5.15 mxk_evnt_mIO

Name: »evnt_mIO«
Parameter:
d0 = long ticks_50hz
a0 = void *unsel
d1 = int cnt


bzw.
a0 = APPL *ap
Beschreibung: evnt_mIO() ermöglicht es, auf MEHRERE externe Ereignisse zu warten, z.B. wird diese Funktion von Fselect verwendet (mehrere Dateien!).

Vorgehensweise:
  1. Für n Ereignisse eine Langwort-Tabelle der Länge 2*n anlegen.
  2. Für jedes Ereignis die Aufräumroutine (unselect-Routine) eintragen, (dahinter folgt ein optionaler Langwortparameter) und den Interrupt aufsetzen. Die Reihenfolge ist wichtig, es muß verhindert werden, daß die unselect-Adresse den Rückgabewert des bereits eingetroffenen Interrupts überschreibt, ggf. Interrupts sperren.
  3. evnt_mIO aufrufen. Die Parameter sind wie bei evnt_IO, in d1.w wird aber die Anzahl der Ereignisse übergeben, a0 ist der Tabellenanfang.
  4. evnt_mIO() liefert keinen Rückgabewert. Die Tabelle muß durchsucht und die Interrupts deinstalliert werden (z.B. die unselect-Routinen aufrufen), dabei kann überprüft werden, welche Interrupts bereits eingetroffen sind.
  5. evnt_emIO mit der aktuellen Applikation aufrufen. Dieser Aufruf stellt sicher, daß nach Deinstallieren aller Interrupts deren jetzt nutzlose Nachrichten an die Applikation gelöscht werden.


Auf die Ereignisse evnt_(m)IO wartende Applikationen erscheinen im Programm-Manager als wartend auf "io" (Input/Output) oder "io ti" (Input/Output mit Timeout).
Gruppe: Kernelfunktionen
Querverweis:

11.21.5.16 mxk_appl_IOcomplete

Weckt eine Applikation auf, die auf evnt_(m)IO wartet.

Dabei gilt:

a0 = APPL *ap

11.21.5.17 mxk_evnt_sem

Name: »evnt_sem«
Parameter:
d0 = int mode
a0 = void *sem
d1 = long timeout
Beschreibung: Für mode sind folgende Unterfunktionen möglich:
0 SEM_FREE Semaphore freigeben (ohne Taskwechsel!)
1 SEM_SET Semaphore setzen, ggf. warten
2 SEM_TEST Eigner der Semaphore ermitteln (ggf. NULL)
3 SEM_CSET Semaphore setzen, falls nicht schon gesetzt
4 SEM_GET Semaphore ermitteln, falls Name bekannt ist.
5 SEM_CREATE Semaphore erstellen, d.h. neue einrichten
6 SEM_DEL Semaphore entfernen


SEM_SET und SEM_CSET sind die einzigen Unterfunktionen, die einen Taskwechsel auslösen können.

Im Gegensatz zu wind_update() kann mit diesen Aufrufen das Setzen und Freigeben von Semaphoren nicht geschachtelt werden. Versucht man, eine bereits reservierte Semaphore nochmal zu reservieren, gibt es einen Fehlercode.

Beim Freigeben der Semaphore wird kein Taskwechsel durchgeführt, d.h. die Semaphore kann zwar ggf. jetzt einer anderen Applikation gehören, die den Status "ready" hat, aber sie hat noch keine Rechenzeit bekommen. Wenn die Situation unkritisch ist, sollte in jedem Fall anschließend ein appl_yield() durchgeführt werden.

Die Bildschirmsemaphore hat den Namen _SCR und darf mit evnt_sem() nur mit der Unterfunktion SEM_TEST behandelt werden.

SEM_CREATE setzt den Erzeuger nicht automatisch als Eigner. Dies ist nicht notwendig, weil kein Taskwechsel stattgefunden hat. Also kann bedenkenlos ein SEM_SET anschließend durchgeführt werden.

SEM_DEL verlangt, daß der Löscher auch der Eigner ist. Beim Löschen werden alle wartenden Applikationen freigegeben, sie erhalten, wenn sie per evnt_sem(SEM_SET, ..) warten, eine -2 als Rückgabewert. Wer System-Semaphoren (solche, deren Namen mit '_' beginnen) löscht, ist selbst schuld.
Gruppe: Kernelfunktionen
Querverweis:

11.21.5.18 SEM_FREE

Parameter:

a0 = Zeiger auf Semaphore
-> 0 OK
-> -1 Semaphore unbenutzt oder von anderer APP benutzt.

11.21.5.19 SEM_SET

Parameter:

a0 = Zeiger auf Semaphore
d1 = Timeout in 50Hz- Ticks
-> 0 OK
-> 1 Timeout
-> -1 Semaphore war schon von mir gesetzt.
-> -2 Semaphore wurde inzwischen entfernt.

11.21.5.20 SEM_TEST

Parameter:

a0 = Zeiger auf Semaphore
-> >0 Eigner
-> 0 nicht benutzt

11.21.5.21 SEM_CSET

Parameter:

a0 = Zeiger auf Semaphore
d1 = Timeout in 50Hz- Ticks
-> 0 OK
-> 1 Semaphore von anderer APPL gesetzt.
-> -1 Semaphore war schon von mir gesetzt.

11.21.5.22 SEM_GET

Parameter:

d1 = Name der Semaphore
-> >0 Zeiger auf Semaphore.
-> -1 Semaphore nicht gefunden.

11.21.5.23 SEM_CREATE

Parameter:

a0 = Zeiger auf Semaphore (32 Bytes auf gerader Adresse)
d1 = Name void

11.21.5.24 SEM_DEL

Parameter:

a0 = Zeiger auf Semaphore
-> 0 OK
-> -1 Semaphore ungültig

11.21.5.25 mxk_Pfree

Gibt den Speicher für einen Prozeß frei, der mit Ptermres beendet  wurde. Dies ist notwendig, um einen Gerätetreiber korrekt zu entfernen.

Dabei gilt:

a0 = void *pd

11.21.5.26 mxk_int_msize

Die Länge eines Speicherblocks der internen (Kernel-) Speicherverwaltung.

11.21.5.27 mxk_int_malloc

Alloziert einen internen Speicherblock. Ist kein Speicher mehr frei, wird zunächst eine globale "garbage collection" durchgeführt (siehe Beschreibung des XFS), dann bei Mißerfolg das System angehalten. Interne Speicherblöcke dürfen nur in kleinen Mengen angefordert werden, sonst erhält man sehr bald ein "Out of internal memory", und das System steht.

11.21.5.28 mxk_int_mfree

Gibt einen Block wieder frei.

Dabei gilt:

a0 = void *memblk

11.21.5.29 mxk_resv_intmem

Erweitert den Kernelspeicher. Es ist keine Möglichkeit vorgesehen, den Speicher zurückzufordern. Da der Kernel nur zur Bootzeit ausreichend internen Speicher für die FAT-Laufwerke anfordert, kann es für ein XFS notwendig sein, beim Start mit dieser Funktion weiteren Kernelspeicher zu reservieren.

Dabei gilt:

a0 = void *mem
d0 = long bytes

11.21.5.30 mxk_diskchange

Muss aufgerufen werden, wenn ein XFS- oder DFS-Treiber einen Diskwechsel erkannt hat. Der XFS-Treiber gibt seine Dateien und Strukturen frei, anschließend der Kernel.

Rückgabe:

EDRIVE Laufwerk ungültig
E_CHNG Laufwerk mit neuer Disk gültig

Dabei gilt:

d0 = int drv

11.21.5.31 mxk_DMD_rdevinit

Ab Kernelversion 1

Initialisiert die Felder d_driver und d_devcode des DMD und benutzt dazu das Feld d_biosdev. Wird für Diskwechselmechanismen benötigt.

Dabei gilt:

a0 = DMD *dmd

11.21.5.32 mxk_proc_info

Ab Kernelversion 2

Ermittelt Daten für den aktuellen Prozeß.

d0 = 0: 0: höchste verfügbare Unterfunktionsnummer,
  1: Domain
  2: Process-ID.

Dabei gilt:

d0 = WORD code
a0 = PD *pd

11.21.5.33 mxk_mxalloc

Ab Kernelversion 4

Ermöglicht eine schnelle Speicherallozierung, z.B. für ein RAMDisk-XFS, ohne über den Trap gehen zu müssen.

gibt den Prozeß an, der als Eigner des neuen Blocks eingetragen wird, daher sollte normalerweise die Basepage des XFS-Treibers übergeben werden.

11.21.5.34 mxk_mfree

Ab Kernelversion 4

Gibt Speicher wieder frei.

11.21.5.35 mshrink

Ab Kernelversion 4

Ändert die Größe eines Speicherblocks.

11.21.6 Symbolische Links und das XFS-Konzept

Symbolische Links (in der Benutzerdokumentation in Übereinstimmung mit der Macintosh Nomenklatur auch als Aliase bezeichnet) sind Dateien, die in irgendeiner Form besonders gekennzeichnet sind und statt Daten einen Pfad enthalten, der wiederum auf eine andere Datei zeigt. Ein derartiger Pfad kann auch auf eine nicht (mehr) bzw. noch nicht existierende Datei zeigen. Pfade können absolut oder relativ sein, wobei letztere das Verzeichnis als Bezug haben, in dem der Link liegt.

Im Speicher werden derartige Links als Strukturen verwaltet:

{
   WORD n;         /* auf gerade Anzahl aufgerundet, inkl. EOS */
   char path[n];   /* Pfad mit EOS am Ende */
}

Hinweis: Einige XFS-Funktionen müssen, wenn sie auf einen Symlink stoßen, diesen dereferenzieren, d.h. sie liefern dem Kernel in d0 den Fehlercode ELINK und in a0 einen Zeiger auf eine Struktur der obigen Form. Der Kernel sorgt dann für die Dereferenzierung und die Begrenzung der maximalen Verschachtelung (falls der Symlink wieder auf einen solchen zeigt). Die XFS-Funktionen, die ELINK liefern dürfen, sind:

xfs_path2DD, xfs_sfirst, xfs_snext, xfs_fopen, xfs_xattr, xfs_attrib.

Querverweis: XFS-Konzept in MagiC

11.21.7 MX_DOSLIMITS

Diese Struktur ist wie folgt definiert:

typedef struct
{
    UWORD version;        /* Versionsnummer               */
    UWORD num_drives;     /* max. Anzahl Laufwerke        */
    ULONG max_secsizb;    /* max. Sektorgröße in Bytes    */
    UWORD min_nfats;      /* min. Anzahl FATs             */
    UWORD max_nfats;      /* max. Anzahl FATs             */
    ULONG min_nclsiz;     /* min. Anzahl Sektoren/Cluster */
    ULONG max_nclsiz;     /* max. Anzahl Sektoren/Cluster */
    ULONG max_ncl;        /* max. Anzahl Cluster          */
    ULONG max_nsec;       /* max. Anzahl Sektoren         */
} MX_DOSLIMITS;

Querverweis: Dcntl   KER_DOSLIMITS   XFS-Konzept in MagiC

11.21.8 XFS-Strukturen

11.21.8.1 dev_descr

Diese Struktur ist wie folgt definiert:

struct dev_descr
{
    DEVDRV  *driver;
    SHORT   dinfo;
    SHORT   flags;
    struct tty *tty;
    LONG    devdrvsiz;
    LONG    reserved[4];
};

Hinweis: Die Komponente devdrvsiz beschreibt dabei die Größe der DEVDRV-Struktur.

Querverweis: Dcntl   XFS-Konzept in MagiC

11.21.8.2 DEVDRV

Diese Struktur ist wie folgt definiert:

typedef struct devdrv
{
    LONG (*open)      (FILEPTR *f);
    LONG (*write)     (FILEPTR *f, BYTE *buf, LONG bytes);
    LONG (*read)      (FILEPTR *f, BYTE *buf, LONG bytes);
    LONG (*lseek)     (FILEPTR *f, LONG where, WORD whence);
    LONG (*ioctl)     (FILEPTR *f, WORD mode, VOID *buf);
    LONG (*datime)    (FILEPTR *f, WORD *timeptr, WORD rwflag);
    LONG (*close)     (FILEPTR *f, WORD pid);
    LONG (*select)    (FILEPTR *f, LONG proc, WORD mode);
    VOID (*unselect)  (FILEPTR *f, LONG proc, WORD mode);
    LONG reserved[3];
} DEVDRV;

Querverweis: Dcntl   dev_descr   FILESYS   XFS-Konzept in MagiC

11.21.8.3 FILESYS

Diese Struktur ist wie folgt definiert:

typedef struct filesys
{
    struct  filesys *next;
    LONG    fsflags;
    LONG    (*root)       (WORD drv, fcookie *fc);
    LONG    (*lookup)     (fcookie *dir, BYTE *name, fcookie *fc);
    LONG    (*creat)      (fcookie *dir, BYTE *name, UWORD mode,
                           WORD attrib, fcookie *fc);
    DEVDRV *(*getdev)     (fcookie *fc, LONG *devspecial);
    LONG    (*getxattr)   (fcookie *fc, XATTR *xattr);
    LONG    (*chattr)     (fcookie *fc, WORD attr);
    LONG    (*chown)      (fcookie *fc, WORD uid, WORD gid);
    LONG    (*chmode)     (fcookie *fc, UWORD mode);
    LONG    (*mkdir)      (fcookie *dir, BYTE *name, UWORD mode);
    LONG    (*rmdir)      (fcookie *dir, BYTE *name);
    LONG    (*remove)     (fcookie *dir, BYTE *name);
    LONG    (*getname)    (fcookie *relto, fcookie *dir, BYTE *pathname,
                           WORD size);
    LONG    (*rename)     (fcookie *olddir, BYTE *oldname,
                           fcookie *newdir, BYTE *newname);
    LONG    (*opendir)    (DIR *dirh, WORD tosflag);
    LONG    (*readdir)    (DIR *dirh, BYTE *nm, WORD nmlen, fcookie *fc);
    LONG    (*rewinddir)  (DIR *dirh);
    LONG    (*closedir)   (DIR *dirh);
    LONG    (*pathconf)   (fcookie *dir, WORD which);
    LONG    (*dfree)      (fcookie *dir, LONG *buf);
    LONG    (*writelabel) (fcookie *dir, BYTE *name);
    LONG    (*readlabel)  (fcookie *dir, BYTE *name, WORD namelen);
    LONG    (*symlink)    (fcookie *dir, BYTE *name, BYTE *to);
    LONG    (*readlink)   (fcookie *dir, BYTE *buf, WORD len);
    LONG    (*hardlink)   (fcookie *fromdir, BYTE *fromname,
                           fcookie *todir, BYTE *toname);
    LONG    (*fscntl)     (fcookie *dir, BYTE *name, WORD cmd, LONG arg);
    LONG    (*dskchng)    (WORD drv);
    LONG    (*release)    (fcookie *fc);
    LONG    (*dupcookie)  (fcookie *dest, fcookie *src);
} FILESYS;

Querverweis: Dcntl   fs_descr   XFS-Konzept in MagiC

11.21.8.4 fs_descr

Diese Struktur ist wie folgt definiert:

struct fs_descr
{
    FILESYS *file_system;
    SHORT   dev_no;
    LONG    flags;
    LONG    reserved[4];
};

Querverweis: Dcntl   XFS-Konzept in MagiC


HomeMagiCDas DFS-Konzept von MagiCVFAT-XFS in MagiC