summaryrefslogtreecommitdiff
path: root/doc/porting-z80/8/doc/Port.Z80
blob: ed3c80a793b3080b40ea01fe41b06587916806b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
#type ("trium8")##limit (12.0)# 
#pagelength(19.5)#
#start(1.5,1.5)# 
#type("triumb36")# 
#free(4.0)# 
  EUMEL 
  Portierungshandbuch 
  Z 80 
#type("triumb18")# 
#free(1.5)# 
          Version 8 #page(1)# 
#type ("trium8")##limit (12.0)# 
#block# 
#pagelength(19.5)# 
#head# 
#center#- % - 
 
 
#end# 
#type("triumb14")#Inhalt#a# 
 
Teil 1: Einführung                                     #topage("ein")# 
#free(0.3)# 
        Zweck dieses Handbuchs                         #topage("zweck")# 
        Referenzliteratur                              #topage("reflit")# 
        Minimale Hardwarevoraussetzungen               #topage("hardw")# 
        Systemdurchsatz                                #topage("durchsatz")# 
        Softwarekomponenten des EUMEL-Systems          #topage("kompo")# 
        Anlieferung des Z80-EUMEL-Systems              #topage("anlief")# 
 
Teil 2: Allgemeine Strukturen                          #topage("allgem")# 
#free(0.3)# 
        Hintergrund                                    #topage("hg")# 
        Archiv                                         #topage("arch")# 
        Hauptspeicher                                 #topage("speicher")# 
 
Teil 3: SHard-Interface Spezifikation                 #topage("shardifc")# 
#free(0.3)# 
   0. Vorbemerkungen                                  #topage("vor")# 
        Zur Notation                                  #topage("not")# 
        Link-Leisten                                  #topage("leist")# 
        Allgemeine Link-Bedingungen                   #topage("link")# 
        Interrupts                                    #topage("intr")# 
   1. System laden                                    #topage("laden")# 
   2. Systemstart und -ende                           #topage("start")# 
   3. Speicherverwaltung                              #topage("spver")# 
      Hauptspeicher                                   #topage("haupt")# 
      Schattenspeicher                                #topage("schatt")# 
      Blocktransfer im Speicher                       #topage("ldir")# 
      Speicherfehler                                  #topage("memerr")# 
   4. Zeitgeber                                       #topage("zeit")# 
   5. Kanäle                                          #topage("channel")# 
   5.1  Stream-IO                                     #topage("stream")# 
        Terminals                                     #topage("term")# 
        Drucker, Plotter                              #topage("druck")# 
        Exoten                                        #topage("exot")# 
   5.2  Block-IO                                      #topage("block")# 
        Block-IO bei Hintergrund und Archiv           #topage("bhgarch")# 
   5.3  IO-Steuerung                                  #topage("iocontrol")# 
        Einstellung serieller Schnittstellen          #topage("v24")# 
        Flußkontrolle                                 #topage("fluss")# 
        Kalender                                      #topage("kalender")# 
   6. SHard-Interface Version                         #topage("shdver")# 
   7. ID-Konstanten                                   #topage("ID")# 
   8. Zusätzliche Leistungen                          #topage("shdelan")# 
   9. Spezialroutinen                                 #topage("ke")# 
 
Teil 4: Tips zur Portierung                           #topage("tips")# 
        0-Version des SHards                          #topage("0ver")# 
        Effizienzprobleme                             #topage("eff")# 
        Typische Fehler                               #topage("fehler")# 
 
Anhang A: EUMEL-Debugger "Info"                       #topage("info")# 
#free(0.3)# 
        Aufruf des Infos                              #topage("aufrinf")# 
        Info-Format                                   #topage("forminf")# 
        Info-Kommandos                                #topage("cmdinf")# 
        Einige Systemadressen                         #topage("sysaddr")# 
        Leitblock                                     #topage("pcb")# 
#page# 
#cc("Teil 1: ","Einführung")# 
#goalpage("ein")# 
 
 
#b("Zweck dieses Handbuchs")# 
#goalpage("zweck")# 
 
Dieses Portierungshandbuch wendet sich an diejenigen, die das EUMEL-System auf einem
neuen Rechnertyp implementieren wollen. Es ist Teil einer Serie von Portierungshandbüchern
für verschiedene Prozessortypen. Dieses bezieht sich auf Rechner mit Z80-Prozessoren. 
 
Zum Betrieb eines EUMEL-Systems wird dieses Handbuch nicht benötigt! 
 
 
 
#b("Referenzliteratur")# 
#goalpage("reflit")# 
 
 
          "EUMEL Benutzerhandbuch" 
 
          "EUMEL Systemhandbuch" 
 
          "EUMEL Quellcode der insertieren ELAN-Pakete" 
 
          "Z80-Assembly Language Programming Manual" 
          Zilog, 1977 
 
 
 
#b("Minimale Hardwarevoraussetzungen")# 
#goalpage("hardw")# 
 
Um das EUMEL-System effizient einsetzen zu können, sollte die Hardware mindestens
folgenden Kriterien genügen: 
 
          #ib#CPU#ie#              Die Z80-CPU sollte mit mindestens 2.5 MHz arbeiten. Falls
                           die Buszugriffe durch einen CRTC o.ä. verlangsamt werden,
                           sollte die echte Z80-Leistung durchschnittlich mindestens
                           einem ungebremsten 2.5 MHz System entsprechen. 
                           Seltene Verlangsamungen (z.B. nur bei I/O-Operationen)
                           spielen bei diesen Überlegungen keine Rolle. 
 
          RAM              Das System sollte über mindestens 64 K Byte #ib#Hauptspeicher#ie#
                           verfügen, besser sind 128 K als Anfangsausrüstung. 
 
          #ib#Hintergrund#ie#      Als Hintergrundmedium sind #ib#Floppy#ie#, #ib#Harddisk#ie# und RAM bzw.
                           ROM denkbar. 
 
                           Kapazität:    > 300 K, besser > 400 K (Single-User) 
                                         > 750 K, besser > 1000 K (Multi-User) 
 
                           Zugriff:      < 500 ms  (Single-User) 
                                         < 200 ms  (Multi-User) *) 
#foot# 
#f#*) Hier ist die durchschnittliche Zugriffszeit auf einen 512 Byte großen Block gemeint. Für Platten und Floppies kann man
sie als Summe der Positionierzeit über die halbe Platte und der Zeit einer halben Umdrehung berechnen.#a# 
#end# 
 
          #ib#Archiv#ie#           Als Archivgerät wird meistens eine Floppy eingesetzt. Aber
                           auch Band oder Kassettenrecorder sind denkbar. Die An­
                           forderungen an Kapazität und Geschwindigkeit sind anwen­
                           dungsspezifisch. 
 
          #ib#Bildschirm#ie#       Angestrebt werden sollte ein Bildschirm mit 24 Zeilen mit je
                           80 Zeichen (oder größer). Kleinere Bildschirme sind anschließ­
                           bar, aber mit 40 Zeichen pro Zeile läßt sich nicht mehr kom­
                           fortabel arbeiten. 
                           Rollup und freie Cursorpositionierung sind notwendige Vor­
                           aussetzungen, invers-video ist erwünscht, aber nicht not­
                           wendig. Weiterhin werden 'Löschen bis Zeilenende' und
                           'Löschen bis Schirmende' benötigt. Lokale Editierfunktionen
                           sind überflüssig. 
 
          #ib#Tastatur#ie#         An Steuertasten sollten mindestens ESC und die vier Cursor­
                           tasten vorhanden sein. Dabei ist es günstig, wenn die Cursor­
                           tasten ergonomisch als Block bzw. Kreuz angeordnet sind.
                           EUMEL benötigt weitere Steuertasten für HOP, RUBIN,
                           RUBOUT und MARK. Dafür können beliebige Tasten der
                           Tastatur gewählt werden. 
 
 
 
#b("Systemdurchsatz")# 
#goalpage("durchsatz")# 
 
Da das EUMEL-System auf dem Prinzip des Demand Paging aufbaut, hängt der System­
durchsatz von 
 
     -  CPU Leistung 
     -  Speichergröße (RAM) 
     -  Geschwindigkeit beim Hintergrundzugriff (Floppy, Harddisk) 
 
ab. Mit zunehmender Benutzerzahl steigen in der Regel die Anforderungen an das Paging
(Hintergrund-Zugriff) schneller als an die CPU. In diesem Bereich kann man die System­
leistung dann durch mehr Speicher und/oder eine schnellere Platte in größerem Umfang
steigern. Dabei läßt sich eine langsame Platte teilweise durch mehr RAM und umgekehrt
wenig RAM durch eine schnelle Platte ausgleichen. 
 
 
 
#b("Softwarekomponenten des EUMEL-Systems")# 
#goalpage("kompo")# 
 
Das EUMEL-System besteht aus mehreren Schichten: 
 
 
 
          EUMEL  2:   Standardpakete, Editor, ... 
 
          EUMEL  1:   ELAN Compiler 
 
          EUMEL  0:   Basismaschine 
 
          EUMEL -1:   SHard 
 
                  H a r d w a r e 
 
 
Dieses #ib#Schichtenmodell#ie# ist nach oben offen und kann deshalb um beliebig viele (höhere)
Schichten erweitert werden. 
 
EUMEL > 0    Die Standardsoftware der Schichten > 0 ist in der Sprache ELAN geschrie­
             ben (siehe "EUMEL Quellcode"). Dementsprechend sind alle Schichten ober­
             halb der EUMEL-0-Maschine prozessor- und rechnerunabhängig, d.h.
             Anpassungen an einen neuen Rechnertyp sind nicht erforderlich. 
 
#ib#EUMEL 0#ie#      Die sogenannte "EUMEL-0-Maschine" enthält alle Basisoperationen und
             hängt davon ab, welchen Prozessortyp der Rechner als CPU verwendet. Sie
             existiert für verschiedene Prozessortypen. Hier wird nur auf den Typ Z80
             Bezug genommen. Bei der Portierung auf einen Z80-Rechner wird die
             Z80-EUMEL-0-Maschine ohne Anpassungen (!) übernommen. 
 
EUMEL -1     Diese Schicht stellt das Interface zwischen der EUMEL-0-Maschine und der
             eigentlichen Hardware (vom Prozessor abgesehen) dar. Insbesondere umfaßt
             sie alle Routinen zur Ansteuerung peripherer Geräte (Gerätetreiber). 
             Diese Schicht wird "SHard" genannt ("S"oftware-"Hard"ware Interface). 
 
Der SHard ist der einzige Teil des Systems, der bei der Portierung auf einen Z80-Rech­
ner angepaßt bzw. neu geschrieben werden muß. Deshalb besteht der größte Teil dieses
Handbuchs aus der Spezifikation des Z80-SHards. 
 
 
 
#b("Anlieferung des Z80-EUMEL-Systems")# 
#goalpage("anlief")# 
 
Der Implementierer erhält die EUMEL-Software auf Disketten. Dabei stehen folgende Stan­
dardformate zur Wahl: 
 
          8", 1D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte 
 
          8", 2D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte 
 
          5", 2D, 40 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte *) 
#foot# 
#f#*)   48 tpi#a# 
#end# 
 
 
Die Diskettenlieferung enthält 
 
          -  Single-User Hintergrund 
          -  Multi-User Hintergrund 
          -  Standardarchive 
          -  Archive mit weiterer Anwendersoftware 
 
Dabei enthält der Hintergrund auch die EUMEL-0-Software (oft auch als "Urlader" be­
zeichnet). 
 
#on("i")#Bitte gehen Sie vorsichtig mit diesen Mutterdisketten um. Verwenden Sie sie nur als Quelle
beim Kopieren. Sie sollten nur auf Kopien davon arbeiten!#off("i")# 
#page# 
#cc("Teil 2: ","Allgemeine Strukturen")# 
#goalpage("allgem")# 
 
 
#b("Hintergrund")# 
#goalpage("hg")# 
 
Der Hintergrund ist in 512 Bytes große Blöcke unterteilt. Sie werden durch Blocknummern (0,
1, 2, ...) adressiert. Die physische Ablage der Blöcke auf dem Hintergrundmedium bleibt dem
SHard überlassen. Er kann sie z.B. linear oder versetzt anordnen. Man sollte darauf achten,
daß Positionierungen auf logisch "nahe" Blöcke möglichst schnell gehen sollten. Deshalb ist
in der Regel zylinderorientierte Anordnung der oberflächenorientierten vorzuziehen. 
 
Falls auf dem Hintergrundgerät spezielle Blöcke z.B. für Boot und SHard freigehalten werden
sollen, muß das bei der Abbildung der Hintergrundblocknummern auf die Sektoren der Floppy
bzw. der Harddisk berücksichtigt werden. 
 
Aufbau des Hintergrundes: 
 
     Block  0                Systemetikett 
 
     Block  10...10+k-1      EUMEL-0-Software (Urlader) 
 
     Block  1...9, 10+k ...  Paging-Bereich 
 
 
Aufbau des #ib#Systemetikett#ie#s (#ib#Block 0#ie#): 
 
     Byte        Wert/Aufgabe 
 
     0...5       "EUMEL-"; Kennzeichen für EUMEL-Hintergrund. 
     6...11      Versionsnummer in druckbaren Zeichen. Sie stellt sicher, daß Urlader und
                 Hintergrund kompatibel sind. 
     12          FFh  ; zur Zeit ohne Bedeutung 
     13          enthält Wert 0 , wenn System im Shutupzustand ist. 
     14..15      Systemlaufzähler (14=low, 15=high). Wird bei jedem Systemstart um 1
                 erhöht. 
     16..35      Reserviert; zur Zeit ohne Bedeutung 
     36..37      Aus historischen Gründen für interne Zwecke belegt. 
     38 .. 69    Hier kann eine Installationsnummer geführt werden. 
     70 .. 79    Info-Paßwort 
     80          =0 Normalzustand 
                 =1 Kompresslauf erforderlich (System frisch von Archiv geladen) 
     81...255    Reserviert. 
     256..511    Kann von SHard beliebig verwendet werden. 
 
 
 
#b("Archiv")# 
#goalpage("arch")# 
 
Wie der Hintergrund sind die Archive in 512 Bytes große Blöcke unterteilt. Bisher gibt es
folgende #dx("Standardformate")#: 
 
 
     8", 1D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte 
     8", 2D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte 
 
          Block           Seite             Spur             Sektor 
 
            0               0                 0                 0 
           16               0                 1                 0 
          77*16             1                 0                 0 
 
            n         n DIV (77*16)   n MOD (77*16) DIV 16   n MOD 16 
 
 
     5", 2D, 40 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte 
 
          Block           Seite             Spur              Sektor 
 
            0               0                 0                 1 
            9               0                 1                 1 
          40*9              1                 0                 1 
 
            n         n DIV (40*9)   n MOD (40*9) DIV 9    n MOD 9 + 1 
 
 
     5", 2D, 80 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte 
 
          Block           Seite             Spur             Sektor 
 
            0               0                 0                 1 
            9               0                 1                 1 
          80*9              1                 0                 1 
 
            n         n DIV (80*9)    n MOD (80*9) DIV 9    n MOD 9 + 1 
 
 
     5", HD, 80 Spuren, 15 Sektoren (\#1...\#15) � 512 Byte 
 
          Block           Seite             Spur             Sektor 
 
            0               0                 0                 1 
           15               0                 1                 1 
          80*15             1                 0                 1 
 
            n        n DIV (80*15)   n MOD (80*15) DIV 15   n MOD 15 + 1 
 
 
Selbstverständlich können auch andere #ib#Archivformate#ie# implementiert werden, falls das aus
Hardwaregründen notwendig ist oder sich dadurch wesentliche Verbesserungen (z.B. in der
Kapazität) ergeben. 
 
Wenn irgend möglich sollte aber mindestens eines der oben aufgeführten Standardformate
unterstützt werden - evtl. als zusätzliches Format -, um den Austausch zwischen verschie­
denen Rechnertypen zu vereinfachen. 
 
#on("i")#Hinweis:  Um den Datenaustausch zwischen verschiedenen Rechnertypen zu vereinfachen,
          sollten möglichst alle der hardwaremäßig möglichen Standardformate (mindestens
          lesend) unterstützt werden. Dabei sollte SHard sich automatisch auf das Format
          der jeweils eingelegten Floppy einstellen:#off("i")# 
 
 
               Laufwerkstyp      Diskettentyp(en) 
 
                  8" 1D              8" 1D 
                  8" 2D              8" 2D, 1D 
 
                  5" 2D-40           5" 2D-40 
                  5" 2D-80           5" 2D-80, 2D-40 *) 
                  5" HD-80           5" HD-80, 2D-80, 2D-40 *) 
#foot# 
#f#*) Bei der Behandlung von 40-Spur-Disketten auf 80-Spur-Laufwerken gelten meistens folgende Regeln: 
     a) Lesen funktioniert sicher. 
     b) Schreiben ist unsicher, funktioniert aber häufig. 
     c) Formatieren funktioniert fast nie. 
#a# 
#end# 
 
 
 
#b("Hauptspeicher")# 
#goalpage("speicher")# 
 
Die 64 K des direkt vom Z80 adressierbaren #ib#Speicher#ie#s sind folgendermaßen aufgeteilt: 
 
          FFFFh          #corner1("-5.0")# 
                           Platz für SHard 
          yyyyh          #box3("T","3","75.0")# 
                         #corner1("-5.0")# 
                           Pagingbereich 
 
          xxxxh          #box3("T","3","75.0")# 
                         #corner1("-5.0")# 
                           EUMEL 0 
 
          1400h          #box3("T","3","75.0")# 
                         #corner1("-5.0")# 
                           Platz für SHard 
          0000h          #box3("T","3","75.0")# 
 
Möglichst große Teile des SHards (am besten alle) sollten im unteren Adreßbereich (bis
13FFh) liegen, damit dem Paging viel Speicher zur Verfügung steht. 
 
Der nicht direkt (aber durch Banking oder DMA) erreichbare Teil des #ib#RAM#ie#s wird Schatten­
speicher (siehe S.#topage("schatt")#) genannt. 
 
 
Hinweis:  Falls ein Teil des Hauptspeicher-Adreßraums fest (d.h. auch nach dem Boot­
          loading nicht ausblendbar) durch ROM belegt ist, muß dieses in einem der beiden
          SHard-Bereichen liegen. 
 
#page# 
#cc("Teil 3: SHard ","Interface Spezifikation")# 
#goalpage("shardifc")# 
 
 
#bb("0.  ","Vorbemerkungen")# 
#goalpage("vor")# 
 
 
#b("Zur Notation")# 
#goalpage("not")# 
 
Im folgenden wird zwischen #dx("0-Routinen")#, die dem SHard vom EUMEL-0-System zur
Verfügung gestellt werden, und #dx("SHard-Routinen")# unterschieden, die der SHard implementie­
ren muß. Damit dieser Unterschied bei der Spezifikation deutlich wird, werden 0-Routinen
folgendermaßen aufgeführt: 
 
          name       (0-Routine) 
 
Zusätzlich werden 0-Routinen grundsätzlich klein und SHard-Routinen groß geschrieben. 
 
Z80-Befehle werden wie in "Z80-Assembly Language Programming Manual" (Zilog, 1977)
notiert: 
 
          ld  a,27 
          add a,l 
 
Hexadezimale Zahlen werden durch ein nachgestelltes 'h' gekennzeichnet: 
 
            12h = 18 
            1Fh = 31 
          FFFFh = 65535 
 
 
#b("Link-Leisten")# 
#goalpage("leist")# 
 
Die Verbindung zwischen SHard und Urlader (EUMEL-0) erfolgt über zwei Tabellen. In der
"0-Leiste" stellt EUMEL-0 dem SHard verschiedene 0-Routinen zur Verfügung. Diese
Leiste beginnt an der Adresse 1400h: 
 
       1400h               defm  'EUMEL           ' 
       1410h               defw  eumel0blocks 
       1412h               defw  hgversion 
       1414h               defw  1        ; Kennzeichen für Z80-Urlader 
       1416h               defw  urladerversion 
       1418h               defw  0        ; reserviert 
       141ah               defw           ; kleinste unterstützte SHardversion 
       141ch               defw           ; größte ... 
       141eh               jp    systemstart 
                           jp    inputinterrupt 
                           jp    timerinterrupt 
                           jp    warte 
                           jp    grab 
                           jp    free 
                           jp    shutup 
                           jp    info 
 
Diese Leiste wird vom Urlader nach dem Systemstart überschrieben. Der SHard muß daher,
bevor er nach systemstart springt, die für ihn relevanten Teile (mindestens die Sprungbefehle)
in einen eigenen Bereich kopieren: 
 
          #ib#eusystemstart#ie#:     jp     0 
          #ib#euinputinterrupt#ie#:  jp     0 
          #ib#eutimerinterrupt#ie#:  jp     0 
          #ib#euwarte#ie#:           jp     0 
          #ib#eugrab#ie#:            jp     0 
          #ib#eufree#ie#:            jp     0 
          #ib#eushutup#ie#:          jp     0 
          #ib#euinfo#ie#             jp     0 
 
So kann SHard die entsprechenden 0-Routinen vermittels der obigen Vereinbarungen aufru­
fen: 
 
          jp    eusystemstart 
          ... 
          call  euwarte 
 
Für die Gegenrichtung muß SHard der 0-Maschine die "SHard-Leiste" zur Verfügung
stellen, deren Adresse beim Sprung nach 'systemstart' in HL stehen muß. Die 0-Maschine
kopiert diese Leiste. SHard darf daher anschliessend den Bereich anderweitig (z.B.
EA-Puffer) verwenden: 
 
 
          #ib#SHDID#ie#:           defm 'SHARD           '   ; 16 Byte 
          #ib#SHDVER#ie#:          defw 8 
          #ib#MODE#ie#:            defw 
          #ib#ID4#ie#:             defw 
          #ib#ID5#ie#:             defw 
          #ib#ID6#ie#:             defw 
          #ib#ID7#ie#:             defw 
                           defw 
                           defw 
          #ib#OUTPUT#ie#:          jp shout 
          #ib#BLOCKIN#ie#:         jp shbin 
          #ib#BLOCKOUT#ie#:        jp shbout 
          #ib#IOCONTROL#ie#:       jp shiocnt 
          #ib#SYSEND#ie#:          jp shend 
          #ib#SCHINF#ie#:          jp shsinf 
          #ib#SCHACC#ie#:          jp shsacc 
                           defw 
          #ib#LIMIT#ie#:           defw 
 
 
#b("Allgemeine Link-Bedingungen")# 
#goalpage("link")# 
 
In der Regel sind sowohl 0-Routinen als auch SHard-Routinen durch 'call' aufzurufen: 
 
          call <routine> 
 
Ausnahmen von dieser Regel sind im folgenden stets besonders vermerkt. 
 
Generelle Link-Bedingung (für SHard- und 0-Routinen) ist: 
 
     Alle Register - bis auf die jeweils spezifizierten Ausgangsparameter und das F-Regi­
     ster *) - bleiben unverändert. 
#foot# 
#f#*) Flags sind i.a. nach dem Aufruf einer Routine undefiniert. Ausnahmen sind natürlich die Flags, die als Ausgangs­
parameter in manchen Fällen definiert sind.#a# 
#end# 
 
Jede SHard-Routine muß also alle Register (bis auf F), die sie verändert und die keine
Ausgangsparameter sind, retten und wiederherstellen. Im Gegenzug braucht SHard beim
Aufruf von 0-Routinen selbst keine Register zu retten. 
 
 
#b("Interrupts")# 
#goalpage("intr")# 
 
Zwei externe Ereignisse (Zeitgeber und Eingabe, siehe S.#topage("zeit")# und S.#topage("inp")#) werden von
EUMEL-0 behandelt. Die entsprechenden Interrupts muß SHard per 'call' an 0-Routinen
weiterleiten. Außerhalb des Moduls SHard wird der 'reti'-Befehl nicht verwendet, damit der
SHard die Kontrolle über die Interruptlevel behält. Die Register (bis auf die Eingangsparame­
ter) werden von den aufzurufenden 0-Routinen selbst gesichert. Die normale Interrupt-
Sequenz im SHard sieht dann folgendermaßen aus: 
 
          intadr: push af 
                  ld a,<parameter> 
                  call <routine> 
                  pop af 
                  reti 
 
Achtung: SHard muß die Interrupt-Routinen im 'disable-int'-Modus anspringen. Dies ist
         normalerweise schon durch die Hardware gegeben. 
 
Die 0-Routinen geben von sich aus den 'ei'-Befehl. Dies erfolgt im allgemeinen sehr
frühzeitig (innerhalb der ersten 30 Befehle), um einen interruptgetriebenen Floppytreiber
zulassen zu können. 
 
 
 
 
#bb("1.  System ","laden")# 
#goalpage("laden")# 
 
SHard muß die EUMEL-0-Software vor dem eigentlichen Start laden. EUMEL-0 befindet
sich normalerweise auf dem Hintergrund. Es müssen von Block 10 an eumel-0-blocks
(siehe 0-Leiste) Blöcke in den Speicher von der Adresse 1400h an aufsteigend geladen
werden. 
 
     Achtung: Zu diesem Zeitpunkt kann SHard die oben aufgeführten 0-Routinen natür­
              lich noch nicht benutzen. Insbesondere dürfen die Laderoutinen nicht 'warte'
              aufrufen. Das wird hier besonders betont, weil der Hintergrundzugriff beim
              eigentlichen Systemlauf in der Regel 'warte' verwenden wird. 
 
     Hinweis: Der erste Block der EUMEL-0-Software (Block 10) enthält in den ersten
              fünf Bytes den Text "EUMEL", um eine Identifikation durch den SHard-
              Lader zu ermöglichen. 
 
Es wird empfohlen, nach folgendem Verfahren zu laden: 
 
     IF archivgeraet enthaelt diskette AND eumel 0 auf archiv 
       THEN lade eumel 0 vom archiv 
     ELIF eumel 0 auf hintergrund 
       THEN lade eumel 0 vom hintergrund 
     ELSE laden unmoeglich 
     FI . 
 
So kann man auch bei einem frisch formatierten Hintergrundmedium einen neuen Hinter­
grund (mit EUMEL-0-Urlader) einspielen, indem man ein Hintergrundarchiv vor dem
Systemstart in das Archivgerät legt. Dann wird EUMEL-0 von dort geladen, so daß man den
Hintergrund dann wie im Systemhandbuch beschrieben vom Archiv auf das Hintergrund­
medium kopieren kann.*) 
#foot# 
#f#*) Kopiervorgänge (Archiv -> Hintergrund) werden vom EUMEL-0-Urlader erledigt, so daß SHard keine derartigen
Routinen enthalten muß.#a# 
#end# 
 
 
 
#bb("2.  System","start und -ende")# 
#goalpage("start")# 
 
SHard muß alle für den Rechner notwendigen (Hardware-) Initialisierungen durchführen und
erst danach die EUMEL-0-Maschine starten ('systemstart'). 
 
     #dx("systemstart")#           (0-Routine) 
 
          Eingang:         HL = Adresse der SHard-Leiste 
                           Interrupts disabled 
 
          Aufruf:          jp systemstart 
 
          Zweck:           Die EUMEL-0-Maschine wird gestartet. Alle notwendigen
                           Hardwareinitialisierungen (Interrupt Modus des Z80 und Ini­
                           tialisierungen der Peripheriebausteine) müssen vorher schon
                           geschehen sein. 
 
          Hinweis:         Der Stackpointer braucht nicht definiert zu sein, da beim
                           Ansprung DI-Zustand herrschen sollte und somit keine
                           Interrupts auftreten können. EUMEL-0 lädt beim Start das
                           SP-Register und läßt Interrupts zu (EI). Falls jedoch in dieser
                           Zeit ein "Non Maskable Interrupt" auftreten kann, muß SHard
                           SP "vorläufig" laden. 
 
          MODE:            Über das MODE-Wort in der SHard-Leiste können Op­
                           tionen gesetzt werden: 
 
                           Bit 0 = 0      EUMEL-0 ist auf dem Hintergrund abge­
                                          speichert. Der entsprechende Bereich bleibt
                                          geschützt. (Standard) 
 
                           Bit 0 = 1      EUMEL-0 befindet sich nicht auf dem Hin­
                                          tergrund. Der entsprechende Bereich steht
                                          zur freien Verfügung für andere EUMEL-
                                          Daten. 
                                          (Da die EUMEL-0-Software nur beim
                                          Systemstart geladen wird (read only!), kann
                                          es bei Geräten mit kleinem Hintergrund
                                          interessant sein, diese Blöcke auf dem
                                          Hintergrund anderweitig zu nutzen. Das
                                          Systemladen kann dann z.B. mit Hilfe einer
                                          speziellen Urladediskette vom Archivgerät
                                          aus erfolgen.) 
 
                           Bit 8 = 0      Beim Systemstart wird der Speicher über­
                                          prüft. (Standard) 
 
                           Bit 8 = 1      Der Speichertest beim Systemstart unter­
                                          bleibt. Man sollte nur bei Rechnern, die
                                          beim Einschalten schon eigene Speicher­
                                          tests durchführen, auf den Speichertest des
                                          EUMEL verzichten. 
 
                           Bit 9 = 0      Beim Systemstart wird die Vortest-Tapete
                                          ausgegeben und man kann durch Eingabe
                                          eines Zeichens die Vortestmenüs aktivieren
                                          (s. Systemhandbuch). (Standard) 
 
                           Bit 9 = 1      Die Vortest-tapete wird unterdrückt. Es gibt
                                          auch keine Möglichkeit, die Vortestfunk­
                                          tionen aufzurufen. Der Speichertest unter­
                                          bleibt ebenfalls. 
 
 
     #dx("SYSEND")# 
 
          Parameter:       - 
 
          Zweck:           Hiermit wird SHard das Ende eines Systemlaufs mitgeteilt.
                           Somit können evtl. notwendige Abschlußbehandlungen durch­
                           geführt werden. SHard kann mit 'ret' zu EUMEL-0 zurück­
                           kehren, muß aber nicht. Diese Routine kann z.B. dazu benutzt
                           werden, die Hardware auszuschalten oder in ein umgebendes
                           System zurückzukehren (EUMEL als Subsystem). In den
                           meisten Fällen wird die Routine leer implementiert werden,
                           d.h. nur aus 'ret' bestehen. 
 
 
#bb("3.  ","Speicherverwaltung")# 
#goalpage("spver")# 
 
 
#b("Hauptspeicher")# 
#goalpage("haupt")# 
 
Der Hauptspeicher (#ib#RAM#ie#) umfaßt die direkt adressierbaren 64 K des Z80. Da die Anfangs­
adresse des für EUMEL-0 und Paging verfügbaren Bereichs fest ist (1400h), muß SHard nur
über die Obergrenze des verfügbaren Bereichs informieren. 
 
     #dx("LIMIT")# 
 
                           Über das LIMIT-Wort in der SHard-Leiste kann sich SHard
                           noch Bereiche vor dem Speicherende (z.B. für CP/M BIOS)
                           freihalten. Auf jeden Fall muß CFFFh <= LIMIT gewährleistet
                           sein, d.h. der Bereich bis CFFFh gehört zum Pagingbereich.
                           Im Normalfall wird FFFFh geliefert werden. 
 
 
 
#b("Schattenspeicher")# 
#goalpage("schatt")# 
 
Das EUMEL-System ist in der Lage, trotz der durch die 16-Bit Adressen gegebenen Ein­
schränkung auf 64 kB, weiteren Speicher anzuschließen. Dieser wird Schattenspeicher
genannt. 
 
Der Schattenspeicher (#ib#RAM#ie#) sollte so angeschlossen sein, daß über ein nicht zu großes #ib##on("italic")#
Fenster#ie##off("italic")# des normalen Adressraumes ( < 4 kB) auf diesen zugegriffen werden kann. Welcher
Bereich des Schattenspeichers dabei gemeint ist, wird durch die SHard-Routine SCHACC
mitgeteilt (s.u.). Diese Art des Zugriffs wird Fenstermodus genannt. Das Restsystem nutzt das
Fenster echt (d.h. ohne den Inhalt in andere Bereiche des normalen Adressraumes zu trans­
portieren). 
 
Ist ein so kleines Fenster in der Hardware nicht vorgesehen (z.B. 48 kB Bänke bzw. nur
DMA-Zugriff), so kann auch solcher Schattenspeicher benutzt werden (Transportmodus).
Wichtig ist dabei, daß EUMEL-0 die oben erwähnten echten Fensterzugriffe unterläßt.
(Simulation im Transportmodus wäre erheblich zu teuer.) Daher muß EUMEL-0 wissen, in
welchem Modus der Schattenspeicher ansprechbar ist (SCHINF). 
 
Hinweis:  Wenn möglich sollte der Fenstermodus implementiert werden, da er im Multi-
          User-Betrieb (ab ca. 3 Teilnehmern) deutliche Effizienzvorteile bietet. 
 
 
Das Schattenspeicherinterface gibt es in 2 Modi: 
 
     -  Fenstermodus (Bit 2**15 von BC gesetzt bei SCHINF) 
     -  Transportmodus (Bit 2**14 von BC gesetzt bei SCHINF) 
 
 
#d("Fenstermodus")# 
 
     #dx("SCHINF")#                (im Fenstermodus) 
 
          Ausgang:         BC    2**15 + Schattenspeichergröße (in K) 
 
          Zweck:           EUMEL-0 kann so die Größe des Schattenspeichers und den
                           gewünschten Modus (hier: Fenstermodus) erfragen. Falls kein
                           Schattenspeicher vorhanden ist, muß 0 als Größe geliefert
                           werden. Das Resultat von SCHINF darf sich innerhalb eines
                           Systemlaufs nicht ändern. 
 
 
     #dx("SCHACC")#                (im Fenstermodus) 
 
          Eingang:         HL    Nummer der 1/2K-Seite, die in das Fenster zu schal­
                                 ten ist. 
          Ausgang:         HL    Anfangsadresse (im Normaladreßraum) des aktuellen
                                 Fensters 
 
          Zweck:           Dient zum Zugriff auf den Schattenspeicher über das Fen­
                           ster. Man beachte, daß mehrere Fenster möglich sind, aber
                           alle im Adreßbereich des SHards liegen müssen! Die Num­
                           mern der 1/2K-Seiten des Schattenspeichers liegen immer
                           im Bereich von 0 bis 2n-1, wobei n die von SCHINF geliefer­
                           te Größe des Schattenspeichers ist. Daraus folgt, daß
                           SCHACC nicht aufgerufen wird, falls kein Schattenspeicher
                           vorhanden ist. 
 
#d("Transportmodus")# 
 
     #dx("SCHINF")#                (im Transportmodus) 
 
          Ausgang:         BC    2**14 + Schattenspeichergröße (in K) 
 
          Zweck:           EUMEL-0 kann so die Größe des Schattenspeichers und den
                           gewünschten Modus (hier: Transportmodus) erfragen. Falls
                           kein Schattenspeicher vorhanden ist, muß 0 als Größe gelie­
                           fert werden. Das Resultat von SCHINF darf sich innerhalb
                           eines Systemlaufs nicht ändern. 
 
 
     #dx("SCHACC")#                (im Transportmodus) 
 
          Eingang:         A = 1  Transport in den Schattenspeicher 
                           A = 2  Transport aus dem Schattenspeicher 
                           DE     Nummer der 1/2K Seite im Schattenspeicher 
                           HL     Adresse im normalen Hauptspeicherbereich 
 
          Zweck:           Es werden jeweils 512 Bytes aus dem Normal- in den
                           Schattenspeicher (A=1) bzw. aus dem Schattenspeicher in
                           den normalen Hauptspeicher (A=2) kopiert. 
                           Die Nummern der 1/2K-Seiten des Schattenspeichers liegen
                           immer im Bereich von 0 bis 2n-1, wobei n die von SCHINF
                           gelieferte Größe des Schattenspeichers ist. Daraus folgt, daß
                           SCHACC nicht aufgerufen wird, falls kein Schattenspeicher
                           vorhanden ist. 
 
          Eingang:         A = 3 
                           E      Index (immer geradzahlig: 0,2,4,...254) 
          Ausgang:         BC     Bereichslänge DIV 3 
                           HL     Bereichsadresse 
 
          Zweck:           Für den angegebenen Index ist die Adresse eines Haupt­
                           speicherbereichs und 1/3 der Länge dieses Bereichs zu­
                           rückzumelden (Anzahl Einträge � 3 Bytes) Es sind also 128
                           solcher Bereiche zur Verfügung zu stellen. Bei n K Schat­
                           tenspeicher sollte jeder Bereich größer als 6*n/128 Bytes sein.
                           Alle Bereiche müssen gleich groß sein. 
 
                           Beispiel: Bei bis zu 256 K sollten 16-Byte-Bereiche
                                     benutzt werden: 
 
                           shacc3:    ld   l,e 
                                      ld   h,0 
                                      add  hl,hl 
                                      add  hl,hl 
                                      add  hl,hl 
                                      ld   bc,schtab 
                                      add  hl,bc      ; <e> DIV 2 * 16 + schtab 
                                      ld   bc,5       ; 16 DIV 3 
                                      ret 
 
                           schtab:    defs 128*16 
 
 
 
 
#b("Blocktransfer im Speicher")# 
#goalpage("ldir")# 
 
 
 
#b("Speicherfehler")# 
#goalpage("memerr")# 
 
Falls die Hardware Speicherfehler aufgrund von Paritybits, ECC oder ähnlichem feststellen
und an SHard melden kann, sollte das zur Erhöhung der Systemsicherheit genutzt werden. 
 
Wenn SHard (z.B. über Interrupt) einen Speicherfehler mitgeteilt bekommt, sollte er wenn
möglich eine entsprechende Meldung ausgeben und das System brutal anhalten: 
 
          rien#ub# #ue#ne#ub# #ue#vas#ub# #ue#plus:   jr   rien#ub# #ue#ne#ub# #ue#vas#ub# #ue#plus 
 
 
Wenn Speicherfehler mit Sicherheit bemerkt werden, verhindert diese Reaktion, daß die
Fehler auf dem Hintergrund festgeschrieben werden und evtl. später zu Systemfehlern führen. 
 
Der Anwender kann dann durch Hardware-Reset auf den letzten Fixpunkt des EUMEL-
Systems zurücksetzen. So verliert er zwar evtl. die letzten Minuten seiner Arbeit, behält aber
auf alle Fälle ein konsistentes System. 
 
 
 
 
#bb("4.  ","Zeitgeber")# 
#goalpage("zeit")# 
 
SHard muß einen Zeitgeberinterrupt erzeugen, der ca. 10 bis 100 mal pro Sekunde auftritt.
Dabei ist die 0-Routine 'timerinterrupt' aufzurufen. Ohne diesen Interrupt wird die Uhr nicht
geführt, und die Zeitscheibenlogik für das Timesharing fällt aus. 
 
     #dx("timerinterrupt")#        (0-Routine) 
 
          Eingang:         A     seit letztem Zeitgeberinterrupt vergangene Zeit (in ms) 
 
          Zweck:           Wird von EUMEL-0 für interne Uhren und für das Schedu­
                           ling (Zeitscheibenlogik) verwendet. Es werden keine hohen
                           Genauigkeitsanforderungen an die Zeitangaben bei #on("i")#einzel­
                           nen#off("i")# Interrupts gestellt. Um EUMEL-0 eine genaue Real­
                           zeituhr zu ermöglichen, sollte die so erzeugte Zeitangabe #on("i")#im
                           Mittel#off("i")# aber möglichst genau sein, d.h. die Summe der inner­
                           halb einer Minute so übergebenen Werte sollte zwischen
                           59995 und 60005 liegen. 
 
 
 
#bb("5.  ","Kanäle")# 
#goalpage("channel")# 
 
Einiges zum Kanalkonzept: 
 
Das System kennt die Kanäle 0..32. 
 
     Kanal 0 ist der Systemhintergrund. 
     Die Kanäle 1..15 sind für Stream-IO (Terminals, Drucker, ...) vorgesehen. 
     Kanal 31 ist der Standard-Archivkanal. 
     Kanal 32 ist der Parameterkanal. 
 
Die Kanäle 2.. 30 können installationsabhängig verfügbar sein oder auch nicht. Deren Funk­
tion ist dann Absprachesache zwischen Installation und SHard. 
 
Kanäle können über Block-IO (BLOCKOUT, BLOCKIN) oder Stream-IO (OUTPUT,..) ange­
sprochen werden. Das System erfährt über IOCONTROL, welche Betriebsart des Kanals
sinnvoll ist. 
 
#on("i")##on("b")#Achtung:  Alle Kanaloperationen müssen grundsätzlich für alle Kanäle (0...32) aufgerufen
          werden können. Dabei können Operationen auf nicht vorhandenen Kanälen und
          unsinnige Operationen (z.B. Stream-IO auf Kanal 0) leer implementiert wer­
          den.#off("b")# (Dafür werden im folgenden bei jeder SHard-Routine Vorschläge gemacht.)#off("i")# 
 
 
 
#bb("5.1 ","Stream-IO")# 
#goalpage("stream")# 
 
Über Stream-IO wickelt das System die übliche zeichenorientierte Ein-/Ausgabe auf Termi­
nals, Druckern, Plottern usw. ab. Stream-IO wird nur für die Kanäle 1...15 gemacht. 
 
     #dx("inputinterrupt")#        (0-Routine)#goalpage("inp")# 
 
          Eingang:         A     Kanalnummer (1...15) 
                           B     eingegebenes Zeichen 
                           C     Fehlerbits: 
                                 Bit 0 = 1           Mindestens ein Zeichen ging
                                                     verloren. 
                                 Bit 1 = 1           Es wurde der BREAK-Zustand
                                                     (bei V24) erkannt. 
                                 Bit 2 = 1           Das Zeichen ist u.U. falsch
                                                     (Paritätsfehler). 
 
          Ausgang:         A     Anzahl Zeichen, die noch übernommen werden kön­
                                 nen. 
 
          Zweck:           SHard muß EUMEL-0 durch Aufruf dieser Routine mitteilen,
                           daß eine Eingabe vorliegt. 
 
          Hinweise:        EUMEL-0 puffert die Zeichen. Siehe auch IOCONTROL:
                           "weiter". 
 
                           Bei Kanalnummern <1 oder >15 wird der Aufruf von
                           EUMEL-0 ignoriert. 
 
                           Falls die Hardware keine Inputinterrupts zur Verfügung stellt,
                           sollte ein Timer benutzt werden, um alle möglichen Input­
                           quellen regelmäßig abzufragen. Dabei muß man allerdings den
                           goldenen Mittelweg zwischen zu häufiger (Systemdurchsatz
                           sinkt) und zu seltener Abfrage (Zeichen gehen verloren)
                           suchen. Man sollte dabei nicht nur an die menschliche Tipp­
                           geschwindigkeit sondern auch an die höchste Baudrate
                           denken, die man für Rechnerkopplungen noch unterstützen
                           will. *) 
#foot# 
#f#*) Eine weitere Möglichkeit, auf manchen Kanälen ohne Interrupts auszukommen, wird bei der IOCONTROL-Funktion
"weiter" beschrieben (siehe S.#topage("weiter")#).#a# 
#end# 
 
                           Falls SHard Flußkontrolle für den Kanal ausüben soll, muß er
                           die Rückmeldung in A auswerten. Dabei ist mit einem geeig­
                           neten Schwellwert zu arbeiten, da in der Regel die sendende
                           Gegenstelle einer Sendeunterbrechung nicht sofort Folge
                           leistet. 
 
          Achtung:         #on("i")#Keinesfalls darf 'inputinterrupt' rekursiv aufgerufen werden.
                           Normalerweise wird das automatisch verhindert, wenn man
                           den zugehörigen Hardwareinterrupt erst nach der 0-Routine
                           wieder freigibt. Falls das nicht möglich ist und unter bestimm­
                           ten Umständen das nächste Zeichen abgeholt werden muß,
                           bevor die 0-Routine beendet ist, muß SHard einen eigenen
                           Puffer implementieren:#off("i")# 
 
                           hardwareinterrupt: 
                               IF input interrupt aktiv 
                                  THEN trage zeichen in shard puffer ein ; 
                                       gib hardware interrupt frei 
                                  ELSE input interrupt aktiv := true ; 
                                       gib hardware interrupt frei ; 
                                       input interrupt ; 
                                       disable interrupt ; 
                                       WHILE shard puffer enthaelt noch zeichen REP 
                                             nimm zeichen aus shard puffer ; 
                                             enable interrupt ; 
                                             input interrupt ; 
                                             disable interrupt 
                                       PER ; 
                                       input interrupt := false ; 
                                       enable interrupt 
                               FI . 
 
 
     #d("OUTPUT")#
 
          Eingang:         A     Kanalnummer (1...15) 
                           BC    Anzahl auszugebender Zeichen 
                           HL    Adresse der Zeichenkette 
          Ausgang:         BC    Anzahl der übernommenen Zeichen 
                           C-Flag gesetzt <=> alle Zeichen übernommen 
 
          Zweck:           Ausgabe einer Zeichenkette. Diese ist (möglichst ganz) zwi­
                           schenzupuffern, denn die Ausführung von OUTPUT sollte kein
                           Warten auf IO enthalten. Der Ausgabepuffer muß mindestens
                           50, besser 100 Zeichen fassen können. Durch eine Inter­
                           ruptlogik oder etwas Äquivalentes ist sicherzustellen, daß
                           dieser Puffer parallel zur normalen Verarbeitung ausgegeben
                           wird. Wenn die auszugebende Zeichenkette nicht vollstän­
                           dig in den Puffer paßt, sollten trotzdem so viele Zeichen wie
                           möglich übernommen werden. Im weiteren Verlauf ruft
                           EUMEL-0 dann wieder OUTPUT mit dem Rest der Zei­
                           chenkette auf. 
 
          Hinweis:         OUTPUT kann mit BC=0 aufgerufen werden. Auch diese
                           leere Operation muß mit gesetztem C-Flag quittiert wer­
                           den. 
 
          Achtung:         #on("i")#Keinesfalls darf innerhalb von OUTPUT die 0-Routine 'warte'
                           aufgerufen werden.#off("i")# 
 
          Vorschlag:       Falls der Kanal nicht existiert bzw. OUTPUT darauf unsinnig
                           ist, sollte vorgegaukelt werden, alle Zeichen seien ausge­
                           geben (BC unverändert und C-Flag gesetzt). 
 
 
 
#b("Terminals")# 
#goalpage("term")# 
 
"Normale" #ib#Terminal#ie(1,", normales")#s können ohne weitere Unterstützung des SHards angeschlossen wer­
den. Die zur Anpassung an den EUMEL-Zeichensatz *) notwendigen #ib#Umcodierungen#ie# werden
von den höheren Ebenen aus eingestellt. Da diese Umsetztabellen vom SHard unabhängig
sind, stehen automatisch alle so angepaßten Terminaltypen allen EUMEL-Anwendern zur
Verfügung! 
#foot# 
#f#*) Siehe "EUMEL Benutzerhandbuch"#a# 
#end# 
 
Für den Anschluß eines #on("b")##on("i")#integrierten #ib#Terminal#ie(1,", integriertes")#s#off("i")##off("b")#, in dessen Bildwiederholspeicher direkt gear­
beitet wird, kann man häufig den Terminaltyp 'psi' verwenden (siehe auch "Exoten"). 
 
Näheres zu Terminaltypen und -anschlüssen findet man im "EUMEL Systemhandbuch"
unter den Stichwörtern #on("i")#Konfiguration#off("i")# und #on("i")#Konfigurierung#off("i")#. 
 
 
 
#bb("Drucker, ","Plotter")# 
#goalpage("druck")# 
 
#ib#Drucker#ie# und Plotter werden vom EUMEL-System wie Terminals angesehen. Da in der Regel
der Rechner aber schneller Zeichen senden als der Drucker drucken kann, müssen solche
Geräte in der Regel mit Flußkontrolle angeschlossen werden (siehe S.#topage("fluss")#). 
 
Wenn Drucker oder Plotter über eine Parallelschnittstelle angeschlossen werden, kann man
auf diesem Kanal möglicherweise auf einen Ausgabepuffer verzichten. Voraussetzung ist
dabei, daß 
 
     a)   der Drucker einen eigenen Puffer hat und 
     b)   der Puffer "schnell" gefüllt werden kann (< 0.1 ms/Zeichen). 
 
Dann kann man auf den bei der SHard-Routine OUTPUT geforderten Puffer verzichten und
die Zeichenkette direkt über die Parallelschnittstelle an den Drucker übergeben. Wenn der
Drucker 'Puffer voll' signalisiert, sollte die Zeichenübernahme bei OUTPUT abgebrochen
werden. *) #on("i")#Auf keinen Fall darf CPU-intensiv auf Freiwerden des Puffers gewartet werden!#off("i")# 
#foot# 
#f#*) siehe auch IOCONTROL "frout", S.#topage("frout")##a# 
#end# 
 
 
 
#b("Exoten")# 
#goalpage("exot")# 
 
Exotische #ib#Terminal#ie(1," exotisches")#s (im Sinne dieser Beschreibung) sind solche, für die eine Umsetztabelle
im System (siehe Konfiguratorbeschreibung) nicht ausreicht bzw. nicht nötig ist (Beispiele:
Terminals, in deren Bildwiederholspeicher direkt gearbeitet wird; Terminals, die soweit
programmierbar sind, daß sie den EUMEL-Zeichencode können). 
 
Für solche Terminals muß in der Konfiguration der Terminaltyp '#ib#psi#ie#' eingestellt werden. Dieser
wirkt ohne Umcodierungen, d.h. die EUMEL-Codes (siehe Benutzerhandbuch) werden direkt
dem SHard zugestellt (wie bei 'transparent'), jedoch mit folgenden Besonderheiten: 
 
Eingabeseitig werden zusätzlich folgende Codezuordnungen getroffen: 
 
     Code     Funktion 
 
     7        SV      (Aktivierung: 'gib supervisor kommando:') 
     17       STOP    (Ausgabe auf diesen Kanal wird gestoppt) 
     23       WEITER  (Ausgabe läuft wieder weiter) 
     4        INFO    (System geht in Debugger, falls Debugoption) 
 
 
 
#bb("5.2 ","Block-IO")# 
#goalpage("block")# 
 
Über Block-IO wickelt das System die Zugriffe zum Pagingmedium und zum Archiv ab.
Ferner ist daran gedacht, auch auf V.24-Schnittstellen Block-IO z.B. für Rechnerkopplung
zuzulassen. Die Kanalnummer in Reg. A unterscheidet diese Fälle. Außer beim Paging (A=0)
wird ein Block-IO durch die ELAN-Prozeduren 'blockin' und blockout' induziert. 
 
Bei Block-IO wird immer ein 512 Byte großer Hauptspeicherbereich mit übergeben. Dieser
kann (im Gegensatz zu OUTPUT) direkt benutzt werden, d.h. es muß keine Umpufferung
erfolgen. 
 
Dieser Hauptspeicherbereich darf nur bei BLOCKIN verändert werden. 
 
SHard darf (anders als bei OUTPUT) erst dann zur Aufrufstelle zurückgeben, wenn die
verlangte Operation abgeschlossen ist. Treten während der Operation Wartezeiten auf, so muß
SHard die 0-Routine 'warte' aufrufen, damit das System andere Prozesse weiterlaufen
lassen kann. 
 
EUMEL-0 definiert bestimmte Funktionen für Hintergrund (Kanal 0) und Archiv (Kanal 31).
Operationen auf anderen Kanälen kann SHard nach Belieben implementieren und deren
Leistung seinen Installationen über ELAN-Pakete zur Verfügung stellen. Das System vergibt
auch in Zukunft für den #ib##on("italic")#Funktionscode#ie##off("italic")# in Register BC nur positive Werte (Bit 7 von B = 0).
Der SHard kann selbst negative Codes einführen. 
 
 
     #d("BLOCKIN")#
 
          Eingang:         A     Kanalnummer (0...32) 
                           BC    Funktionscode 1 
                           DE    Funktionscode 2 
                           HL    Adresse des Hauptspeicherbereichs 
          Ausgang:         A     undefiniert (darf also verändert werden) 
                           BC    Rückmeldecode 
                           HL    darf verändert werden 
 
                           Der Inhalt des Hauptspeicherbereichs (<HL>... <HL>
                           +511) darf verändert sein. 
 
          Zweck:           "Einlesen" von Blöcken. Die genaue Wirkung hängt vom
                           Funktionscode und dem Kanal ab. 
 
          Vorschlag:       Falls der Kanal nicht existiert bzw. BLOCKIN darauf unsinnig
                           ist, sollte die Rückmeldung -1 in BC geliefert werden. 
 
 
     #d("BLOCKOUT")#
 
          Eingang:         A     Kanalnummer (0...32) 
                           BC    Funktionscode 1 
                           DE    Funktionscode 2 
                           HL    Adresse des Hauptspeicherbereichs 
          Ausgang:         A     undefiniert (darf also verändert werden) 
                           BC    Rückmeldecode 
                           HL    darf verändert werden 
 
                           Der Inhalt des Hauptspeicherbereichs darf #on("i")#nicht#off("i")# verändert
                           werden! 
 
          Zweck:           "Ausgeben" von Blöcken. Die genaue Wirkung hängt vom
                           Funktionscode und dem Kanal ab. 
 
          Vorschlag:       Falls der Kanal nicht existiert bzw. BLOCKOUT darauf un­
                           sinnig ist, sollte die Rückmeldung -1 in BC geliefert wer­
                           den. 
 
 
     #dx("warte")#                 (0-Routine) 
 
          Ausgang:         Alle Register undefiniert! 
 
          Zweck:           Diese Routine ist bei 'blockin' oder 'blockout' dann aufzu­
                           rufen, wenn SHard im Augenblick nichts zu tun hat. Durch
                           den Aufruf von 'warte' erhalten andere Systemteile die
                           Möglichkeit, weiterzuarbeiten. Ein 'warte' kann bis zu ca. 1/4
                           Sekunde Zeit aufnehmen. 'warte' darf nicht in Interrupt­
                           routinen und Stream-IO verwendet werden! 'warte' zerstört
                           alle Register! SHard muß davon ausgehen, daß 'warte' sei­
                           nerseits andere SHard-Komponenten aufruft. 
 
 
Die Verwendung der 0-Routine 'warte' soll hier an einigen Beispielen verdeutlicht werden: 
 
 
     blockout auf platte : 
          WHILE platte noch nicht frei REP 
            warte 
          ENDREP ; 
          uebertrage schreibbefehl an controller ; 
          uebertrage daten an controller . 
 
     blockin von platte : 
          WHILE platte noch nicht frei REP 
            warte 
          ENDREP ; 
          uebertrage lesebefehl an controller ; 
          WHILE daten noch nicht gelesen REP 
            warte 
          ENDREP ; 
          hole daten vom controller . 
 
 
     blockout auf floppy : 
          seekbefehl an controller ; 
          WHILE seek noch nicht fertig REP 
            warte 
          ENDREP ; 
          setze dma auf schreiben block zur floppy ; 
          schreibbefehl an controller ; 
          WHILE schreiben noch nicht fertig REP 
            warte 
          ENDREP . 
 
     blockin von floppy : 
          seekbefehl an controller ; 
          WHILE seek noch nicht fertig REP 
            warte 
          ENDREP ; 
          setze dma auf lesen block von floppy ; 
          lesebefehl an controller ; 
          WHILE lesen noch nicht fertig REP 
            warte 
          ENDREP . 
 
 
 
#b("Block-IO bei Hintergrund und Archiv")# 
#goalpage("bhgarch")# 
 
#ib#Hintergrund#ie# (Kanal 0) und #ib#Archiv#ie# (Kanal 31) unterscheiden sich in den Link-Bedingungen nur
in der Kanalnummer. Die Aufrufe von BLOCKIN und BLOCKOUT werden mit folgenden
Eingangsparametern versorgt: 
 
          #on("b")#BLOCKIN#off("b")#          A     0 bzw. 31 
                           B     0 
                           C     Blocknummer DIV 65536 
                           DE    Blocknummer MOD 65536 
                           HL    Hauptspeicheradresse 
 
                           Der angegebene 512-Byte-Block ist in den Hauptspeicher
                           ab <HL> einzulesen. 
 
          #on("b")#BLOCKOUT#off("b")#         A     0 bzw. 31 
                           B     0 
                           C     Blocknummer DIV 65536 
                           DE    Blocknummer MOD 65536 
                           HL    Hauptspeicheradresse 
 
                           Der Hauptspeicherbereich (<HL>...<HL>+511) ist auf den
                           angegebenen Block zu schreiben. 
 
Als Rückmeldungen sind zu liefern:#goalpage("errcod")# 
 
          0                Operation korrekt ausgeführt. 
          1                Manuell behebbarer Fehler (z.B. Laufwerktür offen) 
          2                Permanenter Fehler (z.B. Daten nicht lesbar) 
          3                Versorgungsfehler (zu hohe Blocknummer) 
 
Zusätzlich zu der Rückmeldung muß bei BC <> 0 in HL die Adresse eines Fehlerstrings
(Längenbyte + Fehlertext) geliefert werden. *) 
#foot# 
#f#*) Diese Zusatzrückmeldung ist nur für die BLOCKIN/OUT Aufrufe auf Kanal 0/31 von Bedeutung. Sie wird nur von
EUMEL-0 beim Paging und im Hardwaretest ausgewertet.#a# 
#end# 
 
#dx("Fehlerwiederholungen")#:      Das EUMEL-System führt von sich aus Fehlerwiederho­
                                   lungen beim Hintergrund- und beim Archivzugriff
                                   durch. SHard sollte deshalb im Fehlerfall die Opera­
                                   tion nicht selbst wiederholen, sondern einen Lese/
                                   Schreibfehler zurückmelden. So werden dem
                                   EUMEL-System auch Soft-Errors gemeldet. In
                                   manchen Fällen soll vor einem erneuten Lese- oder
                                   Schreibversuch der Arm auf Spur 0 positioniert
                                   werden o.ä. Um das zu erreichen, sollte SHard diese
                                   "Reparaturaktion" direkt im Anschluß an den fehler­
                                   haften Versuch durchführen. 
 
#dx("Kontrollesen")#:              Falls Kontrollesen (nach jedem Schreibzugriff) notwendig ist,
                                   muß das allerdings vom SHard durchgeführt werden.
                                   In der Regel reicht es dazu, den geschriebenen
                                   Block "ohne Datentransport" zu lesen, so daß nur
                                   CRC überprüft wird. 
 
Will SHard weitere Archivlaufwerke zur Verfügung stellen, so kann er dafür Kanalnummern
(30,29..) vergeben. Auf ELAN-Ebene kann die archivierende Task durch 'continue (x)' das
Laufwerk 'x' ansteuern. 
 
Hinweis:  Das System versucht Hintergrund und Archiv parallel zu betreiben, d.h. wenn
          SHard bei der Hintergrundbehandlung das UP 'warte' aufruft, kann 'warte' seiner­
          seits die Archivbehandlung des SHards aufrufen. Wenn beides z.B. denselben
          Floppykontroller benutzt, muß SHard sicherstellen, daß das gut geht (z.B. durch
          Semaphoren). 
 
 
 
 
#bb("5.3 ","IO-Steuerung")# 
#goalpage("iocontrol")# 
 
Die IO-Steuerung erlaubt Steuerung und Zustandsabfragen der Kanäle. IO-Steuerung wird
(außer bei Kanal 0) auch durch 'control' in ELAN induziert. 
 
Der Funktionscode in BC unterliegt denselben Konventionen wie bei Block-IO, d.h. das
System verwendet nur positive Codes. Der SHard-Schreiber kann auch negative Codes für
Sonderzwecke vorsehen. 
 
 
     #d("IOCONTROL")#
 
          Eingang:         A     Kanalnummer (0...32) 
                           BC    Funktionscode 1 
                           DE    Funktionscode 2 
                           HL    Funktionscode 3 
          Ausgang:         BC    Rückmeldung 
                           A     darf verändert werden, in einigen Fällen zusätzliche
                                 Rückmeldung 
                           C-Flag (in einigen Fällen zusätzliche Meldung) 
 
          Zweck:           abhängig von 'Funktionscode 1' (s.u.) 
 
Das System verlangt folgende Informations- und Steuerleistungen über IOCONTROL: 
 
     #d("IOCONTROL ""typ""")#
 
          Eingang:         A     Kanalnummer (0...31) 
                           BC    1 
          Ausgang:         BC    Kanaltyp 
 
          Zweck:           Informiert EUMEL-0, welche IO für den angegebenen Kanal
                           sinnvoll ist. Die Rückmeldung in BC wird bitweise interpre­
                           tiert: 
 
                           Bit 0 gesetzt  <=>      'inputinterrupt' kann kommen. 
                           Bit 1 gesetzt  <=>      OUTPUT ist sinnvoll. 
                           Bit 2 gesetzt  <=>      BLOCKIN ist sinnvoll. 
                           Bit 3 gesetzt  <=>      BLOCKOUT ist sinnvol. 
                           Bit 4 gesetzt  <=>      IOCONTROL "format" ist sinn­
                                                   voll. 
 
          Hinweis:         #on("i")#Trotz dieser Informationsmöglichkeit wird nicht garantiert, daß
                           nur sinnvolle Operationen für den Kanal aufgerufen werden.#off("i")# 
 
 
     #dx("IOCONTROL ""frout""")##goalpage("frout")# 
 
          Eingang:         A     Kanalnummer (1...15) 
                           BC    2 
          Ausgang:         BC    Anzahl Zeichen, die nächster OUTPUT übernimmt 
                           C-Flag gesetzt <=> Puffer leer 
 
          Zweck:           Liefert Information über die Belegung des Puffers. Diese
                           Information wird von EUMEL-0 zum Scheduling benutzt. 
 
          Achtung:         #on("i")#Wenn EUMEL-0 längere Zeit kein OUTPUT gemacht hat,
                           muß irgendwann BC > 49 gemeldet werden.#off("i")# 
 
          Hinweis:         Unter Berücksichtigung des oben Gesagten darf "gelogen"
                           werden. Man kann z.B. immer 50 in BC zurückmelden, muß
                           dann aber schlechtere Nutzung der CPU bei Multi-User-
                           Systemen in Kauf nehmen. 
 
                           Falls auf dem angegebenen Kanal ein Drucker mit eigenem
                           Puffer über Parallelschnittstelle angeschlossen ist (siehe
                           S.#topage("druck")#) und man auf einen SHard-internen Puffer verzichtet hat,
                           sollte bei 'Druckerpuffer voll' 0 in BC und 'NC' zurückge­
                           meldet werden. Wenn aber Zeichen übernommen werden
                           können, sollte 50 in BC und 'C-Flag gesetzt' gemeldet
                           werden. 
 
          Vorschlag:       Falls der Kanal nicht existiert oder nicht für Stream-IO zur
                           Verfügung steht, sollten 200 in BC und C-Flag gesetzt
                           zurückgemeldet werden. 
 
 
 
 
     #dx("IOCONTROL ""weiter""")##goalpage("weiter")# 
 
          Eingang:         A     Kanalnummer (1...15) 
                           BC    4 
          Ausgang:         - 
 
          Zweck:           Das System ruft "weiter" für den in A angegebenen Kanal
                           auf, wenn es wieder Eingabezeichen puffern kann. 
 
          Hinweis:         "weiter" wird von EUMEL-0 auch immer dann aufgerufen,
                           wenn ein Prozeß auf dem angegebenen Kanal auf Eingabe
                           wartet und keine Zeichen mehr gepuffert sind. Wenn der
                           betroffene Kanal von sich aus keine Interrupts erzeugt, kann
                           SHard dies benutzen, um durch Aufruf von 'inputinterrupt' ein
                           Eingabezeichen zuzustellen. 
                           #on("i")#Diese Betriebsart sollte nicht für normale Terminalkanäle
                           eingesetzt werden. Denn dann wird die SV-Taste nur an
                           EUMEL-0 zugestellt, wenn ein Prozeß auf diesem Kanal auf
                           Eingabe wartet. Somit sind in dieser Betriebsart CPU-inten­
                           sive Endlosschleifen nicht normal abbrechbar!#off("i")# 
 
 
     #d("IOCONTROL ""size""")#
 
          Eingang:         AL    Kanalnummer (0...31) 
                           CX    5 
                           DX    Schlüssel 
          Ausgang:         CX    Anzahl Blöcke MOD 65536 
                           AL    Anzahl Blöcke DIV 65536 
 
          Zweck:           EUMEL-0 ruft 'size' auf, um die Anzahl Blöcke zu erfahren,
                           die ein Block-IO-Kanal verkraften kann (Größe von Hin­
                           tergrund und Archiven). Bei Archivlaufwerken, die mehrere
                           Formate bearbeiten können, dient dieser Aufruf auch zum
                           Einstellen des Formats für die folgenden blockin/blockout-
                           Operationen anhand des Schlüssels. 
 
          Schlüssel:       0     Wenn möglich 'erkennend', sonst 'standard'. Im ersten
                                 Fall erkennt SHard das Format der eingelegten Disket­
                                 te und stellt dieses ein. 
 
                           Die weiteren Schlüssel sind stets definierend. Dabei gibt es
                           die EUMEL-Standardformate: 
 
                                 1     5" 2D-40, Sektor 1..9, 512 Bytes 
                                 2     5" 2D-80, Sektor 1..9, 512 Bytes 
                                 3     5" HD-80, Sektor 1..15, 512 Bytes 
                                 10    8" 1D-77, Sektor 0..15, 512 Bytes 
                                 11    8" 2D-77, Sektor 0..15, 512 Bytes 
 
                           Zusätzlich kann man sämtliche Spezialformate angeben: 
 
                             8192 * laufwerkstyp     1:  8" 
                                                     2:  5" 
                                                     3:  3" 
 
                           + 4096 * seiten           0:  einseitig 
                                                     1:  doppelseitig 
 
                           + 1024 * dichte           0:  single 
                                                     1:  double 
                                                     2:  high 
 
                           +  256 * spuren           0:  35 
                                                     1:  40 
                                                     2:  77 
                                                     3:  80 
 
                           +   64 * sektorbytes      0:  128 
                                                     1:  256 
                                                     2:  512 
 
                           +   32 * erster sektor    0:  \#0 
                                                     1:  \#1 
 
                           +        sektoren pro spur   0 ... 31 
 
                           So bezeichnet '8762' das Format 8" 1S-77 Sektor 1..26 a
                           128 Bytes. 
 
          Anmerkung:       SHard sollte alle physisch möglichen EUMEL-Standard­
                           formate unterstützen. Von den Spezialformaten sollten die für
                           den Datenaustausch wichtigen Formate berücksichtigt werden.
                           Die EUMEL-Standardformate (1,2,3,10,11) sollten auch über
                           die entsprechenden analytischen Codes erreicht werden. (Z.B.
                           bezeichnen 1 und 21929 dasselbe Format.) Die Numerierung
                           der Blöcke ist in jedem Fall seitenorientiert, d.h. entsprechend
                           den Standardformaten (siehe S.#topage("arch")#). 
 
          Hinweis:         Bei Archiven wird 'size' aufgerufen, nachdem der Archivträ­
                           ger eingelegt wurde. D.h. SHard hat die Gelegenheit, die
                           Größe anhand des eingelegten Archivträgers zu bestimmen
                           (z.B. ob single- oder doublesided). 
 
          Vorschlag:       Diese Funktion sollte auf nicht vorhandenen und den
                           Stream-IO-Kanälen 0 liefern. Sie muß aber mindestens auf
                           Kanal 0 (Hintergrund) und Kanal 31 (Archiv) "echte" Werte
                           liefern. 
 
          Achtung:         #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die
                           0-Routine 'warte' aufgerufen werden.#off("i")# 
 
 
     #d("IOCONTROL ""format""")#
 
          Eingang:         A     Kanalnummer (0...31) 
                           BC    7 
          Ausgang:         BC    Fehlercode wie bei Archiv-BLOCKOUT (siehe S.#topage("errcod")#) 
 
          Zweck:           Dient zum Formatieren eines Mediums. Diese Funktion kann
                           für jeden Kanal leer implementiert sein ('ret'). Sie sollte aber
                           "formatierend" (z.B. auf Kanal 31) arbeiten, falls auf diesem
                           Kanal die "typ"-Abfrage "Formatieren sinnvoll" liefert. Falls
                           (bei Diskettenlaufwerken) mehrere Formate möglich sind,
                           bestimmt der Schlüssel das gewünschte Format. 
 
          Schlüssel:       wie bei IOCONTROL "size" 
 
          Hinweis:         Falls für das Formatieren ein großer Speicherbereich benö­
                           tigt wird, sollte das Formatieren von Disketten besser in
                           einem Boot-Dialog vor dem Start von EUMEL-0 angebo­
                           ten werden. Denn sonst müßte der Pagingbereich unnötig
                           eingeschränkt werden. 
                           Man kann das Formatieren einer Spur CPU-intensiv im­
                           plementieren (d.h. ohne DMA im DI-Modus), wenn man in
                           Kauf nimmt, daß alle anderen Tasks des EUMEL-Systems in
                           dieser Zeit "stehen". Dann sollte man aber nach jeder Spur
                           mehrmals die 0-Routine 'warte' aufrufen. 
 
          Achtung:         #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die
                           0-Routine 'warte' aufgerufen werden.#off("i")# 
 
 
 
#b("Konfigurierung serieller Schnittstellen")# 
#goalpage("v24")# 
 
Bei Kanälen, die hardwaremäßig auf #ib#serielle Schnittstellen#ie# (#ib#V.24#ie#) zurückgeführt werden, sind
in der Regel die Größen 
 
          -  #ib#Baudrate#ie# (..., 2400, 4800, 9600, ...) 
          -  #ib#Zeichenlänge#ie# (7 Bits, 8 Bits) 
          -  #ib#Parität#ie# (keine, gerade, ungerade) 
 
einstellbar. Dafür muß SHard die IOCONTROL-Funktionen "baud" und "bits" zur Verfü­
gung stellen. Diese werden in zwei Modi benutzt: 
 
     a)  #on("b")#einstellend#off("b")# 
         Läuft der aufrufende EUMEL-Prozeß auf dem privilegierten Steuerkanal (A = 32),
         wird der als Parameter mit übergebene #on("i")#adressierte Kanal#off("i")# auf die geforderten Werte
         eingestellt, sofern das möglich ist. 
 
     b)  #on("b")#abfragend#off("b")# 
         Läuft der aufrufende EUMEL-Prozeß nicht auf Kanal 32 (A <> 32), wird lediglich
         abgefragt, ob der #on("i")#adressierte Kanal#off("i")# auf die übergebenen Werte eingestellt werden
         könnte. 
 
Aufgrund des zweiten Modus können die höheren EUMEL-Ebenen dem Anwender bei der
Konfigurierung mitteilen, welche Werte sich auf dem jeweiligen Kanal einstellen lassen. Das
nutzt z.B. das Standard-Konfigurationsprogramm aus. 
 
Hinweis:   Bei einigen Kanälen (z.B. bei einem integrierten Terminal oder einer Parallel­
           schnittstelle) sind Baudrateneinstellungen sinnlos. Bei anderen können sie nur
           hardwaremäßig vorgenommen werden (Jumper, Dip Switches). In allen diesen
           Fällen muß SHard bei allen Einstellungen 'unmöglich' melden. (Standardmäßig
           wird der Anwender bei der Einstellung seiner Konfiguration dann auch nicht
           danach gefragt.) 
 
 
     #d("IOCONTROL ""baud""")#
 
          Eingang:         A     eigener Kanal (1...15 / 32) 
                           BC    8 
                           DE    adressierter Kanal 
                           HL    Schlüssel 
          Ausgang:         BC    Rückmeldung (0 = ok, 1 = nicht möglich) 
 
          Zweck:           Wird diese Routine auf dem Steuerkanal (A=32) aufgerufen,
                           wird die angegebene Baudrate für den durch Register DE
                           adressierten Kanal eingestellt, falls das möglich ist. 
                           Wird diese Routine auf einem anderen Kanal als 32 aufge­
                           rufen, informiert sie den Aufrufer lediglich, ob eine derartige
                           Einstellung des adressierten Kanals möglich wäre. 
 
          Schlüssel:             1       50 Baud 
                                 2       75 Baud 
                                 3      110 Baud 
                                 4      134.5 Baud 
                                 5      150 Baud 
                                 6      300 Baud 
                                 7      600 Baud 
                                 8     1200 Baud 
                                 9     1800 Baud 
                                10     2400 Baud 
                                11     3600 Baud 
                                12     4800 Baud 
                                13     7200 Baud 
                                14     9600 Baud 
                                15    19200 Baud 
                                16    38400 Baud 
 
          Anmerkung:       In der Regel werden nicht alle Baudraten vom SHard un­
                           terstützt werden. Bei V.24 Schnittstellen sollten aber min­
                           destens 2400, 4800 und 9600 Baud zur Verfügung stehen,
                           besser auch 300, 600, 1200 und 19200 Baud. 
 
          Hinweis:         Falls SHard-spezifisch weitere Baudraten implementiert
                           werden sollen, darf SHard hierfür negative Schlüsselwerte
                           (Register HL) vergeben. 
 
 
     #d("IOCONTROL ""bits""")#
 
          Eingang:         A     eigener Kanal (1...15 / 32) 
                           BC    9 
                           DE    adressierter Kanal 
                           HL    Schlüssel 
          Ausgang:         BC    Rückmeldung (0 = ok, 1 = nicht möglich) 
 
          Zweck:           Wird diese Routine auf dem Steuerkanal (A=32) aufgerufen,
                           wird die angegebene Zeichenlänge (Bits pro Zeichen) und
                           Parität für den durch Register DE adressierten Kanal einge­
                           stellt, falls das möglich ist. 
                           Wird diese Routine auf einem anderen Kanal als 32 aufge­
                           rufen, informiert sie den Aufrufer lediglich, ob eine derartige
                           Einstellung des adressierten Kanals möglich wäre. 
 
 
          Schlüssel:       stop * 32 + par * 8 + (bit - 1) 
 
                           stop:     0    1 Stopbit 
                                     1    1.5 Stopbits 
                                     2    2 Stopbits 
 
                           par:      0    keine Parität 
                                     1    ungerade Parität 
                                     2    gerade Parität 
 
                           bit:      1...8 Bits pro Zeichen 
 
 
          Anmerkung:       In der Regel werden nicht alle Kombinationen vom SHard
                           unterstützt werden. Bei V.24 Schnittstellen sollten aber
                           möglichst 1 Stopbit, 7 und 8 Bits pro Zeichen und alle drei
                           Paritätseinstellungen zur Verfügung stehen. 
 
          Hinweis:         Falls SHard-spezifisch weitere Einstellungen implementiert
                           werden sollen, darf SHard hierfür negative Schlüsselwerte
                           (Register HL) vergeben. 
 
 
 
 
#b("Flußkontrolle")# 
#goalpage("fluss")# 
 
Die stromorientierten Kanäle (1...15) werden nicht nur zum Anschluß schneller Geräte (wie
Terminals) verwendet, sondern auch, um langsame Geräte (wie Drucker) anzuschließen, die
die Daten u.U. nicht so schnell übernehmen können, wie sie der Rechner schickt. Dabei ist
auf eine geeignete Flußkontrolle zu achten (nicht schneller senden, als der Andere emp­
fangen kann). Dieses Problem stellt sich auch bei einer Rechner-Rechner-Kopplung. Hier
ist in der Regel sogar zweiseitige Flußkontrolle notwendig. 
 
Als Flußkontrolle ist die #ib#REQUEST TO SEND/CLEAR TO SEND#ie# Logik der V.24-Schnitt­
stelle oder das #ib#XON/XOFF#ie#-Protokoll zu verwenden. Das letztere kann auch bei Parallel­
schnittstellen eingesetzt werden. 
 
Zur eingabeseitigen Flußkontrollsteuerung kann SHard die Rückmeldung der 0-Routine
'inputinterrupt' (siehe S.#topage("inp")#) und die IOCONTROL-Funktion "weiter" (siehe S.#topage("weiter")#) verwen­
den: 
 
Unterschreitet die Rückmeldung einen von SHard zu bestimmenden Schwellwert, muß SHard
auf der V.24-Schnittstelle das Signal 'REQUEST TO SEND' wegnehmen bzw. XOFF senden.
Dadurch wird bei den meisten Fremdrechnern ein weiteres Senden unterbrochen, sofern (im
ersten Fall) das Signal 'REQUEST TO SEND' dort mit dem V.24-Eingang 'CLEAR TO
SEND' verbunden ist. Wird von EUMEL-0 "weiter" aufgerufen, so kann auf dem enspre­
chenden Kanal wieder empfangen werden (RTS setzen bzw. XON senden). 
 
Für die ausgabeseitige Flußkontrolle muß rechnerseitig ebenfalls das Signal 'CLEAR TO
SEND' bzw. der Empfang von XOFF/XON berücksichtigt werden. Wenn an der Schnittstelle
das 'CLEAR TO SEND' weggenommen wird, darf SHard keinen weiteren Output auf dieser
Schnittstelle machen, bis 'CLEAR TO SEND' wieder anliegt. Entsprechend muß der Empfang
von XOFF die Ausagbe anhalten und XON sie wieder starten. 
 
Bemerkung:   Die meisten Systeme enthalten die CTS-Funktion schon in ihrer Hardware,
             so daß im SHard dafür keine Vorkehrungen getroffen werden müssen. 
 
 
Zur Einstellung der gewünschten Flußkontrolle eines Kanals dient die IOCONTROL-Funk­
tion "flow". Ähnlich wie "baud" und "bits" wirkt auch "flow" nur auf Kanal 32 #on("i")#einstellend#off("i")#
und auf allen anderen Kanälen lediglich #on("i")#abfragend#off("i")#. 
 
 
     #d("IOCONTROL ""flow""")#
 
          Eingang:         A     eigener Kanal (1...15 / 32) 
                           BC    6 
                           DE    adressierter Kanal 
                           HL    Modus 
          Ausgang:         BC    Rückmeldung (0 = ok, 1 = nicht möglich) 
 
          Zweck:           Wird diese Routine auf dem Steuerkanal (A=32) aufgeru­
                           fen, muß sie den gewünschten Flußkontrollmodus für den
                           adressierten Kanal einstellen. 
                           Dabei sind folgende Modi festgelegt: 
 
                                 HL= 0     Keine Flußkontrolle 
                                 HL= 1     XON/XOFF    (in beide Richtungen) 
                                 HL= 2     RTS/CTS     (in beide Richtungen) 
                                 HL= 5     XON/XOFF    (nur ausgabeseitig) 
                                 HL= 6     RTS/CTS     (nur ausgabeseitig) 
                                 HL= 9     XON/XOFF    (nur eingabesetig) 
                                 HL=10     RTS/CTS     (nur eingabeseitig) 
 
                           Wenn keine Flußkontrolle gewünscht wird (HL=0), muß SHard
                           "weiter" ignorieren; bei HL=1 oder HL=9 muß bei "stop"
                           XOFF und bei "weiter", sofern zuletzt XOFF geschickt wurde,
                           XON geschickt werden; bei HL=2 oder HL=10 muß bei
                           "stop" das Signal RTS auf low und bei "weiter" wieder auf
                           high gesetzt werden. Mit "stop" ist hierbei das Unterschreiten
                           des Schwellwertes bei der Rückmeldung von "inputinterrupt"
                           gemeint. 
                           Bei HL=1 oder HL=5 müssen empfangene XON/XOFF-Zei­
                           chen, bei HL=2 oder HL=6 das Signal CTS beachtet wer­
                           den. 
 
                           Wird diese Routine auf einem anderen Kanal als 32 aufge­
                           rufen, informiert sie den Aufrufer lediglich, ob der geforderte
                           Flußkontrollmodus auf dem adressierten Kanal einstellbar
                           wäre. 
 
          Hinweis:         Falls SHard-spezifisch weitere Flußkontrollmodi implemen­
                           tiert werden sollen, darf SHard hierfür negative Moduswerte
                           (Register HL) vergeben. 
 
                           "weiter" wird von EUMEL-0 sehr oft aufgerufen. Es ist daher
                           nicht sinnvoll, jedesmal XON zu senden, da dies die Gegen­
                           stelle damit überfluten würde. SHard muß sich merken, ob der
                           Kanal im XOFF-Zustand ist und nur dann bei "weiter" ein
                           XON senden. 
 
#b("Kalender")# 
#goalpage("kalender")# 
 
Die Datums- und Uhrzeitabfrage ist bei Rechnern mit eingebauter Uhr unnötig. EUMEL holt
sich Datum und Uhrzeit dann von SHard. 
 
     #d("IOCONTROL ""calendar""")#
 
          Eingang:         CX    10 
                           DX    (1=Minute, 2=Stunde, 3=Tag, 4=Monat, 5=Jahr)
                                 gewünscht 
          Ausgang:         CX    Rückmeldung 
 
          Zweck:           Erfragen von Datum und Uhrzeit. Falls keine Uhr vorhanden
                           ist, muß bei jedem Aufruf -1 zurückgemeldet werden, bei
                           eingebauter Uhr jeweils das Gewünschte (Minute: 0..59,
                           Stunde: 0..23, Tag: 1..7, Monat: 1..12, Jahr: 0..99). Die Rück­
                           meldung muß als BCD-Zahl erfolgen. 
 
          Hinweis:         Die Uhr darf zwischen zwei Aufrufen umspringen. Die daraus
                           resultierende Probleme werden auf höheren Ebenen abgehan­
                           delt. 
 
 
 
 
#bb("6.  SHard-","Interface Version")# 
#goalpage("shdver")# 
 
Die #ib#Versionsnummer#ie# der Interface-Spezifikation, auf der SHard aufbaut, muß als 1-Byte-
Konstante #ib#SHDVER#ie# in der SHard-Leiste stehen. Für das hier beschriebene Interface muß sie
den Wert 8 haben. 
 
So sind spätere Erweiterungen des SHard-Interfaces möglich, ohne daß alle SHard-
Moduln geändert werden müssen. 
 
 
 
#bb("7.  ","ID-Konstanten")# 
#goalpage("ID")# 
 
SHard muß direkt hinter SHDVER vier 2-Byte-Konstanten ablegen. Diese können von den
höheren Ebenen durch die ELAN-Prozedur 
 
          INT PROC #ib#id#ie# (INT CONST no) 
 
abgefragt werden. Dabei werden id(0) bis id(3) von EUMEL-0 geliefert, während SHard in der
Leiste die Werte für id(4) bis id(7) zur Verfügung stellen muß: 
 
          ID4              #ib#Lizenznummer#ie# des SHards *) 
#foot# 
#f#*) Dieser Wert muß mit der Nummer des Lizenzvertrags zwischen Implementierer und GMD übereinstimmen!#a# 
#end# 
 
          ID5              #ib#Installationsnummer#ie# des EUMEL-Anwenders **) 
#foot# 
#f#**) Diese Nummer vergibt der Lizenznehmer an die von ihm belieferten Anwender.#a# 
#end# 
 
          ID6              zur freien Verfügung 
 
          ID7              zur freien Verfügung 
 
 
 
 
#bb("8.  ","Zusätzliche Leistungen")# 
#goalpage("shdelan")# 
 
Will der SHard-Implementierer zusätzliche Leistungen anbieten, die mit den Standardopera­
tionen nicht möglich sind, kann er weitere Codes für BLOCKIN, BLOCKOUT und
IOCONTROL zur Verfügung stellen. Um Überdeckungen mit Codes zu vermeiden, die von
EUMEL-0 intern verwendet oder erst später eingeführt werden, darf SHard für zusätzliche
Leistungen nur negative Werte als 'Funktionscode 1' verwenden. 
 
 
Zum Ansprechen der neuen Leistungen stehen die ELAN-Prozeduren #on("i")#'#ib#blockout#ie#', '#ib#blockin#ie#'#off("i")#
und #on("i")#'#ib#control#ie#'#off("i")# zur Verfügung. 
 
Ferner steht dem SHard ein Parameterkanal (32) zur Verfügung. Funktionen, die (im Multi-
User) nicht jeder Task zur Verfügung stehen dürfen, müssen über diesen Kanal 32 abge­
wickelt werden und dürfen nur dort wirken. 
 
 
     PROC blockout (ROW 256 INT CONST para,      (* --> HL *) 
                    INT CONST funktion1,         (* --> BC *) 
                              funktion2,         (* --> DE *) 
                    INT VAR antwort)             (* <-- BC *) 
 
     PROC blockin (ROW 256 INT VAR para,         (* --> HL *) 
                   INT CONST funktion1,          (* --> BC *) 
                             funktion2,          (* --> DE *) 
                   INT VAR antwort)              (* <-- BC *) 
 
     PROC control (INT CONST funktion1,          (* --> BC *) 
                             funktion2,          (* --> DE *) 
                             funktion3,          (* --> HL *) 
                   INT VAR   antwort)            (* <-- BC *) 
 
Hinweis: Der SHard darf für 'funktion 1' (BC) zusätzlich zu den hier beschriebenen Stan­
         dardcodes nur negative Codes vereinbaren. 
 
 
Beispiel: 
 
     Gibt eine Task, die durch 'continue (x)' an Kanal 'x' hängt, den Befehl 
 
                           control (-7,1200,13,antwort), 
 
     so wird IOCONTROL mit (A='x', BC=-7, HL=13, DE=1200) aufgerufen. Verläßt
     SHard 'control' mit BC = 1, so enthält 'antwort' anschließend eine 1. 
 
 
Hinweis:  Um die zusätzlichen Leistungen dem Anwender einfach (und abgesichert) zur
          Verfügung zu stellen, sollte man sie in ein ELAN-Paket einbetten und dieses
          ebenfalls an die Anwender ausliefern. 
 
          Beispiel:        PACKET zusatz DEFINES fanfare, ... : 
 
                           PROC fanfare (INT CONST tonhoehe, dauer) : 
 
                             IF dauer < 0 
                               THEN errorstop ("negative dauer") 
                             ELIF tonhoehe < 16 
                               THEN errorstop ("infraschall") 
                             ELIF tonhoehe > 20000 
                                THEN errorstop ("ultraschall") 
                             ELSE control (-37, 20000 DIV tonhoehe, dauer) 
                             FI 
 
                           ENDPROC fanfare ; 
 
                                 . . . 
 
 
 
 
#bb("9.  ","Spezialroutinen")# 
#goalpage("ke")# 
 
Als Testhilfe und zur Fehlerdiagnose kann SHard in seine Routinen Kontrollereignisse einbau­
en. Das geschieht durch Aufruf der 0-Routine 'info'. Dieser EUMEL-Debugger wird im
Anhang A (siehe S.#topage("info")#) beschreiben. 
 
     #dx("info")#                  (0-Routine) 
 
          Aufruf:            call info 
                             jr   weiter 
                             defm ' text' 
                           weiter: 
 
          Zweck:           Info wird aufgerufen. Dabei wird 'text' zur Identifikation des
                           Kontrollereignisses ausgegeben. #on("i")#Der übergebene Text muß
                           mit einem Blank beginnen!#off("i")# 
 
          Hinweis:         Bei Systemen "ohne Info" (nur solche dürfen an Anwender
                           ausgeliefert werden) wird nur der Info-Text ausgegeben und
                           EUMEL-0 angehalten. 
 
          Achtung:         Da der Info selbst die hier beschriebenen Stream-IO-Rou­
                           tinen benutzt, darf man ihn von diesen Routinen aus (input­
                           interrupt, OUTPUT, IOCONTROL "frout", IOCONTROL
                           "weiter") nicht aufrufen. Wenn die Ein-/Ausgabe auf Termi­
                           nal 1 interruptgetrieben läuft, dürfen die Interrupts beim
                           Info-Aufruf natürlich nicht gesperrt sein. 
 
 
Falls SHard für bestimmte Aktionen, die selten durchgeführt werden (z.B. Formatieren), viel
Speicher benötigt, kann er diesen dynamisch anfordern und später wieder freigeben. 
 
     #dx("grab")#                  (0-Routine) 
 
          Eingang:         HL    Anfangsadresse des zu reservierenden Bereichs im
                                 Datensegment von EUMEL-0, muß auf 512 Byte
                                 ausgerichtet sein. 
                           BC    Länge des zu reservierenden Bereichs in 512-Byte-
                                 Kacheln 
          Ausgang:         BC    Rückmeldecode 
 
          Zweck:           Wenn möglich wird der zu verlangte Bereich von EUMEL-0
                           "leergekämpft" und SHard zur Verfügung gestellt. 
                           Rückmeldecode:  0  ok, Speicher steht zur Verfügung 
                                           1  augenblicklich nicht möglich 
                                           3  grundsätzlich nicht möglich 
 
          Achtung:         Der Aufruf von 'grab' wird in der Regel 'warte' und Block-IO
                           auf Kanal 0 induzieren. 
 
          Hinweis:         Es wird empfohlen, Speicher ab A000h anzufordern, da diese
                           Adresse stets im frei einplanbaren Paging-Bereich liegt. 
 
 
     #dx("free")#                  (0-Routine) 
 
          Eingang:         HL    Anfangsadresse des freizugebenden Bereichs im
                                 Datensegment von EUMEL-0, muß auf 512 Byte
                                 ausgerichtet sein. 
                           BC    Länge des zu freizugebenden Bereichs in 512-Byte-
                                 Kacheln 
 
          Zweck:           Der entsprechende Bereich muß vorher mit 'grab' beschafft
                           worden sein. Hiermit wird er wieder EUMEL-0 zur freien
                           Verfügung gestellt. 
 
 
Für spezielle Fehlersituationen steht die 0-Routine 'shutup' zur Verfügung. Damit kann
SHard z.B. bei Netzausfall ein kontrolliertes Systemende erzwingen. Das ist allerdings nur
sinnvoll, wenn durch Batteriepufferung oder Ähnliches sichergestellt ist, daß noch genügend
Zeit bleibt, um alle Seiten auf den Hintergrund zurückzuschreiben. 
 
     #dx("shutup")#                (0-Routine) 
 
          Zweck:           Erzwingt Rückschreiben aller Seiten und Systemende, d.h.
                           entspricht der ELAN-Prozedur 'shutup'. 
 
          Achtung:         Der Aufruf von 'shutup' wird in der Regel 'warte' und Block-
                           IO auf Kanal 0 induzieren. 
#page# 
#cc("Teil 4: ","Tips zur Portierung")# 
#goalpage("tips")# 
 
 
#b("0-Version des SHards")# 
#goalpage("0ver")# 
 
 
Es wird empfohlen, zuerst eine "0-Version" des SHard zu entwickeln, die möglichst einfach
aufgebaut und nicht auf Effizienz und vollständige Ausnutzung der Betriebsmittel ausge­
richtet sein sollte. Damit kann man rasch praktische Erfahrung gewinnen, die dann den
Entwurf und die Implementation des eigentlichen SHard erleichtert. Die 0-Version sollte 
 
     -  keinen Schattenspeicher kennen (SCHINF meldet 0), 
 
     -  nur die Kanäle 0 (Hintergrund), 1 (Terminal) und 31 (Archiv) behandeln, 
 
     -  keine Baudraten-, Zeichenlängen-, Paritäts- und Flußkontrolleinstellungen unter­
        stützen (immer 'nicht möglich' melden), 
 
     -  vorhandene (ROM-) Routinen möglichst nutzen, ohne sich um Unschönes wie
        "busy wait" beim Floppy- bzw. Plattenzugriff zu grämen. 
 
Mit dieser 0-Version sollte man dann versuchen, EUMEL zu starten. Da der Hintergrund
beim ersten Mal noch leer ist, muß man das HG-Archiv (Archivfloppy mit EUMEL-0 und
höheren Ebenen) in das Archivlaufwerk einlegen und von dort laden. Der Vortest sollte sich
direkt nach dem Start folgendermaßen auf Terminal 1 melden: 
 
                E U M E L - Vortest 
 
          Terminals:  1, 
          RAM-Groesse (gesamt):     64 kB 
          Pufferbereich:             ? kB 
          Hintergrund-Speicher:      ? kB 
 
          Speichertest: ************ 
 
Man sollte während der ****-Ausgabe des Speichertests irgendein Zeichen eingeben. Das
EUMEL-System muß dann in das ausführliche Start-Menü überwechseln. (Andernfalls
funktioniert die Eingabe nicht richtig!) 
 
Als nächstes sollte man versuchen, den Hintergrund vom Archiv aus zu laden. (Diese Mög­
lichkeit wird im Start-Menü angeboten.) Nach dem Ende dieser Operation wird der
EUMEL-Lauf automatisch beendet. Jetzt kann man das HG-Archiv aus dem Archivlauf­
werk entfernen und das System neu starten. Dann sollte EUMEL-0 vom Hintergrund geladen
werden. 
 
Bei Problemen kann der "Info" (siehe S.#topage("info")#) hilfreich sein. Voraussetzung für seine Ver­
wendung ist aber, daß die Terminal Ein-/Ausgabe schon funktioniert. 
 
Beim Start des EUMEL-Systems kann (wie im Systemhandbuch beschrieben) durch den
Konfigurationsdialog der Terminaltyp von Kanal 1 eingestellt werden. Falls das verwendete
Terminal in dieser Liste nicht aufgeführt wird und auch keinem der aufgeführten (in Bezug auf
die Steuercodes) gleicht, kann man z.B. 
 
     -  den neuen Terminaltyp an einem anderen EUMEL-Rechner verfügbar machen
        (Umsetztabellen definieren) und per Archiv zum neuen Rechner tragen, 
 
     -  die notwendigen Umcodierungen per SHard durchführen. 
 
Diese Problematik entsteht bei Rechnern mit integriertem Terminal in der Regel nicht, weil
Steuerzeichen dort sowieso algorithmisch interpretiert werden müssen. In diesem Fall wird
man direkt die EUMEL-Codes als Grundlage wählen, so daß keine Umsetzungen erfor­
derlich sind. 
 
Bei einer provisorischen Anpassung kann man auf Invers-Video ohne weiteres verzichten. 
 
 
Im Gegensatz zu der 0-Version sollte man bei der eigentlichen SHard-Implementierung
darauf achten, die Möglichkeiten der Hardware effizient zu nutzen. Der Testverlauf entspricht
dann wieder im wesentlichen dem oben beschriebenen Vorgang. 
 
 
 
#b("Typische Fehler")# 
#goalpage("fehler")# 
 
 
     a)   SHard-Routinen zerstören Registerinhalte bzw. sichern sie beim Interrupt nicht
          vollständig. Hierbei sollte man auch an den zweiten Registersatz des Z80-Pro­
          zessors und an die Register IX und IY denken. 
 
     b)   'call' bzw. 'ret' verändern den Stackpointer. 
 
     c)   Fehler bei der Interruptbehandlung führen zu Blockaden ("hängende Interrupts"). 
 
     d)   Cursorpositionierung außerhalb des Bildschirms bei einem internen Terminal
          (Bildwiederholspeicher im Rechner) wird nicht abgefangen. Das führt dann zu
          wildem Schreiben in den Hauptspeicher. 
 
     e)   'warte' wird unerlaubt aufgerufen. ('warte' darf nur von BLOCKIN, BLOCKOUT,
          IOCONTROL "size" und IOCONTROL "format" aus aufgerufen werden. Ferner
          kann man 'warte' noch nicht beim Systemladen aufrufen!) 
 
     f)   OUTPUT-Verhaspler oder -Blockaden entstehen durch Fehlsynchronisation
          zwischen dem Füllen des Ausgabepuffers durch die Routine OUTPUT und der
          Interruptroutine, die den Puffer leert und ausgibt. 
 
     g)   IOCONTROL "frout" meldet in gewissen Situationen nie "mindestens 50 Zei­
          chen im Puffer frei" und "Puffer leer". Das kann schon im Vortest zu Output- 
          Blockaden führen. 
 
     h)   Obwohl "frout" einen Wert größer als x meldet, nimmt "output" nicht alle x
          Zeichen an. 
 
     i)   IOCONTROL "size" meldet falsche Werte. 
 
     j)   IOCONTROL verkraftet keine beliebigen (auch unsinnige) Werte. 
 
     k)   BLOCKIN bzw. BLOCKOUT geben die Kontrolle an das System zurück, bevor alle
          Daten übertragen sind. (Sofort nach der Rückgabe geht EUMEL-0 davon aus,
          daß der Puffer frei ist und anderweitig benutzt werden kann!) 
 
     l)   Einem SIO-Baustein wird nach Ausgabe des letzten Zeichens oder nach Ände­
          rung des externen Status nicht mitgeteilt, daß keine Interrupts mehr erzeugt
          werden sollen. (SIOs wiederholen Interrupts so lange, bis man es ihnen explizit
          verbietet!) 
 
     m)   Die Stepping-Rate eines Festplattencontrollers wird falsch eingestellt, bezie­
          hungsweise die Platte wird nicht im 'buffered step mode' betrieben, obwohl sie
          beschleunigend positionieren kann. Dadurch werden die Zugriffszeiten auf dem
          Hintergrund unnötig verlangsamt. Man bedenke, daß man so einen Fehler leicht
          übersieht, weil sich das System nicht fehlerhaft, sondern nur langsamer verhält.
          Außerdem macht sich die Verlangsamung erst bemerkbar, wenn größere Teile des
          Hintergrundes benutzt werden. 
 
     n)   Bei schnellem Zeichenempfang treten "Dreher" auf. Das deutet meistens auf
          einen rekursiven Aufruf der 0-Routine 'inputinterrupt' hin. Dabei überholt dann
          das zweite Zeichen das erste. 
 
     o)   Bei schnellem Zeichenempfang, speziell bei gleichzeitiger Ausgabe, gehen Einga­
          bezeichen verloren oder werden verfälscht. In der Regel ist das auf Timingpro­
          bleme bei der Interruptbehandlung zurückzuführen. Interrupts gehen verloren bzw.
          die Zeichen werden nicht schnell genug abgeholt. 
 
 
#b("Effizienzprobleme")# 
#goalpage("eff")# 
 
     a)   Bei #on("i")##on("b")#V.24- und Parallelschnittstellen#off("i")##off("b")# ist schlechter Durchsatz in der Regel auf
          Fehlverhalten von "frout" zurückzuführen. Auch kostet es in Multi-User-Sy­
          stemen sehr viel, wenn OUTPUT immer nur ein Zeichen übernimmt. (Dann läuft
          der ganze Apparat der EUMEL-0-Maschine für jedes Zeichen wieder an.) 
 
          Besonders bei der Parallelschnittstelle achte man darauf, daß nicht durch un­
          glückliches Timing häufig Blockaden auftreten. So kann zu kurzes 'busy wait' auf
          Freiwerden der Parallelschnittstelle dazu führen, daß jedes zweite Zeichen
          abgelehnt wird, so daß OUTPUT faktisch zeichenweise arbeitet. Andererseits darf
          natürlich 'busy wait' auch nicht auf Millisekunden ausgedehnt werden. 
 
 
     b)   Wenn #on("i")##on("b")#Floppies ohne DMA#off("i")##off("b")# angeschlossen werden, kann man bei Single-
          User-Systemen ohne weiteres 'busy wait' einsetzen, um nach dem Seek-
          Vorgang auf den Block zu warten. Im Multi-User sollte das aber wenn irgend
          möglich umgangen werden, da eine halbe Umdrehung immerhin ca. 100 ms
          kostet. 
          Falls nur ein Endeinterrupt nach jeder Floppyoperation zur Verfügung steht, kann
          folgendes Verfahren günstig sein: 
 
               seek befehl an controller ; 
               warten auf endeinterrupt ; 
               lesebefehl ohne datentransport auf sektor davor ; 
               warten auf endeinterrupt ; 
               lese oder schreib befehl auf adressierten sektor ; 
               cpu intensives warten und datentransport . 
 
          Die Dummyoperation auf den Sektor vor dem adressierten dient dabei nur dazu,
          ohne CPU-Belastung einen Zeitpunkt zu finden, wo man dem eigentlichen Sektor
          möglichst nahe ist. Die Zeit, in der die CPU benötigt wird, sinkt damit auf ca. 25
          ms. Die Implementation dieses Algorithmus' ist aber nicht ganz einfach, da die
          0-Routine 'warte' wegen der verlangten kurzen Reaktionszeiten nicht verwendet
          werden kann. Alle 'warte auf ...' müssen also durch Interrupts realisiert werden: 
 
               setze interrupt auf lesen davor ; 
               stosse seek an ; 
               REP 
                 warte 
               UNTIL komplette operation beendet ENDREP . 
 
                           lesen davor : 
                                 setze interrupt auf eigentliche operation ; 
                                 stosse lesen davor an . 
 
                           eigentliche operation : 
                                 ignoriere fehler beim datentransport ; 
                                 stosse lesen oder schreiben an ; 
                                 REP 
                                   REP UNTIL bereit ENDREP ; 
                                   uebertrage ein byte 
                                 UNTIL alles uebertragen ENDREP ; 
                                 melde komplette operation beendet . 
 
 
     c)   Bei der Ansteuerung von #on("i")##on("b")#Harddisks#off("b")##off("i")# sollte man darauf achten, daß die 0-Rou­
          tine 'warte' nicht öfter als notwendig aufgerufen wird. Sonst wird das Paging zu­
          gunsten der CPU-intensiven Prozesse zu stark verlangsamt. Z.B. kann man bei
          vielen Plattencontrollern auf eine eigene Seek-Phase verzichten: 
 
               beginne seek ;             beginne seek und lesen ; 
               REP                        REP 
                 warte                      warte 
               UNTIL fertig PER ;         UNTIL fertig PER 
               beginne lesen ; 
               REP 
                 warte 
               UNTIL fertig PER 
 
          Hier braucht die linke Fassung immer mindestens ein 'warte' mehr als die rechte.
          Bei starker CPU Belastung wird sie deshalb bis zu 100 ms länger für das Einle­
          sen eines Blocks benötigen. 
 
          Eine ähnliche Situation kann auftreten, wenn die Platte in 256-Byte-Sektoren
          unterteilt ist, so daß zu jedem EUMEL-Block zwei Sektoren gehören. Wenn
          möglich sollte dann zwischen diesen beiden Sektoren kein 'warte' aufgerufen
          werden. Andererseits darf natürlich auch nicht längere Zeit CPU-intensiv gewar­
          tet werden. Evtl. lohnt es sich in solchem Fall, mit der Sektorverschränkung zu
          experimentieren. 
 
#page# 
#cc("Anhang A: EUMEL-","Debugger ""Info""")# 
#goalpage("info")# 
 
 
Für interne Testzwecke gibt es den "Info". Systeme "mit Info" und "ohne Info" unterschei­
den sich nur im EUMEL-0-Teil (Urlader). Der SHard-Implementierer erhält zum Test
Hintergründe "mit Info" und zur Auslieferung solche "ohne Info". Infofähige Systeme dürfen
nur von den SHard-Implementierern verwendet werden. 
 
     #on("i")##on("b")#Achtung: Infofähige Systeme dürfen auf keinen Fall an Anwender ausgeliefert wer­
              den, da vermittels Info alle Systemsicherungs- und Datenschutzmaßnah­
              men unterlaufen werden können.#off("i")##off("b")# *) 
#foot# 
#f#*) Ausnahmen von dieser Regel bedürfen der expliziten Zustimmung der EUMEL-Systemgruppe (GMD bzw. HRZ
Bielefeld) und des jeweiligen Anwenders. Solche System müssen immer durch spezielle Schlüsselworte abgesichert werden.#a# 
#end# 
 
 
#b("Aufruf des Info")# 
#goalpage("aufrinf")# 
 
Zum Aufruf des Infos gibt es drei Möglichkeiten: 
 
     a)  Beim Start des EUMEL-Systems geht man durch Eingabe eines beliebigen Zei­
         chens während des Vortests in den ausführlichen Start-Dialog. Durch Eingabe von
         'I' gelangt man dann in den Info-Modus. #on("i")#(Diese Möglichkeit wird in dem Start­
         menü nicht aufgeführt.)#off("i")# 
 
     b)  Man kann den Info durch die ELAN-Prozedur 'ke' aufrufen. D.h. wenn das System
         gestartet wurde und sich eine Task am Terminal mit "gib kommando" gemeldet
         hat, kann man durch 'ke *return*' in den Info-Modus gelangen. 
 
     c)  Wenn sich am Terminal keine Task befindet, die auf Eingabe wartet, gelangt man
         durch die Tastenfolge 'i *info*' (*info* meist = CTL d, zur Tastendefinition siehe
         "Systemhandbuch, Konfigurierung") in den Info-Modus. 
 
Alle diese Möglichkeiten funktionieren nur bei infofähigen Systemen. 
 
Bei schweren Systemfehlern, die eine Weitermeldung an die höheren Ebenen des EUMEL-
Systems unmöglich machen, wird soweit möglich ebenfalls der Info aufgerufen. Bei Systemen
"ohne Info" wird lediglich eine Meldung auf Kanal 1 ausgegeben und das System angehalten. 
 
Bevor das System Infokommandos annimmt, muß mit dem Kommando 'P' ein Paßwort einge­
geben werden. Lediglich dieses Kommando und das Kommando 'g' werden immer angenom­
men. Das Paßwort kann mit dem Kommando 'yP' oder mit der ELAN-Prozedur "info
password" eingestellt werden. 
 
#b("Info-Format")# 
#goalpage("forminf")# 
 
Der Info ist bildschirmorientiert. Beim Aufruf des Infos und nach den meisten Info-Kom­
mandos werden die drei obersten Zeilen wie folgt aufgebaut: *) 
#foot# 
#f#*) Bildschirmgetreues Verhalten kann der Info allerdings erst nach der Konfigurierung des Kanals zeigen. Vorher (d.h.
insbesondere beim Aufruf aus dem Vortest heraus) werden Cursorpositionierungen in der Regel nicht korrekt durchgeführt.#a# 
 
#end# 
 
#limit(14.0)# 
XY TEXT 
F   A   C   B   E   D   L   H   F   A   C   B   E   D   L   H   IX      SP      IY      PC 
xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx  xx 
#limit(12.0)# 
 
wobei 
 
     X den Miniprozeß bezeichnet, der den Übergang in den Info veranlaßt hat (A=Archiv,
     E=Elan, L=Lader, M=Müllabfuhr), 
 
     Y den Maxiprozeß (Task) bezeichnet, der gerade durch den Elan-Prozessor bear­
     beitet wird (Y ist code (tasknummer + code ("0"))), 
 
     TEXT den Grund für den Info-Modus anzeigt, 
 
Die zweite und dritte Zeile zeigen die Inhalte der Z80-Register an (beide Registersätze). 
In der untersten Zeile erscheint die Eingabeaufforderung 'info:'. 
 
 
#b("Info-Kommandos")# 
#goalpage("cmdinf")# 
 
Info-Kommandos können in der 'info:'-Zeile mit dem Format 
 
          [<zahl>]<buchstabe> 
 
gegeben werden oder, wenn der Cursor sich im Dump befindet, mit dem Format 
 
          <buchstabe> 
 
wobei dann für <zahl> die der Cursorposition entsprechende Dumpadresse (modulo 2**16)
gesetzt wird (siehe '*cup*'). 
 
<zahl> ist immer in Hexaform einzugeben. 
 
'g'    Der Info-Modus wird wieder verlassen. Dies ist allerdings bei harten Fehlern ge­
       sperrt. 
 
'z'    Der Leitblock des angezeigten Maxiprozesses wird dargestellt, falls <zahl> = 0 ist,
       sonst der Leitblock der Task mit der Nummer <zahl>. (Nur im ELAN-Miniprozeß). 
 
'q'    Die Task mit der Nummer <zahl> wird nach dem nächsten 'g'-Kommando in den
       Info überführt. Dies ist nötig, wenn man sich die Datenräume dieser Task anschauen
       will ('s'). 
 
's'    Dumps werden auf den Datenraum <zahl> eingestellt. Ist <zahl>=FF, so wird der
       Realspeicher eingestellt. (s:=<zahl>) 
 
'l'    Dumps werden auf die Länge <zahl> eingestellt. Desungeachtet kann man einen
       versehentlich zu langen Dump durch eine beliebige Eingabe abbrechen. Dann wird
       allerdings '*cup*' gesperrt (siehe unten). 
 
'p'    Dumps werden auf die Byteadresse <zahl> eingestellt (p:=<zahl>; wmodus:=
       FALSE). 
 
'w'    Dumps werden auf die Wortadresse <zahl> eingestellt. Die vor jeder Dumpzeile
       ausgegebene Adresse ist dann auch eine Wortadresse. Ein Wort = 2 Bytes. (p:=2*
       <zahl>; wmodus:=TRUE) 
 
'k'    Block <zahl> laden und per Dump anzeigen. Es erfolgt dabei eine Umstellung auf
       den Realdatenraum (s=FF). 
 
'P'    Paßworteingabe: P<text>*return* 
       Erst nach diesem Kommando sind die übrigen Kommandos ausführbar. 
 
'x'    Suchen nach Bytekette: 
 
-->    xc text 
-->    xh xx xx ... 
-->    x 
 
       Es wird nach 'text' bzw. Hexafolge 'xx xx ...' bzw. nach der durch das letzte
       'x'-Kommando eingestellten Bytekette gesucht. 
       Das Kommando ist durch *return* abzuschließen. 
       Die Suche beginnt ab Position 'p' und ist auf die Länge <zahl> Seiten (512 Byte-
       Einheiten) begrenzt (0=unendlich). 
       Eine beliebige Eingabe bricht die Suche vorzeitig ab. 
 
'*return*' 
       Es wird der eingestellte Dump ausgegeben (siehe 's','l','p','w'). Bei wmodus (siehe
       'p', 'w') werden Wortadressen ausgegeben. 
 
'o'    Wie '*return*', jedoch wird zuvor p := p+l  gesetzt (zum Weiterblättern). 
 
'r'    Freigabe der anderen Miniprozesse. 
 
       Zunächst werden bei Übergang in den Info alle Miniprozesse gesperrt, um eine
       Verfälschung der Fehlersituation zu vermeiden. Bei manchen Kommandos an den Info
       müssen aber andere Miniprozesse u.U. aktiv werden (z.B. beim 'k' der Lader). Wenn
       dies erforderlich ist, meldet der Info: 
       'paging erforderlich'. Man kann dann 'r' geben und das letzte Infokommando wieder­
       holen, oder mit anderen Kommandos fortfahren, falls man den Fehlerzustand noch so
       beibehalten will. 
 
'y'    Zweitfunktion ausführen. 
 
-->    'yP<text>*return*' 
              Neues Paßwort einstellen (max. 9 Zeichen). Dieses bleibt auch nach 'shutup'
              gültig. 
 
-->    'yt'   Block <zahl> von Archiv lesen. Dient zum Test des Archivs. 
              Es wird eine Kachel freigemacht und der Block mit der Nummer <zahl>
              eingelesen. Der Inhalt wird sofort angezeigt (wie Kommando 'k'). 
 
-->    'yb'   Breakpoint an die Adresse <zahl> setzen. Es wird ein Aufruf an den Info
              abgesetzt. Nur im Realspeicher sinnvoll. Dieser Aufruf meldet sich mit
              TEXT= 'test'. Wird er mit 'g' verlassen, so stellt Info zuvor die alten
              Z80-Befehle wieder her und führt sie an ihrem originalen Ort aus. 
 
-->    'yc'   wie 'yb', jedoch werden die originalen Z80-Befehle an einem anderen Ort
              (im Info) ausgeführt. Sie dürfen daher z.B. keinen Relativsprung enthalten
              und keine 'push'/'pop'-Befehle. Dafür bleibt dieser Breakpoint auch nach
              dem zugehörigen 'g' im Code erhalten. Dieser Breakpoint meldet sich mit
              TEXT='test 2'. 'yc' darf nicht gegeben werden, wenn der Info im 'test 2'
              steht (Umhängen verboten). 
 
              #on("i")#Achtung: Die Verwendung von 'yb' und 'yc' ist sehr kritisch durchzuführen.
                       Zu beachten ist, daß der in den Code eingesetzte Sprung (Z80 jp)
                       3 Byte belegt.#off("i")# 
 
 
-->    'yl'   Lernmodus ein (wie beim Editor). 
 
-->    'ye'   Ende Lernmodus. 
 
-->    'ya'   Ausführen. Die zwischen 'yl' und 'ye' eingegebenen Zeichen werden dem
              Info so vorgesetzt, als kämen sie von der Tastatur. 
 
              Achtung: Rekursion ('ya' im Lernmodus) wird nicht abgefangen. Das Gelern­
                        te wird nach jedem Kommando, das die ersten drei Zeilen
                        wiederaufbaut (z.B. *return*), in der Zeile vier angezeigt, wobei
                        für Steuerzeichen eine Ersatzdarstellung erscheint (%x mit
                        x=code (code (zeichen) +code ("A")), also z.B. %M für
                        *return*). 
 
--> 'y *return*' 
              Wie *return*, jedoch wird der Dump auch beim Ausführen (ya) ausgege­
              ben. (Ein gelerntes *return* führt im Ausführmodus nicht zum Dump). 
 
'*cup*' *)    (Cursor up). Umschaltung in den Modus zum Ändern in Dumps. 
#foot# 
#f#*) Falls der Kanal noch nicht konfiguriert ist, muß man natürlich eine Taste betätigen, die den EUMEL-Code für Cursor
Up erzeugt. In der Regel ist das CTL c. Falls das Terminal ohne Konfigurierung keine Cursorpositionierungen durchführt, ist
dieser Modus nicht sehr gut benutzbar.#a# 
#end# 
              Der Cursor fährt in den Dump und kann mit den Cursortasten dort bewegt
              werden. Wird eine Hexazahl jetzt eingegeben, so wird diese als Inhalt des
              Bytes eingetragen, auf dem der Cursor gerade steht. Dies funktioniert auch
              auf beliebigen Datenräumen. Info beantragt dann bei der Speicherverwal­
              tung einen Schreibzugriff für die entsprechende Datenraumseite, so daß
              Änderungen mit der Copy-on-Write-Logik erfolgen, also nur taskspezi­
              fisch sind (durch 'q' eingestellt). Für diese Task sind die Änderungen al­
              lerdings dann permanent, da sie auch auf den Hintergrund wirken. 
 
              Hinweis: Dumpt man mit 'k' einen Block und ändert dann darin, so sind
                       diese Änderungen u.U. nur temporär, da der Info kein Rückschrei­
                       ben des Blockes veranlaßt. 
 
              Achtung: Jede Eingabe, die kein Positionierzeichen und kein gültiges
                       Zahlzeichen ist, beendet diesen Modus. Das neue Zeichen wird als
                       Info-Kommando aufgefaßt, wobei <zahl> auf die aktuelle Adres­
                       se gesetzt wird. 
                       (Für 'yc' / 'yb' sinnvoll: Man setzt den Cursor auf die Stelle, an
                       der ein Break ausgelöst werden soll und gibt 'yc'/'yb'). 
                       Somit wird dieser Änderungsmodus üblicherweise durch *return*
                       beendet. 
 
#b("Einige Systemadressen")# 
#goalpage("sysaddr")# 
 
Der Info nützt nur wenig, wenn man nicht weiß, was man sich anschauen soll. Wesentliche
Angaben über die Systemstruktur enthält das 'Brikett' (interne Systemdokumentation für
Projekt Mikros der GMD). Da diese etwas allgemeiner gehalten ist, geht sie nicht auf imple­
mentationsabhängige Konstanten ein. Diese sind hier aufgeführt. 
 
Ab 1500h liegt die 'ktab'. Sie enthält Informationen, welche Blöcke an welcher Stelle des
Arbeitsspeicher liegen: In der Kachel mit der Adresse 512*i befindet sich der Inhalt des
Blockes, dessen Nummer in ktab+i, ktab+100h+i steht. Ferner enthält die Tabelle, zu
welchem Datenraum (drid) und welcher Seite des Datenraums der Inhalt gehört. (Nur rele­
vant, wenn die Prozeßnummer <> 255 ist). 
 
Steuerbits:   2**0 :  Inhalt wird gerade transportiert (zum HG oder Archiv). 
              2**1 :  Inhalt ist identisch mit Inhalt auf HG. Wird beim Schreiben auf die
                      Kachel (per Software) zurückgesetzt. 
              2**2 :  Schreiberlaubnis (siehe Brikett). 
              2**3 :  Inhalt wurde kürzlich benutzt. Solche Kacheln werden 'weniger
                      stark' verdrängt. 
 
 
   ktab       frei           niederwertige Blocknummer 
 
   +80h       frei            frei      Steuerbits 
 
   +100h      frei           höherwertige Blocknummer 
 
   +180h      frei            frei      Prozeßnummer 
 
   +200h      frei            frei      drid (prozeßspezifisch) 
 
   +280h      frei            frei      Seitennummer (höherw.) 
 
   +300h      frei            frei      Seitennummer (niederw.) 
 
                           ^          ^ 
         <-- unbenutzt --> !          +-- Beginn echter Kacheln 
                           +-- Beginn der Anforderungen 
 
 
Der 'Beginn echter Kacheln' hängt von der Größe der Z80-Teile ('urlader') ab (i.A.
30h < i < 40h). 
 
'Beginn der Anforderungen' liegt bei i=1Fh. Es handelt sich um Blocknummern von zu
ladenden Blöcken. Ist der höherwertige Teil der Blocknummer gleich FDh, so ist dies keine
Anforderung. 
 
Blocknummern > FF00h stehen für Blöcke mit dem Inhalt 512 FFh's und werden nie auf dem
Hintergrundmedium gespeichert. 
 
 
 
1E2Bh    enthält den DR-Eintrag des drdr (siehe Brikett). 
 
 
'musta': Das System fordert Checkpoints und Müllabfuhren über die Zelle 'musta' an. Diese
         findet man mit dem Info durch 
 
         xc musta 
 
         (hierfür ist der Text 'musta' vor der Zelle abgesetzt). 
 
         Die Zelle selbst enthält 
 
              FFh   : Keine Müllabfuhr oder Checkpoint 
              01h   : Müllabfuhr 
              02h   : Checkpoint 
              03h   : beides 
              04h   : Systemendecheckpoint 
              0Bh   : System auf Archiv schreiben ('save system') 
              F0h   : Müllabfuhr und Checkpoint sind geperrt (nur durch Setzen im Info
                      möglich) 
 
         Durch Einsetzen der Werte mit dem Info kann die entsprechende Operation veran­
         laßt werden. Beim Einsetzen darf der Info nicht im 'r'-Zustand (siehe Eingabe 'r')
         stehen; zum Ausführen der Operation muß 'r' (man bleibt im Info) oder 'g' (Info
         verlassen) gegeben werden. 
 
 
1880h-18FFh: 
         enthält die Aktivierungstabelle. Ist (1880h+i)=01h, so ist die Task i aktiv. Hin­
         weis: 18FFh enthält immer 01h, ohne daß dieser Zelle eine Task zugeordnet ist. 
 
 
#b("Leitblock")# 
#goalpage("pcb")# 
 
Mit dem 'z'-Kommando wird der Leitblock einer Task dargestellt. Es werden Hexapaare,
gefolgt von einer Bezeichnung, ausgegeben. In der folgenden Beschreibung werden die
Hexapaare durch a,b,c dargestellt. 
 
     a b c icount          Der virtuelle Befehlszähler der Task steht auf (cMOD4)*
                           10000h+b*100h+a = <ic> im Datenraum 4 dieser Task.
                           Durch die Eingabefolge: 
                                 4s<ic>w*return* 
                           kann man sich den Code, der ausgeführt werden soll, anse­
                           hen. 
 
                           Bit 2**7 von c zeigt den Fehlerzustand an. 
                           Bit 2**6 von c zeigt 'disable stop' (siehe Benutzerhandbuch)
                                    an. 
                           Bit 2**4 zeigt vorzeichenlose Arithmetik an (Compilierung). 
 
     a b lbas              Die lokale Basis steht auf 10000h+b*100h+c = <lb> im
                           Datenraum 4 (Wortadresse). 
 
     a b hptop             Der Arbeitsheap geht von 30000h (Byteadr.) bis (aMOD16)*
                           10000h+b*100h+(aDIV16)*10h (Byteadr!). 
 
     a b channel           Die Task hängt an Kanal 100h*b+a (Terminalnummer). 0 =
                           kein Terminal angekoppelt. 
 
     a b taskid            Die Tasknummer der betrachteten Task ist a. (b ist die
                           Versionsnummer zum Abdichten von 'send'/ 'wait'). 
 
Um den Code, auf den der 'icount' zeigt, zu interpretieren, ziehe man das Brikett zu Rate. 
 
 
Hinweis: Wenn der Info einen internen Fehler anzeigt, und auch bei 'ke', ist der durch 'z'
         angezeigte Leitblock u.U. nicht aktualisiert. Man kann dies durch die Eingaben 'r',
         'g' erzwingen. (Der Info stellt wegen 'r' dem Interpreter einen Restart zu, der dann
         beim 'g' den Leitblock aktualisiert und den Befehl erneut aufsetzt). Tritt dabei der
         Fehler nicht wieder auf, handelte es sich um einen transienten Fehler (z.B. der
         Codeblock war noch im Einlesen und ist jetzt voll da). So etwas kann z.B. passie­
         ren, wenn der SHard den Abschluß einer Leseoperation zu früh meldet.