summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2017-01-21 11:50:05 +0100
committerLars-Dominik Braun <lars@6xq.net>2017-01-21 11:50:05 +0100
commitd568f2aff352201434f34e3594658ab79c9119ce (patch)
tree1b9a26c4060fa51465978b5423a8787e0a0743d2
parent25512363eb9f619299c336c60c4333c8c759d6d9 (diff)
downloadeumel-src-d568f2aff352201434f34e3594658ab79c9119ce.zip
eumel-src-d568f2aff352201434f34e3594658ab79c9119ce.tar.gz
eumel-src-d568f2aff352201434f34e3594658ab79c9119ce.tar.bz2
Add x86 porting manual
-rw-r--r--doc/PORT-X862482
1 files changed, 2482 insertions, 0 deletions
diff --git a/doc/PORT-X86 b/doc/PORT-X86
new file mode 100644
index 0000000..007ca28
--- /dev/null
+++ b/doc/PORT-X86
@@ -0,0 +1,2482 @@
+#type ("trium6")##limit (12.)#
+#limit (30.0)#
+#type ("trium8")##limit (12.0)#
+#start(1.5,1.5)#
+#type("triumb36")#
+#free(4.0)#
+ EUMEL
+ Portierungshand-
+ buch
+ 8086 / 8088
+#type("triumb18")#
+#free(1.5)#
+ Version 8
+#page(1)#
+#type ("trium8")##limit (12.0)#
+#block#
+#pagelength(19.5)#
+#head#
+#center#- % -
+
+
+#end#
+#type("triumb12")#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 8086/8088-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")#
+ 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")#
+ Block-IO zur MS-DOS-Partition #topage("bmsdosp")#
+ 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")#
+
+#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 8086/ 8088-Prozes-
+soren.
+
+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"
+
+ "iAPX 86,88-Users Manual"
+ intel, 1981
+
+
+
+#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 8086-CPU sollte mit mindestens 2.5 MHz (8088: 4.0 MHz)
+ arbeiten. Falls die Buszugriffe durch einen CRTC o.ä. ver-
+ langsamt werden, sollte die echte 8086/ 8088-Leistung
+ durchschnittlich mindestens einem ungebremsten 2.5 MHz (4.0
+ MHz) System entsprechen.
+ Seltene Verlangsamungen (z.B. nur bei I/O-Operationen)
+ spielen bei diesen Überlegungen keine Rolle.
+
+ RAM Das System sollte über mindestens 80 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 Anfor-
+ derungen 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 komfortabel
+ 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 Cur-
+ sortasten vorhanden sein. Dabei ist es günstig, wenn die
+ Cursortasten 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 8086/
+ 8088 Bezug genommen. Bei der Portierung auf einen 8086/8088-Rechner
+ wird die 8086/8088-EUMEL-0-Maschine ohne Anpassungen (!) übernom-
+ men.
+
+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 8086/8088-
+Rechner angepaßt bzw. neu geschrieben werden muß. Deshalb besteht der größte Teil dieses
+Handbuchs aus der Spezifikation des 8086/8088-SHards.
+
+
+
+#b("Anlieferung des 8086/8088-EUMEL-Systems")#
+#goalpage("anlief")#
+
+Der Implementierer erhält die EUMEL-Software auf Disketten. Dabei stehen folgende
+Standardformate zur Wahl:
+
+ 8", 1D, 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")#
+
+#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...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 vereinfa-
+ chen, sollten möglichst alle der hardwaremäßig möglichen Standardformate (min-
+ destens 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")#
+
+Der #ib#Speicher#ie# wird EUMEL-0 vom SHard in maximal vier Speicherbereichen (M0...M3)
+zugewiesen. M0 muß immer vorhanden sein, M1, M2 und M3 nur in speziellen Betriebsarten:
+
+ #dx("M0")# #on("b")#allgemeines #ib#RAM#ie(1,", allgemeines")##off("b")#
+ Dieser Bereich muß immer vorhanden sein. Bei den meisten Rechnern liegt der
+ Urlader nicht in einem ROM, sondern wird von SHard in das RAM geladen. Das
+ geschieht dann an den Anfang von M0. Der Rest wird für Tabellen und als Pa-
+ gingbereich benutzt. M0 umfaßt deshalb meistens allen verfügbaren Speicher, bis
+ auf den Platz für SHard, Boot-ROM und Bildwiederholspeicher.
+
+ #dx("M1")# #on("b")#Urlader-#ib#ROM#ie(1,", Urlader")##off("b")#
+ Gibt es nur bei Rechnern, die den Urlader in einem ROM haben. (M0 wird dann
+ nur für Tabellen und als Pagingspeicher eingesetzt.)
+
+ #dx("M2")# #on("b")#Hintergrund-#ib#ROM#ie(1,", Hintergrund")##off("b")#
+ Gibt es nur bei Rechnern, die nicht Floppy oder Festplatte sondern ROM und
+ RAM als Hintergrundspeicher verwenden.
+
+ #dx("M3")# #on("b")#Hintergrund-#ib#RAM#ie(1,", Hintergrund")##off("b")#
+ Gibt es nur bei Rechnern, die nicht Floppy oder Festplatte sondern ROM und
+ RAM oder RAM allein als Hintergrundspeicherverwenden.
+
+Damit sind drei verschiedene Betriebsarten des EUMEL-Systems möglich:
+
+ #dx("Normalbetrieb")#: M0 (> 80 K)
+ Hintergrundgerät (Festplatte oder Floppy)
+ Archivgerät (Floppy)
+
+ Im Normalbetrieb befindet sich der Hintergrund auf einer Festplatte oder Floppy.
+ RAM wird für den Urlader und zum Paging eingesetzt. Alle mittleren und grö-
+ ßeren Systeme verwenden den Normalbetrieb.
+
+
+ #dx("Minibetrieb")#: M0 (> 80 K)
+ M3 (mindestens 300 K)
+ Archivgerät (Floppy)
+
+ Im Minibetrieb wird RAM als Hintergrundspeicher eingesetzt. Dieser wird beim
+ Einschalten über das Archivgerät geladen und beim Abschalten ('shutup') wieder
+ zurückgeschrieben.
+
+
+ #dx("ROM-Betrieb")#: M0 (> 24 K)
+ M1 (> 45 K)
+ M2 (> 170 K)
+ M3 (> 60 K)
+ Archivgerät (Kassettenrecorder oder Floppy)
+
+ Im ROM-Betrieb stehen Urlader und Standardteil des Hintergrundes im ROM.
+ Der übrige Hintergrund befindet sich im RAM.
+
+
+#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 implemen-
+tieren 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.
+
+8086/8088-Befehle werden wie in "iAPX 86,88 Users Manual" (intel, 1981) notiert:
+
+ mov al,27
+ add ab,bl
+
+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 M0:0 (im Normal- oder Minimodus) bzw. M1:0 (im ROM-
+Modus):
+
+ Adresse
+
+ 00h eumel0id db 'EUMEL '
+ db 10 dup (?)
+ 10h eumel0blocks dw
+ 12h hgver dw
+ 14h cputype dw 3 ; für 8086 oder kompatible CPU
+ 16h urver dw
+ 18h dw
+ 1Ah shdvermin dw
+ 1Ch shdvermax dw
+ 1E dw
+ 20h systemstart dd
+ 24h inputinterrupt dd
+ 28h timerinterrupt dd
+ 2Ch warte dd
+ 30h grab dd
+ 34h free dd
+ 38h shutup dd
+ 3Ch info dd
+
+Hinweis: Die Segmentteile der 'dd'-Addressen in dieser Link-Leiste sind natürlich unde-
+ finiert. Deshalb muß SHard diese auf M0 bzw. M1 setzen. Dazu ist es mindestens
+ beim ROM-Urlader erforderlich, die 0-Leiste in einen von SHard verwalteten
+ RAM-Bereich zu kopieren.
+
+
+Für die Gegenrichtung muß SHard der 0-Maschine die "SHard-Leiste" zur Verfügung stel-
+len:
+
+ Adresse
+
+ 00h SHDID db 'SHARD '
+ db 10 dup (?)
+ 10h SHDVER dw 8
+ 12h MODE dw
+ 14h ID4 dw
+ 16h ID5 dw
+ 18h ID6 dw
+ 1Ah ID7 dw
+ db 4 dup (?)
+ 20h OUTPUT dd
+ 24h BLOCKIN dd
+ 28h BLOCKOUT dd
+ 2Ch IOCONTROL dd
+ 30h SYSEND dd
+ db 12 dup (?)
+ 40h M0START dw
+ 42h M0SIZE dw
+ 44h M1START dw
+ 46h M1SIZE dw
+ 48h M2START dw
+ 4Ah M2SIZE dw
+ 4Ch M3START dw
+ 4Eh M3SIZE dw
+
+
+Dabei ist als 'MxSTART' eine Paragraphenadresse (d.h. Adresse DIV 16) und entsprechend
+als 'MxSIZE' die Länge des Bereichs als Bytelänge DIV 16 anzugeben.
+
+
+
+
+#b("Allgemeine Link-Bedingungen")#
+#goalpage("link")#
+
+In der Regel sind sowohl 0-Routinen als auch SHard-Routinen durch 'call' aufzurufen:
+
+ call dword ptr <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-Re-
+ gister *) - bleiben unverändert.
+#foot#
+#f#
+*) Flags sind i.a. nach dem Aufruf einer Routine undefiniert. Ausnahmen sind natürlich die Flags, die als Ausgangspara-
+meter 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.
+Das schließt auch die Segmentregister mit ein. Um SHard-eigene Daten über DS zu adres-
+sieren, muß SHard also DS sichern, neu laden und zum Schluß wiederherstellen. Entspre-
+chendes gilt für ES. SS darf nicht verändert werden.
+
+
+#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.
+Die Register (bis auf AX und F) werden von den aufzurufenden 0-Routinen selbst gesi-
+chert. Auch die Segmentregister DS und ES werden von EUMEL-0 geladen. (CS wird
+automatisch durch den "far call" gesetzt, SS darf sowieso nicht verändert werden.) Die
+normale Interrupt-Sequenz im SHard sieht dann folgendermaßen aus:
+
+ intadr: push ax
+ mov al,<parameter>
+ call dword ptr <routine>
+ ; interrupt level freigeben
+ pop ax
+ iret
+
+
+
+#bb("1. System ","laden")#
+#goalpage("laden")#
+
+SHard muß die EUMEL-0-Software vor dem eigentlichen Start an den Anfang der Spei-
+cherregion M0 laden. EUMEL-0 befindet sich normalerweise auf dem Hintergrund von Block
+10 ab. Der erste Block (10) enthält am Anfang die 0-Leiste. Dort steht an der Stelle 10h die
+Größe 'eumel0blocks'. Sie gibt an, wieviel Blöcke konsekutiv geladen werden müssen. Hat
+sie beispielsweise den Wert 80, müssen die Blöcke 10 bis 89 geladen werden.
+
+ Achtung: Zu diesem Zeitpunkt kann SHard die oben aufgeführten 0-Routinen na-
+ türlich 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 Hintergrundme-
+dium 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: DS:BX Adresse der SHard-Leiste
+ Interrupts disabled
+
+ Aufruf: jmp dword ptr systemstart
+
+ Zweck: Die EUMEL-0-Maschine wird gestartet. Alle notwendigen
+ Hardwareinitialisierungen (z.B. der Peripheriebausteine)
+ müssen vorher schon geschehen sein.
+
+ Hinweis: Der Stackpointer und die Segmentregister brauchen nicht
+ definiert zu sein, da beim Ansprung alle Interrupts maskiert
+ sein sollten und somit keine Interrupts auftreten können.
+ EUMEL-0 lädt beim Start CS, SS, SP, DS, ES und läßt In-
+ terrupts zu (STI). Falls jedoch in dieser Zeit ein "Non Maskable
+ Interrupt" auftreten kann, muß SHard SS und SP "vorläufig"
+ laden.
+
+ MODE: Über das MODE-Wort in der SHard-Leiste können Optionen
+ 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 inter-
+ essant sein, diese Blöcke auf dem Hinter-
+ grund anderweitig zu nutzen. Das Systemla-
+ den kann dann z.B. mit Hilfe einer speziellen
+ Urladediskette vom Archivgerät aus erfolgen.)
+
+ Bit 8 = 0 Beim Systemstart wird der Speicher überprüft.
+ (Standard)
+
+ Bit 8 = 1 Der Speichertest beim Systemstart unterbleibt.
+ Man sollte nur bei Rechnern, die beim Ein-
+ schalten schon eigene Speichertests durch-
+ fü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 Vortestfunktionen
+ aufzurufen. Der Speichertest unterbleibt
+ ebenfalls.
+
+
+
+ #d("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 mei-
+ sten 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 umfaßt die Teile des 8086/8088-Speichers, die EUMEL-0 verwalten
+darf, nämlich die Bereiche M0, M1, M2 und M3 (siehe S.#topage("speicher")#). M1, M2 und M3 sind dabei nur
+bei speziellen Betriebsarten nötig. Jeder der vier Bereiche wird in der SHard-Leiste durch
+die Anfagsadresse MxSTART und seine Länge MxSIZE beschrieben:
+
+ MxSTART Anfang des Bereichs als Paragraphenadresse (Byteadresse DIV
+ 16)
+ MxSIZE Größe des Bereichs in Paragraphen (Bytegröße DIV 16)
+
+Nicht vorhandenen Bereiche werden durch MxSIZE = MxSTART = 0 gekennzeichnet.
+
+
+
+
+
+#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 ne vas plus: jmp rien ne vas 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üh-
+ren.
+
+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: AL 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 in-
+ nerhalb 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,..)
+angesprochen 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 Ter-
+minals, Druckern, Plottern usw. ab. Stream-IO wird nur für die Kanäle 1...15 gemacht.
+
+ #dx("inputinterrupt")# (0-Routine)#goalpage("inp")#
+
+ Eingang: AL Kanalnummer (1...15)
+ CH eingegebenes Zeichen
+ CL Fehlerbits:
+ Bit 0 = 1 Mindestens ein Zeichen konnte auf
+ diesem Kanal nicht empfangen
+ werden (z.B. weil Interrupts gesperrt
+ waren).
+ Bit 1 = 1 Es wurde ein BREAK erkannt (bei
+ V24). Dieses Ereignis kann nicht
+ durch ein Sonderzeichen gemeldet
+ werden, da bei einer 8-bit-Über-
+ tragung schon alle Zeichen vergeben
+ sind. Daher wird BREAK hier aufge-
+ nommen, obwohl es im eigentlichen
+ Sinne kein Fehler sein muß.
+ Bit 2 = 1 Das übergebene Zeichen ist verfälscht
+ (z.B. Parität falsch).
+
+ Ausgang: AL Zahl der noch freien Bytes im Eingabepuffer von
+ EUMEL-0. Die Angabe gilt für den Puffer dieses
+ Kanals nach Eintrag des übergebenen Zeichens.
+
+ Zweck: SHard muß EUMEL-0 durch Aufruf dieser Routine mitteilen,
+ daß eine Eingabe vorliegt.
+
+ Hinweise: EUMEL-0 puffert die Zeichen. Falls 0 geliefert wird, ist der
+ Puffer voll und EUMEL-0 ignoriert weitere Eingaben, bis
+ wieder Platz im Puffer vorhanden ist. (siehe IOCONTROL
+ "weiter", S.#topage("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) such-
+ en. Man sollte dabei nicht nur an die menschliche Tippge-
+ schwindigkeit sondern auch an die höchste Baudrate denken,
+ die man für Rechnerkopplungen noch unterstützen will. *)
+
+ Falls SHard Flußkontrolle für den Kanal
+ ausüben soll, muß er die Rückmeldung in AL
+ auswerten. Dabei ist mit einem geeigneten
+ Schwellwert zu arbeiten, da in der Regel die
+ sendende Gegenstelle einer Sendeunterbrechung
+ nicht sofort Folge leistet.
+
+#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#
+
+ 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 enthält noch
+ zeichen REP
+ nimm zeichen aus shard puffer ;
+ enable interrupt ;
+ input interrupt ;
+ disable interrupt
+ PER ;
+ input interrupt := false ;
+ enable interrupt
+ FI .
+
+
+
+ #d("OUTPUT")#
+
+ Eingang: AL Kanalnummer (1...15)
+ CX Anzahl auszugebender Zeichen
+ DS:BX Adresse der Zeichenkette
+ Ausgang: CX 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 Interrupt-
+ logik oder etwas Äquivalentes ist sicherzustellen, daß dieser
+ Puffer parallel zur normalen Verarbeitung ausgegeben wird.
+ Wenn die auszugebende Zeichenkette nicht vollständig 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 Zeichenkette auf.
+
+ Hinweis: OUTPUT kann mit CX=0 aufgerufen werden. Auch diese leere
+ Operation muß mit gesetztem C-Flag quittiert werden.
+
+ 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 ausgege-
+ ben (CX 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, Teil 3: Editor, 5. Zeichencode"#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 pro-
+grammierbar 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 1.7
+Seite 106) 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 Rechnerkopp-
+lung zuzulassen. Die Kanalnummer in Reg. AL unterscheidet diese Fälle. Außer beim Paging
+(AL=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 ver-
+langte 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 Parameter in Register CX nur positive Werte (Bit 7 von CH = 0).
+Der SHard kann selbst negative Codes einführen.
+
+
+ #d("BLOCKIN")#
+
+ Eingang: AL Kanalnummer (0...32)
+ CX Parameter 1
+ DX Parameter 2
+ DS:BX Adresse des Hauptspeicherbereichs
+ Ausgang: AL undefiniert (darf also verändert werden)
+ CX Rückmeldecode
+ DS:BX darf verändert werden
+
+ Der Inhalt des Hauptspeicherbereichs (<DS:BX>... <DS:
+ BX> +511) darf verändert sein.
+
+ Zweck: "Einlesen" von Blöcken. Die genaue Wirkung hängt vom
+ Parameter und dem Kanal ab.
+
+ Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKIN darauf unsinnig
+ ist, sollte die Rückmeldung -1 in CX geliefert werden.
+
+
+ #d("BLOCKOUT")#
+
+ Eingang: AL Kanalnummer (0...32)
+ CX Parameter 1
+ DX Parameter 2
+ DS:BX Adresse des Hauptspeicherbereichs
+ Ausgang: AL undefiniert (darf also verändert werden)
+ CX Rückmeldecode
+ DS:BX 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
+ Parameter und dem Kanal ab.
+
+ Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKOUT darauf un-
+ sinnig ist, sollte die Rückmeldung -1 in CX 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,
+ weiter zu arbeiten. Ein 'warte' kann bis zu ca. 1/4 Sekunde
+ Zeit aufnehmen. 'warte' darf nicht in Interruptroutinen und
+ Stream-IO verwendet werden! 'warte' zerstört alle Register,
+ bis auf die Segmentregister CS und SS! SHard muß davon
+ ausgehen, daß 'warte' seinerseits andere SHard-Kompo-
+ nenten aufruft.
+
+
+Die Verwendung der 0-Routine 'warte' soll hier an einigen Beispielen verdeutlicht wer-
+den:
+
+
+ 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")# AL 0 bzw. 31
+ CH 0
+ CL Blocknummer DIV 65536
+ DX Blocknummer MOD 65536
+ DS:BX Hauptspeicheradresse
+
+ Der angegebene 512-Byte-Block ist in den Hauptspeicher
+ ab <DS:BX> einzulesen.
+
+ #on("b")#BLOCKOUT#off("b")# AL 0 bzw. 31
+ CH 0
+ CL Blocknummer DIV 65536
+ DX Blocknummer MOD 65536
+ DS:BX Hauptspeicheradresse
+
+ Der Hauptspeicherbereich (<DS:BX>... <DS:BX>+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 CX <> 0 in DS:BX 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 Fehlerwiederholungen
+ beim Hintergrund- und beim Archivzugriff durch. SHard sollte
+ deshalb im Fehlerfall die Operation 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
+ fehlerhaften 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 Datentrans-
+ port" 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' sei-
+ nerseits die Archivbehandlung des SHards aufrufen. Wenn beides z.B. denselben
+ Floppykontroller benutzt, muß SHard sicherstellen, daß das gut geht (z.B. durch
+ Semaphoren).
+
+
+Sollen auch #on("b")#Disketten nach #ib#DIN 66 239#ie##off("b")# auf dem Archivkanal gelesen und geschrieben
+werden können, müssen auf Kanal 31 zusätzlich Blöcke mit 'deleted data mark' gelesen und
+geschrieben werden können. Dafür kann BLOCKIN (beim Lesen einer Diskette) als weitere
+Rückmeldung liefern:
+
+ 4 'Deleted data mark' gelesen.
+
+Ausgabeseitig wird ein entsprechendes BLOCKOUT benötigt:
+
+ #on("b")#BLOCKOUT#off("b")# AL 31
+ CH 40h
+ CL Blocknummer DIV 65536
+ DX Blocknummer MOD 65536
+ DS:BX Hauptspeicheradresse
+
+ Der Hauptspeicherbereich (<DS:BX>... <DS:BX>+511) ist
+ mit der Kennung 'deleted data mark' auf den angegebenen
+ Block zu schreiben.
+
+Anmerkung: Diese Funktion muß nur implementiert werden, wenn Disketten nach DIN 66 239
+ beschrieben können werden sollen.
+
+
+
+#b("Block-IO zur MS-DOS-Partition")#
+#goalpage("bmsdosp")#
+
+Auf EUMEL-Rechnern, die mit einer Festplatte ausgerüstet sind, kann man einen Teil der
+Platte als MS-DOS-Partition und einen anderen als EUMEL-Partition reservieren. Für den
+Datenaustausch auf Dateiebene existiert EUMEL-Software, die über den Kanal 29 auf die
+MS-DOS-Partition zugreift. Falls SHard dieses unterstützen will, muß er entsprechende
+BLOCKIN/OUT-Operationen zur Verfügung stellen. Diese entsprechen den Operationen auf
+Kanal 0:
+
+ #on("b")#BLOCKIN#off("b")# AL 29
+ CH 0
+ CL Blocknummer DIV 65536
+ DX Blocknummer MOD 65536
+ DS:BX Hauptspeicheradresse
+
+ Der angegebene 512-Byte-Block ist in den Hauptspeicher
+ ab <DS:BX> einzulesen. Hier bezieht sich die Blocknummer
+ auf die MS-DOS-Partition. Dabei muß Block 0 derjenige
+ sein, der den Urladesektor der MS-DOS-Partition enthält.
+ (Hier steht der Bios-Parameterblock.) Die weiteren Blöcke
+ werden genauso wie in der von MS-DOS verwendeten
+ Numerierung relativ zu diesem Urladesektor adressiert.
+
+ #on("b")#BLOCKOUT#off("b")# AL 29
+ CH 0
+ CL Blocknummer DIV 65536
+ DX Blocknummer MOD 65536
+ DS:BX Hauptspeicheradresse
+
+ Der Hauptspeicherbereich (<DS:BX>... <DS:BX>+511) ist
+ auf den angegebenen Block zu schreiben. Für die Blocknu-
+ merierung gilt das oben beschreibenen.
+
+Als Rückmeldungen sind zu liefern:
+
+ 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)
+
+ Wichtig: Wird ein Block angesprochen, der nicht zur MS-DOS-Parti-
+ tion gehört, so muß 'Versorgungsfehler' (3) gemeldet werden.
+
+
+Anmerkung: Diese Funktionen müssen nur implementiert werden, wenn Datenaustausch
+ mit MS-DOS-Partitionen auf Plattenmaschinen unterstützt werden soll.
+
+
+#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 CX 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: AL Kanalnummer (0...32)
+ CX Funktionscode 1
+ DX Funktionscode 2
+ BX Funktionscode 3
+ Ausgang: CX Rückmeldung
+ AL 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: AL Kanalnummer (0...31)
+ CX 1
+ Ausgang: CX Kanaltyp
+
+ Zweck: Informiert EUMEL-0, welche IO für den angegebenen Kanal
+ sinnvoll ist. Die Rückmeldung in CX 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")#
+
+
+ #d("IOCONTROL ""frout""")#
+ #goalpage("frout")#
+
+ Eingang: AL Kanalnummer (1...15)
+ CX 2
+ Ausgang: CX 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 CX > 49 gemeldet werden.#off("i")#
+
+ Hinweis: Unter Berücksichtigung des oben Gesagten darf "gelogen"
+ werden. Man kann z.B. immer 50 in CX 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 CX und 'NC' zurückge-
+ meldet werden. Wenn aber Zeichen übernommen werden
+ können, sollte 50 in CX und 'C-Flag gesetzt' gemeldet wer-
+ den.
+
+ Vorschlag: Falls der Kanal nicht existiert oder nicht für Stream-IO zur
+ Verfügung steht, sollten 200 in CX und C-Flag gesetzt zu-
+ rückgemeldet werden.
+
+
+ #d("IOCONTROL ""weiter""")#
+ #goalpage("weiter")#
+
+ Eingang: AL Kanalnummer (1...15)
+ CX 4
+ Ausgang: -
+
+ Zweck: Das System ruft "weiter" für den in AL angegebenen Kanal
+ auf, wenn es wieder Eingabezeichen puffern kann. (siehe
+ auch: Flußkontrolle S.#topage("fluss")#)
+
+ 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 be-
+ troffene 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 Diskette
+ 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: AL Kanalnummer (0...31)
+ CX 7
+ DX Schlüssel
+ Ausgang: CX Fehlercode wie bei Archiv-BLOCKOUT (siehe S.#topage("errcod")#)
+
+ Zweck: Dient zum Formatieren einen 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"
+
+ 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 (AL = 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 (AL <> 32), wird le-
+ diglich 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: AL eigener Kanal (1...15 / 32)
+ CX 8
+ DX adressierter Kanal
+ BX Schlüssel
+ Ausgang: CX Rückmeldung (0 = ok, 1 = nicht möglich)
+
+ Zweck: Wird diese Routine auf dem Steuerkanal (AL=32) aufgeru-
+ fen, wird die angegebene Baudrate für den durch Register DX
+ 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 unter-
+ stützt werden. Bei V.24 Schnittstellen sollten aber minde-
+ stens 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 BX) vergeben.
+
+
+ #d("IOCONTROL ""bits""")#
+
+ Eingang: AL eigener Kanal (1...15 / 32)
+ CX 9
+ DX adressierter Kanal
+ BX Schlüssel
+ Ausgang: CX Rückmeldung (0 = ok, 1 = nicht möglich)
+
+ Zweck: Wird diese Routine auf dem Steuerkanal (AL=32) aufgeru-
+ fen, wird die angegebene Zeichenlänge (Bits pro Zeichen) und
+ Parität für den durch Register DX 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ög-
+ lichst 1 Stopbit, 7 und 8 Bits pro Zeichen und alle drei Pari-
+ tätseinstellungen zur Verfügung stehen.
+
+ Hinweis: Falls SHard-spezifisch weitere Einstellungen implementiert
+ werden sollen, darf SHard hierfür negative Schlüsselwerte
+ (Register BX) 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")#), die "stop" signalisieren kann, und die IOCONTROL-Funktion
+"weiter" (siehe S.#topage("weiter")#)verwenden:
+
+Allerspätestens bei der 'inputinterrupt'-Rückmeldung AL=0 muß SHard
+auf der V.24-Schnittstelle das Signal 'REQUEST TO SEND' wegnehmen bzw. XON senden
+(oder
+weiter einlaufenden Input selbst zwischenpuffern). Dadurch wird bei den meisten Fremd-
+rechnern 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 ensprechenden Kanal wieder empfangen
+werden (RTS setzen bzw. XON senden). In der Regel wird SHard schon reagieren müssen,
+bevor der EUMEL-Puffer gänzlich gefüllt ist, da die Sendehardware nicht schnell genug
+reagieren kann bzw. da noch sich noch Zeichen in Hardwarepuffern befinden können.
+
+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: AL eigener Kanal (1...15 / 32)
+ CX 6
+ DX adressierter Kanal
+ BX Modus
+ Ausgang: CX Rückmeldung (0 = ok, 1 = nicht möglich)
+
+ Zweck: Wird diese Routine auf dem Steuerkanal (AL=32) aufgeru-
+ fen, muß sie den gewünschten Flußkontrollmodus für den
+ adressierten Kanal einstellen.
+ Dabei sind folgende Modi festgelegt:
+
+ BX= 0 Keine Flußkontrolle
+ BX= 1 XON/XOFF (in beide Richtungen)
+ BX= 2 RTS/CTS (in beide Richtungen)
+ BX= 5 XON/XOFF (nur ausgabeseitig)
+ BX= 6 RTS/CTS (nur ausgabeseitig)
+ BX= 9 XON/XOFF (nur eingabesetig)
+ BX=10 RTS/CTS (nur eingabeseitig)
+
+ SHard wird hierdurch informiert, wie er auf "Puffer voll" und
+ "weiter" reagieren soll. Wenn keine Flußkontrolle gewünscht
+ wird (BX=0), muß SHard "stop" und "weiter" ignorieren; bei
+ BX=1 oder BX=9 muß bei "stop" XOFF und bei "weiter" XON
+ geschickt werden; bei BX=2 oder BX=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 BX=1 oder BX=5 müssen empfangene XON/XOFF-Zei-
+ chen, bei BX=2 oder BX=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 BX) vergeben.
+
+ "weiter" wird von EUMEL-0 sehr oft aufgerufen. Es
+ ist daher nicht sinnvoll, jedesmal XON zu senden, da dies die Gegenstelle
+ 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ückmeldung muß als BCD-Zahl erfolgen.
+
+ Hinweis: Die Uhr darf zwischen zwei Aufrufen umspringen. Die daraus
+ resultierende Probleme werden auf höheren Ebenen abge-
+ handelt.
+
+
+
+
+#bb("6. SHard-","Interface Version")#
+#goalpage("shdver")#
+
+Die #ib#Versionsnummer#ie# der Interface-Spezifikation, auf der SHard aufbaut, muß als 2-By-
+te-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-Mo-
+duln 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 Standardope-
+rationen 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ätzli-
+che 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 Mul-
+ti-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, (* --> DS:BX *)
+ INT CONST funktion1, (* --> CX *)
+ funktion2, (* --> DX *)
+ INT VAR antwort) (* <-- CX *)
+
+ PROC blockin (ROW 256 INT VAR para, (* --> DS:BX *)
+ INT CONST funktion1, (* --> CX *)
+ funktion2, (* --> DX *)
+ INT VAR antwort) (* <-- CX *)
+
+ PROC control (INT CONST funktion1, (* --> CX *)
+ funktion2, (* --> DX *)
+ funktion3, (* --> BX *)
+ INT VAR antwort) (* <-- CX *)
+
+Hinweis: Der SHard darf für 'funktion 1' (CX) 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 (AL='x', CX=-7, BX=13, DX=1200) aufgerufen. Verläßt
+ SHard 'control' mit CX = 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 ein-
+bauen. 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 dword ptr info
+ jr weiter
+ db ' text'
+ weiter:
+
+ Zweck: Info wird aufgerufen. Dabei wird 'text' zur Identifikation des
+ Kontrollereignisses ausgegeben. Der übergebene Text darf
+ nicht mit 0h beginnen.
+
+ 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-Routi-
+ nen benutzt, darf man ihn von diesen Routinen aus (inputin-
+ terrupt, OUTPUT, IOCONTROL "frout", IOCONTROL "weiter")
+ nicht aufrufen. Wenn die Ein-/Ausgabe auf Terminal 1 inter-
+ ruptgetrieben 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: BX Anfangsadresse des zu reservierenden Bereichs im
+ Datensegment von EUMEL-0, muß auf 512 Byte
+ ausgerichtet sein.
+ CX Länge des zu reservierenden Bereichs in 512-Byte-
+ Kacheln
+ Ausgang: CX 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 grundsätzlich nicht möglich
+ 2 augenblicklich 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 3800h anzufordern, da diese
+ Adresse stets im frei einplanbaren Paging-Bereich liegt.
+
+
+ #dx("free")# (0-Routine)
+
+ Eingang: BX Anfangsadresse des freizugebenden Bereichs im Da-
+ tensegment von EUMEL-0, muß auf 512 Byte ausge-
+ richtet sein.
+ CX Länge des zu freizugebenden Bereichs als 'Bytes DIV
+ 512'
+
+ 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, abschließend wird 'sysend'
+ aufgerufen.
+
+#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 soll-
+te
+
+ - nur die Kanäle 0 (Hintergrund), 1 (Terminal) und 31 (Archiv) behandeln,
+
+ - keine Baudraten-, Zeichenlängen-, Paritäts- und Flußkontrolleinstellungen un-
+ terstü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 Hintergrund-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): ? 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 gela-
+den 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 die Segmentregister 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 Zeichen
+ im Puffer frei" und "Puffer leer". Das kann schon im Vortest zu Output-Blok-
+ kaden führen.
+
+ h) Obwohl "frout" einen Wert größer als x meldet, nimmt "output" nicht alle x Zei-
+ chen 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) Fälschlicherweise wird davon ausgegangen, daß DS oder ES konstant bleiben.
+
+ m) Die Stepping-Rate eines Festplattencontrollers wird falsch eingestellt, bezie-
+ hungsweise die Platte wird nicht im 'buffered step mode' betrieben, obwohl
+ 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 Ein-
+ gabezeichen verloren oder werden verfälscht. In der Regel ist das auf Timing-
+ probleme 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-
+ Systemen 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 ung-
+ lückliches Timing häufig Blockaden auftreten. So kann zu kurzes 'busy wait' auf
+ Freiwerden der Parallelschnittstelle dazu führen, daß jedes zweite Zeichen abge-
+ lehnt 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 um-
+ gangen 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 ver-
+ wendet 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 .
+
+ Hinweis: Solche Systeme sind über V.24 nicht netzfähig, da sie Eingabezeichen
+ verlieren werden.
+
+
+ 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
+ zugunsten 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 Einlesen
+ 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.
+
+
+#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 werden,
+ da vermittels Info alle Systemsicherungs- und Datenschutzmaßnahmen un-
+ terlaufen werden können.#off("i")##off("b")# *)
+#foot#
+#f#
+*) Ausnahmen von dieser Regel bedürfen der expliziten Zustimmung der EUMEL-Systemgruppe (GMD bzw. HRZ Bie-
+lefeld) 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 Startmenü
+ 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
+eingegeben werden. Lediglich dieses Kommando und das Kommando 'g' werden immer
+angenommen. Das Paßwort kann mit dem Kommando 'yP' 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)#
+XYY TEXT
+F AL AH CL CH DL DH BL BH SI DI SP BP PC DS ES
+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),
+
+ YY den Maxiprozeß (Task) bezeichnet, der gerade durch den Elan-Prozessor bear-
+ beitet wird (YY ist die hexadezimale Tasknummer),
+
+ TEXT den Grund für den Info-Modus anzeigt,
+
+Die zweite und dritte Zeile zeigen die Inhalte der 8086/8088-Register an. 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. (s:=<zahl>)
+ Auch der Realspeicher kann hiermit in verschiedenen Modi eingestellt werden:
+ FF absolute Adressierung
+ 0 CS-relativ
+ 1 DS-relativ
+ 2 ES-relativ
+ 3 SS-relativ
+
+'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=1).
+
+'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 Ver-
+ fä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 wie-
+ derholen, 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 wird bei 'shutup' (erst
+ dann!) in Block 0 eingetragen.
+
+--> '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 INT3 (für Aufruf von
+ Info) abgesetzt. Info verwaltet gleichzeitig bis zu 10 gesetzte Breakpoints. Die
+ Breakpointnummer kann man aus der nach jedem Setzen (und Löschen)
+ angezeigten Breakpoint-Tabelle entnehmen. Breakpoints sind nur im Real-
+ speicher sinnvoll. Ein Aufruf meldet sich mit TEXT= 'break z--xxxx:yyyy' (z
+ = Breakpointnummer, xxxx = CS, yyyy = PC beim Aufruf des Breakpoints).
+ Wird Info mit 'g' verlassen, so stellt er zuvor die alten 8086/8088-Befehle
+ wieder her und führt sie an ihrem originalen Ort aus. Direkt danach wird der
+ Breakpoint wieder hergestellt.
+
+--> 'yc' Löscht den Breakpoint an der Adresse <zahl> und stellt die ursprüngli-
+ chen Befehle wieder her. In der Breakpoint-Tabelle muß ein Breakpoint an
+ dieser Adresse vermerkt sein.
+
+--> 'yw' Zu anderen Miniprozeß wechseln. Nur sinnvoll, wenn ein anderer Mini unter
+ 'vor info' aufgeführt ist.
+
+--> '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 Ge-
+ lernte 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 *re-
+ turn*).
+
+--> 'y *return*'
+ Wie *return*, jedoch wird der Dump auch beim Ausführen (ya) ausgegeben.
+ (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 aller-
+ dings 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 Zahl-
+ zeichen ist, beendet diesen Modus. Das neue Zeichen wird als
+ Info-Kommando aufgefaßt, wobei <zahl> auf die aktuelle
+ Adresse 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 1s100h 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 8086/8088-Teile ('urlader') ab (i.A.
+30h < i < 40h).
+
+'Beginn der Anforderungen' liegt bei i=2. Es handelt sich um Blocknummern von zu laden-
+den Blöcken. Ist der höherwertige Teil der Blocknummer gleich FDh, so ist dies keine Anfor-
+derung.
+
+Blocknummern > FF00h stehen für Blöcke mit dem Inhalt 512 FFh's und werden nie auf
+dem Hintergrundmedium gespeichert.
+
+
+
+1sA00h 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 ver-
+ anlaß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.
+
+
+1s480h-4FFh:
+ enthält die Aktivierungstabelle. Ist (480h+i)=01h, so ist die Task i aktiv. Hin-
+ weis: 4FFh 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, ansehen.
+
+ 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 Ver-
+ sionsnummer 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.
+
+
+
+
+
+
+
+
+
+
+