From 04e68443040c7abad84d66477e98f93bed701760 Mon Sep 17 00:00:00 2001
From: Lars-Dominik Braun <lars@6xq.net>
Date: Mon, 4 Feb 2019 13:09:03 +0100
Subject: Initial import

---
 doc/porting-z80/8/doc/Port.Z80 | 2484 ++++++++++++++++++++++++++++++++++++++++
 doc/porting-z80/8/source-disk  |    1 +
 2 files changed, 2485 insertions(+)
 create mode 100644 doc/porting-z80/8/doc/Port.Z80
 create mode 100644 doc/porting-z80/8/source-disk

(limited to 'doc/porting-z80')

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
-- 
cgit v1.2.3