← ST-Computer 02 / 1988

Auf der Schwelle zum Licht (3): Die Fehlermeldung des TOS (Teil 2)

Grundlagen

Der Critical-Error-Handler

Zur Benutzerfreundlichkeit einer grafischen OberflĂ€che wie GEM gehört auch, dass Fehlermeldungen des Betriebssystems nicht von jedem Programm in einer anderen Art und Weise - wenn ĂŒberhaupt - ausgegeben werden, sondern vom Betriebssystem selbst in einheitlicher Form prĂ€sentiert werden.

Der Critical Error Handler des GEM ist verantwortlich fĂŒr die Anzeige der BIOS-Fehler mittels Alert-Boxen. Er ist Ihnen durch Fehlermeldungen wie “Floppy A: antwortet nicht...” sicherlich bestens bekannt und wird vom TOS dazu benutzt, Fehler beim Diskzugriff bzw. bei der Druckeransteuerung (bei “Datei zeigen” des Desktop) anzuzeigen. Da die BIOS-Floppy-Routinen in einer sehr tiefen Software-Ebene des TOS hegen, geschieht dies automatisch und ohne Wissen der Anwenderprogramme.

Die Adresse des aktuellen Critical Error Handlers steht in der Systemvariablen ‘etv_critic’ ($404).

Der Critical Error Handler kann jedoch auch aus eigenen Programmen heraus aufgerufen werden. Hier bieten sich vor allem eigene Treiberprogramme fĂŒr Harddisks oder RAM-Disks an, die somit die von der Floppy her bekannten Fehlermeldungen benutzen können. Er muß jedoch nicht unbedingt aus Exception-Routinen (wie dem BIOS-TRAP) heraus aufgerufen werden, sondern kann auch von “normalen” Programmen aus benutzt werden. Der Prozessor muß sich dabei allerdings im Supervisor-Modus befinden. Es ist nicht erforderlich, das Programm deswegen mit ‘appl_init’ beim GEM anzumelden, da die Ausgabe der Alert-Boxen nur ĂŒber das GEM-Resource des AES lĂ€uft.

long alrt_crit (err, drv) int err; /* BIOS-Fehlernummer */ int drv; /* Laufwerkskennung 0,1,... */ { long ret; supon(); /* supon () /supoff () aus letzter Folge */ ret = (*{long (*} {))peekl(etv_critic)} (err,drv); supoff(); return ret; }

Listing 1 - Aufruf des Critical Error Handlers in C

Der Critical Error Handler kann recht einfach von C oder Assembler heraus aufgerufen werden (Listing 1 und 2). Der C-Aufruf funktioniert so zumindest bei MEGAMAX C, bei anderen Compilern mĂŒssen eventuell die wilden “Casts” geĂ€ndert werden.

Dem Critical Error Handler wird die BIOS-Fehlernummer und die Laufwerkskennung (0,1,... fĂŒr A:,B:,„.) ĂŒbergeben. E_OK gilt hierbei nicht als ‘OK’, sondern wird als Fehler behandelt, daher muß man E_OK vorher selbst abfangen. Er liefert entweder einen Fehlercode zurĂŒck, mit dem abgebrochen werden soll, oder $10000, um anzuzeigen, daß die Funktion, die zu dem Fehler gefĂŒhrt hat, wiederholt werden soll. Er kann sogar E_OK zurĂŒckgeben, um den Fehler zu ignorieren. Man sollte im Fehlerfall also nicht die ĂŒbergebene Fehlernummer, sondern die zurĂŒckgelieferte weiterverarbeiten. Die Register D3-D7 und A3-A6 werden vom Critical Error Handler selbst gerettet. Der Aufruf sollte so Ă€hnlich wie in Listing 2 angegeben durchgefĂŒhrt werden. Das BIOS setzt DO vorher auf -1, obwohl der Critical Error Handler dies nicht beachtet. Da dies eventuell fĂŒr zukĂŒnftige Erweiterungen gedacht ist, wird es im Beispiel-Aufruf auch so gemacht.

Da das BIOS also somit ĂŒber die Möglichkeit verfĂŒgt, bei Fehlem mehrere Versuche zu machen, die gewĂŒnschte Operation doch noch auszufĂŒhren, ist es also unsinnig, selbst auch noch Wiederholungen zu programmieren, wie es bei einigen Programmen leider der Fall ist.

etv_critic = $404 ;Vektor Critical Error Handler do: ;hier steht der Programmteil, bei dem ein Fehler auftreten kann ;D0 enthĂ€lt BIOS-Fehlercode ;D1 enthĂ€lt Laufwerkskennung (0 fĂŒr A: usw.) ;Achtung: CPU mu_ sich im Supervisor-Modus befinden error: tst.1 D0 ;ĂŒberhaupt Fehler aufgetreten ? beq.s end ;-> nein: alles ok movem.l A0-A2/D1-D2,-(SP) ;Register retten move.w D1,-(SP) ;Laufwerkskennung move.w D0,-(SP) ;Fehlercode moveq #-1,D0 ;KompatibilitĂ€t zum BIOS move.l etv_critic,A0 jsr (A0) ;Critical Error Handler aufrufen addq.w #4,SP movem.l (SP)+,A0-A2/D1-D2 ;Register wieder zurĂŒck cmp.l #$10000,D0 ;Retry ? beq.s do ;-> ja: das Ganze nochmal end: ;D0 enthĂ€lt jetzt die Fehlermeldung fĂŒr den Aufrufer

Listing 2 - Aufruf des Critical Error Handlers in Assembler

Critical Error Handler des TOS

Das TOS selbst hat zwei Critical Error Handler-Routinen. Eine ist fĂŒr TOS/TTP-Programme vorgesehen und gibt immer ERROR zurĂŒck. Deswegen ist hier keine vernĂŒnftige Fehlerbehandlung möglich. Besser wĂ€re es hier gewesen, den ĂŒbergebenen Fehler unverĂ€ndert zurĂŒckzugeben.

Der andere HĂ€ndler ist bei GEM-Applikationen aktiv und sorgt fĂŒr die Anzeige der bekannten Alert-Boxen. Beantwortet der Benutzer diese mit "WEITER”, so gibt der Critical Error Handler den Retry-Code S10000 zurĂŒck, bei “ABBRUCH” wird die Fehlermeldung unverĂ€ndert zurĂŒckgegeben. Bei Meldungen mit nur einem Button wirkt dieser immer wie ein ABBRUCH-Button. Mit einem dritten Button hĂ€tte man eine Ignorier-Option (RĂŒckgabe von E_OK) realisieren können; dies wurde vermutlich unterlassen, da das Nicht-Beachten von Diskettenfehlern gefĂ€hrliche Folgen haben kann.

Zur Anzeige von Fehlermeldungen wird der Critical Error Handler nur von ‘Rwabs’ und ‘Getbpb’ benutzt, die Disk-Funktionen der unteren Ebene liefern sofort BIOS-Fehlercodes. Einzig die Verwaltung der zwei logischen Floppy-Laufwerke mittels EOTHER (s.u.) geschieht auch auf der untersten Ebene ĂŒber den Critical Error Handler.

Das AES nimmt die Umschaltung zwischen GEM- und TOS-Routine vor, wenn Programme mittels AES-’shel_write’ gestartet werden, wie es z.B. beim Start vom Desktop aus der Fall ist. Shell-Programme wie z.B. die C- oder Pascal-Shells laden Programme dagegen ĂŒber GEMDOS-'Pexec’ sozusagen “am GEM vorbei”. Bei TOS-Programmen wird zwar vielleicht der Bildschirm gelöscht, doch die GEM-internen Umstellungen bleiben aus. Dasselbe Problem tritt auch auf, wenn als GEM-Programme angemeldete Programme (‘.PRG’) gar keine sind, wie es vor allem bei

Spielen hÀufig der Fall ist. Daher darf man sich nicht wundern, wenn plötzlich Alert-Boxen erscheinen, aber vielleicht der Maus-Cursor weit und breit nicht zu sehen ist.

Beim Schreiben eines eigenen Critical Error Handlers muß man wissen, daß das AES darauf keine RĂŒcksicht nimmt. Bei seiner Initialisierung merkt es sich den Critical Error Handler Vektor und setzt ihn jedesmal darauf zurĂŒck, wenn ein TOS-Programm gestartet wird. Vor der RĂŒckkehr auf den Desktop wird wieder der HĂ€ndler des AES eingehĂ€ngt, egal was inzwischen mit dem Vektor passiert ist. Beim Start und Beenden eines GEM-Programms dagegen wird ‘etv_critic’ ĂŒberhaupt nicht verĂ€ndert. Programme im AUTO-Ordner können daher zwar einen eigenen Handler installieren, doch wird dieser nur bei TOS-Programmen aktiviert. Doch nun zurĂŒck zum Critical Error Handler des GEM. Das dokumentierte Listing zum TOS vom 6.2.1986 findet sich als Listing 3. Es kann als Anregung und Hilfe fĂŒr das Schreiben eines eigenen HĂ€ndlers dienen.

;Critical Error Handler des GEM ;Aufruf nur im Supervisor-Mode erlaubt ;Register D0,D1,D2,A0,A1,A2 werden verĂ€ndert FE3226 MOVE.W $0004 (A7) ,D0 ;Fehlercode FE322A MOVE.W $0006(A7),D1 ;Drive FE322E JSR $FE2C06 ; IPL merken und auf 7 setzen FE3234 MOVE.L A7,$00643A ;SP merken FE323A MOVE.L #$00006C3E,A7 ;eigenen Stack aufsetzen FE3240 JSR $FE2C12 ;IPL zurĂŒck FE3246 MOVEM.L D3-D7/A3-A6,-(A7) FE324A MOVE.L #$00FEF598,A1 ;Tabelle fĂŒr Zuordnung Fehler -> Alert FE3250 MOVE.W D0,-(A7) ;ĂŒbergebenen Fehlercode merken FE3252 BNE $FE325A FE3254 MOVE.W #$0000,A0 ;0 ĂŒbergeben: Default-Fehler erzeugen FE3258 BRA $FE3268 FE325A NOT.W D0 ;umrechnen: -1,-2,... -> 0,1,... FE325C MOVE.W D0,A0 FE325E CMP.W #$0011,D0 FE3262 BLE $FE3268 FE3264 MOVE.W #$0000,A0 ;Fehlernummer <= -19:Default-Fehler ;Achtung: Abfrage fĂŒr Codes > 0 fehlt ! ! FE3268 MOVE.B $00(A0,A1.L) , D0 ;Nummer des Alerts auf Tabelle holen FE326C MOVE.W D1,-(A7) ;Drive-Nummer FE326E MOVE.W D0,-(A7) ;Alert-Nummer FE3270 JSR $FE6CA6 ;Alert erzeugen und ausgeben FE3276 ADDQ.L #4,A7 FE3278 MOVE.W (A7)+,D1 ;ĂŒbergebener Fehlercode FE327A EXT.L D1 FE327C CMP.W #$0000,D0 FE3280 BEQ $FE3288 ;Abbruch-Button: ĂŒbergebenen Code zurĂŒck FE3282 MOVE.L #$00010000,D1 ;OK-Button: Retry-Code zurĂŒck FE3288 MOVE.L D1,D0 FE328A MOVEM.L (A7)+, D3-D7/A3-A6 FE328E MOVE.L $00643A,A7 ;SP zurĂŒck FE3294 RTS ;interne Alert-Nummern fĂŒr Fehlercodes -1,..,-18 FEF598 de.b 04,01,01,02,01,01,02,02,04,02,02,02,00,03,04, 02,06,00

Listing 3 - Dokumentiertes Listing des Critical Error Handlers

Den Fehlermeldungen -1...-18 wird ĂŒber eine Tabelle einer von 7 Alert-Strings zugeordnet. Die nachfolgend aufgerufenen Routinen ermitteln zu dieser “Alert-Nummer” zuerst den Objekt-Index des Strings im AES-Resource, sowie die Nummer des vorgesehenen Default-Buttons. Als Platzhalter fĂŒr die Laufwerks-Kennung enthalten manche dieser Strings ein ‘%S’. In solch einem Fall wird der String ins RAM (GEM-Variablen-Bereich) kopiert und der Platzhalter ersetzt. Die eigentliche Ausgabe auf dem Bildschirm erfolgt dann mit der normalen AES - 'form_alert ’ -Funktion.

Bei E_OK oder Fehlercodes kleiner als -18 wird der gleiche Fehler wie bei -1 erzeugt. Auf Grund eines Programmierfehlers werden jedoch positive Fehlermeldungen nicht abgefangen, was zu sehr merkwĂŒrdigen Effekten (gestreifte, gerasterte oder verschobene Alert-Boxen) oder Bomben fĂŒhren kann.

Übrigens benutzt der Critical Error Handler einen eigenen Stack, so daß der Stack des Aufrufers nicht noch durch den großen Verbrauch des AES belastet wird. Kommen wir nun zu den Alert-Boxen. Die Alerts sind intern von 0 bis 6 durchnummeriert (vgl. Listing)

Nr.0: “Disk in Floppy %S: ist schreibgeschĂŒtzt...”

Diese Meldung kommt nicht nur bei EWRPRO sondern auch bei dem nicht verwendeten Fehlercode -18.

Nr.1: “Floppy %S: antwortet nicht...”

Hiermit wird angezeigt, daß der FDC nicht ordentlich auf die Diskette selbst zugreifen konnte (EDRVNR, EUNCMD, EBADRQ, E_SEEK).

Nr.2: “Daten auf Floppy %S: defekt..."

Die Daten konnten nicht korrekt geschrieben oder gelesen werden, bzw. ein Formatierfehler trat auf (E_CRC, EMEDIA. ESECNF, EWRITF, EREADF, EBADSF oder -12).

Nr.3: “Anwendung kann Disk %S: nicht lesen...”

Diese Fehlermeldung ist Ihnen vermutlich noch nicht ĂŒber den Weg gelaufen. Sie wĂŒrde nĂ€mlich nur bei E_CHNG erscheinen, aber der BIOS-Disk-Treiber behandelt Diskettenwechsel separat und ruft den Critical Error Handler dabei nicht auf. Diese Fehlermeldung lĂ€ĂŸt sich daher hervorragend fĂŒr eigene Zwecke verwenden.

Nr.4: “AusgabegerĂ€t antwortet nicht...”

Dies tritt bei Disketten-Operationen ebenfalls nicht auf, aber der Desktop erzeugt diese Meldung, wenn beim Ausdrucken einer Datei der Drucker nicht ansprechbar ist. Dies ist die Default-Meldung und erfolgt bei E_OK, ERROR, EP APER, EUNDEV und den nicht benutzten Fehlercodes kleiner als -18.

Nr.5: “GEM Fehler"

Diese Meldung dĂŒrfte Ihnen ebenfalls unbekannt sein. Sie ist zwar fĂŒr den Critical Error Handler vorgesehen, ist aber ĂŒberhaupt keiner BIOS-Fehlermeldung zugeordnet und kann daher auch nicht erscheinen.

Falls Sie sich den Spaß machen wollen, so können Sie z.B. ihr altes RAM-TOS booten, mit einem Maschinensprache-Monitor die Zuordnungs-Tabelle (s. Listing 3) heraussuchen und an einer Stelle eine 5 eintragen.

Nr.6: “Bitte Disk einlegen”

Hierbei handelt es sich nicht um eine Fehlermeldung, sondern um eine Aufforderung, die das BIOS bei EOTHER ausgeben lĂ€ĂŸt.

Die 'form_error'-Funktion

GEM unterstĂŒtzt nicht nur die Anzeige von BIOS-Fehlern, sondern auch die von GEMDOS-Fehlern. Dies geschieht jedoch nicht automatisch ĂŒber den Critical Error Handler, sondern mittels der vom Programmierer selbst aufzurufenden AES-Funktion ‘formerror’.

Doch wer 'form_error’ so wie in den Dokumentationen angegeben ausprobiert, wird eine EnttĂ€uschung erleben, da z.B. bei ‘form_error(EFILNF)’ nur ein ‘TOS Fehler #65503’ erscheint.

Doch nicht gleich verzweifeln. ‘form_error’ ist keineswegs kaputt, sondern nur schlecht an den ST angepaßt. Dazu muß man wissen, daß die GEMDOS-Fehlercodes aus denen des PC-DOS abgeleitet wurden. Die ST-Codes von -32 an abwĂ€rts entsprechen denen des PC-DOS von 1 an aufwĂ€rts, mit einigen Abweichungen: Einige PC-DOS-Fehler gibt es beim GEMDOS nicht, und einige Fehlermeldungen sind beim ST (Codes kleiner als -64) hinzugekommen. Bei der Implementierung hat man anscheinend ‘nur’ vergessen, Torm_error’ fĂŒr die GEMDOS-Fehlermeldungen anzupassen.

Die Funktion ‘alrt_tos’ (Listing 4) rechnet die GEMDOS-Fehlernummern auf die zugehörigen PC-DOS-Nummern um, so daß bei den hĂ€ufigsten Fehlem eine vernĂŒnftige Fehlermeldung erscheint, mit den EinschrĂ€nkungen, die generell bei der Bedeutung der GEMDOS-Fehlermeldungen zu machen sind. Man braucht sich somit fĂŒr den “Kleinkram” keine eigenen Alerts mehr zu definieren.

Im einzelnen stellt ‘alrt_tos’ mittels ‘form_error’ die folgenden Alert-Boxen zur VerfĂŒgung. Angegeben sind die GEMDOS-Codes und in Klammem der fĂŒr‘form_error’ benötigte Wert.

“Diese Anwendung kann das angesprochene Objekt nicht finden.”
EFILNF (2), EPTHNF (3), ENMFIL (18)

“Die Anwendung benötigt mehr Platz zum Öffnen einer neuen Datei. Schließen Sie eine nicht benötigte Datei.”
ENHNDL (4)

“Objekt mit gleichem Namen bereits vorhanden bzw. hat den Nur-Lesen-Status.”
EACCDN (5)

“Der Arbeitsspeicher reicht nicht fĂŒr diese Anwendung.”
ENSMEM (8), auch bei nicht benutzten -41 (10) und -42(11)

“Floppy mit dieser Kennung unbekannt.”
EDRIVE (15)

Bei allen anderen Fehlercodes zwischen -32768 und 63 (einschließlich der Null) kommt die bekannte allgemeine Meldung ‘TOS Fehler #’, wobei negative Nummern als positive 16-Bit-Integer aufgefaßt werden. Fehlercodes von 64 bis 32767 werden ignoriert. Dies sollte wohl eher so funktionieren, daß auch die negativen Werte ignoriert werden, aber hier wurde wieder nicht berĂŒcksichtigt, daß ‘ints’ in C normalerweise vorzeichenbehaftete Zahlen sind.

Bei den ignorierten Fehlercodes gibt ‘form_error’ immer 0 zurĂŒck. Bei den anderen ist ‘form_error’ dafĂŒr ausgelegt, auch Alerts mit zwei Buttons auszugeben. Bei OK erhielte man dann eine 1, bei ABBRUCH eine 0. Da in dieser GEM-Version aber alle Alerts nur einen Button haben, bekommt man immer 0 zurĂŒck.

Im AES Resource findet man noch den Alert “Falsche Funktionsnummer”, der eigentlich recht gut zu EINVFN passen wĂŒrde. Bei EINVFN gibt’s jedoch nur den ĂŒblichen ‘TOS Fehler #65504’. Es gibt auch keinen anderen Fehlercode, der diese Meldung ĂŒber ‘form_error‘ erzeugt. In einigen FĂ€llen tritt diese Fehlermeldung aber auf, so daß ich vermute, daß GEM diesen Fehler unter bestimmten Bedingungen selbst ausgibt.

'form_error' auf dem Desktop

In Anwenderprogrammen finden sich diese Fehlermeldungen recht selten, da sich die richtige Benutzung von ‘form_error‘ anscheinend noch nicht herumgesprochen hat. Der Desktop verwendet sie jedoch, d.h. dort werden die Codes korrekt umgerechnet.

Wie schon bei der “Programmverwaltung” erlĂ€utert, können Prozesse mit ‘Pterm’ Fehlermeldungen an die sie aufrufenden Prozesse zurĂŒckgeben.

Beim Starten eines Programms “vom Desktop aus” wird es in Wirklichkeit vom AES geladen, nachdem der Desktop sich beendet hat. Nach der Terminierung des Programms bekommt zuerst das AES wieder die Kontrolle ĂŒber das System, bevor es den Desktop erneut startet. Handelt es sich dabei um ein GEM-Programm, das einen Fehlercode zurĂŒckgegeben hat, so wird dieser ĂŒber ‘form_error’ ausgegeben, wobei hier die Codes ebenfalls korrekt umgerechnet werden! Beendet man also ein GEM-Programm durch RĂŒckgabe einer GEMDOS-Fehlermeldung, so zeigt das AES den Fehler dem Anwender an.

Bei TOS-Programmen erfolgt diese Anzeige jedoch nicht.

Ausblick

NĂ€chsten Monat geht es endlich an den wichtigsten Teil des GEMDOS - das eigentliche Disketten-Betriebssystem. Begonnen wird mit der internen Verwaltung von Dateien und der File Allocation Table (FAT).

Alex Esser