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