diff options
author | Lars-Dominik Braun <lars@6xq.net> | 2019-02-04 13:09:03 +0100 |
---|---|---|
committer | Lars-Dominik Braun <lars@6xq.net> | 2019-02-04 13:09:03 +0100 |
commit | 04e68443040c7abad84d66477e98f93bed701760 (patch) | |
tree | 2b6202afae659e773bf6916157d23e83edfa44e3 /doc/porting-z80/8 | |
download | eumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.gz eumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.bz2 eumel-src-04e68443040c7abad84d66477e98f93bed701760.zip |
Initial import
Diffstat (limited to 'doc/porting-z80/8')
-rw-r--r-- | doc/porting-z80/8/doc/Port.Z80 | 2484 | ||||
-rw-r--r-- | doc/porting-z80/8/source-disk | 1 |
2 files changed, 2485 insertions, 0 deletions
diff --git a/doc/porting-z80/8/doc/Port.Z80 b/doc/porting-z80/8/doc/Port.Z80 new file mode 100644 index 0000000..ed3c80a --- /dev/null +++ b/doc/porting-z80/8/doc/Port.Z80 @@ -0,0 +1,2484 @@ +#type ("trium8")##limit (12.0)# +#pagelength(19.5)# +#start(1.5,1.5)# +#type("triumb36")# +#free(4.0)# + EUMEL + Portierungshandbuch + Z 80 +#type("triumb18")# +#free(1.5)# + Version 8 #page(1)# +#type ("trium8")##limit (12.0)# +#block# +#pagelength(19.5)# +#head# +#center#- % - + + +#end# +#type("triumb14")#Inhalt#a# + +Teil 1: Einführung #topage("ein")# +#free(0.3)# + Zweck dieses Handbuchs #topage("zweck")# + Referenzliteratur #topage("reflit")# + Minimale Hardwarevoraussetzungen #topage("hardw")# + Systemdurchsatz #topage("durchsatz")# + Softwarekomponenten des EUMEL-Systems #topage("kompo")# + Anlieferung des Z80-EUMEL-Systems #topage("anlief")# + +Teil 2: Allgemeine Strukturen #topage("allgem")# +#free(0.3)# + Hintergrund #topage("hg")# + Archiv #topage("arch")# + Hauptspeicher #topage("speicher")# + +Teil 3: SHard-Interface Spezifikation #topage("shardifc")# +#free(0.3)# + 0. Vorbemerkungen #topage("vor")# + Zur Notation #topage("not")# + Link-Leisten #topage("leist")# + Allgemeine Link-Bedingungen #topage("link")# + Interrupts #topage("intr")# + 1. System laden #topage("laden")# + 2. Systemstart und -ende #topage("start")# + 3. Speicherverwaltung #topage("spver")# + Hauptspeicher #topage("haupt")# + Schattenspeicher #topage("schatt")# + Blocktransfer im Speicher #topage("ldir")# + Speicherfehler #topage("memerr")# + 4. Zeitgeber #topage("zeit")# + 5. Kanäle #topage("channel")# + 5.1 Stream-IO #topage("stream")# + Terminals #topage("term")# + Drucker, Plotter #topage("druck")# + Exoten #topage("exot")# + 5.2 Block-IO #topage("block")# + Block-IO bei Hintergrund und Archiv #topage("bhgarch")# + 5.3 IO-Steuerung #topage("iocontrol")# + Einstellung serieller Schnittstellen #topage("v24")# + Flußkontrolle #topage("fluss")# + Kalender #topage("kalender")# + 6. SHard-Interface Version #topage("shdver")# + 7. ID-Konstanten #topage("ID")# + 8. Zusätzliche Leistungen #topage("shdelan")# + 9. Spezialroutinen #topage("ke")# + +Teil 4: Tips zur Portierung #topage("tips")# + 0-Version des SHards #topage("0ver")# + Effizienzprobleme #topage("eff")# + Typische Fehler #topage("fehler")# + +Anhang A: EUMEL-Debugger "Info" #topage("info")# +#free(0.3)# + Aufruf des Infos #topage("aufrinf")# + Info-Format #topage("forminf")# + Info-Kommandos #topage("cmdinf")# + Einige Systemadressen #topage("sysaddr")# + Leitblock #topage("pcb")# +#page# +#cc("Teil 1: ","Einführung")# +#goalpage("ein")# + + +#b("Zweck dieses Handbuchs")# +#goalpage("zweck")# + +Dieses Portierungshandbuch wendet sich an diejenigen, die das EUMEL-System auf einem +neuen Rechnertyp implementieren wollen. Es ist Teil einer Serie von Portierungshandbüchern +für verschiedene Prozessortypen. Dieses bezieht sich auf Rechner mit Z80-Prozessoren. + +Zum Betrieb eines EUMEL-Systems wird dieses Handbuch nicht benötigt! + + + +#b("Referenzliteratur")# +#goalpage("reflit")# + + + "EUMEL Benutzerhandbuch" + + "EUMEL Systemhandbuch" + + "EUMEL Quellcode der insertieren ELAN-Pakete" + + "Z80-Assembly Language Programming Manual" + Zilog, 1977 + + + +#b("Minimale Hardwarevoraussetzungen")# +#goalpage("hardw")# + +Um das EUMEL-System effizient einsetzen zu können, sollte die Hardware mindestens +folgenden Kriterien genügen: + + #ib#CPU#ie# Die Z80-CPU sollte mit mindestens 2.5 MHz arbeiten. Falls + die Buszugriffe durch einen CRTC o.ä. verlangsamt werden, + sollte die echte Z80-Leistung durchschnittlich mindestens + einem ungebremsten 2.5 MHz System entsprechen. + Seltene Verlangsamungen (z.B. nur bei I/O-Operationen) + spielen bei diesen Überlegungen keine Rolle. + + RAM Das System sollte über mindestens 64 K Byte #ib#Hauptspeicher#ie# + verfügen, besser sind 128 K als Anfangsausrüstung. + + #ib#Hintergrund#ie# Als Hintergrundmedium sind #ib#Floppy#ie#, #ib#Harddisk#ie# und RAM bzw. + ROM denkbar. + + Kapazität: > 300 K, besser > 400 K (Single-User) + > 750 K, besser > 1000 K (Multi-User) + + Zugriff: < 500 ms (Single-User) + < 200 ms (Multi-User) *) +#foot# +#f#*) Hier ist die durchschnittliche Zugriffszeit auf einen 512 Byte großen Block gemeint. Für Platten und Floppies kann man +sie als Summe der Positionierzeit über die halbe Platte und der Zeit einer halben Umdrehung berechnen.#a# +#end# + + #ib#Archiv#ie# Als Archivgerät wird meistens eine Floppy eingesetzt. Aber + auch Band oder Kassettenrecorder sind denkbar. Die An + forderungen an Kapazität und Geschwindigkeit sind anwen + dungsspezifisch. + + #ib#Bildschirm#ie# Angestrebt werden sollte ein Bildschirm mit 24 Zeilen mit je + 80 Zeichen (oder größer). Kleinere Bildschirme sind anschließ + bar, aber mit 40 Zeichen pro Zeile läßt sich nicht mehr kom + fortabel arbeiten. + Rollup und freie Cursorpositionierung sind notwendige Vor + aussetzungen, invers-video ist erwünscht, aber nicht not + wendig. Weiterhin werden 'Löschen bis Zeilenende' und + 'Löschen bis Schirmende' benötigt. Lokale Editierfunktionen + sind überflüssig. + + #ib#Tastatur#ie# An Steuertasten sollten mindestens ESC und die vier Cursor + tasten vorhanden sein. Dabei ist es günstig, wenn die Cursor + tasten ergonomisch als Block bzw. Kreuz angeordnet sind. + EUMEL benötigt weitere Steuertasten für HOP, RUBIN, + RUBOUT und MARK. Dafür können beliebige Tasten der + Tastatur gewählt werden. + + + +#b("Systemdurchsatz")# +#goalpage("durchsatz")# + +Da das EUMEL-System auf dem Prinzip des Demand Paging aufbaut, hängt der System +durchsatz von + + - CPU Leistung + - Speichergröße (RAM) + - Geschwindigkeit beim Hintergrundzugriff (Floppy, Harddisk) + +ab. Mit zunehmender Benutzerzahl steigen in der Regel die Anforderungen an das Paging +(Hintergrund-Zugriff) schneller als an die CPU. In diesem Bereich kann man die System +leistung dann durch mehr Speicher und/oder eine schnellere Platte in größerem Umfang +steigern. Dabei läßt sich eine langsame Platte teilweise durch mehr RAM und umgekehrt +wenig RAM durch eine schnelle Platte ausgleichen. + + + +#b("Softwarekomponenten des EUMEL-Systems")# +#goalpage("kompo")# + +Das EUMEL-System besteht aus mehreren Schichten: + + + + EUMEL 2: Standardpakete, Editor, ... + + EUMEL 1: ELAN Compiler + + EUMEL 0: Basismaschine + + EUMEL -1: SHard + + H a r d w a r e + + +Dieses #ib#Schichtenmodell#ie# ist nach oben offen und kann deshalb um beliebig viele (höhere) +Schichten erweitert werden. + +EUMEL > 0 Die Standardsoftware der Schichten > 0 ist in der Sprache ELAN geschrie + ben (siehe "EUMEL Quellcode"). Dementsprechend sind alle Schichten ober + halb der EUMEL-0-Maschine prozessor- und rechnerunabhängig, d.h. + Anpassungen an einen neuen Rechnertyp sind nicht erforderlich. + +#ib#EUMEL 0#ie# Die sogenannte "EUMEL-0-Maschine" enthält alle Basisoperationen und + hängt davon ab, welchen Prozessortyp der Rechner als CPU verwendet. Sie + existiert für verschiedene Prozessortypen. Hier wird nur auf den Typ Z80 + Bezug genommen. Bei der Portierung auf einen Z80-Rechner wird die + Z80-EUMEL-0-Maschine ohne Anpassungen (!) übernommen. + +EUMEL -1 Diese Schicht stellt das Interface zwischen der EUMEL-0-Maschine und der + eigentlichen Hardware (vom Prozessor abgesehen) dar. Insbesondere umfaßt + sie alle Routinen zur Ansteuerung peripherer Geräte (Gerätetreiber). + Diese Schicht wird "SHard" genannt ("S"oftware-"Hard"ware Interface). + +Der SHard ist der einzige Teil des Systems, der bei der Portierung auf einen Z80-Rech +ner angepaßt bzw. neu geschrieben werden muß. Deshalb besteht der größte Teil dieses +Handbuchs aus der Spezifikation des Z80-SHards. + + + +#b("Anlieferung des Z80-EUMEL-Systems")# +#goalpage("anlief")# + +Der Implementierer erhält die EUMEL-Software auf Disketten. Dabei stehen folgende Stan +dardformate zur Wahl: + + 8", 1D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + + 8", 2D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + + 5", 2D, 40 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte *) +#foot# +#f#*) 48 tpi#a# +#end# + + +Die Diskettenlieferung enthält + + - Single-User Hintergrund + - Multi-User Hintergrund + - Standardarchive + - Archive mit weiterer Anwendersoftware + +Dabei enthält der Hintergrund auch die EUMEL-0-Software (oft auch als "Urlader" be +zeichnet). + +#on("i")#Bitte gehen Sie vorsichtig mit diesen Mutterdisketten um. Verwenden Sie sie nur als Quelle +beim Kopieren. Sie sollten nur auf Kopien davon arbeiten!#off("i")# +#page# +#cc("Teil 2: ","Allgemeine Strukturen")# +#goalpage("allgem")# + + +#b("Hintergrund")# +#goalpage("hg")# + +Der Hintergrund ist in 512 Bytes große Blöcke unterteilt. Sie werden durch Blocknummern (0, +1, 2, ...) adressiert. Die physische Ablage der Blöcke auf dem Hintergrundmedium bleibt dem +SHard überlassen. Er kann sie z.B. linear oder versetzt anordnen. Man sollte darauf achten, +daß Positionierungen auf logisch "nahe" Blöcke möglichst schnell gehen sollten. Deshalb ist +in der Regel zylinderorientierte Anordnung der oberflächenorientierten vorzuziehen. + +Falls auf dem Hintergrundgerät spezielle Blöcke z.B. für Boot und SHard freigehalten werden +sollen, muß das bei der Abbildung der Hintergrundblocknummern auf die Sektoren der Floppy +bzw. der Harddisk berücksichtigt werden. + +Aufbau des Hintergrundes: + + Block 0 Systemetikett + + Block 10...10+k-1 EUMEL-0-Software (Urlader) + + Block 1...9, 10+k ... Paging-Bereich + + +Aufbau des #ib#Systemetikett#ie#s (#ib#Block 0#ie#): + + Byte Wert/Aufgabe + + 0...5 "EUMEL-"; Kennzeichen für EUMEL-Hintergrund. + 6...11 Versionsnummer in druckbaren Zeichen. Sie stellt sicher, daß Urlader und + Hintergrund kompatibel sind. + 12 FFh ; zur Zeit ohne Bedeutung + 13 enthält Wert 0 , wenn System im Shutupzustand ist. + 14..15 Systemlaufzähler (14=low, 15=high). Wird bei jedem Systemstart um 1 + erhöht. + 16..35 Reserviert; zur Zeit ohne Bedeutung + 36..37 Aus historischen Gründen für interne Zwecke belegt. + 38 .. 69 Hier kann eine Installationsnummer geführt werden. + 70 .. 79 Info-Paßwort + 80 =0 Normalzustand + =1 Kompresslauf erforderlich (System frisch von Archiv geladen) + 81...255 Reserviert. + 256..511 Kann von SHard beliebig verwendet werden. + + + +#b("Archiv")# +#goalpage("arch")# + +Wie der Hintergrund sind die Archive in 512 Bytes große Blöcke unterteilt. Bisher gibt es +folgende #dx("Standardformate")#: + + + 8", 1D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + 8", 2D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 0 + 16 0 1 0 + 77*16 1 0 0 + + n n DIV (77*16) n MOD (77*16) DIV 16 n MOD 16 + + + 5", 2D, 40 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 9 0 1 1 + 40*9 1 0 1 + + n n DIV (40*9) n MOD (40*9) DIV 9 n MOD 9 + 1 + + + 5", 2D, 80 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 9 0 1 1 + 80*9 1 0 1 + + n n DIV (80*9) n MOD (80*9) DIV 9 n MOD 9 + 1 + + + 5", HD, 80 Spuren, 15 Sektoren (\#1...\#15) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 15 0 1 1 + 80*15 1 0 1 + + n n DIV (80*15) n MOD (80*15) DIV 15 n MOD 15 + 1 + + +Selbstverständlich können auch andere #ib#Archivformate#ie# implementiert werden, falls das aus +Hardwaregründen notwendig ist oder sich dadurch wesentliche Verbesserungen (z.B. in der +Kapazität) ergeben. + +Wenn irgend möglich sollte aber mindestens eines der oben aufgeführten Standardformate +unterstützt werden - evtl. als zusätzliches Format -, um den Austausch zwischen verschie +denen Rechnertypen zu vereinfachen. + +#on("i")#Hinweis: Um den Datenaustausch zwischen verschiedenen Rechnertypen zu vereinfachen, + sollten möglichst alle der hardwaremäßig möglichen Standardformate (mindestens + lesend) unterstützt werden. Dabei sollte SHard sich automatisch auf das Format + der jeweils eingelegten Floppy einstellen:#off("i")# + + + Laufwerkstyp Diskettentyp(en) + + 8" 1D 8" 1D + 8" 2D 8" 2D, 1D + + 5" 2D-40 5" 2D-40 + 5" 2D-80 5" 2D-80, 2D-40 *) + 5" HD-80 5" HD-80, 2D-80, 2D-40 *) +#foot# +#f#*) Bei der Behandlung von 40-Spur-Disketten auf 80-Spur-Laufwerken gelten meistens folgende Regeln: + a) Lesen funktioniert sicher. + b) Schreiben ist unsicher, funktioniert aber häufig. + c) Formatieren funktioniert fast nie. +#a# +#end# + + + +#b("Hauptspeicher")# +#goalpage("speicher")# + +Die 64 K des direkt vom Z80 adressierbaren #ib#Speicher#ie#s sind folgendermaßen aufgeteilt: + + FFFFh #corner1("-5.0")# + Platz für SHard + yyyyh #box3("T","3","75.0")# + #corner1("-5.0")# + Pagingbereich + + xxxxh #box3("T","3","75.0")# + #corner1("-5.0")# + EUMEL 0 + + 1400h #box3("T","3","75.0")# + #corner1("-5.0")# + Platz für SHard + 0000h #box3("T","3","75.0")# + +Möglichst große Teile des SHards (am besten alle) sollten im unteren Adreßbereich (bis +13FFh) liegen, damit dem Paging viel Speicher zur Verfügung steht. + +Der nicht direkt (aber durch Banking oder DMA) erreichbare Teil des #ib#RAM#ie#s wird Schatten +speicher (siehe S.#topage("schatt")#) genannt. + + +Hinweis: Falls ein Teil des Hauptspeicher-Adreßraums fest (d.h. auch nach dem Boot + loading nicht ausblendbar) durch ROM belegt ist, muß dieses in einem der beiden + SHard-Bereichen liegen. + +#page# +#cc("Teil 3: SHard ","Interface Spezifikation")# +#goalpage("shardifc")# + + +#bb("0. ","Vorbemerkungen")# +#goalpage("vor")# + + +#b("Zur Notation")# +#goalpage("not")# + +Im folgenden wird zwischen #dx("0-Routinen")#, die dem SHard vom EUMEL-0-System zur +Verfügung gestellt werden, und #dx("SHard-Routinen")# unterschieden, die der SHard implementie +ren muß. Damit dieser Unterschied bei der Spezifikation deutlich wird, werden 0-Routinen +folgendermaßen aufgeführt: + + name (0-Routine) + +Zusätzlich werden 0-Routinen grundsätzlich klein und SHard-Routinen groß geschrieben. + +Z80-Befehle werden wie in "Z80-Assembly Language Programming Manual" (Zilog, 1977) +notiert: + + ld a,27 + add a,l + +Hexadezimale Zahlen werden durch ein nachgestelltes 'h' gekennzeichnet: + + 12h = 18 + 1Fh = 31 + FFFFh = 65535 + + +#b("Link-Leisten")# +#goalpage("leist")# + +Die Verbindung zwischen SHard und Urlader (EUMEL-0) erfolgt über zwei Tabellen. In der +"0-Leiste" stellt EUMEL-0 dem SHard verschiedene 0-Routinen zur Verfügung. Diese +Leiste beginnt an der Adresse 1400h: + + 1400h defm 'EUMEL ' + 1410h defw eumel0blocks + 1412h defw hgversion + 1414h defw 1 ; Kennzeichen für Z80-Urlader + 1416h defw urladerversion + 1418h defw 0 ; reserviert + 141ah defw ; kleinste unterstützte SHardversion + 141ch defw ; größte ... + 141eh jp systemstart + jp inputinterrupt + jp timerinterrupt + jp warte + jp grab + jp free + jp shutup + jp info + +Diese Leiste wird vom Urlader nach dem Systemstart überschrieben. Der SHard muß daher, +bevor er nach systemstart springt, die für ihn relevanten Teile (mindestens die Sprungbefehle) +in einen eigenen Bereich kopieren: + + #ib#eusystemstart#ie#: jp 0 + #ib#euinputinterrupt#ie#: jp 0 + #ib#eutimerinterrupt#ie#: jp 0 + #ib#euwarte#ie#: jp 0 + #ib#eugrab#ie#: jp 0 + #ib#eufree#ie#: jp 0 + #ib#eushutup#ie#: jp 0 + #ib#euinfo#ie# jp 0 + +So kann SHard die entsprechenden 0-Routinen vermittels der obigen Vereinbarungen aufru +fen: + + jp eusystemstart + ... + call euwarte + +Für die Gegenrichtung muß SHard der 0-Maschine die "SHard-Leiste" zur Verfügung +stellen, deren Adresse beim Sprung nach 'systemstart' in HL stehen muß. Die 0-Maschine +kopiert diese Leiste. SHard darf daher anschliessend den Bereich anderweitig (z.B. +EA-Puffer) verwenden: + + + #ib#SHDID#ie#: defm 'SHARD ' ; 16 Byte + #ib#SHDVER#ie#: defw 8 + #ib#MODE#ie#: defw + #ib#ID4#ie#: defw + #ib#ID5#ie#: defw + #ib#ID6#ie#: defw + #ib#ID7#ie#: defw + defw + defw + #ib#OUTPUT#ie#: jp shout + #ib#BLOCKIN#ie#: jp shbin + #ib#BLOCKOUT#ie#: jp shbout + #ib#IOCONTROL#ie#: jp shiocnt + #ib#SYSEND#ie#: jp shend + #ib#SCHINF#ie#: jp shsinf + #ib#SCHACC#ie#: jp shsacc + defw + #ib#LIMIT#ie#: defw + + +#b("Allgemeine Link-Bedingungen")# +#goalpage("link")# + +In der Regel sind sowohl 0-Routinen als auch SHard-Routinen durch 'call' aufzurufen: + + call <routine> + +Ausnahmen von dieser Regel sind im folgenden stets besonders vermerkt. + +Generelle Link-Bedingung (für SHard- und 0-Routinen) ist: + + Alle Register - bis auf die jeweils spezifizierten Ausgangsparameter und das F-Regi + ster *) - bleiben unverändert. +#foot# +#f#*) Flags sind i.a. nach dem Aufruf einer Routine undefiniert. Ausnahmen sind natürlich die Flags, die als Ausgangs +parameter in manchen Fällen definiert sind.#a# +#end# + +Jede SHard-Routine muß also alle Register (bis auf F), die sie verändert und die keine +Ausgangsparameter sind, retten und wiederherstellen. Im Gegenzug braucht SHard beim +Aufruf von 0-Routinen selbst keine Register zu retten. + + +#b("Interrupts")# +#goalpage("intr")# + +Zwei externe Ereignisse (Zeitgeber und Eingabe, siehe S.#topage("zeit")# und S.#topage("inp")#) werden von +EUMEL-0 behandelt. Die entsprechenden Interrupts muß SHard per 'call' an 0-Routinen +weiterleiten. Außerhalb des Moduls SHard wird der 'reti'-Befehl nicht verwendet, damit der +SHard die Kontrolle über die Interruptlevel behält. Die Register (bis auf die Eingangsparame +ter) werden von den aufzurufenden 0-Routinen selbst gesichert. Die normale Interrupt- +Sequenz im SHard sieht dann folgendermaßen aus: + + intadr: push af + ld a,<parameter> + call <routine> + pop af + reti + +Achtung: SHard muß die Interrupt-Routinen im 'disable-int'-Modus anspringen. Dies ist + normalerweise schon durch die Hardware gegeben. + +Die 0-Routinen geben von sich aus den 'ei'-Befehl. Dies erfolgt im allgemeinen sehr +frühzeitig (innerhalb der ersten 30 Befehle), um einen interruptgetriebenen Floppytreiber +zulassen zu können. + + + + +#bb("1. System ","laden")# +#goalpage("laden")# + +SHard muß die EUMEL-0-Software vor dem eigentlichen Start laden. EUMEL-0 befindet +sich normalerweise auf dem Hintergrund. Es müssen von Block 10 an eumel-0-blocks +(siehe 0-Leiste) Blöcke in den Speicher von der Adresse 1400h an aufsteigend geladen +werden. + + Achtung: Zu diesem Zeitpunkt kann SHard die oben aufgeführten 0-Routinen natür + lich noch nicht benutzen. Insbesondere dürfen die Laderoutinen nicht 'warte' + aufrufen. Das wird hier besonders betont, weil der Hintergrundzugriff beim + eigentlichen Systemlauf in der Regel 'warte' verwenden wird. + + Hinweis: Der erste Block der EUMEL-0-Software (Block 10) enthält in den ersten + fünf Bytes den Text "EUMEL", um eine Identifikation durch den SHard- + Lader zu ermöglichen. + +Es wird empfohlen, nach folgendem Verfahren zu laden: + + IF archivgeraet enthaelt diskette AND eumel 0 auf archiv + THEN lade eumel 0 vom archiv + ELIF eumel 0 auf hintergrund + THEN lade eumel 0 vom hintergrund + ELSE laden unmoeglich + FI . + +So kann man auch bei einem frisch formatierten Hintergrundmedium einen neuen Hinter +grund (mit EUMEL-0-Urlader) einspielen, indem man ein Hintergrundarchiv vor dem +Systemstart in das Archivgerät legt. Dann wird EUMEL-0 von dort geladen, so daß man den +Hintergrund dann wie im Systemhandbuch beschrieben vom Archiv auf das Hintergrund +medium kopieren kann.*) +#foot# +#f#*) Kopiervorgänge (Archiv -> Hintergrund) werden vom EUMEL-0-Urlader erledigt, so daß SHard keine derartigen +Routinen enthalten muß.#a# +#end# + + + +#bb("2. System","start und -ende")# +#goalpage("start")# + +SHard muß alle für den Rechner notwendigen (Hardware-) Initialisierungen durchführen und +erst danach die EUMEL-0-Maschine starten ('systemstart'). + + #dx("systemstart")# (0-Routine) + + Eingang: HL = Adresse der SHard-Leiste + Interrupts disabled + + Aufruf: jp systemstart + + Zweck: Die EUMEL-0-Maschine wird gestartet. Alle notwendigen + Hardwareinitialisierungen (Interrupt Modus des Z80 und Ini + tialisierungen der Peripheriebausteine) müssen vorher schon + geschehen sein. + + Hinweis: Der Stackpointer braucht nicht definiert zu sein, da beim + Ansprung DI-Zustand herrschen sollte und somit keine + Interrupts auftreten können. EUMEL-0 lädt beim Start das + SP-Register und läßt Interrupts zu (EI). Falls jedoch in dieser + Zeit ein "Non Maskable Interrupt" auftreten kann, muß SHard + SP "vorläufig" laden. + + MODE: Über das MODE-Wort in der SHard-Leiste können Op + tionen gesetzt werden: + + Bit 0 = 0 EUMEL-0 ist auf dem Hintergrund abge + speichert. Der entsprechende Bereich bleibt + geschützt. (Standard) + + Bit 0 = 1 EUMEL-0 befindet sich nicht auf dem Hin + tergrund. Der entsprechende Bereich steht + zur freien Verfügung für andere EUMEL- + Daten. + (Da die EUMEL-0-Software nur beim + Systemstart geladen wird (read only!), kann + es bei Geräten mit kleinem Hintergrund + interessant sein, diese Blöcke auf dem + Hintergrund anderweitig zu nutzen. Das + Systemladen kann dann z.B. mit Hilfe einer + speziellen Urladediskette vom Archivgerät + aus erfolgen.) + + Bit 8 = 0 Beim Systemstart wird der Speicher über + prüft. (Standard) + + Bit 8 = 1 Der Speichertest beim Systemstart unter + bleibt. Man sollte nur bei Rechnern, die + beim Einschalten schon eigene Speicher + tests durchführen, auf den Speichertest des + EUMEL verzichten. + + Bit 9 = 0 Beim Systemstart wird die Vortest-Tapete + ausgegeben und man kann durch Eingabe + eines Zeichens die Vortestmenüs aktivieren + (s. Systemhandbuch). (Standard) + + Bit 9 = 1 Die Vortest-tapete wird unterdrückt. Es gibt + auch keine Möglichkeit, die Vortestfunk + tionen aufzurufen. Der Speichertest unter + bleibt ebenfalls. + + + #dx("SYSEND")# + + Parameter: - + + Zweck: Hiermit wird SHard das Ende eines Systemlaufs mitgeteilt. + Somit können evtl. notwendige Abschlußbehandlungen durch + geführt werden. SHard kann mit 'ret' zu EUMEL-0 zurück + kehren, muß aber nicht. Diese Routine kann z.B. dazu benutzt + werden, die Hardware auszuschalten oder in ein umgebendes + System zurückzukehren (EUMEL als Subsystem). In den + meisten Fällen wird die Routine leer implementiert werden, + d.h. nur aus 'ret' bestehen. + + +#bb("3. ","Speicherverwaltung")# +#goalpage("spver")# + + +#b("Hauptspeicher")# +#goalpage("haupt")# + +Der Hauptspeicher (#ib#RAM#ie#) umfaßt die direkt adressierbaren 64 K des Z80. Da die Anfangs +adresse des für EUMEL-0 und Paging verfügbaren Bereichs fest ist (1400h), muß SHard nur +über die Obergrenze des verfügbaren Bereichs informieren. + + #dx("LIMIT")# + + Über das LIMIT-Wort in der SHard-Leiste kann sich SHard + noch Bereiche vor dem Speicherende (z.B. für CP/M BIOS) + freihalten. Auf jeden Fall muß CFFFh <= LIMIT gewährleistet + sein, d.h. der Bereich bis CFFFh gehört zum Pagingbereich. + Im Normalfall wird FFFFh geliefert werden. + + + +#b("Schattenspeicher")# +#goalpage("schatt")# + +Das EUMEL-System ist in der Lage, trotz der durch die 16-Bit Adressen gegebenen Ein +schränkung auf 64 kB, weiteren Speicher anzuschließen. Dieser wird Schattenspeicher +genannt. + +Der Schattenspeicher (#ib#RAM#ie#) sollte so angeschlossen sein, daß über ein nicht zu großes #ib##on("italic")# +Fenster#ie##off("italic")# des normalen Adressraumes ( < 4 kB) auf diesen zugegriffen werden kann. Welcher +Bereich des Schattenspeichers dabei gemeint ist, wird durch die SHard-Routine SCHACC +mitgeteilt (s.u.). Diese Art des Zugriffs wird Fenstermodus genannt. Das Restsystem nutzt das +Fenster echt (d.h. ohne den Inhalt in andere Bereiche des normalen Adressraumes zu trans +portieren). + +Ist ein so kleines Fenster in der Hardware nicht vorgesehen (z.B. 48 kB Bänke bzw. nur +DMA-Zugriff), so kann auch solcher Schattenspeicher benutzt werden (Transportmodus). +Wichtig ist dabei, daß EUMEL-0 die oben erwähnten echten Fensterzugriffe unterläßt. +(Simulation im Transportmodus wäre erheblich zu teuer.) Daher muß EUMEL-0 wissen, in +welchem Modus der Schattenspeicher ansprechbar ist (SCHINF). + +Hinweis: Wenn möglich sollte der Fenstermodus implementiert werden, da er im Multi- + User-Betrieb (ab ca. 3 Teilnehmern) deutliche Effizienzvorteile bietet. + + +Das Schattenspeicherinterface gibt es in 2 Modi: + + - Fenstermodus (Bit 2**15 von BC gesetzt bei SCHINF) + - Transportmodus (Bit 2**14 von BC gesetzt bei SCHINF) + + +#d("Fenstermodus")# + + #dx("SCHINF")# (im Fenstermodus) + + Ausgang: BC 2**15 + Schattenspeichergröße (in K) + + Zweck: EUMEL-0 kann so die Größe des Schattenspeichers und den + gewünschten Modus (hier: Fenstermodus) erfragen. Falls kein + Schattenspeicher vorhanden ist, muß 0 als Größe geliefert + werden. Das Resultat von SCHINF darf sich innerhalb eines + Systemlaufs nicht ändern. + + + #dx("SCHACC")# (im Fenstermodus) + + Eingang: HL Nummer der 1/2K-Seite, die in das Fenster zu schal + ten ist. + Ausgang: HL Anfangsadresse (im Normaladreßraum) des aktuellen + Fensters + + Zweck: Dient zum Zugriff auf den Schattenspeicher über das Fen + ster. Man beachte, daß mehrere Fenster möglich sind, aber + alle im Adreßbereich des SHards liegen müssen! Die Num + mern der 1/2K-Seiten des Schattenspeichers liegen immer + im Bereich von 0 bis 2n-1, wobei n die von SCHINF geliefer + te Größe des Schattenspeichers ist. Daraus folgt, daß + SCHACC nicht aufgerufen wird, falls kein Schattenspeicher + vorhanden ist. + +#d("Transportmodus")# + + #dx("SCHINF")# (im Transportmodus) + + Ausgang: BC 2**14 + Schattenspeichergröße (in K) + + Zweck: EUMEL-0 kann so die Größe des Schattenspeichers und den + gewünschten Modus (hier: Transportmodus) erfragen. Falls + kein Schattenspeicher vorhanden ist, muß 0 als Größe gelie + fert werden. Das Resultat von SCHINF darf sich innerhalb + eines Systemlaufs nicht ändern. + + + #dx("SCHACC")# (im Transportmodus) + + Eingang: A = 1 Transport in den Schattenspeicher + A = 2 Transport aus dem Schattenspeicher + DE Nummer der 1/2K Seite im Schattenspeicher + HL Adresse im normalen Hauptspeicherbereich + + Zweck: Es werden jeweils 512 Bytes aus dem Normal- in den + Schattenspeicher (A=1) bzw. aus dem Schattenspeicher in + den normalen Hauptspeicher (A=2) kopiert. + Die Nummern der 1/2K-Seiten des Schattenspeichers liegen + immer im Bereich von 0 bis 2n-1, wobei n die von SCHINF + gelieferte Größe des Schattenspeichers ist. Daraus folgt, daß + SCHACC nicht aufgerufen wird, falls kein Schattenspeicher + vorhanden ist. + + Eingang: A = 3 + E Index (immer geradzahlig: 0,2,4,...254) + Ausgang: BC Bereichslänge DIV 3 + HL Bereichsadresse + + Zweck: Für den angegebenen Index ist die Adresse eines Haupt + speicherbereichs und 1/3 der Länge dieses Bereichs zu + rückzumelden (Anzahl Einträge � 3 Bytes) Es sind also 128 + solcher Bereiche zur Verfügung zu stellen. Bei n K Schat + tenspeicher sollte jeder Bereich größer als 6*n/128 Bytes sein. + Alle Bereiche müssen gleich groß sein. + + Beispiel: Bei bis zu 256 K sollten 16-Byte-Bereiche + benutzt werden: + + shacc3: ld l,e + ld h,0 + add hl,hl + add hl,hl + add hl,hl + ld bc,schtab + add hl,bc ; <e> DIV 2 * 16 + schtab + ld bc,5 ; 16 DIV 3 + ret + + schtab: defs 128*16 + + + + +#b("Blocktransfer im Speicher")# +#goalpage("ldir")# + + + +#b("Speicherfehler")# +#goalpage("memerr")# + +Falls die Hardware Speicherfehler aufgrund von Paritybits, ECC oder ähnlichem feststellen +und an SHard melden kann, sollte das zur Erhöhung der Systemsicherheit genutzt werden. + +Wenn SHard (z.B. über Interrupt) einen Speicherfehler mitgeteilt bekommt, sollte er wenn +möglich eine entsprechende Meldung ausgeben und das System brutal anhalten: + + rien#ub# #ue#ne#ub# #ue#vas#ub# #ue#plus: jr rien#ub# #ue#ne#ub# #ue#vas#ub# #ue#plus + + +Wenn Speicherfehler mit Sicherheit bemerkt werden, verhindert diese Reaktion, daß die +Fehler auf dem Hintergrund festgeschrieben werden und evtl. später zu Systemfehlern führen. + +Der Anwender kann dann durch Hardware-Reset auf den letzten Fixpunkt des EUMEL- +Systems zurücksetzen. So verliert er zwar evtl. die letzten Minuten seiner Arbeit, behält aber +auf alle Fälle ein konsistentes System. + + + + +#bb("4. ","Zeitgeber")# +#goalpage("zeit")# + +SHard muß einen Zeitgeberinterrupt erzeugen, der ca. 10 bis 100 mal pro Sekunde auftritt. +Dabei ist die 0-Routine 'timerinterrupt' aufzurufen. Ohne diesen Interrupt wird die Uhr nicht +geführt, und die Zeitscheibenlogik für das Timesharing fällt aus. + + #dx("timerinterrupt")# (0-Routine) + + Eingang: A seit letztem Zeitgeberinterrupt vergangene Zeit (in ms) + + Zweck: Wird von EUMEL-0 für interne Uhren und für das Schedu + ling (Zeitscheibenlogik) verwendet. Es werden keine hohen + Genauigkeitsanforderungen an die Zeitangaben bei #on("i")#einzel + nen#off("i")# Interrupts gestellt. Um EUMEL-0 eine genaue Real + zeituhr zu ermöglichen, sollte die so erzeugte Zeitangabe #on("i")#im + Mittel#off("i")# aber möglichst genau sein, d.h. die Summe der inner + halb einer Minute so übergebenen Werte sollte zwischen + 59995 und 60005 liegen. + + + +#bb("5. ","Kanäle")# +#goalpage("channel")# + +Einiges zum Kanalkonzept: + +Das System kennt die Kanäle 0..32. + + Kanal 0 ist der Systemhintergrund. + Die Kanäle 1..15 sind für Stream-IO (Terminals, Drucker, ...) vorgesehen. + Kanal 31 ist der Standard-Archivkanal. + Kanal 32 ist der Parameterkanal. + +Die Kanäle 2.. 30 können installationsabhängig verfügbar sein oder auch nicht. Deren Funk +tion ist dann Absprachesache zwischen Installation und SHard. + +Kanäle können über Block-IO (BLOCKOUT, BLOCKIN) oder Stream-IO (OUTPUT,..) ange +sprochen werden. Das System erfährt über IOCONTROL, welche Betriebsart des Kanals +sinnvoll ist. + +#on("i")##on("b")#Achtung: Alle Kanaloperationen müssen grundsätzlich für alle Kanäle (0...32) aufgerufen + werden können. Dabei können Operationen auf nicht vorhandenen Kanälen und + unsinnige Operationen (z.B. Stream-IO auf Kanal 0) leer implementiert wer + den.#off("b")# (Dafür werden im folgenden bei jeder SHard-Routine Vorschläge gemacht.)#off("i")# + + + +#bb("5.1 ","Stream-IO")# +#goalpage("stream")# + +Über Stream-IO wickelt das System die übliche zeichenorientierte Ein-/Ausgabe auf Termi +nals, Druckern, Plottern usw. ab. Stream-IO wird nur für die Kanäle 1...15 gemacht. + + #dx("inputinterrupt")# (0-Routine)#goalpage("inp")# + + Eingang: A Kanalnummer (1...15) + B eingegebenes Zeichen + C Fehlerbits: + Bit 0 = 1 Mindestens ein Zeichen ging + verloren. + Bit 1 = 1 Es wurde der BREAK-Zustand + (bei V24) erkannt. + Bit 2 = 1 Das Zeichen ist u.U. falsch + (Paritätsfehler). + + Ausgang: A Anzahl Zeichen, die noch übernommen werden kön + nen. + + Zweck: SHard muß EUMEL-0 durch Aufruf dieser Routine mitteilen, + daß eine Eingabe vorliegt. + + Hinweise: EUMEL-0 puffert die Zeichen. Siehe auch IOCONTROL: + "weiter". + + Bei Kanalnummern <1 oder >15 wird der Aufruf von + EUMEL-0 ignoriert. + + Falls die Hardware keine Inputinterrupts zur Verfügung stellt, + sollte ein Timer benutzt werden, um alle möglichen Input + quellen regelmäßig abzufragen. Dabei muß man allerdings den + goldenen Mittelweg zwischen zu häufiger (Systemdurchsatz + sinkt) und zu seltener Abfrage (Zeichen gehen verloren) + suchen. Man sollte dabei nicht nur an die menschliche Tipp + geschwindigkeit sondern auch an die höchste Baudrate + denken, die man für Rechnerkopplungen noch unterstützen + will. *) +#foot# +#f#*) Eine weitere Möglichkeit, auf manchen Kanälen ohne Interrupts auszukommen, wird bei der IOCONTROL-Funktion +"weiter" beschrieben (siehe S.#topage("weiter")#).#a# +#end# + + Falls SHard Flußkontrolle für den Kanal ausüben soll, muß er + die Rückmeldung in A auswerten. Dabei ist mit einem geeig + neten Schwellwert zu arbeiten, da in der Regel die sendende + Gegenstelle einer Sendeunterbrechung nicht sofort Folge + leistet. + + Achtung: #on("i")#Keinesfalls darf 'inputinterrupt' rekursiv aufgerufen werden. + Normalerweise wird das automatisch verhindert, wenn man + den zugehörigen Hardwareinterrupt erst nach der 0-Routine + wieder freigibt. Falls das nicht möglich ist und unter bestimm + ten Umständen das nächste Zeichen abgeholt werden muß, + bevor die 0-Routine beendet ist, muß SHard einen eigenen + Puffer implementieren:#off("i")# + + hardwareinterrupt: + IF input interrupt aktiv + THEN trage zeichen in shard puffer ein ; + gib hardware interrupt frei + ELSE input interrupt aktiv := true ; + gib hardware interrupt frei ; + input interrupt ; + disable interrupt ; + WHILE shard puffer enthaelt noch zeichen REP + nimm zeichen aus shard puffer ; + enable interrupt ; + input interrupt ; + disable interrupt + PER ; + input interrupt := false ; + enable interrupt + FI . + + + #d("OUTPUT")# + + Eingang: A Kanalnummer (1...15) + BC Anzahl auszugebender Zeichen + HL Adresse der Zeichenkette + Ausgang: BC Anzahl der übernommenen Zeichen + C-Flag gesetzt <=> alle Zeichen übernommen + + Zweck: Ausgabe einer Zeichenkette. Diese ist (möglichst ganz) zwi + schenzupuffern, denn die Ausführung von OUTPUT sollte kein + Warten auf IO enthalten. Der Ausgabepuffer muß mindestens + 50, besser 100 Zeichen fassen können. Durch eine Inter + ruptlogik oder etwas Äquivalentes ist sicherzustellen, daß + dieser Puffer parallel zur normalen Verarbeitung ausgegeben + wird. Wenn die auszugebende Zeichenkette nicht vollstän + dig in den Puffer paßt, sollten trotzdem so viele Zeichen wie + möglich übernommen werden. Im weiteren Verlauf ruft + EUMEL-0 dann wieder OUTPUT mit dem Rest der Zei + chenkette auf. + + Hinweis: OUTPUT kann mit BC=0 aufgerufen werden. Auch diese + leere Operation muß mit gesetztem C-Flag quittiert wer + den. + + Achtung: #on("i")#Keinesfalls darf innerhalb von OUTPUT die 0-Routine 'warte' + aufgerufen werden.#off("i")# + + Vorschlag: Falls der Kanal nicht existiert bzw. OUTPUT darauf unsinnig + ist, sollte vorgegaukelt werden, alle Zeichen seien ausge + geben (BC unverändert und C-Flag gesetzt). + + + +#b("Terminals")# +#goalpage("term")# + +"Normale" #ib#Terminal#ie(1,", normales")#s können ohne weitere Unterstützung des SHards angeschlossen wer +den. Die zur Anpassung an den EUMEL-Zeichensatz *) notwendigen #ib#Umcodierungen#ie# werden +von den höheren Ebenen aus eingestellt. Da diese Umsetztabellen vom SHard unabhängig +sind, stehen automatisch alle so angepaßten Terminaltypen allen EUMEL-Anwendern zur +Verfügung! +#foot# +#f#*) Siehe "EUMEL Benutzerhandbuch"#a# +#end# + +Für den Anschluß eines #on("b")##on("i")#integrierten #ib#Terminal#ie(1,", integriertes")#s#off("i")##off("b")#, in dessen Bildwiederholspeicher direkt gear +beitet wird, kann man häufig den Terminaltyp 'psi' verwenden (siehe auch "Exoten"). + +Näheres zu Terminaltypen und -anschlüssen findet man im "EUMEL Systemhandbuch" +unter den Stichwörtern #on("i")#Konfiguration#off("i")# und #on("i")#Konfigurierung#off("i")#. + + + +#bb("Drucker, ","Plotter")# +#goalpage("druck")# + +#ib#Drucker#ie# und Plotter werden vom EUMEL-System wie Terminals angesehen. Da in der Regel +der Rechner aber schneller Zeichen senden als der Drucker drucken kann, müssen solche +Geräte in der Regel mit Flußkontrolle angeschlossen werden (siehe S.#topage("fluss")#). + +Wenn Drucker oder Plotter über eine Parallelschnittstelle angeschlossen werden, kann man +auf diesem Kanal möglicherweise auf einen Ausgabepuffer verzichten. Voraussetzung ist +dabei, daß + + a) der Drucker einen eigenen Puffer hat und + b) der Puffer "schnell" gefüllt werden kann (< 0.1 ms/Zeichen). + +Dann kann man auf den bei der SHard-Routine OUTPUT geforderten Puffer verzichten und +die Zeichenkette direkt über die Parallelschnittstelle an den Drucker übergeben. Wenn der +Drucker 'Puffer voll' signalisiert, sollte die Zeichenübernahme bei OUTPUT abgebrochen +werden. *) #on("i")#Auf keinen Fall darf CPU-intensiv auf Freiwerden des Puffers gewartet werden!#off("i")# +#foot# +#f#*) siehe auch IOCONTROL "frout", S.#topage("frout")##a# +#end# + + + +#b("Exoten")# +#goalpage("exot")# + +Exotische #ib#Terminal#ie(1," exotisches")#s (im Sinne dieser Beschreibung) sind solche, für die eine Umsetztabelle +im System (siehe Konfiguratorbeschreibung) nicht ausreicht bzw. nicht nötig ist (Beispiele: +Terminals, in deren Bildwiederholspeicher direkt gearbeitet wird; Terminals, die soweit +programmierbar sind, daß sie den EUMEL-Zeichencode können). + +Für solche Terminals muß in der Konfiguration der Terminaltyp '#ib#psi#ie#' eingestellt werden. Dieser +wirkt ohne Umcodierungen, d.h. die EUMEL-Codes (siehe Benutzerhandbuch) werden direkt +dem SHard zugestellt (wie bei 'transparent'), jedoch mit folgenden Besonderheiten: + +Eingabeseitig werden zusätzlich folgende Codezuordnungen getroffen: + + Code Funktion + + 7 SV (Aktivierung: 'gib supervisor kommando:') + 17 STOP (Ausgabe auf diesen Kanal wird gestoppt) + 23 WEITER (Ausgabe läuft wieder weiter) + 4 INFO (System geht in Debugger, falls Debugoption) + + + +#bb("5.2 ","Block-IO")# +#goalpage("block")# + +Über Block-IO wickelt das System die Zugriffe zum Pagingmedium und zum Archiv ab. +Ferner ist daran gedacht, auch auf V.24-Schnittstellen Block-IO z.B. für Rechnerkopplung +zuzulassen. Die Kanalnummer in Reg. A unterscheidet diese Fälle. Außer beim Paging (A=0) +wird ein Block-IO durch die ELAN-Prozeduren 'blockin' und blockout' induziert. + +Bei Block-IO wird immer ein 512 Byte großer Hauptspeicherbereich mit übergeben. Dieser +kann (im Gegensatz zu OUTPUT) direkt benutzt werden, d.h. es muß keine Umpufferung +erfolgen. + +Dieser Hauptspeicherbereich darf nur bei BLOCKIN verändert werden. + +SHard darf (anders als bei OUTPUT) erst dann zur Aufrufstelle zurückgeben, wenn die +verlangte Operation abgeschlossen ist. Treten während der Operation Wartezeiten auf, so muß +SHard die 0-Routine 'warte' aufrufen, damit das System andere Prozesse weiterlaufen +lassen kann. + +EUMEL-0 definiert bestimmte Funktionen für Hintergrund (Kanal 0) und Archiv (Kanal 31). +Operationen auf anderen Kanälen kann SHard nach Belieben implementieren und deren +Leistung seinen Installationen über ELAN-Pakete zur Verfügung stellen. Das System vergibt +auch in Zukunft für den #ib##on("italic")#Funktionscode#ie##off("italic")# in Register BC nur positive Werte (Bit 7 von B = 0). +Der SHard kann selbst negative Codes einführen. + + + #d("BLOCKIN")# + + Eingang: A Kanalnummer (0...32) + BC Funktionscode 1 + DE Funktionscode 2 + HL Adresse des Hauptspeicherbereichs + Ausgang: A undefiniert (darf also verändert werden) + BC Rückmeldecode + HL darf verändert werden + + Der Inhalt des Hauptspeicherbereichs (<HL>... <HL> + +511) darf verändert sein. + + Zweck: "Einlesen" von Blöcken. Die genaue Wirkung hängt vom + Funktionscode und dem Kanal ab. + + Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKIN darauf unsinnig + ist, sollte die Rückmeldung -1 in BC geliefert werden. + + + #d("BLOCKOUT")# + + Eingang: A Kanalnummer (0...32) + BC Funktionscode 1 + DE Funktionscode 2 + HL Adresse des Hauptspeicherbereichs + Ausgang: A undefiniert (darf also verändert werden) + BC Rückmeldecode + HL darf verändert werden + + Der Inhalt des Hauptspeicherbereichs darf #on("i")#nicht#off("i")# verändert + werden! + + Zweck: "Ausgeben" von Blöcken. Die genaue Wirkung hängt vom + Funktionscode und dem Kanal ab. + + Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKOUT darauf un + sinnig ist, sollte die Rückmeldung -1 in BC geliefert wer + den. + + + #dx("warte")# (0-Routine) + + Ausgang: Alle Register undefiniert! + + Zweck: Diese Routine ist bei 'blockin' oder 'blockout' dann aufzu + rufen, wenn SHard im Augenblick nichts zu tun hat. Durch + den Aufruf von 'warte' erhalten andere Systemteile die + Möglichkeit, weiterzuarbeiten. Ein 'warte' kann bis zu ca. 1/4 + Sekunde Zeit aufnehmen. 'warte' darf nicht in Interrupt + routinen und Stream-IO verwendet werden! 'warte' zerstört + alle Register! SHard muß davon ausgehen, daß 'warte' sei + nerseits andere SHard-Komponenten aufruft. + + +Die Verwendung der 0-Routine 'warte' soll hier an einigen Beispielen verdeutlicht werden: + + + blockout auf platte : + WHILE platte noch nicht frei REP + warte + ENDREP ; + uebertrage schreibbefehl an controller ; + uebertrage daten an controller . + + blockin von platte : + WHILE platte noch nicht frei REP + warte + ENDREP ; + uebertrage lesebefehl an controller ; + WHILE daten noch nicht gelesen REP + warte + ENDREP ; + hole daten vom controller . + + + blockout auf floppy : + seekbefehl an controller ; + WHILE seek noch nicht fertig REP + warte + ENDREP ; + setze dma auf schreiben block zur floppy ; + schreibbefehl an controller ; + WHILE schreiben noch nicht fertig REP + warte + ENDREP . + + blockin von floppy : + seekbefehl an controller ; + WHILE seek noch nicht fertig REP + warte + ENDREP ; + setze dma auf lesen block von floppy ; + lesebefehl an controller ; + WHILE lesen noch nicht fertig REP + warte + ENDREP . + + + +#b("Block-IO bei Hintergrund und Archiv")# +#goalpage("bhgarch")# + +#ib#Hintergrund#ie# (Kanal 0) und #ib#Archiv#ie# (Kanal 31) unterscheiden sich in den Link-Bedingungen nur +in der Kanalnummer. Die Aufrufe von BLOCKIN und BLOCKOUT werden mit folgenden +Eingangsparametern versorgt: + + #on("b")#BLOCKIN#off("b")# A 0 bzw. 31 + B 0 + C Blocknummer DIV 65536 + DE Blocknummer MOD 65536 + HL Hauptspeicheradresse + + Der angegebene 512-Byte-Block ist in den Hauptspeicher + ab <HL> einzulesen. + + #on("b")#BLOCKOUT#off("b")# A 0 bzw. 31 + B 0 + C Blocknummer DIV 65536 + DE Blocknummer MOD 65536 + HL Hauptspeicheradresse + + Der Hauptspeicherbereich (<HL>...<HL>+511) ist auf den + angegebenen Block zu schreiben. + +Als Rückmeldungen sind zu liefern:#goalpage("errcod")# + + 0 Operation korrekt ausgeführt. + 1 Manuell behebbarer Fehler (z.B. Laufwerktür offen) + 2 Permanenter Fehler (z.B. Daten nicht lesbar) + 3 Versorgungsfehler (zu hohe Blocknummer) + +Zusätzlich zu der Rückmeldung muß bei BC <> 0 in HL die Adresse eines Fehlerstrings +(Längenbyte + Fehlertext) geliefert werden. *) +#foot# +#f#*) Diese Zusatzrückmeldung ist nur für die BLOCKIN/OUT Aufrufe auf Kanal 0/31 von Bedeutung. Sie wird nur von +EUMEL-0 beim Paging und im Hardwaretest ausgewertet.#a# +#end# + +#dx("Fehlerwiederholungen")#: Das EUMEL-System führt von sich aus Fehlerwiederho + lungen beim Hintergrund- und beim Archivzugriff + durch. SHard sollte deshalb im Fehlerfall die Opera + tion nicht selbst wiederholen, sondern einen Lese/ + Schreibfehler zurückmelden. So werden dem + EUMEL-System auch Soft-Errors gemeldet. In + manchen Fällen soll vor einem erneuten Lese- oder + Schreibversuch der Arm auf Spur 0 positioniert + werden o.ä. Um das zu erreichen, sollte SHard diese + "Reparaturaktion" direkt im Anschluß an den fehler + haften Versuch durchführen. + +#dx("Kontrollesen")#: Falls Kontrollesen (nach jedem Schreibzugriff) notwendig ist, + muß das allerdings vom SHard durchgeführt werden. + In der Regel reicht es dazu, den geschriebenen + Block "ohne Datentransport" zu lesen, so daß nur + CRC überprüft wird. + +Will SHard weitere Archivlaufwerke zur Verfügung stellen, so kann er dafür Kanalnummern +(30,29..) vergeben. Auf ELAN-Ebene kann die archivierende Task durch 'continue (x)' das +Laufwerk 'x' ansteuern. + +Hinweis: Das System versucht Hintergrund und Archiv parallel zu betreiben, d.h. wenn + SHard bei der Hintergrundbehandlung das UP 'warte' aufruft, kann 'warte' seiner + seits die Archivbehandlung des SHards aufrufen. Wenn beides z.B. denselben + Floppykontroller benutzt, muß SHard sicherstellen, daß das gut geht (z.B. durch + Semaphoren). + + + + +#bb("5.3 ","IO-Steuerung")# +#goalpage("iocontrol")# + +Die IO-Steuerung erlaubt Steuerung und Zustandsabfragen der Kanäle. IO-Steuerung wird +(außer bei Kanal 0) auch durch 'control' in ELAN induziert. + +Der Funktionscode in BC unterliegt denselben Konventionen wie bei Block-IO, d.h. das +System verwendet nur positive Codes. Der SHard-Schreiber kann auch negative Codes für +Sonderzwecke vorsehen. + + + #d("IOCONTROL")# + + Eingang: A Kanalnummer (0...32) + BC Funktionscode 1 + DE Funktionscode 2 + HL Funktionscode 3 + Ausgang: BC Rückmeldung + A darf verändert werden, in einigen Fällen zusätzliche + Rückmeldung + C-Flag (in einigen Fällen zusätzliche Meldung) + + Zweck: abhängig von 'Funktionscode 1' (s.u.) + +Das System verlangt folgende Informations- und Steuerleistungen über IOCONTROL: + + #d("IOCONTROL ""typ""")# + + Eingang: A Kanalnummer (0...31) + BC 1 + Ausgang: BC Kanaltyp + + Zweck: Informiert EUMEL-0, welche IO für den angegebenen Kanal + sinnvoll ist. Die Rückmeldung in BC wird bitweise interpre + tiert: + + Bit 0 gesetzt <=> 'inputinterrupt' kann kommen. + Bit 1 gesetzt <=> OUTPUT ist sinnvoll. + Bit 2 gesetzt <=> BLOCKIN ist sinnvoll. + Bit 3 gesetzt <=> BLOCKOUT ist sinnvol. + Bit 4 gesetzt <=> IOCONTROL "format" ist sinn + voll. + + Hinweis: #on("i")#Trotz dieser Informationsmöglichkeit wird nicht garantiert, daß + nur sinnvolle Operationen für den Kanal aufgerufen werden.#off("i")# + + + #dx("IOCONTROL ""frout""")##goalpage("frout")# + + Eingang: A Kanalnummer (1...15) + BC 2 + Ausgang: BC Anzahl Zeichen, die nächster OUTPUT übernimmt + C-Flag gesetzt <=> Puffer leer + + Zweck: Liefert Information über die Belegung des Puffers. Diese + Information wird von EUMEL-0 zum Scheduling benutzt. + + Achtung: #on("i")#Wenn EUMEL-0 längere Zeit kein OUTPUT gemacht hat, + muß irgendwann BC > 49 gemeldet werden.#off("i")# + + Hinweis: Unter Berücksichtigung des oben Gesagten darf "gelogen" + werden. Man kann z.B. immer 50 in BC zurückmelden, muß + dann aber schlechtere Nutzung der CPU bei Multi-User- + Systemen in Kauf nehmen. + + Falls auf dem angegebenen Kanal ein Drucker mit eigenem + Puffer über Parallelschnittstelle angeschlossen ist (siehe + S.#topage("druck")#) und man auf einen SHard-internen Puffer verzichtet hat, + sollte bei 'Druckerpuffer voll' 0 in BC und 'NC' zurückge + meldet werden. Wenn aber Zeichen übernommen werden + können, sollte 50 in BC und 'C-Flag gesetzt' gemeldet + werden. + + Vorschlag: Falls der Kanal nicht existiert oder nicht für Stream-IO zur + Verfügung steht, sollten 200 in BC und C-Flag gesetzt + zurückgemeldet werden. + + + + + #dx("IOCONTROL ""weiter""")##goalpage("weiter")# + + Eingang: A Kanalnummer (1...15) + BC 4 + Ausgang: - + + Zweck: Das System ruft "weiter" für den in A angegebenen Kanal + auf, wenn es wieder Eingabezeichen puffern kann. + + Hinweis: "weiter" wird von EUMEL-0 auch immer dann aufgerufen, + wenn ein Prozeß auf dem angegebenen Kanal auf Eingabe + wartet und keine Zeichen mehr gepuffert sind. Wenn der + betroffene Kanal von sich aus keine Interrupts erzeugt, kann + SHard dies benutzen, um durch Aufruf von 'inputinterrupt' ein + Eingabezeichen zuzustellen. + #on("i")#Diese Betriebsart sollte nicht für normale Terminalkanäle + eingesetzt werden. Denn dann wird die SV-Taste nur an + EUMEL-0 zugestellt, wenn ein Prozeß auf diesem Kanal auf + Eingabe wartet. Somit sind in dieser Betriebsart CPU-inten + sive Endlosschleifen nicht normal abbrechbar!#off("i")# + + + #d("IOCONTROL ""size""")# + + Eingang: AL Kanalnummer (0...31) + CX 5 + DX Schlüssel + Ausgang: CX Anzahl Blöcke MOD 65536 + AL Anzahl Blöcke DIV 65536 + + Zweck: EUMEL-0 ruft 'size' auf, um die Anzahl Blöcke zu erfahren, + die ein Block-IO-Kanal verkraften kann (Größe von Hin + tergrund und Archiven). Bei Archivlaufwerken, die mehrere + Formate bearbeiten können, dient dieser Aufruf auch zum + Einstellen des Formats für die folgenden blockin/blockout- + Operationen anhand des Schlüssels. + + Schlüssel: 0 Wenn möglich 'erkennend', sonst 'standard'. Im ersten + Fall erkennt SHard das Format der eingelegten Disket + te und stellt dieses ein. + + Die weiteren Schlüssel sind stets definierend. Dabei gibt es + die EUMEL-Standardformate: + + 1 5" 2D-40, Sektor 1..9, 512 Bytes + 2 5" 2D-80, Sektor 1..9, 512 Bytes + 3 5" HD-80, Sektor 1..15, 512 Bytes + 10 8" 1D-77, Sektor 0..15, 512 Bytes + 11 8" 2D-77, Sektor 0..15, 512 Bytes + + Zusätzlich kann man sämtliche Spezialformate angeben: + + 8192 * laufwerkstyp 1: 8" + 2: 5" + 3: 3" + + + 4096 * seiten 0: einseitig + 1: doppelseitig + + + 1024 * dichte 0: single + 1: double + 2: high + + + 256 * spuren 0: 35 + 1: 40 + 2: 77 + 3: 80 + + + 64 * sektorbytes 0: 128 + 1: 256 + 2: 512 + + + 32 * erster sektor 0: \#0 + 1: \#1 + + + sektoren pro spur 0 ... 31 + + So bezeichnet '8762' das Format 8" 1S-77 Sektor 1..26 a + 128 Bytes. + + Anmerkung: SHard sollte alle physisch möglichen EUMEL-Standard + formate unterstützen. Von den Spezialformaten sollten die für + den Datenaustausch wichtigen Formate berücksichtigt werden. + Die EUMEL-Standardformate (1,2,3,10,11) sollten auch über + die entsprechenden analytischen Codes erreicht werden. (Z.B. + bezeichnen 1 und 21929 dasselbe Format.) Die Numerierung + der Blöcke ist in jedem Fall seitenorientiert, d.h. entsprechend + den Standardformaten (siehe S.#topage("arch")#). + + Hinweis: Bei Archiven wird 'size' aufgerufen, nachdem der Archivträ + ger eingelegt wurde. D.h. SHard hat die Gelegenheit, die + Größe anhand des eingelegten Archivträgers zu bestimmen + (z.B. ob single- oder doublesided). + + Vorschlag: Diese Funktion sollte auf nicht vorhandenen und den + Stream-IO-Kanälen 0 liefern. Sie muß aber mindestens auf + Kanal 0 (Hintergrund) und Kanal 31 (Archiv) "echte" Werte + liefern. + + Achtung: #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die + 0-Routine 'warte' aufgerufen werden.#off("i")# + + + #d("IOCONTROL ""format""")# + + Eingang: A Kanalnummer (0...31) + BC 7 + Ausgang: BC Fehlercode wie bei Archiv-BLOCKOUT (siehe S.#topage("errcod")#) + + Zweck: Dient zum Formatieren eines Mediums. Diese Funktion kann + für jeden Kanal leer implementiert sein ('ret'). Sie sollte aber + "formatierend" (z.B. auf Kanal 31) arbeiten, falls auf diesem + Kanal die "typ"-Abfrage "Formatieren sinnvoll" liefert. Falls + (bei Diskettenlaufwerken) mehrere Formate möglich sind, + bestimmt der Schlüssel das gewünschte Format. + + Schlüssel: wie bei IOCONTROL "size" + + Hinweis: Falls für das Formatieren ein großer Speicherbereich benö + tigt wird, sollte das Formatieren von Disketten besser in + einem Boot-Dialog vor dem Start von EUMEL-0 angebo + ten werden. Denn sonst müßte der Pagingbereich unnötig + eingeschränkt werden. + Man kann das Formatieren einer Spur CPU-intensiv im + plementieren (d.h. ohne DMA im DI-Modus), wenn man in + Kauf nimmt, daß alle anderen Tasks des EUMEL-Systems in + dieser Zeit "stehen". Dann sollte man aber nach jeder Spur + mehrmals die 0-Routine 'warte' aufrufen. + + Achtung: #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die + 0-Routine 'warte' aufgerufen werden.#off("i")# + + + +#b("Konfigurierung serieller Schnittstellen")# +#goalpage("v24")# + +Bei Kanälen, die hardwaremäßig auf #ib#serielle Schnittstellen#ie# (#ib#V.24#ie#) zurückgeführt werden, sind +in der Regel die Größen + + - #ib#Baudrate#ie# (..., 2400, 4800, 9600, ...) + - #ib#Zeichenlänge#ie# (7 Bits, 8 Bits) + - #ib#Parität#ie# (keine, gerade, ungerade) + +einstellbar. Dafür muß SHard die IOCONTROL-Funktionen "baud" und "bits" zur Verfü +gung stellen. Diese werden in zwei Modi benutzt: + + a) #on("b")#einstellend#off("b")# + Läuft der aufrufende EUMEL-Prozeß auf dem privilegierten Steuerkanal (A = 32), + wird der als Parameter mit übergebene #on("i")#adressierte Kanal#off("i")# auf die geforderten Werte + eingestellt, sofern das möglich ist. + + b) #on("b")#abfragend#off("b")# + Läuft der aufrufende EUMEL-Prozeß nicht auf Kanal 32 (A <> 32), wird lediglich + abgefragt, ob der #on("i")#adressierte Kanal#off("i")# auf die übergebenen Werte eingestellt werden + könnte. + +Aufgrund des zweiten Modus können die höheren EUMEL-Ebenen dem Anwender bei der +Konfigurierung mitteilen, welche Werte sich auf dem jeweiligen Kanal einstellen lassen. Das +nutzt z.B. das Standard-Konfigurationsprogramm aus. + +Hinweis: Bei einigen Kanälen (z.B. bei einem integrierten Terminal oder einer Parallel + schnittstelle) sind Baudrateneinstellungen sinnlos. Bei anderen können sie nur + hardwaremäßig vorgenommen werden (Jumper, Dip Switches). In allen diesen + Fällen muß SHard bei allen Einstellungen 'unmöglich' melden. (Standardmäßig + wird der Anwender bei der Einstellung seiner Konfiguration dann auch nicht + danach gefragt.) + + + #d("IOCONTROL ""baud""")# + + Eingang: A eigener Kanal (1...15 / 32) + BC 8 + DE adressierter Kanal + HL Schlüssel + Ausgang: BC Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (A=32) aufgerufen, + wird die angegebene Baudrate für den durch Register DE + adressierten Kanal eingestellt, falls das möglich ist. + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob eine derartige + Einstellung des adressierten Kanals möglich wäre. + + Schlüssel: 1 50 Baud + 2 75 Baud + 3 110 Baud + 4 134.5 Baud + 5 150 Baud + 6 300 Baud + 7 600 Baud + 8 1200 Baud + 9 1800 Baud + 10 2400 Baud + 11 3600 Baud + 12 4800 Baud + 13 7200 Baud + 14 9600 Baud + 15 19200 Baud + 16 38400 Baud + + Anmerkung: In der Regel werden nicht alle Baudraten vom SHard un + terstützt werden. Bei V.24 Schnittstellen sollten aber min + destens 2400, 4800 und 9600 Baud zur Verfügung stehen, + besser auch 300, 600, 1200 und 19200 Baud. + + Hinweis: Falls SHard-spezifisch weitere Baudraten implementiert + werden sollen, darf SHard hierfür negative Schlüsselwerte + (Register HL) vergeben. + + + #d("IOCONTROL ""bits""")# + + Eingang: A eigener Kanal (1...15 / 32) + BC 9 + DE adressierter Kanal + HL Schlüssel + Ausgang: BC Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (A=32) aufgerufen, + wird die angegebene Zeichenlänge (Bits pro Zeichen) und + Parität für den durch Register DE adressierten Kanal einge + stellt, falls das möglich ist. + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob eine derartige + Einstellung des adressierten Kanals möglich wäre. + + + Schlüssel: stop * 32 + par * 8 + (bit - 1) + + stop: 0 1 Stopbit + 1 1.5 Stopbits + 2 2 Stopbits + + par: 0 keine Parität + 1 ungerade Parität + 2 gerade Parität + + bit: 1...8 Bits pro Zeichen + + + Anmerkung: In der Regel werden nicht alle Kombinationen vom SHard + unterstützt werden. Bei V.24 Schnittstellen sollten aber + möglichst 1 Stopbit, 7 und 8 Bits pro Zeichen und alle drei + Paritätseinstellungen zur Verfügung stehen. + + Hinweis: Falls SHard-spezifisch weitere Einstellungen implementiert + werden sollen, darf SHard hierfür negative Schlüsselwerte + (Register HL) vergeben. + + + + +#b("Flußkontrolle")# +#goalpage("fluss")# + +Die stromorientierten Kanäle (1...15) werden nicht nur zum Anschluß schneller Geräte (wie +Terminals) verwendet, sondern auch, um langsame Geräte (wie Drucker) anzuschließen, die +die Daten u.U. nicht so schnell übernehmen können, wie sie der Rechner schickt. Dabei ist +auf eine geeignete Flußkontrolle zu achten (nicht schneller senden, als der Andere emp +fangen kann). Dieses Problem stellt sich auch bei einer Rechner-Rechner-Kopplung. Hier +ist in der Regel sogar zweiseitige Flußkontrolle notwendig. + +Als Flußkontrolle ist die #ib#REQUEST TO SEND/CLEAR TO SEND#ie# Logik der V.24-Schnitt +stelle oder das #ib#XON/XOFF#ie#-Protokoll zu verwenden. Das letztere kann auch bei Parallel +schnittstellen eingesetzt werden. + +Zur eingabeseitigen Flußkontrollsteuerung kann SHard die Rückmeldung der 0-Routine +'inputinterrupt' (siehe S.#topage("inp")#) und die IOCONTROL-Funktion "weiter" (siehe S.#topage("weiter")#) verwen +den: + +Unterschreitet die Rückmeldung einen von SHard zu bestimmenden Schwellwert, muß SHard +auf der V.24-Schnittstelle das Signal 'REQUEST TO SEND' wegnehmen bzw. XOFF senden. +Dadurch wird bei den meisten Fremdrechnern ein weiteres Senden unterbrochen, sofern (im +ersten Fall) das Signal 'REQUEST TO SEND' dort mit dem V.24-Eingang 'CLEAR TO +SEND' verbunden ist. Wird von EUMEL-0 "weiter" aufgerufen, so kann auf dem enspre +chenden Kanal wieder empfangen werden (RTS setzen bzw. XON senden). + +Für die ausgabeseitige Flußkontrolle muß rechnerseitig ebenfalls das Signal 'CLEAR TO +SEND' bzw. der Empfang von XOFF/XON berücksichtigt werden. Wenn an der Schnittstelle +das 'CLEAR TO SEND' weggenommen wird, darf SHard keinen weiteren Output auf dieser +Schnittstelle machen, bis 'CLEAR TO SEND' wieder anliegt. Entsprechend muß der Empfang +von XOFF die Ausagbe anhalten und XON sie wieder starten. + +Bemerkung: Die meisten Systeme enthalten die CTS-Funktion schon in ihrer Hardware, + so daß im SHard dafür keine Vorkehrungen getroffen werden müssen. + + +Zur Einstellung der gewünschten Flußkontrolle eines Kanals dient die IOCONTROL-Funk +tion "flow". Ähnlich wie "baud" und "bits" wirkt auch "flow" nur auf Kanal 32 #on("i")#einstellend#off("i")# +und auf allen anderen Kanälen lediglich #on("i")#abfragend#off("i")#. + + + #d("IOCONTROL ""flow""")# + + Eingang: A eigener Kanal (1...15 / 32) + BC 6 + DE adressierter Kanal + HL Modus + Ausgang: BC Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (A=32) aufgeru + fen, muß sie den gewünschten Flußkontrollmodus für den + adressierten Kanal einstellen. + Dabei sind folgende Modi festgelegt: + + HL= 0 Keine Flußkontrolle + HL= 1 XON/XOFF (in beide Richtungen) + HL= 2 RTS/CTS (in beide Richtungen) + HL= 5 XON/XOFF (nur ausgabeseitig) + HL= 6 RTS/CTS (nur ausgabeseitig) + HL= 9 XON/XOFF (nur eingabesetig) + HL=10 RTS/CTS (nur eingabeseitig) + + Wenn keine Flußkontrolle gewünscht wird (HL=0), muß SHard + "weiter" ignorieren; bei HL=1 oder HL=9 muß bei "stop" + XOFF und bei "weiter", sofern zuletzt XOFF geschickt wurde, + XON geschickt werden; bei HL=2 oder HL=10 muß bei + "stop" das Signal RTS auf low und bei "weiter" wieder auf + high gesetzt werden. Mit "stop" ist hierbei das Unterschreiten + des Schwellwertes bei der Rückmeldung von "inputinterrupt" + gemeint. + Bei HL=1 oder HL=5 müssen empfangene XON/XOFF-Zei + chen, bei HL=2 oder HL=6 das Signal CTS beachtet wer + den. + + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob der geforderte + Flußkontrollmodus auf dem adressierten Kanal einstellbar + wäre. + + Hinweis: Falls SHard-spezifisch weitere Flußkontrollmodi implemen + tiert werden sollen, darf SHard hierfür negative Moduswerte + (Register HL) vergeben. + + "weiter" wird von EUMEL-0 sehr oft aufgerufen. Es ist daher + nicht sinnvoll, jedesmal XON zu senden, da dies die Gegen + stelle damit überfluten würde. SHard muß sich merken, ob der + Kanal im XOFF-Zustand ist und nur dann bei "weiter" ein + XON senden. + +#b("Kalender")# +#goalpage("kalender")# + +Die Datums- und Uhrzeitabfrage ist bei Rechnern mit eingebauter Uhr unnötig. EUMEL holt +sich Datum und Uhrzeit dann von SHard. + + #d("IOCONTROL ""calendar""")# + + Eingang: CX 10 + DX (1=Minute, 2=Stunde, 3=Tag, 4=Monat, 5=Jahr) + gewünscht + Ausgang: CX Rückmeldung + + Zweck: Erfragen von Datum und Uhrzeit. Falls keine Uhr vorhanden + ist, muß bei jedem Aufruf -1 zurückgemeldet werden, bei + eingebauter Uhr jeweils das Gewünschte (Minute: 0..59, + Stunde: 0..23, Tag: 1..7, Monat: 1..12, Jahr: 0..99). Die Rück + meldung muß als BCD-Zahl erfolgen. + + Hinweis: Die Uhr darf zwischen zwei Aufrufen umspringen. Die daraus + resultierende Probleme werden auf höheren Ebenen abgehan + delt. + + + + +#bb("6. SHard-","Interface Version")# +#goalpage("shdver")# + +Die #ib#Versionsnummer#ie# der Interface-Spezifikation, auf der SHard aufbaut, muß als 1-Byte- +Konstante #ib#SHDVER#ie# in der SHard-Leiste stehen. Für das hier beschriebene Interface muß sie +den Wert 8 haben. + +So sind spätere Erweiterungen des SHard-Interfaces möglich, ohne daß alle SHard- +Moduln geändert werden müssen. + + + +#bb("7. ","ID-Konstanten")# +#goalpage("ID")# + +SHard muß direkt hinter SHDVER vier 2-Byte-Konstanten ablegen. Diese können von den +höheren Ebenen durch die ELAN-Prozedur + + INT PROC #ib#id#ie# (INT CONST no) + +abgefragt werden. Dabei werden id(0) bis id(3) von EUMEL-0 geliefert, während SHard in der +Leiste die Werte für id(4) bis id(7) zur Verfügung stellen muß: + + ID4 #ib#Lizenznummer#ie# des SHards *) +#foot# +#f#*) Dieser Wert muß mit der Nummer des Lizenzvertrags zwischen Implementierer und GMD übereinstimmen!#a# +#end# + + ID5 #ib#Installationsnummer#ie# des EUMEL-Anwenders **) +#foot# +#f#**) Diese Nummer vergibt der Lizenznehmer an die von ihm belieferten Anwender.#a# +#end# + + ID6 zur freien Verfügung + + ID7 zur freien Verfügung + + + + +#bb("8. ","Zusätzliche Leistungen")# +#goalpage("shdelan")# + +Will der SHard-Implementierer zusätzliche Leistungen anbieten, die mit den Standardopera +tionen nicht möglich sind, kann er weitere Codes für BLOCKIN, BLOCKOUT und +IOCONTROL zur Verfügung stellen. Um Überdeckungen mit Codes zu vermeiden, die von +EUMEL-0 intern verwendet oder erst später eingeführt werden, darf SHard für zusätzliche +Leistungen nur negative Werte als 'Funktionscode 1' verwenden. + + +Zum Ansprechen der neuen Leistungen stehen die ELAN-Prozeduren #on("i")#'#ib#blockout#ie#', '#ib#blockin#ie#'#off("i")# +und #on("i")#'#ib#control#ie#'#off("i")# zur Verfügung. + +Ferner steht dem SHard ein Parameterkanal (32) zur Verfügung. Funktionen, die (im Multi- +User) nicht jeder Task zur Verfügung stehen dürfen, müssen über diesen Kanal 32 abge +wickelt werden und dürfen nur dort wirken. + + + PROC blockout (ROW 256 INT CONST para, (* --> HL *) + INT CONST funktion1, (* --> BC *) + funktion2, (* --> DE *) + INT VAR antwort) (* <-- BC *) + + PROC blockin (ROW 256 INT VAR para, (* --> HL *) + INT CONST funktion1, (* --> BC *) + funktion2, (* --> DE *) + INT VAR antwort) (* <-- BC *) + + PROC control (INT CONST funktion1, (* --> BC *) + funktion2, (* --> DE *) + funktion3, (* --> HL *) + INT VAR antwort) (* <-- BC *) + +Hinweis: Der SHard darf für 'funktion 1' (BC) zusätzlich zu den hier beschriebenen Stan + dardcodes nur negative Codes vereinbaren. + + +Beispiel: + + Gibt eine Task, die durch 'continue (x)' an Kanal 'x' hängt, den Befehl + + control (-7,1200,13,antwort), + + so wird IOCONTROL mit (A='x', BC=-7, HL=13, DE=1200) aufgerufen. Verläßt + SHard 'control' mit BC = 1, so enthält 'antwort' anschließend eine 1. + + +Hinweis: Um die zusätzlichen Leistungen dem Anwender einfach (und abgesichert) zur + Verfügung zu stellen, sollte man sie in ein ELAN-Paket einbetten und dieses + ebenfalls an die Anwender ausliefern. + + Beispiel: PACKET zusatz DEFINES fanfare, ... : + + PROC fanfare (INT CONST tonhoehe, dauer) : + + IF dauer < 0 + THEN errorstop ("negative dauer") + ELIF tonhoehe < 16 + THEN errorstop ("infraschall") + ELIF tonhoehe > 20000 + THEN errorstop ("ultraschall") + ELSE control (-37, 20000 DIV tonhoehe, dauer) + FI + + ENDPROC fanfare ; + + . . . + + + + +#bb("9. ","Spezialroutinen")# +#goalpage("ke")# + +Als Testhilfe und zur Fehlerdiagnose kann SHard in seine Routinen Kontrollereignisse einbau +en. Das geschieht durch Aufruf der 0-Routine 'info'. Dieser EUMEL-Debugger wird im +Anhang A (siehe S.#topage("info")#) beschreiben. + + #dx("info")# (0-Routine) + + Aufruf: call info + jr weiter + defm ' text' + weiter: + + Zweck: Info wird aufgerufen. Dabei wird 'text' zur Identifikation des + Kontrollereignisses ausgegeben. #on("i")#Der übergebene Text muß + mit einem Blank beginnen!#off("i")# + + Hinweis: Bei Systemen "ohne Info" (nur solche dürfen an Anwender + ausgeliefert werden) wird nur der Info-Text ausgegeben und + EUMEL-0 angehalten. + + Achtung: Da der Info selbst die hier beschriebenen Stream-IO-Rou + tinen benutzt, darf man ihn von diesen Routinen aus (input + interrupt, OUTPUT, IOCONTROL "frout", IOCONTROL + "weiter") nicht aufrufen. Wenn die Ein-/Ausgabe auf Termi + nal 1 interruptgetrieben läuft, dürfen die Interrupts beim + Info-Aufruf natürlich nicht gesperrt sein. + + +Falls SHard für bestimmte Aktionen, die selten durchgeführt werden (z.B. Formatieren), viel +Speicher benötigt, kann er diesen dynamisch anfordern und später wieder freigeben. + + #dx("grab")# (0-Routine) + + Eingang: HL Anfangsadresse des zu reservierenden Bereichs im + Datensegment von EUMEL-0, muß auf 512 Byte + ausgerichtet sein. + BC Länge des zu reservierenden Bereichs in 512-Byte- + Kacheln + Ausgang: BC Rückmeldecode + + Zweck: Wenn möglich wird der zu verlangte Bereich von EUMEL-0 + "leergekämpft" und SHard zur Verfügung gestellt. + Rückmeldecode: 0 ok, Speicher steht zur Verfügung + 1 augenblicklich nicht möglich + 3 grundsätzlich nicht möglich + + Achtung: Der Aufruf von 'grab' wird in der Regel 'warte' und Block-IO + auf Kanal 0 induzieren. + + Hinweis: Es wird empfohlen, Speicher ab A000h anzufordern, da diese + Adresse stets im frei einplanbaren Paging-Bereich liegt. + + + #dx("free")# (0-Routine) + + Eingang: HL Anfangsadresse des freizugebenden Bereichs im + Datensegment von EUMEL-0, muß auf 512 Byte + ausgerichtet sein. + BC Länge des zu freizugebenden Bereichs in 512-Byte- + Kacheln + + Zweck: Der entsprechende Bereich muß vorher mit 'grab' beschafft + worden sein. Hiermit wird er wieder EUMEL-0 zur freien + Verfügung gestellt. + + +Für spezielle Fehlersituationen steht die 0-Routine 'shutup' zur Verfügung. Damit kann +SHard z.B. bei Netzausfall ein kontrolliertes Systemende erzwingen. Das ist allerdings nur +sinnvoll, wenn durch Batteriepufferung oder Ähnliches sichergestellt ist, daß noch genügend +Zeit bleibt, um alle Seiten auf den Hintergrund zurückzuschreiben. + + #dx("shutup")# (0-Routine) + + Zweck: Erzwingt Rückschreiben aller Seiten und Systemende, d.h. + entspricht der ELAN-Prozedur 'shutup'. + + Achtung: Der Aufruf von 'shutup' wird in der Regel 'warte' und Block- + IO auf Kanal 0 induzieren. +#page# +#cc("Teil 4: ","Tips zur Portierung")# +#goalpage("tips")# + + +#b("0-Version des SHards")# +#goalpage("0ver")# + + +Es wird empfohlen, zuerst eine "0-Version" des SHard zu entwickeln, die möglichst einfach +aufgebaut und nicht auf Effizienz und vollständige Ausnutzung der Betriebsmittel ausge +richtet sein sollte. Damit kann man rasch praktische Erfahrung gewinnen, die dann den +Entwurf und die Implementation des eigentlichen SHard erleichtert. Die 0-Version sollte + + - keinen Schattenspeicher kennen (SCHINF meldet 0), + + - nur die Kanäle 0 (Hintergrund), 1 (Terminal) und 31 (Archiv) behandeln, + + - keine Baudraten-, Zeichenlängen-, Paritäts- und Flußkontrolleinstellungen unter + stützen (immer 'nicht möglich' melden), + + - vorhandene (ROM-) Routinen möglichst nutzen, ohne sich um Unschönes wie + "busy wait" beim Floppy- bzw. Plattenzugriff zu grämen. + +Mit dieser 0-Version sollte man dann versuchen, EUMEL zu starten. Da der Hintergrund +beim ersten Mal noch leer ist, muß man das HG-Archiv (Archivfloppy mit EUMEL-0 und +höheren Ebenen) in das Archivlaufwerk einlegen und von dort laden. Der Vortest sollte sich +direkt nach dem Start folgendermaßen auf Terminal 1 melden: + + E U M E L - Vortest + + Terminals: 1, + RAM-Groesse (gesamt): 64 kB + Pufferbereich: ? kB + Hintergrund-Speicher: ? kB + + Speichertest: ************ + +Man sollte während der ****-Ausgabe des Speichertests irgendein Zeichen eingeben. Das +EUMEL-System muß dann in das ausführliche Start-Menü überwechseln. (Andernfalls +funktioniert die Eingabe nicht richtig!) + +Als nächstes sollte man versuchen, den Hintergrund vom Archiv aus zu laden. (Diese Mög +lichkeit wird im Start-Menü angeboten.) Nach dem Ende dieser Operation wird der +EUMEL-Lauf automatisch beendet. Jetzt kann man das HG-Archiv aus dem Archivlauf +werk entfernen und das System neu starten. Dann sollte EUMEL-0 vom Hintergrund geladen +werden. + +Bei Problemen kann der "Info" (siehe S.#topage("info")#) hilfreich sein. Voraussetzung für seine Ver +wendung ist aber, daß die Terminal Ein-/Ausgabe schon funktioniert. + +Beim Start des EUMEL-Systems kann (wie im Systemhandbuch beschrieben) durch den +Konfigurationsdialog der Terminaltyp von Kanal 1 eingestellt werden. Falls das verwendete +Terminal in dieser Liste nicht aufgeführt wird und auch keinem der aufgeführten (in Bezug auf +die Steuercodes) gleicht, kann man z.B. + + - den neuen Terminaltyp an einem anderen EUMEL-Rechner verfügbar machen + (Umsetztabellen definieren) und per Archiv zum neuen Rechner tragen, + + - die notwendigen Umcodierungen per SHard durchführen. + +Diese Problematik entsteht bei Rechnern mit integriertem Terminal in der Regel nicht, weil +Steuerzeichen dort sowieso algorithmisch interpretiert werden müssen. In diesem Fall wird +man direkt die EUMEL-Codes als Grundlage wählen, so daß keine Umsetzungen erfor +derlich sind. + +Bei einer provisorischen Anpassung kann man auf Invers-Video ohne weiteres verzichten. + + +Im Gegensatz zu der 0-Version sollte man bei der eigentlichen SHard-Implementierung +darauf achten, die Möglichkeiten der Hardware effizient zu nutzen. Der Testverlauf entspricht +dann wieder im wesentlichen dem oben beschriebenen Vorgang. + + + +#b("Typische Fehler")# +#goalpage("fehler")# + + + a) SHard-Routinen zerstören Registerinhalte bzw. sichern sie beim Interrupt nicht + vollständig. Hierbei sollte man auch an den zweiten Registersatz des Z80-Pro + zessors und an die Register IX und IY denken. + + b) 'call' bzw. 'ret' verändern den Stackpointer. + + c) Fehler bei der Interruptbehandlung führen zu Blockaden ("hängende Interrupts"). + + d) Cursorpositionierung außerhalb des Bildschirms bei einem internen Terminal + (Bildwiederholspeicher im Rechner) wird nicht abgefangen. Das führt dann zu + wildem Schreiben in den Hauptspeicher. + + e) 'warte' wird unerlaubt aufgerufen. ('warte' darf nur von BLOCKIN, BLOCKOUT, + IOCONTROL "size" und IOCONTROL "format" aus aufgerufen werden. Ferner + kann man 'warte' noch nicht beim Systemladen aufrufen!) + + f) OUTPUT-Verhaspler oder -Blockaden entstehen durch Fehlsynchronisation + zwischen dem Füllen des Ausgabepuffers durch die Routine OUTPUT und der + Interruptroutine, die den Puffer leert und ausgibt. + + g) IOCONTROL "frout" meldet in gewissen Situationen nie "mindestens 50 Zei + chen im Puffer frei" und "Puffer leer". Das kann schon im Vortest zu Output- + Blockaden führen. + + h) Obwohl "frout" einen Wert größer als x meldet, nimmt "output" nicht alle x + Zeichen an. + + i) IOCONTROL "size" meldet falsche Werte. + + j) IOCONTROL verkraftet keine beliebigen (auch unsinnige) Werte. + + k) BLOCKIN bzw. BLOCKOUT geben die Kontrolle an das System zurück, bevor alle + Daten übertragen sind. (Sofort nach der Rückgabe geht EUMEL-0 davon aus, + daß der Puffer frei ist und anderweitig benutzt werden kann!) + + l) Einem SIO-Baustein wird nach Ausgabe des letzten Zeichens oder nach Ände + rung des externen Status nicht mitgeteilt, daß keine Interrupts mehr erzeugt + werden sollen. (SIOs wiederholen Interrupts so lange, bis man es ihnen explizit + verbietet!) + + m) Die Stepping-Rate eines Festplattencontrollers wird falsch eingestellt, bezie + hungsweise die Platte wird nicht im 'buffered step mode' betrieben, obwohl sie + beschleunigend positionieren kann. Dadurch werden die Zugriffszeiten auf dem + Hintergrund unnötig verlangsamt. Man bedenke, daß man so einen Fehler leicht + übersieht, weil sich das System nicht fehlerhaft, sondern nur langsamer verhält. + Außerdem macht sich die Verlangsamung erst bemerkbar, wenn größere Teile des + Hintergrundes benutzt werden. + + n) Bei schnellem Zeichenempfang treten "Dreher" auf. Das deutet meistens auf + einen rekursiven Aufruf der 0-Routine 'inputinterrupt' hin. Dabei überholt dann + das zweite Zeichen das erste. + + o) Bei schnellem Zeichenempfang, speziell bei gleichzeitiger Ausgabe, gehen Einga + bezeichen verloren oder werden verfälscht. In der Regel ist das auf Timingpro + bleme bei der Interruptbehandlung zurückzuführen. Interrupts gehen verloren bzw. + die Zeichen werden nicht schnell genug abgeholt. + + +#b("Effizienzprobleme")# +#goalpage("eff")# + + a) Bei #on("i")##on("b")#V.24- und Parallelschnittstellen#off("i")##off("b")# ist schlechter Durchsatz in der Regel auf + Fehlverhalten von "frout" zurückzuführen. Auch kostet es in Multi-User-Sy + stemen sehr viel, wenn OUTPUT immer nur ein Zeichen übernimmt. (Dann läuft + der ganze Apparat der EUMEL-0-Maschine für jedes Zeichen wieder an.) + + Besonders bei der Parallelschnittstelle achte man darauf, daß nicht durch un + glückliches Timing häufig Blockaden auftreten. So kann zu kurzes 'busy wait' auf + Freiwerden der Parallelschnittstelle dazu führen, daß jedes zweite Zeichen + abgelehnt wird, so daß OUTPUT faktisch zeichenweise arbeitet. Andererseits darf + natürlich 'busy wait' auch nicht auf Millisekunden ausgedehnt werden. + + + b) Wenn #on("i")##on("b")#Floppies ohne DMA#off("i")##off("b")# angeschlossen werden, kann man bei Single- + User-Systemen ohne weiteres 'busy wait' einsetzen, um nach dem Seek- + Vorgang auf den Block zu warten. Im Multi-User sollte das aber wenn irgend + möglich umgangen werden, da eine halbe Umdrehung immerhin ca. 100 ms + kostet. + Falls nur ein Endeinterrupt nach jeder Floppyoperation zur Verfügung steht, kann + folgendes Verfahren günstig sein: + + seek befehl an controller ; + warten auf endeinterrupt ; + lesebefehl ohne datentransport auf sektor davor ; + warten auf endeinterrupt ; + lese oder schreib befehl auf adressierten sektor ; + cpu intensives warten und datentransport . + + Die Dummyoperation auf den Sektor vor dem adressierten dient dabei nur dazu, + ohne CPU-Belastung einen Zeitpunkt zu finden, wo man dem eigentlichen Sektor + möglichst nahe ist. Die Zeit, in der die CPU benötigt wird, sinkt damit auf ca. 25 + ms. Die Implementation dieses Algorithmus' ist aber nicht ganz einfach, da die + 0-Routine 'warte' wegen der verlangten kurzen Reaktionszeiten nicht verwendet + werden kann. Alle 'warte auf ...' müssen also durch Interrupts realisiert werden: + + setze interrupt auf lesen davor ; + stosse seek an ; + REP + warte + UNTIL komplette operation beendet ENDREP . + + lesen davor : + setze interrupt auf eigentliche operation ; + stosse lesen davor an . + + eigentliche operation : + ignoriere fehler beim datentransport ; + stosse lesen oder schreiben an ; + REP + REP UNTIL bereit ENDREP ; + uebertrage ein byte + UNTIL alles uebertragen ENDREP ; + melde komplette operation beendet . + + + c) Bei der Ansteuerung von #on("i")##on("b")#Harddisks#off("b")##off("i")# sollte man darauf achten, daß die 0-Rou + tine 'warte' nicht öfter als notwendig aufgerufen wird. Sonst wird das Paging zu + gunsten der CPU-intensiven Prozesse zu stark verlangsamt. Z.B. kann man bei + vielen Plattencontrollern auf eine eigene Seek-Phase verzichten: + + beginne seek ; beginne seek und lesen ; + REP REP + warte warte + UNTIL fertig PER ; UNTIL fertig PER + beginne lesen ; + REP + warte + UNTIL fertig PER + + Hier braucht die linke Fassung immer mindestens ein 'warte' mehr als die rechte. + Bei starker CPU Belastung wird sie deshalb bis zu 100 ms länger für das Einle + sen eines Blocks benötigen. + + Eine ähnliche Situation kann auftreten, wenn die Platte in 256-Byte-Sektoren + unterteilt ist, so daß zu jedem EUMEL-Block zwei Sektoren gehören. Wenn + möglich sollte dann zwischen diesen beiden Sektoren kein 'warte' aufgerufen + werden. Andererseits darf natürlich auch nicht längere Zeit CPU-intensiv gewar + tet werden. Evtl. lohnt es sich in solchem Fall, mit der Sektorverschränkung zu + experimentieren. + +#page# +#cc("Anhang A: EUMEL-","Debugger ""Info""")# +#goalpage("info")# + + +Für interne Testzwecke gibt es den "Info". Systeme "mit Info" und "ohne Info" unterschei +den sich nur im EUMEL-0-Teil (Urlader). Der SHard-Implementierer erhält zum Test +Hintergründe "mit Info" und zur Auslieferung solche "ohne Info". Infofähige Systeme dürfen +nur von den SHard-Implementierern verwendet werden. + + #on("i")##on("b")#Achtung: Infofähige Systeme dürfen auf keinen Fall an Anwender ausgeliefert wer + den, da vermittels Info alle Systemsicherungs- und Datenschutzmaßnah + men unterlaufen werden können.#off("i")##off("b")# *) +#foot# +#f#*) Ausnahmen von dieser Regel bedürfen der expliziten Zustimmung der EUMEL-Systemgruppe (GMD bzw. HRZ +Bielefeld) und des jeweiligen Anwenders. Solche System müssen immer durch spezielle Schlüsselworte abgesichert werden.#a# +#end# + + +#b("Aufruf des Info")# +#goalpage("aufrinf")# + +Zum Aufruf des Infos gibt es drei Möglichkeiten: + + a) Beim Start des EUMEL-Systems geht man durch Eingabe eines beliebigen Zei + chens während des Vortests in den ausführlichen Start-Dialog. Durch Eingabe von + 'I' gelangt man dann in den Info-Modus. #on("i")#(Diese Möglichkeit wird in dem Start + menü nicht aufgeführt.)#off("i")# + + b) Man kann den Info durch die ELAN-Prozedur 'ke' aufrufen. D.h. wenn das System + gestartet wurde und sich eine Task am Terminal mit "gib kommando" gemeldet + hat, kann man durch 'ke *return*' in den Info-Modus gelangen. + + c) Wenn sich am Terminal keine Task befindet, die auf Eingabe wartet, gelangt man + durch die Tastenfolge 'i *info*' (*info* meist = CTL d, zur Tastendefinition siehe + "Systemhandbuch, Konfigurierung") in den Info-Modus. + +Alle diese Möglichkeiten funktionieren nur bei infofähigen Systemen. + +Bei schweren Systemfehlern, die eine Weitermeldung an die höheren Ebenen des EUMEL- +Systems unmöglich machen, wird soweit möglich ebenfalls der Info aufgerufen. Bei Systemen +"ohne Info" wird lediglich eine Meldung auf Kanal 1 ausgegeben und das System angehalten. + +Bevor das System Infokommandos annimmt, muß mit dem Kommando 'P' ein Paßwort einge +geben werden. Lediglich dieses Kommando und das Kommando 'g' werden immer angenom +men. Das Paßwort kann mit dem Kommando 'yP' oder mit der ELAN-Prozedur "info +password" eingestellt werden. + +#b("Info-Format")# +#goalpage("forminf")# + +Der Info ist bildschirmorientiert. Beim Aufruf des Infos und nach den meisten Info-Kom +mandos werden die drei obersten Zeilen wie folgt aufgebaut: *) +#foot# +#f#*) Bildschirmgetreues Verhalten kann der Info allerdings erst nach der Konfigurierung des Kanals zeigen. Vorher (d.h. +insbesondere beim Aufruf aus dem Vortest heraus) werden Cursorpositionierungen in der Regel nicht korrekt durchgeführt.#a# + +#end# + +#limit(14.0)# +XY TEXT +F A C B E D L H F A C B E D L H IX SP IY PC +xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx +#limit(12.0)# + +wobei + + X den Miniprozeß bezeichnet, der den Übergang in den Info veranlaßt hat (A=Archiv, + E=Elan, L=Lader, M=Müllabfuhr), + + Y den Maxiprozeß (Task) bezeichnet, der gerade durch den Elan-Prozessor bear + beitet wird (Y ist code (tasknummer + code ("0"))), + + TEXT den Grund für den Info-Modus anzeigt, + +Die zweite und dritte Zeile zeigen die Inhalte der Z80-Register an (beide Registersätze). +In der untersten Zeile erscheint die Eingabeaufforderung 'info:'. + + +#b("Info-Kommandos")# +#goalpage("cmdinf")# + +Info-Kommandos können in der 'info:'-Zeile mit dem Format + + [<zahl>]<buchstabe> + +gegeben werden oder, wenn der Cursor sich im Dump befindet, mit dem Format + + <buchstabe> + +wobei dann für <zahl> die der Cursorposition entsprechende Dumpadresse (modulo 2**16) +gesetzt wird (siehe '*cup*'). + +<zahl> ist immer in Hexaform einzugeben. + +'g' Der Info-Modus wird wieder verlassen. Dies ist allerdings bei harten Fehlern ge + sperrt. + +'z' Der Leitblock des angezeigten Maxiprozesses wird dargestellt, falls <zahl> = 0 ist, + sonst der Leitblock der Task mit der Nummer <zahl>. (Nur im ELAN-Miniprozeß). + +'q' Die Task mit der Nummer <zahl> wird nach dem nächsten 'g'-Kommando in den + Info überführt. Dies ist nötig, wenn man sich die Datenräume dieser Task anschauen + will ('s'). + +'s' Dumps werden auf den Datenraum <zahl> eingestellt. Ist <zahl>=FF, so wird der + Realspeicher eingestellt. (s:=<zahl>) + +'l' Dumps werden auf die Länge <zahl> eingestellt. Desungeachtet kann man einen + versehentlich zu langen Dump durch eine beliebige Eingabe abbrechen. Dann wird + allerdings '*cup*' gesperrt (siehe unten). + +'p' Dumps werden auf die Byteadresse <zahl> eingestellt (p:=<zahl>; wmodus:= + FALSE). + +'w' Dumps werden auf die Wortadresse <zahl> eingestellt. Die vor jeder Dumpzeile + ausgegebene Adresse ist dann auch eine Wortadresse. Ein Wort = 2 Bytes. (p:=2* + <zahl>; wmodus:=TRUE) + +'k' Block <zahl> laden und per Dump anzeigen. Es erfolgt dabei eine Umstellung auf + den Realdatenraum (s=FF). + +'P' Paßworteingabe: P<text>*return* + Erst nach diesem Kommando sind die übrigen Kommandos ausführbar. + +'x' Suchen nach Bytekette: + +--> xc text +--> xh xx xx ... +--> x + + Es wird nach 'text' bzw. Hexafolge 'xx xx ...' bzw. nach der durch das letzte + 'x'-Kommando eingestellten Bytekette gesucht. + Das Kommando ist durch *return* abzuschließen. + Die Suche beginnt ab Position 'p' und ist auf die Länge <zahl> Seiten (512 Byte- + Einheiten) begrenzt (0=unendlich). + Eine beliebige Eingabe bricht die Suche vorzeitig ab. + +'*return*' + Es wird der eingestellte Dump ausgegeben (siehe 's','l','p','w'). Bei wmodus (siehe + 'p', 'w') werden Wortadressen ausgegeben. + +'o' Wie '*return*', jedoch wird zuvor p := p+l gesetzt (zum Weiterblättern). + +'r' Freigabe der anderen Miniprozesse. + + Zunächst werden bei Übergang in den Info alle Miniprozesse gesperrt, um eine + Verfälschung der Fehlersituation zu vermeiden. Bei manchen Kommandos an den Info + müssen aber andere Miniprozesse u.U. aktiv werden (z.B. beim 'k' der Lader). Wenn + dies erforderlich ist, meldet der Info: + 'paging erforderlich'. Man kann dann 'r' geben und das letzte Infokommando wieder + holen, oder mit anderen Kommandos fortfahren, falls man den Fehlerzustand noch so + beibehalten will. + +'y' Zweitfunktion ausführen. + +--> 'yP<text>*return*' + Neues Paßwort einstellen (max. 9 Zeichen). Dieses bleibt auch nach 'shutup' + gültig. + +--> 'yt' Block <zahl> von Archiv lesen. Dient zum Test des Archivs. + Es wird eine Kachel freigemacht und der Block mit der Nummer <zahl> + eingelesen. Der Inhalt wird sofort angezeigt (wie Kommando 'k'). + +--> 'yb' Breakpoint an die Adresse <zahl> setzen. Es wird ein Aufruf an den Info + abgesetzt. Nur im Realspeicher sinnvoll. Dieser Aufruf meldet sich mit + TEXT= 'test'. Wird er mit 'g' verlassen, so stellt Info zuvor die alten + Z80-Befehle wieder her und führt sie an ihrem originalen Ort aus. + +--> 'yc' wie 'yb', jedoch werden die originalen Z80-Befehle an einem anderen Ort + (im Info) ausgeführt. Sie dürfen daher z.B. keinen Relativsprung enthalten + und keine 'push'/'pop'-Befehle. Dafür bleibt dieser Breakpoint auch nach + dem zugehörigen 'g' im Code erhalten. Dieser Breakpoint meldet sich mit + TEXT='test 2'. 'yc' darf nicht gegeben werden, wenn der Info im 'test 2' + steht (Umhängen verboten). + + #on("i")#Achtung: Die Verwendung von 'yb' und 'yc' ist sehr kritisch durchzuführen. + Zu beachten ist, daß der in den Code eingesetzte Sprung (Z80 jp) + 3 Byte belegt.#off("i")# + + +--> 'yl' Lernmodus ein (wie beim Editor). + +--> 'ye' Ende Lernmodus. + +--> 'ya' Ausführen. Die zwischen 'yl' und 'ye' eingegebenen Zeichen werden dem + Info so vorgesetzt, als kämen sie von der Tastatur. + + Achtung: Rekursion ('ya' im Lernmodus) wird nicht abgefangen. Das Gelern + te wird nach jedem Kommando, das die ersten drei Zeilen + wiederaufbaut (z.B. *return*), in der Zeile vier angezeigt, wobei + für Steuerzeichen eine Ersatzdarstellung erscheint (%x mit + x=code (code (zeichen) +code ("A")), also z.B. %M für + *return*). + +--> 'y *return*' + Wie *return*, jedoch wird der Dump auch beim Ausführen (ya) ausgege + ben. (Ein gelerntes *return* führt im Ausführmodus nicht zum Dump). + +'*cup*' *) (Cursor up). Umschaltung in den Modus zum Ändern in Dumps. +#foot# +#f#*) Falls der Kanal noch nicht konfiguriert ist, muß man natürlich eine Taste betätigen, die den EUMEL-Code für Cursor +Up erzeugt. In der Regel ist das CTL c. Falls das Terminal ohne Konfigurierung keine Cursorpositionierungen durchführt, ist +dieser Modus nicht sehr gut benutzbar.#a# +#end# + Der Cursor fährt in den Dump und kann mit den Cursortasten dort bewegt + werden. Wird eine Hexazahl jetzt eingegeben, so wird diese als Inhalt des + Bytes eingetragen, auf dem der Cursor gerade steht. Dies funktioniert auch + auf beliebigen Datenräumen. Info beantragt dann bei der Speicherverwal + tung einen Schreibzugriff für die entsprechende Datenraumseite, so daß + Änderungen mit der Copy-on-Write-Logik erfolgen, also nur taskspezi + fisch sind (durch 'q' eingestellt). Für diese Task sind die Änderungen al + lerdings dann permanent, da sie auch auf den Hintergrund wirken. + + Hinweis: Dumpt man mit 'k' einen Block und ändert dann darin, so sind + diese Änderungen u.U. nur temporär, da der Info kein Rückschrei + ben des Blockes veranlaßt. + + Achtung: Jede Eingabe, die kein Positionierzeichen und kein gültiges + Zahlzeichen ist, beendet diesen Modus. Das neue Zeichen wird als + Info-Kommando aufgefaßt, wobei <zahl> auf die aktuelle Adres + se gesetzt wird. + (Für 'yc' / 'yb' sinnvoll: Man setzt den Cursor auf die Stelle, an + der ein Break ausgelöst werden soll und gibt 'yc'/'yb'). + Somit wird dieser Änderungsmodus üblicherweise durch *return* + beendet. + +#b("Einige Systemadressen")# +#goalpage("sysaddr")# + +Der Info nützt nur wenig, wenn man nicht weiß, was man sich anschauen soll. Wesentliche +Angaben über die Systemstruktur enthält das 'Brikett' (interne Systemdokumentation für +Projekt Mikros der GMD). Da diese etwas allgemeiner gehalten ist, geht sie nicht auf imple +mentationsabhängige Konstanten ein. Diese sind hier aufgeführt. + +Ab 1500h liegt die 'ktab'. Sie enthält Informationen, welche Blöcke an welcher Stelle des +Arbeitsspeicher liegen: In der Kachel mit der Adresse 512*i befindet sich der Inhalt des +Blockes, dessen Nummer in ktab+i, ktab+100h+i steht. Ferner enthält die Tabelle, zu +welchem Datenraum (drid) und welcher Seite des Datenraums der Inhalt gehört. (Nur rele +vant, wenn die Prozeßnummer <> 255 ist). + +Steuerbits: 2**0 : Inhalt wird gerade transportiert (zum HG oder Archiv). + 2**1 : Inhalt ist identisch mit Inhalt auf HG. Wird beim Schreiben auf die + Kachel (per Software) zurückgesetzt. + 2**2 : Schreiberlaubnis (siehe Brikett). + 2**3 : Inhalt wurde kürzlich benutzt. Solche Kacheln werden 'weniger + stark' verdrängt. + + + ktab frei niederwertige Blocknummer + + +80h frei frei Steuerbits + + +100h frei höherwertige Blocknummer + + +180h frei frei Prozeßnummer + + +200h frei frei drid (prozeßspezifisch) + + +280h frei frei Seitennummer (höherw.) + + +300h frei frei Seitennummer (niederw.) + + ^ ^ + <-- unbenutzt --> ! +-- Beginn echter Kacheln + +-- Beginn der Anforderungen + + +Der 'Beginn echter Kacheln' hängt von der Größe der Z80-Teile ('urlader') ab (i.A. +30h < i < 40h). + +'Beginn der Anforderungen' liegt bei i=1Fh. Es handelt sich um Blocknummern von zu +ladenden Blöcken. Ist der höherwertige Teil der Blocknummer gleich FDh, so ist dies keine +Anforderung. + +Blocknummern > FF00h stehen für Blöcke mit dem Inhalt 512 FFh's und werden nie auf dem +Hintergrundmedium gespeichert. + + + +1E2Bh enthält den DR-Eintrag des drdr (siehe Brikett). + + +'musta': Das System fordert Checkpoints und Müllabfuhren über die Zelle 'musta' an. Diese + findet man mit dem Info durch + + xc musta + + (hierfür ist der Text 'musta' vor der Zelle abgesetzt). + + Die Zelle selbst enthält + + FFh : Keine Müllabfuhr oder Checkpoint + 01h : Müllabfuhr + 02h : Checkpoint + 03h : beides + 04h : Systemendecheckpoint + 0Bh : System auf Archiv schreiben ('save system') + F0h : Müllabfuhr und Checkpoint sind geperrt (nur durch Setzen im Info + möglich) + + Durch Einsetzen der Werte mit dem Info kann die entsprechende Operation veran + laßt werden. Beim Einsetzen darf der Info nicht im 'r'-Zustand (siehe Eingabe 'r') + stehen; zum Ausführen der Operation muß 'r' (man bleibt im Info) oder 'g' (Info + verlassen) gegeben werden. + + +1880h-18FFh: + enthält die Aktivierungstabelle. Ist (1880h+i)=01h, so ist die Task i aktiv. Hin + weis: 18FFh enthält immer 01h, ohne daß dieser Zelle eine Task zugeordnet ist. + + +#b("Leitblock")# +#goalpage("pcb")# + +Mit dem 'z'-Kommando wird der Leitblock einer Task dargestellt. Es werden Hexapaare, +gefolgt von einer Bezeichnung, ausgegeben. In der folgenden Beschreibung werden die +Hexapaare durch a,b,c dargestellt. + + a b c icount Der virtuelle Befehlszähler der Task steht auf (cMOD4)* + 10000h+b*100h+a = <ic> im Datenraum 4 dieser Task. + Durch die Eingabefolge: + 4s<ic>w*return* + kann man sich den Code, der ausgeführt werden soll, anse + hen. + + Bit 2**7 von c zeigt den Fehlerzustand an. + Bit 2**6 von c zeigt 'disable stop' (siehe Benutzerhandbuch) + an. + Bit 2**4 zeigt vorzeichenlose Arithmetik an (Compilierung). + + a b lbas Die lokale Basis steht auf 10000h+b*100h+c = <lb> im + Datenraum 4 (Wortadresse). + + a b hptop Der Arbeitsheap geht von 30000h (Byteadr.) bis (aMOD16)* + 10000h+b*100h+(aDIV16)*10h (Byteadr!). + + a b channel Die Task hängt an Kanal 100h*b+a (Terminalnummer). 0 = + kein Terminal angekoppelt. + + a b taskid Die Tasknummer der betrachteten Task ist a. (b ist die + Versionsnummer zum Abdichten von 'send'/ 'wait'). + +Um den Code, auf den der 'icount' zeigt, zu interpretieren, ziehe man das Brikett zu Rate. + + +Hinweis: Wenn der Info einen internen Fehler anzeigt, und auch bei 'ke', ist der durch 'z' + angezeigte Leitblock u.U. nicht aktualisiert. Man kann dies durch die Eingaben 'r', + 'g' erzwingen. (Der Info stellt wegen 'r' dem Interpreter einen Restart zu, der dann + beim 'g' den Leitblock aktualisiert und den Befehl erneut aufsetzt). Tritt dabei der + Fehler nicht wieder auf, handelte es sich um einen transienten Fehler (z.B. der + Codeblock war noch im Einlesen und ist jetzt voll da). So etwas kann z.B. passie + ren, wenn der SHard den Abschluß einer Leseoperation zu früh meldet. + diff --git a/doc/porting-z80/8/source-disk b/doc/porting-z80/8/source-disk new file mode 100644 index 0000000..ff072f3 --- /dev/null +++ b/doc/porting-z80/8/source-disk @@ -0,0 +1 @@ +porting/portdoc-z80-8.img |