Somewhere over the Rainbow: Intimes zu TOS 1.4

Nun ist es endlich soweit - die von vielen lang erwartete neue Version unseres Lieblings-Betriebssystems TOS ist fertig. Das neue TOS 1.4 wurde auf der Düsseldorfer ATARI-Messe offiziell vorgestellt und endgültig freigegeben. Dies ist Grund genug, es auch unseren Lesern vorzustellen.

TOS 1.4 hört auch auf den Decknamen “Rainbow TOS", da das ATARI-Zeichen in der “Desktop info"-Dialogbox in einer farbigen Animation (nur im Farbmodus) zu sehen ist, die wohl an einen Regenbogen erinnern soll (engl. “rainbow" = Regenbogen). Diese offizielle Version datiert vom 6.4.1989 und ist damit zu unterscheiden von den “Beta-Versionen" des Jahres 1988 und dem “Messe-TOS" vom 22.2.1989, das auf der letzten CeBIT zu sehen war.

Erfreulicherweise gibt es für Software-Entwickler auch eine Dokumentation, in der Änderungen, Fehler und besondere Programmierhinweise aufgeführt sind. Diese Doku ist zwar nicht ganz vollständig und fehlerfrei, aber bietet wesentlich mehr, als man sonst von ATARI gewohnt ist. Überhaupt ist die Unterstützung der Software-Entwickler besser geworden, als sie es früher einmal war. Trotzdem konnte ich es nicht lassen, mir das TOS (speziell BIOS und GEMDOS) ein wenig unter der Lupe anzusehen, sprich zu disassemblieren und recompilieren.

Heute möchte ich Ihnen die Ergebnisse bezüglich des BIOS mitteilen, und zwar in drei Stufen: für Anwender, Programmierer und die TOS-Spezialisten, die ihren Computer bis in die letzten Eingeweide kennen möchten. In den nächsten Ausgaben der ST Computer beschäftige ich mich dann intensiv mit den Neuerungen beim GEMDOS, in Anlehnung und als Ergänzung zur GEMDOS-Serie “Auf der Schwelle zum Licht" (ST 1/88-11/88). Auf die für Nicht-Programmierer interessanteren Verbesserungen am Desktop wird in dieser Zeitschrift an anderer Stelle eingegangen.

Für den Anwender

Kommen wir also zunächst zu den Änderungen, die für den Anwender interessant sind. Bekanntlich gibt es die sogenannten boot-fähigen Disketten, d.h. Disketten, von denen beim Reset automatisch ein kleines Programm geladen wird, das allerlei nützliche Dinge tun kann. Dazu zählen z.B. der “TOS-Loader" von ATARI, mit dem ein RAM-TOS von Diskette gebootet werden kann, Programme, die einem das Einstellen der Systemuhr erlauben oder Hinweise über die Diskette ausgeben (Aladin). Es gibt vor allem bei Spielen sogar Boot-Sektor-Programme, die gleich das eigentliche Programm starten (Auto-Start-Disketten). Am verbreitetsten unter den Boot-Programmen sind aber wohl die “Boot-Sektor-Viren", über die wohl schon genug geschrieben wurde.

Das Laden und Starten dieser Boot-Programme geschah aber bisher nur beim Kaltstart (d.h. nach dem Einschalten des Rechners) oder wenn keine weiteren boot-fähigen Laufwerke vorhanden waren (Harddisk, EPROM-Disk, reset-residente RAM-Disk). Dies ist nun anders, da jetzt bei jedem Reset auf jeden Fall versucht wird, ein Boot-Sektor-Programm von Laufwerk A: zu laden. Dies vereinfacht die Benutzung der oben erwähnten Auto-Start-Disketten, erhöht aber auch die Virengefahr. Ferner sollte man nun immer eine Diskette in A: haben, wenn man nicht von Diskette bootet, da der Boot-Vorgang sonst unnötig lange dauert (wegen des versuchten Zugriffs auf eine nicht vorhandene Diskette).

Beim Booten von Harddisk (oder anderen DMA-Geräten) wird nun beim Lesen des Boot-Sektors ein zweiter Versuch gemacht, falls beim ersten ein Fehler auftrat. Ausgenommen ist der Fall, daß keine Harddisk angeschlossen ist; dann wird weiterhin nur ein Leseversuch gemacht.

Eine wichtige und schwierige Aufgabe des TOS ist die sichere Erkennung von Diskettenwechseln, da sonst sehr leicht Daten auf Disketten zerstört werden können. Bei Benutzung eines physikalischen Laufwerks als zwei logische Laufwerke, was zur bekannten häufigen Aufforderung “Bitte Disk X: in Floppy A: einlegen" führt, konnte es passieren, daß ein Diskettenwechsel nicht erkannt wurde, wenn er und die Bestätigung dieser Aufforderung sehr schnell (unter 1,5 Sekunden) erfolgten. Dieser Mangel ist nun behoben.

Auch an der Tastaturbehandlung wurde einiges geändert. So kann ein Reset nun endlich durch Tastendruck, nämlich durch CONTROL-ALTERNATE-DELETE, ausgelöst werden. Dabei wird ein Warmstart durchgeführt, d.h. reset-residente RAM-Disks usw. bleiben erhalten. Auch ein Kaltstart ist möglich, wenn zusätzlich noch die rechte SHIFT-Taste gedrückt wird. Dabei wird fast der gesamte Speicher gelöscht, so daß dies vorher gut überlegt sein will.

Die Tastenwiederholung wurde leicht modifiziert. Wenn man eine Taste gedrückt hielt (z.B. ’a’), bis die Tastenwiederholung ansprach, und dann eine weitere betätigte (z.B. ’s’), erschien nur ein 's', und die Tastenwiederholung blockierte, bis mindestens eine der Tasten losgelassen und eine weitere gedrückt wurde. Nun wird auch das ‘s’ automatisch wiederholt, bis eine weitere Taste gedrückt wird, usw.

Für den Programmierer

Auch für den Programmierer gibt es einige Neuigkeiten. Da wären zunächst einmal eine geänderte und eine neue XBIOS-Funktion. Die neue XBIOS-Funktion Floprate (Nummer 41) erlaubt das Ermitteln und Verstellen der Floppy-Seek-Rate (Spurwechselzeit), und zwar für jedes Laufwerk einzeln. Dies ging bisher nur mit bestenfalls halblegalen Methoden (s. [1], Kapitel 8.2.). Warum ATARI die XBIOS-Nummer 40 unbenutzt gelassen hat, bleibt wohl ein Geheimnis. Die Deklaration in C sieht so aus:

long Floprate(int drive, int rate)

Für die Nicht-C-Programmierer: Die Funktion hat zwei 16-Bit-Integer-Parameter und liefert einen 32-Bit-Integer-Wert zurück. Der erste Parameter drive gibt das Laufwerk an (0 oder 1, andere Werte sind zu vermeiden), der zweite die neue Seek-Rate. rate ist dabei genauso wie die Systemvariable i ($440) kodiert. Werte von 0 bis 3 stehen dabei für Seek-Raten von 6, 12, 2 bzw. 3 Millisekunden.

Die XBIOS-Funktion Rsconf wurde erweitert und besser dokumentiert. Übergibt man als ersten Parameter (Baud-Rate) den Wert -2, liefert die Funktion die mit Rsconf eingestellte Baud-Rate zurück. Wenn der MFP-Chip durch direkten Zugriff programmiert wird, bemerkt dies

# Übersicht über das BIOS des TOS 1.4
; L=siehe Listing, T=siehe Text 
; sonst inhaltlich unverändert

fc0000 L system header block 
fc0030   reset, Kaltstart
fc01f2 L Warmstart 
fc0530   von Floppy booten
fc054c   von DMA booten
fc0578 L Boot-Sektor von DMA-Bus laden 
fc060e   DMA-Kommandobyte ausgeben
fc0628   ROM-Modul testen und init.
fc0652   Dummy-RTS-Routine
fc0654   RAM-Lesetest
fc066a   Speicherkonfigurationstest
fc068a   Standard-BIOS-Farbpalette
fc06aa   HBL-Handler
fc06c0 L VBL-Handler fc07a2   XBIOS-Vsync
fc07ba   BIOS-Critical-Error-Handler
fc07c4   TRAP #14/TRAP #13-Handler
fc0950   XBIOS-Supexec
fc0956   BIOS-Bcon...
fc09f8   BIOS-Drvmap
fc09fe   BIOS-Kbshift
fc0a10   BIOS-Getmpb
fc0a3c   BIOS-Setexc
fc0a54   BIOS-Tickcal
fc0a5c   XBIOS-Physbase/Logbase/Getrez/Setscreen
fc0ac4   XBIOS-Setpalette/Setcolor
fc0af0   XBIOS-Puntaes
fc0b0a   Bömbchen-Routinen
fc0bb6   Sektor kopieren
fc0bd8   Laufwerke init. (Sprung über hdv_init)
fc0bf4   Auto-Ordner-Programme ausführen
fc0efa   XBIOS-Scrdmp
fc0d0c   über 'dumpvec' aufgerufene Hardcopy-Routine
fc0dc2   Timer-B-Zählroutine
fc0dfe   reset-residente "Päckchen"-Programme suchen und ausführen
fc0e3e   XBIOS-Gettime/Settime
fc0e62   Kopie des System-header-blocks anlegen
fc0e9e   XBIOS-Blitmode
fc0ec6   Test, ob Blitter vorhanden

Floppy-Routinen
fc0ef0   Laufwerk init. (flopini)
fc0f38   XBIOS-Floprd
fc0fe8   Fehlernummer aus FDC-Fehler bestimmen
fc100a   XBIOS-Flopwr
fc10c6   XBIOS-Flopfmt
fc1286   XBIOS-Flopver
fc1360   Floppy-VBL-Handler
fc13dc   floplock
fc145c   flopfail
fc146a   flopok
fc14b0   Spur ansteuern
fc14ce   Restore und Seek
fc1502   Spur suchen (go2track)
fc1528   Restore
fc153e   FDC-Kommando schicken
fc1582   FDC-Reset
fc159c   Laufwerk und Seite selektieren (2 Routinen)
fc16d8   Kommando-Bytes an FDC schicken
fc1640 L Test auf Diskettenwechsel für 'Bitte Disk einlegen...' 
fc1682   DSB neu setzen
fc1692 L *** XBIOS-Floprate: Seek-Rate ermitteln/neu setzen *** 
fc16ba T Floppy-hdv_init 
fc1732   BIOS-Getdsb
fc173c   BIOS-Getbpb
fc18ec T BIOS-Mediach
fc1956   interne Diskettenwechsel-Routine
fc1a24   BIOS-Rwabs
fc1aac   floprw
fc1c76   XBIOS-Random
fc1cc6 L Floppy-hdv_boot
fc1d42 T XBIOS-Protobt
fc1e2e   Checksumme für Boot-Sektor berechnen
fc1e5e   Intel- nach Motorola-Format wandeln

Rsconf nicht und liefert einen falschen Wert. Die restlichen Parameter sind bei diesem Aufruf beliebig.

Rsconf hat laut ATARI-XBIOS-Dokumentation keinen Rückgabewert, aber schon immer wurden die MFP-Register UCR, TSR, RSR und UDR vor dem Rsconf zurückgeliefert (außer bei einer “Baud-Rate” von “-2”). Dabei sind alle vier Register in einem Langwort zusammengepackt (UCR im höchstwertigen Byte, usw.). Die Rainbow-TOS-Dokumentation segnet diese nun ab, doch spricht sie dabei von den Registern SCR, UCR, RSR und TSR. Diese Bezeichnungen wären auch sinnvoller, da dies die Register sind, die man mit Rsconf auch setzen kann.

Protobt soll “IBM-kompatiblere” Boot-Sektoren erzeugen. Die einzige Änderung, die ich feststellen konnte, ist ein verändertes Media-Byte im Boot-Sektor bei einseitigen 80-Track-Disketten. Statt $F8 steht hier nunmehr $F9, obwohl eigentlich unter PC-DOS $F8 vorgesehen ist ([1]). Da ich zu wenig von PC-DOS verstehe, kann ich nicht sagen, ob das ein neuer Fehler oder tatsächlich eine Verbesserung ist. Um volle MS-DOS-Kompatibilität zu erreichen, sollen die ersten drei Bytes im Boot-Sektor $E9,$00,$4E sein. Der eigentliche Fortschritt besteht aber in einer verbesserten Formatierroutine des Desktops, die das Media-Byte in der FAT und die ersten drei Bytes im Boot-Sektor richtig setzt.

Die “Bömbchen”-Routine, die unerwartete Exceptions “behandelt”, terminiert das aktive Programm nun mit Pterm(-1) statt mit Pterm(0), so daß das übergeordnete Programm 0x0000ffff von Pexec zurückbekommt.

Eigene Tastatur-Interrupt-Routinen standen immer vor dem Problem, “normale” Tastendrücke von aus mehreren Bytes bestehenden “Paketen” (z.B. Maus-Bewegungs-Paket) unterscheiden zu müssen. Am Offset $24 ab dem von Kbdvbase zurückgelieferten Zeiger fand sich in allen TOS-Versionen ein Byte-Flag, das anzeigt, ob gerade ein aus mehreren Zeichen bestehendes “Paket” vom Tastaturprozessor erwartet wird. Ab nun ist seine Lage (dieser Offset) offiziell dokumentiert.

Eigene Tastatur-Interrupt-Routinen. die sich in den ikbdsys-Vektor einklinken und Tastendrücke einer “Sonderbehandlung” unterziehen wollen, sollten Bytes nur berücksichtigen, wenn das Flag Null ist.

Diverses

fc1e84   Hardcopy-Ausgaberoutinen (4 Stück) 
fc1ee0   superschnelle Löschroutine
fc1f4c   MEGA-Uhr nach GEMDOS-Ühr
fc1f70 L Test, ob MEGA-Uhr vorhanden 
fc1fc2   Gettime für MEGA-Uhr
fc2080   Settime für MEGA-Uhr
fc215c   Hardcopy

IKBD, RS232, Centronics, MFP
fc315e   Uhrzeit-Paket in BIOS-Format umrechnen
fc31a8 L IKBD-Gettime
fc31d2   IKBD-Settime
fc3240   Byte -> BCD
fc3254   BCD -> Byte
fc326a   MIDI-I/O-Routinen
fc32f6 L Centronics-I/O-Routinen
fc33a6   RS232-Routinen (Ein-/Ausgabe und Status)
fc344a   IKBD-Routinen (Ausgabe und Status) 
fc3480   XBIOS-Ikbdws
fc3494   Tastatur-Routinen (Eingabe, Status, Ausgabestatus) 
fc34e4   "Glocke" starten
fc34fc   MFP init.
fc365e   Default-IOREC-Daten und RS232-Interrupt-Vektoren
fc36ac   MFP-Timer init.
fc3754   XBIOS-Mfpint
fc377e   XBIOS-Jdisint/Jenabint
fc37f2   RS232-Interrupt-Routinen (4 Stück)
fc3932   weitere RS232-Routinen
fc39fe   XBIOS-Iorec
fc3a16 L XBIOS-Rsconf
fc3aec T IKBD/MIDI-Interrupt
fc3c70 L Keyboard-Interrupt
fc3fbe MIDI-Eingabe-Interrupt
fc3fec   Maus-Emulator
fc4034 L *** Shift-Ctrl-Alt-Routine ***
fc407e   XBIOS-Giaccess/Ongibit/Offgibit
fc4102   XBIOS-Initmous
fc41cc   XBIOS-Xbtimer
fc4206   XBIOS-Keytbl/Bioskeys
fc424c   XBIOS-Dosound
fc4260   XBIOS-Setprt
fc4272   XBIOS-Kbrate/Kbdvbase
fc429c   200 Hz-Interrupt-Handler
fc42fe   Sound-Interrupt-Routine (ohne Sound-Daten)

Ende des BIOS
fc4388   GEMDOS und BIOS-Routinen für GEMDOS

BIOS-Bildschirmtreiber 
fca2ec   VDI-ESC-Handler
fca342   VDI-ESC 101
fca358   ASCII-Out/Conout-Einsprung
fca38e   CTRL-Kodes
fca3b4   TAB
fca3c6 T ESC-Behandlung
fca45c   ESC-Verteiler
fca4b6   VDI   ESC   1
fca4d8   VDI   ESC   17,3,2,   ESC   E,A,C,D,H
fca540   Rest-Bildschirm, -Zeile löschen 
fca564   VDI   ESC   11,13,14,15,16,18,19
fca5e8   ESC   I,L,M
fca636   Cursor ein, ESC e,f,j,k,l
fca6b6   Bildschirmbereich löschen, LF
fca720   XBIOS-Cursconf
fca778   ASCII-Zeichen ausgeben
fca846 T Blitter-Routine #0
fca8d4   ab Cursor nach oben scrollen
fca8da T Blitter-Routine #1
fca936   ab Cursor nach unten scrollen
fca93c T Blitter-Routine #2
fca9b4   Bildschirmbereich löschen
fcaa46   Cursor positionieren
fcab20   ...
fcb4fc   TOS-Bildschirmausgabe je nach Auflösung init. 
fcb586   Blitter-Vektoren installieren 
fcb5a0   ...
fcb5de   Blitter-Vektor-Tabelle laden 
fcb65e   ...

Es wird vom BIOS auf ungleich Null gesetzt, wenn ein Header-Byte eines “Paketes” empfangen wurde, und ist wieder Null, wenn der Empfang des “Pakets” beendet ist. Wenn man das Flag abfragen möchte, bevor man seine Interrupt-Routine installiert, sollte man zuerst solange warten, bis es Null wird, dann das Interrupt-Level (IPL) der CPU auf 7 setzen. und, falls das Flag nun schon wieder gesetzt ist, den IPL wieder zurücksetzen und erneut warten. Ansonsten kann ikbsys neu gesetzt und der IPL restauriert werden. So schlägt es ATARI vor. Ich würde zusätzlich noch eine Timeout-Abfrage einbauen, um eine Endlosschleife zu verhindern, falls das “Paket” aus irgendwelchen Gründen nicht vollständig gesendet wird bzw. ankommt.

Hier noch einige Erklärungen zur verbesserten Diskettenwechselerkennung, die oben schon erwähnt wurde. Bei jedem Diskettenzugriff merkt sich das BIOS die aktuelle Systemzeit. Die Mediach-Routine meldet nun, wenn es eigentlich einen “unsicheren” Wechselstatus festgestellt hat, trotzdem ein “kein Wechsel”, wenn seit dem letzten Zugriff nicht mehr als eine bestimmte maximale Zugriffszeit vergangen ist. Es geht also davon aus, daß “schnelle” Diskettenwechsel (kürzer als die maximale Zugriffszeit) nicht möglich sind. Dies spart das zu häufige Lesen des Boot-Sektors bei schreibgeschützten Disketten (wo ein unsicherer Status ständig auftritt).

Bisher wurde zur Zeitmessung der 200-Hz-Zähler (_hz_200) benutzt, nun wird frclock genommen (warum nur?). Daher ist die maximale Zugriffszeit jetzt von der Bildwiederholfrequenz abhängig. Sie liegt bei 1.2 s, 1,37 s bzw. 1,64 s für 71 Hz, 60 Hz bzw. 50 Hz Bildwiederholfrequenz (bisher immer 1,5 s). Daher wird in hdvjnit die interne Variable für die maximale Zugriffszeit auf 82 statt bisher 300 gesetzt. Die eigentliche Verbesserung besteht nun darin, daß die gemerkte letzte Zugriffszeit beim Wechsel zwischen den logischen Laufwerken A: und B: nach der Aufforderung “Bitte Disk X: in Floppy A: einlegen” auf Null gesetzt wird. Damit liefert Mediach nach einem solchen Wechsel nun auf jeden Fall den wahren Diskettenwechselstatus zurück; bisher wurde also bei einer Wechselzeit unter 1,5 s der Wechsel von Mediach nicht gemeldet.

BIOS-Listing wesentlich geänderter Routinen

;OS Header

FCOOOO BRA     $FC0030
FC0002 dc.b    1,4                  ;Version 1.4
FC0004 dc.l    $FC0030              ;Reset-Adresse
FC0008 dc.l    $FC0000              ;Beginn TOS
FC000C dc.l    $00611c              ;Beginn freies RAM
FC0010 dc.l    $FC0030
FC0014 dc.l    $FE8230              ;Adresse GEM-MAGIC
FC0018 dc.l    $04061989            ;Default-Systemdatum 22.2.1989
FC001C dc.w    3                    ;Land: FRG, PAL-Norm
FC001E dc.w    $1286                ;Default-Systemdatum im GEMDOS-Format
FC0020 dc.l    $00378c              ;Adresse GEMDOS-Variable 'mifl'
FC0024 dc.l    $000E7d              ;Adresse BIOS-Tastaturvariablen
FC0028 dc.l    $005622              ;Adresse GEMDOS-Variable 'act_pd'
FC002C dc.l    0

Listings wesentlich geänderter Routinen

;Warmstart
...
FC0432 JSR     $FC95C8              ;GEMDOS init.
FC0438 MOVE.W  $FC001E,$0060BE      ;Default-Datum setzen
FC0442 JSR     $FC1F4C              ;MEGA-Uhr übernehmen, falls vorhanden
FC0448 BCC     $FC0462              ;*** -> MEGA-Uhr da     ***
FC044A BSR     $FC31A8              ;*** IKBD-Uhr auslesen  ***
FC044E SWAP    D0                   ;*** Datum holen        ***
FC0450 TST.B   D0                   ;***                    ***
FC0452 BEQ     $FC0462              ;*** -> "Zeit ungültig" ***
FC0454 MOVE.W  D0,$0060BE           ;*** Datum übernehmen   ***
FC045A SWAP    D0                   ;***                    ***
FC045C MOVE.W  D0,$00378A           ;*** Zeit übernehmen    ***
FC0462 BSR     $FC0530              ;Floppy-Boot versuchen

;Boot-Sektor vom DMA-Bus laden 
;A4 von DMA-Boot-Routine gelöscht
FC0578 MOVEQ   #$01,D5              ;*** 2 Versuche ***
FC057A LEA     $8606(A4),A6         ;alles wie bisher...
FC057E LEA     $8604(A4),A5
FC0582 ST      $043E(A4)
FC0586 MOVE.L  $04C6(A4),-(A7)
FCO58A MOVE.B  $0003(A7),$860D(A4)
FC0590 MOVE.B  $0002(A7),$860B(A4)
FC0596 MOVE.B  $0001(A7),$8609(A4)
FC059C ADDQ.W  #4,A7
FC059E MOVE.W  #$0098,(A6)
FC05A2 MOVE.W  #$0198,(A6)
FC05A6 MOVE.W  #$0098,(A6)
FC05AA MOVE.W  #$0001,(A5)
FC05AE MOVE.W  #$0088,(A6)
FC05B2 MOVE.B  D7,D0
FC05B4 OR.B    #$08,D0
FC05B8 SWAP    D0
FC05BA MOVE.W  #$008A,D0
FC05BE BSR     $FC060E
FC05C0 BNE     $FC05F0              ;-> Timeout bei Kommando-Byte: Abbruch
FC05C2 MOVEQ   #$03,D6 
FC05C4 LEA     $FC05FE(PC),A0
FC05C8 MOVE.L  (A0)+,D0 
FC05CA BSR     $FC060E
FC05CC BNE     $FC05F0              ;-> Timeout bei Kommando-Byte: Abbruch
FC05CE DBF     D6,$FC05C8
FC05D2 MOVE.L  #$0000000A,(A5)
FC05D8 MOVE.W  #$0190,D1 
FC05DC BSR     $FC0612
FC05DE BNE     $FC05F0              ;-> Timeout bei Kommando-Byte: Abbruch
FC05E0 MOVE.W  #$008A,(A6)
FC05E4 MOVE.W  (A5),D0              ;DMA-Statusregister
FC05E6 AND.W   #$00FF,D0
FC05EA BEQ     $FC05F2              ;-> ok
FC05EC DBF     D5,$FC057A           ;*** DMA-Fehler: neuer Versuch ***
FC05F0 MOVEQ   #$FF,D0              ;Fehlermeldung
FC05F2 MOVE.W  #$0080,(A6)          ;Rest wie bisher...
FC05F6 TST.B   D0 
FC05F8 SF      $043E(A4)
FC05FC RTS

;VBL-Routine
FC06C0 ADDQ.L  #1,$000466           ;zunächst wie bisher
FC06C6 SUBQ.W  #1,$000452 
FC06CC BMI     $FC079A
FC06D0 MOVEM.L D0-A6,-(A7)
FC06D4 ADDQ.L  #1,$000462 
FCO6DA SUBA.L  A5 , A5
FC06DC MOVE.B  $FA01(A5),D1         ;*** Monochrom-Bit nur einmal lesen ***
FC06E0 MOVE.B  $8260(A5),D0
FC06E4 AND.B   #$03,D0
FC06E8 CMP.B   #$02,D0
FC06EC BGE     $FC0702
FC06EE BTST    #$07,D1              ;*** Abfrage im Register            ***
FC06F2 BNE     $FC0722
FC06F4 MOVE.W  #$07D0,D0
FC06F8 DBF     D0,$FC06F8
FC06FC MOVE.B  #$02,D0
FC0700 BRA     $FC0714
FC0702 BTST    #$07,D1              ;*** Abfrage im Register            ***
FC0706 BEQ     $FC0722
...                                 ;ab hier weiter wie bisher

;Diskettenwechsel-Aufforderung
FC1640 CMPI.W  #$0001,$0004A6       ;zunächst nichts  Neues
FC1648 BNE     $FC1680
FC164A MOVE.W  $0010(A7),D0
FC164E CMP.W   $000ED4,D0
FC1654 BEQ     $FC167C
FC1656 MOVE.W  D0,-(A7)
FC1658 MOVE.W  #$FFEF,-(A7)
FC165C BSR     $FC07BA
FC1660 ADDQ.W  #4,A7
FC1662 MOVE.W  #$FFFF,$0009FA       ;Schreibschutzstatus A,B unsicher
FC166A LEA     $0009FC,A0           ;*** letzte Zugriffszeit  ***
FC1670 CLR.L   (A0)+                ;*** rücksetzen für A:    ***
FC1672 CLR.L   (A0)                 ;*** und B                ***
FC1674 MOVE.W  $0010(A7),$000ED4    ;akt. Floppy neu setzen
FC167C CLR.W   $0010(A7)
FC1680 RTS

;XBIOS #41: Seek-Rate ermitteln/neu setzen 
FC1692 LEA     $000A4C,A0           ;DSB Floppy A
FC1698 TST.W   $0004(A7)            ;Laufwerk
FC169C BEQ     $FC16A4
FC169E LEA     $000A50,A0           ;DSB Floppy B
FC16A4 MOVE.W  $0002(A0),D0
FC16A8 MOVE.W  $0006(A7),D1         ;neue Seek-Rate
FC16AC CMP.W   #$FFFF,D1
FC16B0 BEQ     $FC16B6              ;-> nein: nur lesen
FC16B2 MOVE.W  D1,$0002(A0)         ;neue Seek-Rate setzen
FC16B6 EXT.L   D0                   ;akt. Seek-Rate zurück
FC16B8 RTS

Die folgenden Änderungen sind von ATARI nicht dokumentiert worden, aber trotzdem wahr.

Die ESC Y-Funktion des VT52-Emulators zum Setzen der Cursor-Position kontrolliert nun den Spalten- und Zeilenparameter. Bei Werten größer als die maximale Spalte bzw. Zeile wird der Maximalwert benutzt. Bisher wurden beliebige Koordinaten “geschluckt”. Negative Werte werden weiterhin nicht abgefangen.

Die XBIOS-Funktion Gettime blieb bisher in einer Endlosschleife hängen, wenn das vom Tastaturprozessor angeforderte Uhrzeit-Paket nicht ankam. Nun erfolgt nach einer Sekunde ein Timeout, und Gettime liefert dann Null zurück.

Die über die IOREC-Strukturen verwalteten I/O-Puffer für Tastatur, RS232 und Midi durften nur maximal 32 kB groß sein. Jetzt sind sogar 64 kB erlaubt.

Für Leute, die eigene Interrupt-Routinen über die Kbdvbase-Vektoren midisys und ikbdsys einhängen, hat TOS 1.4 noch eine Überraschung parat. Vom BIOS werden die Register D0-D3, A0-A3 und A5 gerettet, so daß man annehmen konnte, daß man diese Register selbst nicht retten muß (dokumentiert ist die Programmierung solcher Interrupt-Routinen ja nirgends). Wer nun A5 verändert hat, guckt ab TOS 1.4 in die Röhre, da A5 nach Beendigung der eigenen Routinen immer Null sein muß. Dies kommt durch die Code-Optimierungen zustande, die ATARI vorgenommen hat.

Neue garantierte Systemvariablen gibt es eigentlich keine. “Eigentlich” heißt, daß die in früheren TOS-Versionen unbenutzte Systemvariable $59E (Wort) beim Reset zwar gelöscht, aber sonst nirgendwo im TOS angesprochen wird. Noch merkwürdiger ist, daß bei der Beta-Version an dieser Stelle stattdessen noch die Systemvariable _bootdev ($446) gelöscht wurde, wozu das auch immer gut sein sollte. Falls dies nicht einfach Unsinn ist, könnte es höchstens sein, daß $59E von einem anderen ATARI-Programm noch benötigt wird (ähnlich dem punptr des Harddisk-Treibers), wer weiß.

Der system header block, der am Anfang des TOS zu finden ist (die Systemvariable _sysbase ($4f2) zeigt darauf), ist nun offiziell dokumentiert (s. Abb. 1). Eine genauere Erläuterung findet sich in [4].

Neu ist allerdings die Dokumentation zu den Konfigurations-Bits. Bit 0 steht hier für NTSC- bzw. PAL-Fernsehnorm, Bits 1 bis 15 beinhalten eine Länderkennung (s. Abb. 2).

Für die Benutzung von p_run aus dem OS-Header ist es wichtig, die Adresse unter TOS 1.0 zu kennen. Bei allen TOS-Versionen außer der spanischen (!) lautet sie $602C, bei der spanischen $873C.

Offset Name C-Datentyp Bedeutung
$00 os_entry unsigned int Sprungbefehl auf Reset-Handler
$02 os_version unsigned int TOS-Versionsnummer
$04 reseth char * Zeiger auf Reset-Handler
$08 os_beg OSHEADER* Zeiger auf diesen Header
$0c os_end char * Zeiger auf Ende des von BIOS/GEMDOS/VDI benutzten RAMs
$10 os_rsv1 char * unbenutzt, reserviert
$14 os_magic char * Zeiger auf Parameterblock für Speicherbedarf des GEM
$18 os_date long Datum der TOS-Erstellung (Format $JJJJMMDD)
$1C os_conf unsigned int Konfigurations-Bits (s. Text)
$1E os_dosdate unsigned int Datum der TOS-Erstellung (GEMDOS-Format)
:ab hier erst ab TOS 1.2
$20 p_root char ** Zeiger auf ‘mifl’-Listen
$24 pkbshift char ** Zeiger auf Keyboard-Shift-Variable
$28 p_run char ** Zeiger auf Zeiger des aktuellen GEMDOS-Prozeßdescriptors
$2C p_rsv2 char * unbenutzt, reserviert

Abb. 1: Der “OS-header” (OSHEADER)

Alte und neue Fehler

Leider hat ATARI einige Fehler im BIOS immer noch nicht beseitigt. BIOS/XBIOS-Aufrufe aus Interrupt-Routinen heraus sind immer noch gefährlich, da die Interrupts während des Rettens der Register in die BIOS save area weiterhin nicht gesperrt werden (s. hierzu [2]).

Der Boot Device-Fehler besteht noch immer. Beim Erstellen der Ur-Environment-Strings wird das Boot-Laufwerk fälschlich mit ‘move.b $446,d0' statt ‘move.w $446,d0’ ermittelt. Beim Laden der Auto-Ordner-Programme ist an einer Stelle eine Stack-Korrektur immer noch falsch (addq #6 statt add #12), was in ungünstigen Fällen zum Absturz führen kann.

Einige Fehler wurden nun zum Feature deklariert, d.h. man muß mit ihnen leben bzw. sie umgehen, wobei auch hier ATARI hilfreich zur Seite steht:

Die Ausgabe-Status-Routinen (Bcostat) für Tastaturprozessor und MIDI-Schnittstelle waren und bleiben vertauscht. Bcostat(4) liefert also nun offiziell den MIDI-und Bcostat(3) den IKBD-Status. Witzigerweise ist dies in der TOS-Doku genau verkehrt herum, also so wie es eigentlich sein sollte, angegeben!

screenpt wird nach dem Setzen der neuen Bildschirmadresse in der VBL-Routine nicht gelöscht. Dies führt zu Komplikationen, wenn parallel mit Setscreen gearbeitet wird (s. [4]). ATARI empfiehlt hier, entweder nur jeweils eine Möglichkeit zu benutzen, oder vor dem Aufruf von Setscreen screenpt auf Null zu setzen. Da aber ein vorher gelaufenes Programm schon screenpt benutzt haben könnte, bleibt einem wohl nichts anderes übrig, als screenpt bei jedem Setscreen zu löschen!

Programme, die sich in den resvector eingehängt haben, können zwar mit 'jmp (a6)’ ins BIOS zurückspringen, doch müssen sie sich dann vorher aus resvector aushängen, da sie sonst erneut aufgerufen werden. Daher hatte ATARI in der Dokumentation zur Beta-Test-Version des TOS 1.4 garantiert, daß ‘jmp $24(a6)’ zum Sprung ins BIOS nach der resvector-Abfrage führt (siehe [4]). Dies ist in der TOS 1.4-Doku wieder verschwunden, vermutlich weil sich damit nur jeweils ein Programm in resvector installieren kann. Nun wird eine andere Methode vorgeschrieben, nach der sich jedes Programm bei der Installation seiner Reset-Routine resvector und resvalid merken soll, um diese Werte, wenn es über resvector aufgerufen wird, wieder zurückzusetzen. Dadurch können mehrere Programme auf diese Weise resident gemacht werden, allerdings müssen sie sich nun auch beim Reset aushängen!

TOS 1.4 sollte dafür sorgen, daß Zeit und Datum zumindest beim Reset nicht verlorengehen, indem es ausnutzt, daß der Tastaturprozessor die Zeit beim Reset nicht vergißt. Für ST-Benutzer, die über keine eingebaute Uhr verfügen, wäre dies eine Erleichterung, da sie die Uhr nur einmal nach dem Einschalten stellen müßten (z.B. mit dem Kontrollfeld-Accessory). Nur wenn die Uhr beim Warmstart nicht sinnvoll eingestellt ist, würde sie auf den bekannten Default-Wert (hier 6.4.1989) gesetzt. Beim Warmstart wird also zunächst geprüft, ob eine eingebaute MEGA-Uhr vorhanden ist, um ihr gegebenenfalls die Priorität zu geben. Diese Abfrage ist falsch programmiert, so daß stets angenommen wird, daß eine MEGA-Uhr vorhanden ist, und somit niemals die Zeit aus der Tastaturprozessor-Uhr übernommen wird. Dokumentiert ist dieses offensichtlich geplante Feature übrigens auch nicht. Vielleicht deshalb, weil man bei ATARI den Fehler nicht finden konnte?!

     
0 USA USA
1 FRG BR Deutschland
2 FRA Frankreich
3 UK Großbritannien
4 SPA Spanien
5 ITA Italien
6 SWE Schweden
7 SWF Schweiz (Französisch)
8 SWG Schweiz (Deutsch)
9 TUR Türkei
10 FIN Finnland
11 NOR Norwegen
12 DEN Dänemark
13 SAU Saudi-Arabien
14 HOL Niederlande

Abb. 2: Länderkennungen

Beim Überarbeiten der Rsconf-Funktion des XBIOS schlich sich leider ein Fehler ein, der dazu führt, daß der Handshake-Modus sich nicht richtig setzen läßt. Auch ATARI hat dies erkannt und bietet daher ein Patch-Programm, das diesen und einen weiteren Fehler in shel_find korrigiert. Dieser Patch liegt reset-resident von $600-$800 und wird von einem AUTO-Ordner-Programm installiert.

Die TOS-Dokumentation behauptet, das Setzen von ‘RTS/CTS’ würde zum Abschalten jeden Handshakes führen. Für mich sieht das eher so aus, als würde das Setzen von ‘XON/XOFF’ zum Abschalten und das Setzen von ‘RTS/CTS‘ zum Aktivieren von ‘XON/XOFF‘ führen, ich konnte dies aber nicht genau verifizieren. Auch das Patch-Programm liegt mir zur Zeit nicht vor, so daß ich über dessen Funktionsfähigkeit nichts sagen kann.

Kommentiertes BIOS-Listing

Für die Spezialisten unter Ihnen möchte ich noch direkt auf die Änderungen im BIOS eingehen. Generell wurden einige Optimierungen vorgenommen. Der Zugriff auf Systemvariablen wird nun noch häufiger mit der Adressierungsart “Adreßregister indirekt mit 16-Bit-Offset” (bei gelöschtem Adreßregister) statt “absolut lang” vorgenommen. Diese Methode wird außerdem jetzt auch bei den I/O-Adressen ab $FF8000 benutzt. Daraus darf man wohl schließen, daß ATARI immer noch keinen Assembler verwendet, der die “absolut kurz”-Adres-sierung beherrscht. Weiterhin wurden jetzt einige (aber noch nicht alle) “MOVE.X #0,..’’-Befehle durch “CLR.X ..” ersetzt, und andere Kleinigkeiten wurden geschickter programmiert. Prinzipielle Optimierungen gibt es sonst keine.

Zur Analyse habe ich das BIOS bis auf die Hardcopy-Routine disassembliert und mehr oder weniger gründlich mit dem des TOS 1.2 verglichen. Im abgedruckten Listing finden sich alle Routinen, an denen inhaltliche Änderungen vorgenommen wurden (markiert durch ***). Ausgenommen sind nur einige Teile, bei denen lediglich Kleinigkeiten verändert wurden, die hier im Text erwähnt werden. Die Tabelle umfaßt die Anfangsadressen aller wichtigen Routinen, was - zusammen mit einem BIOS-Listing des TOS 1.2, z.B. [3] - eine gute Orientierungshilfe bietet.

Noch nicht erwähnt habe ich bisher einige Kleinigkeiten. In der VBL-Routine wurde zweimal die Monochrommonitor-Detect-Leitung direkt am MFP abgefragt. Da sie sich zwischen den beiden Abfragen geändert haben könnte, wird der MFP nur noch einmal angesprochen; das zweite Mal wird der beim ersten Mal gemerkte Zustand getestet.

Bei der Ausgabe eines Zeichens über die Centronics-Schnittstelle werden alle Interrupts gesperrt, während der Strobe gesendet wird. Damit wird verhindert, daß der Strobe wesentlich länger als üblich (zu lange?) dauern kann.

Beim Test, ob die Hardware-Uhr des MEGA ST vorhanden ist, wird nun auch ein Bus-Error abgefangen. Normalerweise gibt es zwar keinen Bus-Error, wenn auf den Adreßbereich der MEGA-Uhr zugegriffen wird, obwohl diese gar nicht vorhanden ist, aber vielleicht gibt es hier Ausnahmen oder Fehlfunktionen, denen hiermit abgeholfen werden soll.

In den Blitter-Routinen um BUdschirmtreiber die Nummer 0 bis 2) gibt es Schleifen, die warten, bis der Blitter seine Arbeit beendet hat. Bisher sahen die so aus:

   ...
   moveq #7,D4 
   loop:
   bset d4,(a5) ;Blitter Busy testen und neu starten
   nop
   bne.s loop    ;-> Blitter noch beschäftigt 

Nun wird folgendes gemacht:

   loop:
   tas (a5)       ;Blitter Busy testen und neu starten
   nop
   bmi.s loop     ;-> Blitter noch beschäftigt

Der Unterschied besteht darin, daß bei tas das Testen und Setzen des Bits 7 des Zieloperanden in einem nicht-unterbrechbaren Schreib-Lese-Zugriff des 68000 erfolgt. Beim bset könnte zwischen dem Testen und Neustarten des Blitters z.B. der DMA-Chip die Kontrolle über den Prozessor-Bus übernehmen. Sicherer ist die Verwendung von tas auf jeden Fall: ob es auch praktische Konsequenzen hat. weiß ich nicht.

Ein letztes Wort

So das war’s für heute. Auch wenn ich das BIOS relativ gründlich durchgearbeitet habe, ist dazu sicherlich noch nicht das letzte Wort gesprochen. Warten wir’ s also ab. Festzuhalten bleibt, daß einige wichtige Punkte geändert oder verbessert wurden, anderes unverständlicherweise beim alten geblieben ist. Auch die TOS-Dokumentation ist ganz brauchbar und informativ. Ich kann das “Rainbow-TOS” nur empfehlen, da es einige ganz entscheidende Vorteile bietet, die hier nicht deutlich wurden, da sie hauptsächlich GEMDOS und Desktop betreffen. Bei dieser Gelegenheit möchte ich noch erwähnen, daß ich seit einiger Zeit auch in der MAUS-Mailbox Aachen (0241/154...) zu erreichen bin (bzw. im angeschlossenen MAUS- und FIDO-Net), falls Sie noch Fragen zur GEMDOS-Serie oder dem TOS im allgemeinen haben sollten.

Alex Esser

Literatur:

[1] Brod/Stepper: “Scheibenkleister II". MAXON 1989
[2] Esser: "EXTKEY-Tastaturbelegung einmal anders”, ST-Computer 4/89
[3] Brückmann/Englisch/Gerits: "ST intern", Data Becker 1987
[4] Esser: "Die Systemvariablen des TOS”, ST-Computer 11-12/88

;Floppy-hdv_boot
FC1CC6 LINK    A6,#$0000
FC1CCA MOVEM.L D6-D7,-(A7)
FC1CCE JSR     $FC0BD8              ;hdv_init aufrufen
FC1CD4 TST.W   $0004A6              ;nflops
FC1CDA BEQ     $FC1D12              ;-> keine Floppy: Abbruch mit 1
FC1CDC MOVEQ   #$02,D7
FC1CDE MOVE.W  #$0001,(A7)          ;1 Sektor
FC1CE2 CLR.L   -(A7)                ;Seite 0 und Spur 0 (*** optimiert! ***)
FC1CE4 MOVE.W  #$0001,-(A7)         ;Sektor 1
FC1CE8 CLR.W   -(A7)                ;*** immer Floppy A: statt 'bootdev' ***
                                    ;(Abbruch bei 'bootdev' >=2 fehlt jetzt) 
FC1CEA CLR.L   -(A7)                ;Filler
FC1CEC MOVE.L  #$0000181C,-(A7)     ;BIOS-Sektorpuffer
FC1CF2 JSR     $FC0F38              ;Floprd
FC1CF8 ADDA.W  #$0010,A7
FC1CFC TST.L   D0
FC1CFE BNE     $FC1D04              ;-> Sektor nicht lesbar: Abbruch mit 2
FC1D00 CLR.W   D7                   ;Boot-Sektor gelesen: kein Fehler
FC1D02 BRA     $FC1D10
FC1D04 TST.B   $0009F8              ;WP-Status von A: (früher falsch bei B:)
FC1D0A BNE     $FC1D10              ;-> nein: Abbruch mit 2
FC1D0C MOVEQ   #$03,D0              ;ja: Abbruch mit 3
FC1D0E BRA     $FC1D38
FC1D10 BRA     $FC1D14
FC1D12 MOVEQ   #$01,D7              ;Abbruch mit 1
FC1D14 TST.W   D7
FC1D16 BEQ     $FC1D0C              ;-> bisher kein Fehler
FC1D18 MOVE.W  D7,D0                ;Abbruch mit D7
FC1D1A BRA     $FC1D38
FC1D1C MOVE.W  #$0100,(A7)          ;Checksumme berechnen
FC1D20 MOVE.L  #$0000181C,-(A7)
FC1D26 BSR     $FC1E2E
FC1D2A ADDQ.L  #4,A7 
FC1D2C CMP.W   #$1234,D0
FC1D30 BNE     $FC1D36              ;-> Boot-Sektor nicht ausführbar: Abbruch mit 4
FC1D32 CLR.W   D0                   ;Boot-Sektor ausführbar: Ende mit 0
FC1D34 BRA     $FC1D38
FC1D36 MOVEQ   #$04,D0              ;Abbruch mit 4
FC1D38 TST.L   (A7) +
FC1D3A MOVEM.L (A7)+,D7
FC1D3E UNLK    A6
FC1D40 RTS

;Test ob MEGA-Uhr vorhanden
FC1F70 SUBA.L  A1,A1                ;*** für optimierten Zugriff ***
FC1F72 MOVE.W  #$FC20,A0            ;I/O-Basisadresse der MEGA-Uhr
FC1F76 MOVE.L  $0008(A1),D2         ;*** Bus-Error-Vektor merken ***
FC1F7A MOVE.L  A7,A2                ;*** SP merken ***
FC1F7C MOVE.L  #$FC1FB6,$0008(A1)   ;*** eigene Bus-Error-Routine ***
FC1F84 MOVE.B  #$09,$001B(A0)       ;Uhr an, Alarm aus, Bank 1 anwählen
FC1F8A MOVE.L  D2,$0008(A1)         ;*** alte Bus Error-Routine ***
FC1F8E MOVE.W  #$0A05,D0
FC1F92 MOVEP.W D0,$0005(A0)         ;Alarmzeit-Minuten auf unsinnigen Wert
FC1F96 MOVEP.W $0005(A0),D1
FC1F9A AND.W   #$0F0F,D1            ;hat dies geklappt ?
FC1F9E CMP.W   D0,D1
FC1FA0 BNE     $FC1FBC              ;-> nein: MEGA-Uhr nicht vorhanden
FC1FA2 MOVE.B  #$01,$0001(A0)       ;CLKOUT auf 16384 Hz
FC1FA8 MOVE.B  #$08,$001B(A0)       ;Uhr an, Alarm aus, Bank 0 anwählen
FC1FAE MOVE.B  #$00,$001D(A0)       ;Testregister löschen, C=0 !
FC1FB4 RTS
;eigene Bus Error-Routine
FC1FB6 MOVE.L  A2,A7                ;*** SP restaurieren ***
FC1FB8 MOVE.L  D2,$0008(A1)         ;*** Bus-Error-Vektor restaurieren ***
FC1FBC ORI.B   #$01,CCR             ;C=1: MEGA-Uhr nicht vorhanden
FC1FC0 RTS

;Gettime von IKBD
FC31A8 MOVE.B  #$FF,$0EAE(A5)       ;Flag setzen: Zeitpaket noch nicht da
FC31AE MOVE.B  #$1C,D1              ;Befehl 'interrogate time-of-day clock'
FC31B2 BSR     $FC3460              ;Zeitpaket vom IKBD anfordern
;*** auf Zeit-Paket warten mit Timeout ***
FC31B6 MOVE.L  $04BA(A5),A0
FC31BA ADDA.W  #$00C8,A0            ;hz_200 + 200 (Startzeit + ls)
FC31BE MOVEQ   #$00,D0
FC31C0 CMPA.L  $04BA(A5),A0
FC31C4 BCS     $FC31D0              ;-> 1s überschritten: 0L zurückgeben
FC31C6 TST.B   $0EAE(A5)            ;Flag testen
FC31CA BNE     $FC31C0              ;-> Zeitpaket noch nicht empfangen
FC31CC MOVE.L  $0E6C(A5),D0         ;empfangenes Paket im XBIOS-Format
FC31D0 RTS

;Zeichen über Centronics ausgeben
FC3332 MOVE.W  SR,D3                ;SR retten
FC3334 ORI.W   #$0700,SR            ;IPL 7
FC3338 MOVEQ   #$07,D1              ;Register 7 PSG lesen
FC333A BSR     $FC4086              ;(Giaccess)
FC333E ORI.B   #$80,D0              ;Port B auf Ausgabe schalten
FC3342 MOVEQ   #$87,D1
FC3344 BSR     $FC4086              ;(Giaccess)
FC3348 MOVE.W  D3,SR                ;IPL restaurieren
FC334A MOVE.W  $0006(A7),D0         ;auszugebendes Zeichen
FC334E MOVEQ   #$8F,D1              ;nach Port B schreiben
FC3350 BSR     $FC4086              ;(Giaccess)
FC3354 MOVE.W  SR,-(A7)             ;*** SR retten ***
FC3356 ORI.W   #$0700,SR            ;*** IPL 7 ***
FC335A BSR     $FC336C              ;Strobe low setzen
FC335C BSR     $FC336C              ;nochmal !? (= Pause)
FC335E BSR     $FC3366              ;Strobe high setzen
FC3360 MOVE.W  (A7)+,SR             ;*** IPL restaurieren ***
FC3362 MOVEQ   #$FF,D0              ;alles klar
FC3364 RTS
FC3366 MOVEQ   #$20,D2              ;Strobe (Bit 5)
FC3368 BRA     $FC40BC              ;mit 'ongibit' setzen
FC336C MOVEQ   #$DF,D2              ;Strobe (Bit 5)
FC336E BRA     $FC40E2              ;mit 'offgibit' löschen
;Rsconf
FC3A16 CMPI.W  #$FFFE,$0004(A7)     ;"Baudrate" = -2 ? 
FC3A1C BNE     $FC3A26
FC3A1E MOVE.W  $000A6E,D0           ;ja: alte Baudrate zurück
FC3A24 RTS
FC3A26 ORI.W   #$0700,SR            ;IPL 7 bis zum Ende des TRAP-Aufrufs
FC3A2A LEA     $000C70,A0           ;Adresse IOREC für RS232-Eingabe
FC3A30 LEA     $FFFA01,A1           ;Adress MFP
FC3A36 MOVEP.L $0028(A1),D7         ;UCR, RSR, TSR und UDR merken
                                    ;statt SCR, UCR, RSR und TSR 
FC3A3A MOVE.W  $0006(A7),D0         ;Handshake-Modus
FC3A3E CMP.W   #$FFFF,D0            ;*** Test auf '-1' statt '<0' ! ***
FC3A42 BEQ     $FC3A58              ;-> nicht ändern
FC3A44 MOVE.B  D0,$0020(A0)         ;in IOREC-Verlängerung merken
FC3A48 BEQ     $FC3A54              ;-> kein Handshake
FC3A4A AND.B   #$3E,D0              ;*** Bits 0,6,7 löschen statt Bit 1 ***
FC3A4E BEQ     $FC3A54              ;-> kein Handshake
FC3A50 MOVE.B  #$01,D0
FC3A54 MOVE.B  D0,$0020(A0)         ;Handshake-Flag in IOREC setzen
                                    ;*** jetzt immer nur 0 oder 1 ***
FC3A58 TST.W   $0004(A7)            ;Baudrate
FC3A5C BMI     $FC3A98              ;-> nicht ändern
FC3A5E MOVEQ   #$00,D0
FC3A60 MOVE.B  D0,$002A(A1)         ;RSR löschen
FC3A64 MOVE.B  D0,$002C(A1)         ;TSR löschen
FC3A68 MOVE.W  $0004(A7),D1         ;neue Baudrate
FC3A6C MOVE.W  D1,$000A6E           ;merken für Rsconf(-2)
FC3A72 LEA     $FC3ACC,A2
FC3A78 MOVE.B  $00(A2,D1.W),D0      ;Timer-Control-Wert
FC3A7C LEA     $FC3ADC,A2
FC3A82 MOVE.B  $00(A2,D1.W),D2      ;Timer-Data-Wert
FC3A86 MOVE.L  D0,D1
FC3A88 MOVEQ   #$03,D0              ;Timer D
FC3A8A BSR     $FC36AC              ;Timer setzen
FC3A8E MOVEQ   #$01,D0
FC3A90 MOVE.B  D0,$002A(A1)         ;RSR: Empfänger ein etc.
FC3A94 MOVE.B  D0,$002C(A1)         ;TSR: Sender ein etc.
FC3A98 TST.W   $0008(A7)            ;UCR
FC3A9C BMI     $FC3AA4              ;-> nicht ändern
FC3A9E MOVE.B  $0009(A7),$0028(A1)  ;UCR setzen
FC3AA4 TST.W   $000A(A7)            ;RSR
FC3AA8 BMI     $FC3AB0              ;-> nicht ändern
FC3AAA MOVE.B  $000B(A7),$002A(A1)  ;RSR setzen
FC3AB0 TST.W   $000C(A7)            ;TSR
FC3AB4 BMI     $FC3ABC
FC3AB6 MOVE.B  $000D(A7),$002C(A1)  ;TSR setzen
FC3ABC TST.W   $000E(A7)            ;SCR
FC3AC0 BMI     $FC3AC8              ;-> nicht ändern
FC3AC2 MOVE.B  $000F(A7),$0026(A1)  ;SCR setzen
FC3AC8 MOVE.L  D7,D0
FC3ACA RTS

;aus Tastatur-Interrupt (nach Behandlung SHIFT/CTRL/ALT/CAPS)
;verbesserte Tastenwiederholung 
FC3CFA BTST    #$07,D0
FC3D04 BNE     $FC3D16              ;-> Taste losgelassen
FC3D00 MOVE.B  D0,$0E9B(A5)         ;Scancode für Tastenwiederholung
FC3D04 MOVE.B  $000E9E,$0E9C(A5)    ;Zähler für Wiederholschwelle init. 
FC3D0C MOVE.B  $000E9F,$0E9D(A5)    ;Zähler für Wiederholrate init.
FC3D14 BRA     $FC3D48              ;Taste in Tastaturpuffer übernehmen
FC3D16 MOVE.B  D0,D1                ;Taste losgelassen
FC3D18 BCLR    #$07,D1              ;reiner Scancode
FC3D1C CMP.B   $0E9B(A5),D1
FC3D20 BNE     $FC3D30              ;-> andere Taste als letzte gedrückte
FC3D22 MOVEQ   #$00,D1              ;Tastenwiederholung aus
FC3D24 MOVE.B  D1,$0E9B(A5)
FC3D28 MOVE.B  D1,$0E9C(A5)
FC3D2C MOVE.B  D1,$0E9D(A5)
FC3D30 CMPI.B  #$C7,D0              ;HOME losgelassen ?
FC3D34 BEQ     $FC3D3E
FC3D36 CMPI.B  #$D2,D0              ;INSERT losgelassen ?
FC3D3A BNE     $FC3FBC              ;-> weder HOME noch INSERT: fertig
FC3D3E BTST    #$03,$0E7D(A5)       ;ALT gedrückt ?
FC3D44 BEQ     $FC3FBC              ;-> nein: fertig
FC3D48 ;Tastencode soll nach Tastaturpuffer, dazu weiter untersuchen

;Ende des Tastatur-Interrupts: Zeichen nach Tastaturpuffer
;D0: ASCII-Kode in Bits 0-7, Scan-Kode in Bits 8-15 
FC3F74 MOVE.L  $0000(A0),A2         ;Pufferadresse
FC3F78 SWAP    D0                   ;Scan- u. ASCII-Kode nach Bits 16-31
FC3F7A MOVE.W  #$0000,D0
FC3F7E MOVE.B  $0E7D(A5),D0         ;Kbshift-Status
FC3F82 SWAP    D0                   ;Status jetzt nach Bits 16-23
FC3F84 LSL.L   #8,D0
FC3F86 LSR.W   #8,D0                ;Bits 0-7: ASCII, 16-23: Scan, 24-31: Kbshift
FC3F88 MOVE.L  D0,D2
FC3F8A BCLR    #$1C,D2              ;CAPS ignorieren
FC3F8E SWAP    D2
FC3F90 CMP.W   #$0C53,D2            ;CTRL-ALT-DEL ?
FC3F94 BEQ     $FC0030              ;-> Warmstart
FC3F98 CMP.W   #$0D53,D2            ;CTRL-ALT-SHIFT RECHTS-DEL ?
FC3F9C BEQ     $FC4034              ;-> Kaltstart
FC3FA0 BTST    #$03,$0484(A5)       ;conterm: Kbshift für Bconin ?
FC3FA6 BNE     $FC3FAE
FC3FA8 ANDI.L  #$00FFFFFF,D0        ;nein: Kbshift löschen
FC3FAE AND.L   #$0000FFFF,D1
FC3FB4 MOVE.L  D0,$00(A2,D1.L)      ;Zeichen nach Tastaturpuffer 
FC3FB8 MOVE.W  D1,$0008(A0)         ;neuer Pufferzeiger
FC3FBC RTS

;Kaltstart auslösen
;äußerst gründlich, da Hauptspeicher komplett gelöscht 
;es fehlt höchstens noch das RAM im IKBD...
FC4034 MOVE.W  #$2700,SR            ;IPL 7
FC4038 LEA     $FC4050(PC),A0       ;Löschroutine ins RAM kopieren
FC403C MOVE.W  #$000F,D0            ;32 Worte (ein bißchen viel zwar...)
FC4040 MOVE.W  #$0008,A1            ;ab Adresse $8 (Bus-Error-Vektor) !
FC4044 MOVE.L  (A0)+,(A1)+
FC4046 DBF     D0,$FC4044
FC404A SUBA.L  A5,A5
FC404C JMP     $0008(A5)            ;Löschroutine starten
;Speicher-Löschroutine für Kaltstart, ins RAM ab $8 kopiert
FC4050 LEA     $FC4076(PC),A0       ;eigener Bus-Error-Handler
FC4054 MOVE.L  A0,$0008(A5)         ;Anfang dieser Routine nun selbst zerstört !!!
FC4058 LEA     $FC4082(PC),A0       ;Beginn löschen nach dieser Routine
FC405C MOVEQ   #$00,D0
FC405E MOVE.L  D0,D1
FC4060 MOVE.L  D0,D2
FC4062 MOVE.L  D0,D3
FC4064 MOVE.L  D0,D4
FC4066 MOVE.L  D0,D5
FC4068 MOVE.L  D0,D6
FC406A MOVE.L  D0,D7
FC406C MOVEM.L D0-D7,(A0)           ;schnelles Löschen
FC4070 ADDA.W  #$0020,A0
FC4074 BRA     $FC4072              ;immer weiter... bis Bus-Error kommt 
FC4076 MOVE.L  $0004(A5),A0         ;ROM-Reset-Adresse
FC407A JMP     (A0)                 ;Reset (wirkt wie Kaltstart) durch ROM
       dc.w 0                       ;???

Alex Esser
Aus: ST-Computer 11 / 1989, Seite 151

Links

Copyright-Bestimmungen: siehe Über diese Seite