diff options
Diffstat (limited to 'doc/porting-8086/8/doc')
| -rw-r--r-- | doc/porting-8086/8/doc/Port.8086 | 2483 | 
1 files changed, 2483 insertions, 0 deletions
| diff --git a/doc/porting-8086/8/doc/Port.8086 b/doc/porting-8086/8/doc/Port.8086 new file mode 100644 index 0000000..a709a2a --- /dev/null +++ b/doc/porting-8086/8/doc/Port.8086 @@ -0,0 +1,2483 @@ +#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")#  +#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 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")#  +#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...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.  +  +#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 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.  +#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 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.  +  +#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 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.  + + + + + + + + + + + + | 
