This source file includes following definitions.
- iom_core_read
- iom_core_read2
- iom_core_write
- iom_core_write2
- iom_core_read_lock
- iom_core_write_unlock
- iom_action
- iom_show_mbx
- iom_show_units
- iom_set_units
- iom_show_config
- iom_set_config
- iom_reset_unit
- iom_unit_reset_idx
- iom_reset
- init_memory_iom
- boot_svc
- iom_boot
- mbxLoc
- status_service
- build_AUXPTW_address
- build_DDSPTW_address
- fetch_DDSPTW
- build_IDSPTW_address
- fetch_IDSPTW
- build_LPWPTW_address
- fetch_LPWPTW
- iom_direct_data_service
- iom_indirect_data_service
- update_chan_mode
- write_LPW
- dumpDCW
- dumpLPW
- fetch_and_parse_LPW
- unpack_DCW
- pack_DCW
- pack_LPW
- fetch_and_parse_PCW
- fetch_and_parse_DCW
- send_general_interrupt
- iom_fault
- iom_list_service
- doPayloadChannel
- doConnectChan
- send_marker_interrupt
- send_special_interrupt
- send_terminate_interrupt
- iom_interrupt
- chan_thread_main
- iom_thread_main
- iom_init
- do_boot
- iomProcess
- iomChar
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 #include "dps8.h"
550 #include "dps8_cpu.h"
551 #include "dps8_sys.h"
552 #include "dps8_faults.h"
553 #include "dps8_scu.h"
554 #include "dps8_iom.h"
555 #include "dps8_cable.h"
556 #include "dps8_console.h"
557 #include "dps8_fnp2.h"
558 #include "dps8_utils.h"
559 #if defined(LOCKLESS)
560 # include "threadz.h"
561 #endif
562
563 #define DBG_CTR 1
564
565
566
567
568
569
570
571
572 #define N_IOM_UNITS 1
573
574 #define IOM_UNIT_IDX(uptr) ((uptr) - iom_unit)
575
576 #define IOM_SYSTEM_FAULT_CHAN 1U
577 #define IOM_CONNECT_CHAN 2U
578 #define IOM_SPECIAL_STATUS_CHAN 6U
579
580 iom_chan_data_t iom_chan_data[N_IOM_UNITS_MAX][MAX_CHANNELS];
581
582 typedef enum iom_status_t
583 {
584 iomStatNormal = 0,
585 iomStatLPWTRO = 1,
586 iomStat2TDCW = 2,
587 iomStatBoundaryError = 3,
588 iomStatAERestricted = 4,
589 iomStatIDCWRestricted = 5,
590 iomStatCPDiscrepancy = 6,
591 iomStatParityErr = 7
592 } iom_status_t;
593
594 enum config_sw_OS_t
595 {
596 CONFIG_SW_STD_GCOS,
597 CONFIG_SW_EXT_GCOS,
598 CONFIG_SW_MULTICS
599 };
600
601 enum config_sw_model_t
602 {
603 CONFIG_SW_MODEL_IOM,
604 CONFIG_SW_MODEL_IMU
605 };
606
607
608 enum config_sw_bootload_device_e { CONFIG_SW_BLCT_CARD, CONFIG_SW_BLCT_TAPE };
609
610 typedef struct
611 {
612
613
614
615 word12 configSwIomBaseAddress;
616
617
618
619
620
621
622
623
624
625
626
627
628 word9 configSwMultiplexBaseAddress;
629
630 enum config_sw_model_t config_sw_model;
631
632
633 enum config_sw_OS_t config_sw_OS;
634
635
636 enum config_sw_bootload_device_e configSwBootloadCardTape;
637
638
639 word6 configSwBootloadMagtapeChan;
640
641
642 word6 configSwBootloadCardrdrChan;
643
644
645
646
647
648
649
650
651 word3 configSwBootloadPort;
652
653
654
655
656 uint configSwPortAddress[N_IOM_PORTS];
657
658
659 uint configSwPortInterface[N_IOM_PORTS];
660
661
662 uint configSwPortEnable[N_IOM_PORTS];
663
664
665 uint configSwPortSysinitEnable[N_IOM_PORTS];
666
667
668 uint configSwPortHalfsize[N_IOM_PORTS];
669
670 uint configSwPortStoresize[N_IOM_PORTS];
671
672
673
674
675 iom_status_t iomStatus;
676
677 uint invokingScuUnitIdx;
678 } iom_unit_data_t;
679
680 static iom_unit_data_t iom_unit_data[N_IOM_UNITS_MAX];
681
682 typedef enum iomSysFaults_t
683 {
684
685 iomNoFlt = 000,
686 iomIllChanFlt = 001,
687
688 iomIllSrvReqFlt = 002,
689
690
691
692 iomBndryVioFlt = 003,
693 iom256KFlt = 004,
694
695 iomLPWTRPConnFlt = 005,
696
697
698 iomNotPCWFlt = 006,
699 iomCP1Flt = 007,
700
701
702
703
704
705
706 iomIllTalCChnFlt = 013,
707
708
709
710 iomPTWFlagFault = 015,
711
712
713 iomNoPortFault = 017,
714
715 } iomSysFaults_t;
716
717 typedef enum iomFaultServiceRequest
718 {
719
720 iomFsrFirstList = (1 << 2) | 2,
721 iomFsrList = (1 << 2) | 0,
722 iomFsrStatus = (2 << 2) | 0,
723 iomFsrIntr = (3 << 2) | 0,
724 iomFsrSPIndLoad = (4 << 2) | 0,
725 iomFsrDPIndLoad = (4 << 2) | 1,
726 iomFsrSPIndStore = (5 << 2) | 0,
727 iomFsrDPIndStore = (5 << 2) | 1,
728 iomFsrSPDirLoad = (6 << 2) | 0,
729 iomFsrDPDirLoad = (6 << 2) | 1,
730 iomFsrSPDirStore = (7 << 2) | 0,
731 iomFsrDPDirStore = (7 << 2) | 1
732 } iomFaultServiceRequest;
733
734 #if defined(IO_THREADZ)
735 __thread uint this_iom_idx;
736 __thread uint this_chan_num;
737 #endif
738
739 #if defined(TESTING)
740 static char * cmdNames [] =
741 {
742 "Request Status",
743 "",
744 "Rd Ctrlr Mem",
745 "Rd 9 Rcrd",
746 "",
747 "Rd Bin Rcrd",
748 "Initiate Rd Data Xfer",
749 "",
750 "",
751 "",
752 "",
753 "Wr 9 Rcrd",
754 "",
755 "Wr Bin Rcrd",
756 "Initiate Wr Data Xfer",
757 "",
758 "Release Ctlr",
759 "",
760 "RdStatReg",
761 "",
762 "",
763 "Read",
764 "",
765 "",
766 "Seek 512",
767 "",
768 "MTP Wr Mem",
769 "Write ASCII",
770 "",
771 "",
772 "",
773 "",
774 "Reset Status",
775 "Set 6250 CPI",
776 "Restore",
777 "",
778 "Forward Skip Rcrd",
779 "Forward Skip File",
780 "Backward Skip Rcrd",
781 "Backspace File",
782 "Request Status",
783 "Reset Dev Stat/Alert",
784 "",
785 "",
786 "",
787 "Write EOF",
788 "",
789 "Survey Devs/ReadID",
790 "Set 800 BPI",
791 "Set 556 BPI",
792 "",
793 "Set File Permit",
794 "Set 200 BPI",
795 "Set 1600 CPI",
796 "",
797 "",
798 "Rewind",
799 "",
800 "Rewind/Unload",
801 "",
802 "",
803 "",
804 "",
805 "",
806 };
807 #endif
808
809 void iom_core_read (UNUSED uint iom_unit_idx, word24 addr, word36 *data, UNUSED const char * ctx)
810 {
811 #if defined(LOCKLESS)
812 # if !defined(SUNLINT)
813 word36 v;
814 LOAD_ACQ_CORE_WORD(v, addr);
815 * data = v & DMASK;
816 # endif
817 #else
818 * data = M[addr] & DMASK;
819 #endif
820 }
821
822 void iom_core_read2 (UNUSED uint iom_unit_idx, word24 addr, word36 *even, word36 *odd, UNUSED const char * ctx)
823 {
824 #if defined(LOCKLESS)
825 # if !defined(SUNLINT)
826 word36 v;
827 LOAD_ACQ_CORE_WORD(v, addr);
828 * even = v & DMASK;
829 # endif
830 addr++;
831 # if !defined(SUNLINT)
832 LOAD_ACQ_CORE_WORD(v, addr);
833 * odd = v & DMASK;
834 # endif
835 #else
836 * even = M[addr ++] & DMASK;
837 * odd = M[addr] & DMASK;
838 #endif
839 }
840
841 void iom_core_write (UNUSED uint iom_unit_idx, word24 addr, word36 data, UNUSED const char * ctx)
842 {
843 #if defined(LOCKLESS)
844 cpu_state_t * cpup = _cpup;
845 #endif
846 #if defined(LOCKLESS)
847 LOCK_CORE_WORD(addr);
848 # if !defined(SUNLINT)
849 STORE_REL_CORE_WORD(addr, data);
850 # endif
851 #else
852 M[addr] = data & DMASK;
853 #endif
854 }
855
856 void iom_core_write2 (UNUSED uint iom_unit_idx, word24 addr, word36 even, word36 odd, UNUSED const char * ctx)
857 {
858 #if defined(LOCKLESS)
859 cpu_state_t * cpup = _cpup;
860 #endif
861 #if defined(LOCKLESS)
862 LOCK_CORE_WORD(addr);
863 # if !defined(SUNLINT)
864 STORE_REL_CORE_WORD(addr, even);
865 # endif
866 addr++;
867 LOCK_CORE_WORD(addr);
868 # if !defined(SUNLINT)
869 STORE_REL_CORE_WORD(addr, odd);
870 # endif
871 #else
872 M[addr ++] = even;
873 M[addr] = odd;
874 #endif
875 }
876
877 void iom_core_read_lock (UNUSED uint iom_unit_idx, word24 addr, word36 *data, UNUSED const char * ctx)
878 {
879 #if defined(LOCKLESS)
880 cpu_state_t * cpup = _cpup;
881 #endif
882 #if defined(LOCKLESS)
883 LOCK_CORE_WORD(addr);
884 # if !defined(SUNLINT)
885 word36 v;
886 LOAD_ACQ_CORE_WORD(v, addr);
887 * data = v & DMASK;
888 # endif
889 #else
890 * data = M[addr] & DMASK;
891 #endif
892 }
893
894 void iom_core_write_unlock (UNUSED uint iom_unit_idx, word24 addr, word36 data, UNUSED const char * ctx)
895 {
896 #if defined(LOCKLESS)
897 # if !defined(SUNLINT)
898 STORE_REL_CORE_WORD(addr, data);
899 # endif
900 #else
901 M[addr] = data & DMASK;
902 #endif
903 }
904
905 static t_stat iom_action (UNIT *up)
906 {
907
908 uint scu_unit_idx = (uint) (up -> u3);
909 uint iom_unit_idx = (uint) (up -> u4);
910 iom_interrupt (scu_unit_idx, iom_unit_idx);
911 return SCPE_OK;
912 }
913
914 static UNIT iom_unit[N_IOM_UNITS_MAX] = {
915 #if defined(NO_C_ELLIPSIS)
916 { UDATA (iom_action, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
917 { UDATA (iom_action, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
918 { UDATA (iom_action, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
919 { UDATA (iom_action, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
920 #else
921 [0 ... N_IOM_UNITS_MAX - 1] = {
922 UDATA (iom_action, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
923 }
924 #endif
925 };
926
927 static t_stat iom_show_mbx (UNUSED FILE * st,
928 UNUSED UNIT * uptr, UNUSED int val,
929 UNUSED const void * desc)
930 {
931 return SCPE_OK;
932 }
933
934 static t_stat iom_show_units (UNUSED FILE * st, UNUSED UNIT * uptr, UNUSED int val, UNUSED const void * desc)
935 {
936 sim_printf ("Number of IOM units in system is %d\n", iom_dev.numunits);
937 return SCPE_OK;
938 }
939
940 static t_stat iom_set_units (UNUSED UNIT * uptr, UNUSED int value, const char * cptr, UNUSED void * desc)
941 {
942 if (! cptr)
943 return SCPE_ARG;
944 int n = atoi (cptr);
945 if (n < 1 || n > N_IOM_UNITS_MAX)
946 return SCPE_ARG;
947
948
949
950 iom_dev.numunits = (unsigned) n;
951 return SCPE_OK;
952 }
953
954 static t_stat iom_show_config (UNUSED FILE * st, UNIT * uptr, UNUSED int val,
955 UNUSED const void * desc)
956 {
957 uint iom_unit_idx = (uint) IOM_UNIT_IDX (uptr);
958 if (iom_unit_idx >= iom_dev.numunits)
959 {
960 sim_printf ("error: Invalid unit number %lu\n", (unsigned long) iom_unit_idx);
961 return SCPE_ARG;
962 }
963
964 sim_printf ("IOM unit number %lu\n", (unsigned long) iom_unit_idx);
965 iom_unit_data_t * p = iom_unit_data + iom_unit_idx;
966
967 char * os = "<out of range>";
968 switch (p -> config_sw_OS)
969 {
970 case CONFIG_SW_STD_GCOS:
971 os = "Standard GCOS";
972 break;
973 case CONFIG_SW_EXT_GCOS:
974 os = "Extended GCOS";
975 break;
976 case CONFIG_SW_MULTICS:
977 os = "Multics";
978 break;
979 }
980 char * blct = "<out of range>";
981 switch (p -> configSwBootloadCardTape)
982 {
983 case CONFIG_SW_BLCT_CARD:
984 blct = "CARD";
985 break;
986 case CONFIG_SW_BLCT_TAPE:
987 blct = "TAPE";
988 break;
989 }
990
991 sim_printf ("Allowed Operating System: %s\n", os);
992 sim_printf ("IOM Base Address: %03o(8)\n", p -> configSwIomBaseAddress);
993 sim_printf ("Multiplex Base Address: %04o(8)\n", p -> configSwMultiplexBaseAddress);
994 sim_printf ("Bootload Card/Tape: %s\n", blct);
995 sim_printf ("Bootload Tape Channel: %02o(8)\n", p -> configSwBootloadMagtapeChan);
996 sim_printf ("Bootload Card Channel: %02o(8)\n", p -> configSwBootloadCardrdrChan);
997 sim_printf ("Bootload Port: %02o(8)\n", p -> configSwBootloadPort);
998 sim_printf ("Port Address: ");
999 int i;
1000 for (i = 0; i < N_IOM_PORTS; i ++)
1001 sim_printf (" %03o", p -> configSwPortAddress[i]);
1002 sim_printf ("\n");
1003 sim_printf ("Port Interlace: ");
1004 for (i = 0; i < N_IOM_PORTS; i ++)
1005 sim_printf (" %3o", p -> configSwPortInterface[i]);
1006 sim_printf ("\n");
1007 sim_printf ("Port Enable: ");
1008 for (i = 0; i < N_IOM_PORTS; i ++)
1009 sim_printf (" %3o", p -> configSwPortEnable[i]);
1010 sim_printf ("\n");
1011 sim_printf ("Port Sysinit Enable: ");
1012 for (i = 0; i < N_IOM_PORTS; i ++)
1013 sim_printf (" %3o", p -> configSwPortSysinitEnable[i]);
1014 sim_printf ("\n");
1015 sim_printf ("Port Halfsize: ");
1016 for (i = 0; i < N_IOM_PORTS; i ++)
1017 sim_printf (" %3o", p -> configSwPortHalfsize[i]);
1018 sim_printf ("\n");
1019 sim_printf ("Port Storesize: ");
1020 for (i = 0; i < N_IOM_PORTS; i ++)
1021 sim_printf (" %3o", p -> configSwPortStoresize[i]);
1022 sim_printf ("\n");
1023
1024 return SCPE_OK;
1025 }
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046 static config_value_list_t cfg_model_list[] =
1047 {
1048 { "iom", CONFIG_SW_MODEL_IOM },
1049 { "imu", CONFIG_SW_MODEL_IMU }
1050 };
1051
1052 static config_value_list_t cfg_os_list[] =
1053 {
1054 { "gcos", CONFIG_SW_STD_GCOS },
1055 { "gcosext", CONFIG_SW_EXT_GCOS },
1056 { "multics", CONFIG_SW_MULTICS },
1057 { NULL, 0 }
1058 };
1059
1060 static config_value_list_t cfg_boot_list[] =
1061 {
1062 { "card", CONFIG_SW_BLCT_CARD },
1063 { "tape", CONFIG_SW_BLCT_TAPE },
1064 { NULL, 0 }
1065 };
1066
1067 static config_value_list_t cfg_base_list[] =
1068 {
1069 { "multics", 014 },
1070 { "multics1", 014 },
1071 { "multics2", 020 },
1072 { "multics3", 024 },
1073 { "multics4", 030 },
1074 { NULL, 0 }
1075 };
1076
1077 static config_value_list_t cfg_size_list[] =
1078 {
1079 { "32", 0 },
1080 { "64", 1 },
1081 { "128", 2 },
1082 { "256", 3 },
1083 { "512", 4 },
1084 { "1024", 5 },
1085 { "2048", 6 },
1086 { "4096", 7 },
1087 { "32K", 0 },
1088 { "64K", 1 },
1089 { "128K", 2 },
1090 { "256K", 3 },
1091 { "512K", 4 },
1092 { "1024K", 5 },
1093 { "2048K", 6 },
1094 { "4096K", 7 },
1095 { "1M", 5 },
1096 { "2M", 6 },
1097 { "4M", 7 },
1098 { NULL, 0 }
1099 };
1100
1101 static config_list_t iom_config_list[] =
1102 {
1103 { "model", 1, 0, cfg_model_list },
1104 { "os", 1, 0, cfg_os_list },
1105 { "boot", 1, 0, cfg_boot_list },
1106 { "iom_base", 0, 07777, cfg_base_list },
1107 { "multiplex_base", 0, 0777, NULL },
1108 { "tapechan", 0, 077, NULL },
1109 { "cardchan", 0, 077, NULL },
1110 { "scuport", 0, 07, NULL },
1111 { "port", 0, N_IOM_PORTS - 1, NULL },
1112 { "addr", 0, 7, NULL },
1113 { "interlace", 0, 1, NULL },
1114 { "enable", 0, 1, NULL },
1115 { "initenable", 0, 1, NULL },
1116 { "halfsize", 0, 1, NULL },
1117 { "store_size", 0, 7, cfg_size_list },
1118 { NULL, 0, 0, NULL }
1119 };
1120
1121 static t_stat iom_set_config (UNIT * uptr, UNUSED int value, const char * cptr, UNUSED void * desc)
1122 {
1123 uint iom_unit_idx = (uint) IOM_UNIT_IDX (uptr);
1124 if (iom_unit_idx >= iom_dev.numunits)
1125 {
1126 sim_printf ("error: %s: Invalid unit number %ld\n", __func__, (long) iom_unit_idx);
1127 return SCPE_ARG;
1128 }
1129
1130 iom_unit_data_t * p = iom_unit_data + iom_unit_idx;
1131
1132 static uint port_num = 0;
1133
1134 config_state_t cfg_state = { NULL, NULL };
1135
1136 for (;;)
1137 {
1138 int64_t v;
1139 int rc = cfg_parse (__func__, cptr, iom_config_list, & cfg_state, & v);
1140
1141 if (rc == -1)
1142 break;
1143
1144 if (rc == -2)
1145 {
1146 cfg_parse_done (& cfg_state);
1147 continue;
1148 }
1149 const char * name = iom_config_list[rc].name;
1150
1151 if (strcmp (name, "model") == 0)
1152 {
1153 p -> config_sw_model = (enum config_sw_model_t) v;
1154 continue;
1155 }
1156
1157 if (strcmp (name, "os") == 0)
1158 {
1159 p -> config_sw_OS = (enum config_sw_OS_t) v;
1160 continue;
1161 }
1162
1163 if (strcmp (name, "boot") == 0)
1164 {
1165 p -> configSwBootloadCardTape = (enum config_sw_bootload_device_e) v;
1166 continue;
1167 }
1168
1169 if (strcmp (name, "iom_base") == 0)
1170 {
1171 p -> configSwIomBaseAddress = (word12) v;
1172 continue;
1173 }
1174
1175 if (strcmp (name, "multiplex_base") == 0)
1176 {
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193 p -> configSwMultiplexBaseAddress = (word9) v;
1194 continue;
1195 }
1196
1197 if (strcmp (name, "tapechan") == 0)
1198 {
1199 p -> configSwBootloadMagtapeChan = (word6) v;
1200 continue;
1201 }
1202
1203 if (strcmp (name, "cardchan") == 0)
1204 {
1205 p -> configSwBootloadCardrdrChan = (word6) v;
1206 continue;
1207 }
1208
1209 if (strcmp (name, "scuport") == 0)
1210 {
1211 p -> configSwBootloadPort = (word3) v;
1212 continue;
1213 }
1214
1215 if (strcmp (name, "port") == 0)
1216 {
1217 port_num = (uint) v;
1218 continue;
1219 }
1220
1221 if (strcmp (name, "addr") == 0)
1222 {
1223 p -> configSwPortAddress[port_num] = (uint) v;
1224 continue;
1225 }
1226
1227 if (strcmp (name, "interlace") == 0)
1228 {
1229 p -> configSwPortInterface[port_num] = (uint) v;
1230 continue;
1231 }
1232
1233 if (strcmp (name, "enable") == 0)
1234 {
1235 p -> configSwPortEnable[port_num] = (uint) v;
1236 continue;
1237 }
1238
1239 if (strcmp (name, "initenable") == 0)
1240 {
1241 p -> configSwPortSysinitEnable[port_num] = (uint) v;
1242 continue;
1243 }
1244
1245 if (strcmp (name, "halfsize") == 0)
1246 {
1247 p -> configSwPortHalfsize[port_num] = (uint) v;
1248 continue;
1249 }
1250
1251 if (strcmp (name, "store_size") == 0)
1252 {
1253 p -> configSwPortStoresize[port_num] = (uint) v;
1254 continue;
1255 }
1256
1257 sim_printf ("error: %s: Invalid cfg_parse rc <%ld>\n", __func__, (long) rc);
1258 cfg_parse_done (& cfg_state);
1259 return SCPE_ARG;
1260 }
1261 cfg_parse_done (& cfg_state);
1262 return SCPE_OK;
1263 }
1264
1265 static t_stat iom_reset_unit (UNIT * uptr, UNUSED int32 value, UNUSED const char * cptr,
1266 UNUSED void * desc)
1267 {
1268 uint iom_unit_idx = (uint) (uptr - iom_unit);
1269 iom_unit_reset_idx (iom_unit_idx);
1270 return SCPE_OK;
1271 }
1272
1273 static MTAB iom_mod[] =
1274 {
1275 {
1276 MTAB_XTD | MTAB_VUN | \
1277 MTAB_NMO | MTAB_NC,
1278 0,
1279 "MBX",
1280 NULL,
1281 NULL,
1282 iom_show_mbx,
1283 NULL,
1284 NULL
1285 },
1286 {
1287 MTAB_XTD | MTAB_VUN | \
1288 MTAB_NMO | MTAB_VALR,
1289 0,
1290 "CONFIG",
1291 "CONFIG",
1292 iom_set_config,
1293 iom_show_config,
1294 NULL,
1295 NULL
1296 },
1297 {
1298 MTAB_XTD | MTAB_VUN | \
1299 MTAB_NMO | MTAB_VALR,
1300 0,
1301 (char *) "RESET",
1302 (char *) "RESET",
1303 iom_reset_unit,
1304 NULL,
1305 (char *) "reset IOM unit",
1306 NULL
1307 },
1308 {
1309 MTAB_XTD | MTAB_VDV | \
1310 MTAB_NMO | MTAB_VALR,
1311 0,
1312 "NUNITS",
1313 "NUNITS",
1314 iom_set_units,
1315 iom_show_units,
1316 "Number of IOM units in the system",
1317 NULL
1318 },
1319 {
1320 0, 0, NULL, NULL, 0, 0, NULL, NULL
1321 }
1322 };
1323
1324 static DEBTAB iom_dt[] =
1325 {
1326 { "NOTIFY", DBG_NOTIFY, NULL },
1327 { "INFO", DBG_INFO, NULL },
1328 { "ERR", DBG_ERR, NULL },
1329 { "WARN", DBG_WARN, NULL },
1330 { "DEBUG", DBG_DEBUG, NULL },
1331 { "TRACE", DBG_TRACE, NULL },
1332 { "ALL", DBG_ALL, NULL },
1333 { NULL, 0, NULL }
1334 };
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346 t_stat iom_unit_reset_idx (UNUSED uint iom_unit_idx)
1347 {
1348 return SCPE_OK;
1349 }
1350
1351 static t_stat iom_reset (UNUSED DEVICE * dptr)
1352 {
1353
1354
1355 for (uint iom_unit_idx = 0; iom_unit_idx < iom_dev.numunits; iom_unit_idx ++)
1356 {
1357 iom_unit_reset_idx (iom_unit_idx);
1358 }
1359 return SCPE_OK;
1360 }
1361
1362 static t_stat boot_svc (UNIT * unitp);
1363 static UNIT boot_channel_unit[N_IOM_UNITS_MAX] = {
1364 #if defined(NO_C_ELLIPSIS)
1365 { UDATA (& boot_svc, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1366 { UDATA (& boot_svc, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1367 { UDATA (& boot_svc, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1368 { UDATA (& boot_svc, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
1369 #else
1370 [0 ... N_IOM_UNITS_MAX - 1] = {
1371 UDATA (& boot_svc, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
1372 }
1373 #endif
1374 };
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390 static void init_memory_iom (uint iom_unit_idx)
1391 {
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404 word12 base = iom_unit_data[iom_unit_idx].configSwIomBaseAddress;
1405
1406
1407
1408
1409
1410 word36 pi_base = (((word36) iom_unit_data[iom_unit_idx].configSwMultiplexBaseAddress) << 3) |
1411 (((word36) (iom_unit_data[iom_unit_idx].configSwIomBaseAddress & 07700U)) << 6) ;
1412 word3 iom_num = ((word36) iom_unit_data[iom_unit_idx].configSwMultiplexBaseAddress) & 3;
1413 word36 cmd = 5;
1414 word36 dev = 0;
1415
1416
1417 word36 imu = iom_unit_data[iom_unit_idx].config_sw_model == CONFIG_SW_MODEL_IMU ? 1 : 0;
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428 enum config_sw_bootload_device_e bootdev = iom_unit_data[iom_unit_idx].configSwBootloadCardTape;
1429
1430 word6 bootchan;
1431 if (bootdev == CONFIG_SW_BLCT_CARD)
1432 bootchan = iom_unit_data[iom_unit_idx].configSwBootloadCardrdrChan;
1433 else
1434 bootchan = iom_unit_data[iom_unit_idx].configSwBootloadMagtapeChan;
1435
1436
1437
1438
1439
1440 word36 dis0 = 0616200;
1441
1442 M[010 + 2 * iom_num + 0] = (imu << 34) | dis0;
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454 M[010 + 2 * iom_num + 1] = 0;
1455
1456
1457
1458
1459 M[030 + 2 * iom_num] = dis0;
1460
1461
1462
1463
1464
1465 word24 base_addr = (word24) base << 6;
1466 M[base_addr + 7] = ((word36) base_addr << 18) | 02000002;
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476 M[base_addr + 010] = 040000;
1477
1478
1479
1480
1481 word24 mbx = base_addr + 4u * bootchan;
1482 M[mbx] = 03020003;
1483
1484
1485
1486
1487 M[4] = 030 << 18;
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498 M[mbx + 2] = ((word36)base_addr << 18);
1499
1500
1501
1502
1503 M[0] = 0720201;
1504
1505
1506
1507
1508
1509 word3 port = iom_unit_data[iom_unit_idx].configSwBootloadPort;
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532 M[1] = ((word36) (bootchan) << 27) | port;
1533
1534
1535
1536
1537 M[2] = ((word36) base_addr << 18) | (pi_base) | iom_num;
1538
1539
1540
1541
1542 M[3] = (cmd << 30) | (dev << 24) | 0700000;
1543 }
1544
1545 static t_stat boot_svc (UNIT * unitp)
1546 {
1547 uint iom_unit_idx = (uint) (unitp - boot_channel_unit);
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559 for (int port_num = 0; port_num < N_SCU_PORTS; port_num ++)
1560 {
1561 if (! cables->iom_to_scu[iom_unit_idx][port_num].in_use)
1562 continue;
1563 uint scu_unit_idx = cables->iom_to_scu[iom_unit_idx][port_num].scu_unit_idx;
1564 scu_unit_reset ((int) scu_unit_idx);
1565 }
1566
1567
1568 init_memory_iom (iom_unit_idx);
1569
1570
1571 startRemoteConsole ();
1572
1573
1574 startFNPListener ();
1575
1576
1577
1578 if (! cables->iom_to_scu[iom_unit_idx][0].in_use)
1579 {
1580 sim_warn ("boot iom can't find a SCU\n");
1581 return SCPE_ARG;
1582 }
1583 uint scu_unit_idx = cables->iom_to_scu[iom_unit_idx][0].scu_unit_idx;
1584 iom_interrupt (scu_unit_idx, iom_unit_idx);
1585
1586
1587
1588
1589 return SCPE_OK;
1590 }
1591
1592 static t_stat iom_boot (int unitNum, UNUSED DEVICE * dptr)
1593 {
1594 if (unitNum < 0 || unitNum >= (int) iom_dev.numunits)
1595 {
1596 sim_printf ("%s: Invalid unit number %d\n", __func__, unitNum);
1597 return SCPE_ARG;
1598 }
1599
1600 boot_svc (& boot_channel_unit[unitNum]);
1601 return SCPE_OK;
1602 }
1603
1604 DEVICE iom_dev =
1605 {
1606 "IOM",
1607 iom_unit,
1608 NULL,
1609 iom_mod,
1610 N_IOM_UNITS,
1611 10,
1612 8,
1613 1,
1614 8,
1615 8,
1616 NULL,
1617 NULL,
1618 iom_reset,
1619 iom_boot,
1620 NULL,
1621 NULL,
1622 NULL,
1623 DEV_DEBUG,
1624 0,
1625 iom_dt,
1626 NULL,
1627 NULL,
1628 NULL,
1629 NULL,
1630 NULL,
1631 NULL,
1632 NULL
1633 };
1634
1635 static uint mbxLoc (uint iom_unit_idx, uint chan)
1636 {
1637
1638
1639 word12 base = iom_unit_data[iom_unit_idx].configSwIomBaseAddress;
1640 word24 base_addr = ((word24) base) << 6;
1641 word24 mbx = base_addr + 4 * chan;
1642
1643
1644 return mbx;
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 static int status_service (uint iom_unit_idx, uint chan, bool marker)
1722 {
1723 #if defined(TESTING)
1724 cpu_state_t * cpup = _cpup;
1725 #endif
1726 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1727
1728
1729
1730
1731 word36 word1, word2;
1732 word1 = 0;
1733 putbits36_12 (& word1, 0, p -> stati);
1734
1735
1736
1737 putbits36_1 (& word1, 13, marker ? 1 : 0);
1738 putbits36_2 (& word1, 14, 0);
1739 putbits36_1 (& word1, 16, p -> initiate ? 1 : 0);
1740 putbits36_1 (& word1, 17, 0);
1741 putbits36_3 (& word1, 18, (word3) p -> chanStatus);
1742
1743 putbits36_3 (& word1, 21, 0);
1744
1745
1746
1747
1748 putbits36_6 (& word1, 30, p -> recordResidue);
1749
1750 word2 = 0;
1751
1752
1753
1754
1755
1756 putbits36_3 (& word2, 18, p -> charPos);
1757 putbits36_1 (& word2, 21, p -> isRead ? 1 : 0);
1758 putbits36_12 (& word2, 24, p -> tallyResidue);
1759
1760
1761
1762
1763
1764
1765 uint chanloc = mbxLoc (iom_unit_idx, chan);
1766 word24 scwAddr = chanloc + IOM_MBX_SCW;
1767 word36 scw;
1768 iom_core_read_lock (iom_unit_idx, scwAddr, & scw, __func__);
1769 word18 addr = getbits36_18 (scw, 0);
1770 uint lq = getbits36_2 (scw, 18);
1771 uint tally = getbits36_12 (scw, 24);
1772
1773 sim_debug (DBG_DEBUG, & iom_dev, "%s: Status: 0%012"PRIo64" 0%012"PRIo64"\n",
1774 __func__, word1, word2);
1775 if (lq == 3)
1776 {
1777 sim_debug (DBG_WARN, &iom_dev,
1778 "%s: SCW for channel %d has illegal LQ\n",
1779 __func__, chan);
1780 lq = 0;
1781 }
1782 iom_core_write2 (iom_unit_idx, addr, word1, word2, __func__);
1783
1784
1785 if (tally > 0 || (tally == 0 && lq != 0))
1786 {
1787 switch (lq)
1788 {
1789 case 0:
1790
1791 if (tally != 0)
1792 {
1793 tally --;
1794 addr += 2;
1795 }
1796 break;
1797
1798 case 1:
1799
1800 if (tally % 8 == 1 )
1801 addr -= 8;
1802 else
1803 addr += 2;
1804 tally --;
1805 break;
1806
1807 case 2:
1808
1809 if (tally % 32 == 1 )
1810 addr -= 32;
1811 else
1812 addr += 2;
1813 tally --;
1814 break;
1815 }
1816
1817
1818 if (tally & ~07777U)
1819 {
1820 sim_debug (DBG_WARN, & iom_dev,
1821 "%s: Tally SCW address 0%o under/over flow\n",
1822 __func__, tally);
1823 tally &= 07777;
1824 }
1825
1826 putbits36_12 (& scw, 24, (word12) tally);
1827 putbits36_18 (& scw, 0, addr);
1828 }
1829
1830 iom_core_write_unlock (iom_unit_idx, scwAddr, scw, __func__);
1831
1832
1833 return 0;
1834 }
1835
1836 static word24 UNUSED build_AUXPTW_address (uint iom_unit_idx, int chan)
1837 {
1838
1839
1840
1841
1842
1843
1844
1845
1846 word12 IOMBaseAddress = iom_unit_data[iom_unit_idx].configSwIomBaseAddress;
1847 word24 addr = (((word24) IOMBaseAddress) & MASK12) << 6;
1848 addr |= ((uint) chan & MASK6) << 2;
1849 addr |= 03;
1850 return addr;
1851 }
1852
1853 static word24 build_DDSPTW_address (word18 PCW_PAGE_TABLE_PTR, word8 pageNumber)
1854 {
1855
1856
1857
1858
1859
1860
1861
1862
1863 if (PCW_PAGE_TABLE_PTR & 3)
1864 sim_warn ("%s: pcw_ptp %#o page_no %#o\n", __func__, PCW_PAGE_TABLE_PTR, pageNumber);
1865 word24 addr = (((word24) PCW_PAGE_TABLE_PTR) & MASK18) << 6;
1866 addr |= pageNumber;
1867 return addr;
1868 }
1869
1870
1871
1872 static void fetch_DDSPTW (uint iom_unit_idx, int chan, word18 addr)
1873 {
1874 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1875 word24 pgte = build_DDSPTW_address (p -> PCW_PAGE_TABLE_PTR,
1876 (addr >> 10) & MASK8);
1877 iom_core_read (iom_unit_idx, pgte, (word36 *) & p -> PTW_DCW, __func__);
1878 if ((p -> PTW_DCW & 0740000777747) != 04llu)
1879 sim_warn ("%s: chan %ld addr %#llo pgte %08llo ptw %012llo\n",
1880 __func__, (long)chan, (unsigned long long)addr,
1881 (unsigned long long)pgte, (unsigned long long)p -> PTW_DCW);
1882 }
1883
1884 static word24 build_IDSPTW_address (word18 PCW_PAGE_TABLE_PTR, word1 seg, word8 pageNumber)
1885 {
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901 word24 addr = (((word24) PCW_PAGE_TABLE_PTR) & MASK18) << 6;
1902 addr += (((word24) seg) & 01) << 8;
1903 addr += pageNumber;
1904 return addr;
1905 }
1906
1907
1908
1909 static void fetch_IDSPTW (uint iom_unit_idx, int chan, word18 addr)
1910 {
1911 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1912 word24 pgte = build_IDSPTW_address (p -> PCW_PAGE_TABLE_PTR,
1913 p -> SEG,
1914 (addr >> 10) & MASK8);
1915 iom_core_read (iom_unit_idx, pgte, (word36 *) & p -> PTW_DCW, __func__);
1916 if ((p -> PTW_DCW & 0740000777747) != 04llu)
1917 sim_warn ("%s: chan %d addr %#o ptw %012llo\n",
1918 __func__, chan, addr, (unsigned long long)p -> PTW_DCW);
1919 }
1920
1921 static word24 build_LPWPTW_address (word18 PCW_PAGE_TABLE_PTR, word1 seg, word8 pageNumber)
1922 {
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938 word24 addr = (((word24) PCW_PAGE_TABLE_PTR) & MASK18) << 6;
1939 addr += (((word24) seg) & 01) << 8;
1940 addr += pageNumber;
1941 return addr;
1942 }
1943
1944 static void fetch_LPWPTW (uint iom_unit_idx, uint chan)
1945 {
1946 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1947 word24 addr = build_LPWPTW_address (p -> PCW_PAGE_TABLE_PTR,
1948 p -> SEG,
1949 (p -> LPW_DCW_PTR >> 10) & MASK8);
1950 iom_core_read (iom_unit_idx, addr, (word36 *) & p -> PTW_LPW, __func__);
1951 if ((p -> PTW_LPW & 0740000777747) != 04llu)
1952 sim_warn ("%s: chan %d addr %#o ptw %012llo\n",
1953 __func__, chan, addr, (unsigned long long)p -> PTW_LPW);
1954 }
1955
1956
1957
1958
1959 void iom_direct_data_service (uint iom_unit_idx, uint chan, word24 daddr, word36 * data,
1960 iom_direct_data_service_op op)
1961 {
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1975
1976 if (p -> masked)
1977 return;
1978
1979 if (p -> PCW_63_PTP && p -> PCW_64_PGE)
1980 {
1981 fetch_DDSPTW (iom_unit_idx, (int) chan, daddr);
1982 daddr = ((uint) getbits36_14 (p -> PTW_DCW, 4) << 10) | (daddr & MASK10);
1983 }
1984
1985 if (op == direct_store)
1986 iom_core_write (iom_unit_idx, daddr, * data, __func__);
1987 else if (op == direct_load)
1988 iom_core_read (iom_unit_idx, daddr, data, __func__);
1989 else if (op == direct_read_clear)
1990 {
1991 iom_core_read_lock (iom_unit_idx, daddr, data, __func__);
1992 iom_core_write_unlock (iom_unit_idx, daddr, 0, __func__);
1993 }
1994 }
1995
1996
1997
1998
1999
2000
2001 void iom_indirect_data_service (uint iom_unit_idx, uint chan, word36 * data, uint * cnt, bool write) {
2002 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2003
2004 if (p->masked)
2005 return;
2006
2007
2008
2009 p->initiate = false;
2010
2011 uint tally = p->DDCW_TALLY;
2012 uint daddr = p->DDCW_ADDR;
2013 if (tally == 0) {
2014 tally = 4096;
2015 }
2016 p->tallyResidue = (word12) tally;
2017
2018 if (write) {
2019 uint c = * cnt;
2020 while (p->tallyResidue) {
2021 if (c == 0)
2022 break;
2023
2024 if (! IS_IONTP (p)) {
2025 if (p->PCW_63_PTP && p->PCW_64_PGE) {
2026 fetch_IDSPTW (iom_unit_idx, (int) chan, daddr);
2027 word24 addr = ((word24) (getbits36_14 (p -> PTW_DCW, 4) << 10)) | (daddr & MASK10);
2028 iom_core_write (iom_unit_idx, addr, * data, __func__);
2029 } else {
2030 if (daddr > MASK18) {
2031 sim_warn ("%s 256K ovf\n", __func__);
2032 daddr &= MASK18;
2033 }
2034
2035
2036
2037 uint daddr2 = daddr | (uint) p->ADDR_EXT << 18;
2038 iom_core_write (iom_unit_idx, daddr2, * data, __func__);
2039 }
2040 }
2041 daddr ++;
2042 data ++;
2043 p->tallyResidue --;
2044 c --;
2045 }
2046 } else {
2047 uint c = 0;
2048 while (p -> tallyResidue) {
2049 if (IS_IONTP (p)) {
2050 * data = 0;
2051 } else {
2052 if (p -> PCW_63_PTP && p -> PCW_64_PGE) {
2053 fetch_IDSPTW (iom_unit_idx, (int) chan, daddr);
2054 word24 addr = ((word24) (getbits36_14 (p -> PTW_DCW, 4) << 10)) | (daddr & MASK10);
2055 iom_core_read (iom_unit_idx, addr, data, __func__);
2056 } else {
2057
2058 if (daddr > MASK18) {
2059 sim_warn ("%s 256K ovf\n", __func__);
2060 daddr &= MASK18;
2061 }
2062
2063
2064
2065 uint daddr2 = daddr | (uint) p -> ADDR_EXT << 18;
2066 iom_core_read (iom_unit_idx, daddr2, data, __func__);
2067 }
2068 }
2069 daddr ++;
2070 p->tallyResidue --;
2071 data ++;
2072 c ++;
2073 }
2074 * cnt = c;
2075 }
2076 }
2077
2078 static void update_chan_mode (uint iom_unit_idx, uint chan, bool tdcw)
2079 {
2080 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2081 if (chan == IOM_CONNECT_CHAN)
2082 {
2083 p -> chanMode = cm1;
2084 return;
2085 }
2086
2087 if (! tdcw)
2088 {
2089 if (p -> PCW_64_PGE == 0)
2090 {
2091 if (p -> LPW_20_AE == 0)
2092 {
2093 p -> chanMode = cm1e;
2094 }
2095 else
2096 {
2097 p -> chanMode = cm2e;
2098 }
2099
2100 }
2101 else
2102 {
2103 if (p -> LPW_20_AE == 0)
2104 {
2105 if (p -> LPW_23_REL == 0)
2106 {
2107 p -> chanMode = cm1;
2108 }
2109 else
2110 {
2111 p -> chanMode = cm3a;
2112 }
2113
2114 }
2115 else
2116 {
2117 if (p -> LPW_23_REL == 0)
2118 {
2119 p -> chanMode = cm3b;
2120 }
2121 else
2122 {
2123 p -> chanMode = cm4;
2124 }
2125
2126 }
2127 }
2128 }
2129 else
2130 {
2131 switch (p -> chanMode)
2132 {
2133 case cm1:
2134 if (p -> TDCW_32_PDTA)
2135 {
2136 p -> chanMode = cm2;
2137 break;
2138 }
2139 if (p -> TDCW_33_PDCW)
2140 if (p -> TDCW_35_REL)
2141 p -> chanMode = cm4;
2142 else
2143 p -> chanMode = cm3b;
2144 else
2145 if (p -> TDCW_35_REL)
2146 p -> chanMode = cm3a;
2147 else
2148 p -> chanMode = cm2;
2149 break;
2150
2151 case cm2:
2152 if (p -> TDCW_33_PDCW)
2153 if (p -> TDCW_35_REL)
2154 p -> chanMode = cm4;
2155 else
2156 p -> chanMode = cm3b;
2157 else
2158 if (p -> TDCW_35_REL)
2159 p -> chanMode = cm3a;
2160 else
2161 p -> chanMode = cm2;
2162 break;
2163
2164 case cm3a:
2165 if (p -> TDCW_33_PDCW)
2166 p -> chanMode = cm4;
2167 break;
2168
2169 case cm3b:
2170 if (p -> TDCW_35_REL)
2171 p -> chanMode = cm4;
2172 break;
2173
2174 case cm4:
2175 p -> chanMode = cm5;
2176 break;
2177
2178 case cm5:
2179 break;
2180
2181 case cm1e:
2182 {
2183 if (p -> chanMode == cm1e && p -> TDCW_33_EC)
2184 p -> chanMode = cm2e;
2185 }
2186 break;
2187
2188 case cm2e:
2189 break;
2190 }
2191 }
2192 }
2193
2194 static void write_LPW (uint iom_unit_idx, uint chan)
2195 {
2196 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2197
2198 uint chanLoc = mbxLoc (iom_unit_idx, chan);
2199 iom_core_write (iom_unit_idx, chanLoc + IOM_MBX_LPW, p -> LPW, __func__);
2200
2201
2202
2203 if (chan != IOM_CONNECT_CHAN)
2204 {
2205 iom_core_write (iom_unit_idx, chanLoc + IOM_MBX_LPWX, p -> LPWX, __func__);
2206 }
2207 }
2208
2209 #if defined(TESTING)
2210 void dumpDCW (word36 DCW, word1 LPW_23_REL) {
2211 static char * charCtrls[4] =
2212 { "terminate", "undefined", "proceed", "marker" };
2213 static char * chanCmds[16] =
2214 { "record", "undefined", "nondata", "undefined",
2215 "undefined", "undefined", "multirecord", "undefined",
2216 "character", "undefined", "undefined", "undefined",
2217 "undefined", "undefined", "undefined", "undefined"
2218 };
2219 word3 DCW_18_20_CP = getbits36_3 (DCW, 18);
2220
2221 if (DCW_18_20_CP == 07) {
2222 word6 IDCW_DEV_CMD = getbits36_6 (DCW, 0);
2223 word6 IDCW_DEV_CODE = getbits36_6 (DCW, 6);
2224
2225
2226
2227
2228
2229
2230 word2 IDCW_CHAN_CTRL = getbits36_2 (DCW, 22);
2231 word6 IDCW_CHAN_CMD = getbits36_6 (DCW, 24);
2232 word6 IDCW_COUNT = getbits36_6 (DCW, 30);
2233 sim_printf ("// IDCW %012llo\r\n", DCW);
2234 sim_printf ("// cmd %02o %s\r\n", IDCW_DEV_CMD, cmdNames[IDCW_DEV_CMD]);
2235 sim_printf ("// dev code %02o\r\n", IDCW_DEV_CODE);
2236 sim_printf ("// ctrl %o (%s)\r\n", IDCW_CHAN_CTRL, charCtrls[IDCW_CHAN_CTRL]);
2237 sim_printf ("// chancmd %o (%s)\r\n", IDCW_CHAN_CMD, IDCW_CHAN_CMD < 16 ? chanCmds[IDCW_CHAN_CMD] : "unknown");
2238 sim_printf ("// count %o\r\n", IDCW_COUNT);
2239 } else {
2240 word18 TDCW_DATA_ADDRESS = getbits36_18 (DCW, 0);
2241 word1 TDCW_31_SEG = getbits36_1 (DCW, 31);
2242 word1 TDCW_32_PDTA = getbits36_1 (DCW, 32);
2243 word1 TDCW_33_PDCW = getbits36_1 (DCW, 33);
2244 word1 TDCW_33_EC = getbits36_1 (DCW, 33);
2245 word1 TDCW_34_RES = getbits36_1 (DCW, 34);
2246 word1 TDCW_35_REL = getbits36_1 (DCW, 35);
2247
2248 word12 DDCW_TALLY = getbits36_12 (DCW, 24);
2249 word18 DDCW_ADDR = getbits36_18 (DCW, 0);
2250 word2 DDCW_22_23_TYPE = getbits36_2 (DCW, 22);
2251 static char * types[4] = { "IOTD", "IOTP", "TDCW", "IONTP" };
2252 if (DDCW_22_23_TYPE == 2) {
2253 sim_printf ("// TDCW (2) %012llo\r\n", DCW);
2254 sim_printf ("// dcw ptr %06o\r\n", TDCW_DATA_ADDRESS);
2255 sim_printf ("// seg %o\r\n", TDCW_31_SEG);
2256 sim_printf ("// pdta %o\r\n", TDCW_32_PDTA);
2257 sim_printf ("// pdcw %o\r\n", TDCW_33_PDCW);
2258 sim_printf ("// ec %o\r\n", TDCW_33_EC);
2259 sim_printf ("// res %o\r\n", TDCW_34_RES);
2260 sim_printf ("// rel %o\r\n", TDCW_35_REL);
2261 } else {
2262 sim_printf ("// %s (%o) %012llo\r\n", types[DDCW_22_23_TYPE], DDCW_22_23_TYPE, DCW);
2263 sim_printf ("// tally %04o\r\n", DDCW_TALLY);
2264 sim_printf ("// addr %02o\r\n", DDCW_ADDR);
2265 sim_printf ("// cp %o\r\n", getbits36_3 (DCW, 18));
2266 }
2267 }
2268 }
2269
2270 static void dumpLPW (uint iom_unit_idx, uint chan) {
2271 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2272 char updateCase;
2273 if (p->LPW_21_NC)
2274 updateCase = 'c';
2275 else if (p->LPW_22_TAL)
2276 updateCase = 'b';
2277 else
2278 updateCase = 'a';
2279 static char * chanName[64] = {
2280 "0.",
2281 "1.",
2282 "Connect",
2283 "3.",
2284 "4.",
2285 "5.",
2286 "6.",
2287 "7.",
2288 "8.",
2289 "9.",
2290 "MTP Tape",
2291 "IPC Disk",
2292 "MPC Disk",
2293 "Card reader",
2294 "Card punch",
2295 "Printer",
2296 "FNP",
2297 "FNP",
2298 "FNP",
2299 "FNP",
2300 "FNP",
2301 "FNP",
2302 "FNP",
2303 "FNP",
2304 "24.",
2305 "25.",
2306 "ABSI",
2307 "27.",
2308 "28.",
2309 "29.",
2310 "Console",
2311 "31.",
2312 "Socket",
2313 "Socket",
2314 "Socket",
2315 "Socket",
2316 "Socket",
2317 "Socket",
2318 "Socket",
2319 "39.",
2320 "40.",
2321 "41.",
2322 "42.",
2323 "43.",
2324 "44.",
2325 "45.",
2326 "46.",
2327 "47.",
2328 "48.",
2329 "49.",
2330 "50.",
2331 "51.",
2332 "52.",
2333 "53.",
2334 "54.",
2335 "55.",
2336 "56.",
2337 "57.",
2338 "58.",
2339 "59.",
2340 "60.",
2341 "61.",
2342 "62.",
2343 "63."
2344 };
2345 sim_printf ("// %s channel LPW %012llo (case %c)\r\n", chanName[chan], p->LPW, updateCase);
2346 sim_printf ("// DCW pointer %06o\r\n", p->LPW_DCW_PTR);
2347 sim_printf ("// RES %o\r\n", p->LPW_18_RES);
2348 sim_printf ("// REL %o\r\n", p->LPW_19_REL);
2349 sim_printf ("// AE %o\r\n", p->LPW_20_AE);
2350 sim_printf ("// NC 21 %o\r\n", p->LPW_21_NC);
2351 sim_printf ("// TAL 22 %o\r\n", p->LPW_22_TAL);
2352 sim_printf ("// REL %o\r\n", p->LPW_23_REL);
2353 sim_printf ("// TALLY %04o\r\n", p->LPW_TALLY);
2354 sim_printf ("// \r\n");
2355 }
2356 #endif
2357
2358 static void fetch_and_parse_LPW (uint iom_unit_idx, uint chan)
2359 {
2360 #if defined(TESTING)
2361 cpu_state_t * cpup = _cpup;
2362 #endif
2363 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2364 uint chanLoc = mbxLoc (iom_unit_idx, chan);
2365
2366 iom_core_read (iom_unit_idx, chanLoc + IOM_MBX_LPW, (word36 *) & p -> LPW, __func__);
2367 sim_debug (DBG_DEBUG, & iom_dev,
2368 "%s: lpw %08o %012"PRIo64"\n", __func__, chanLoc + IOM_MBX_LPW, p->LPW);
2369
2370 p -> LPW_DCW_PTR = getbits36_18 (p -> LPW, 0);
2371 p -> LPW_18_RES = getbits36_1 (p -> LPW, 18);
2372 p -> LPW_19_REL = getbits36_1 (p -> LPW, 19);
2373 p -> LPW_20_AE = getbits36_1 (p -> LPW, 20);
2374 p -> LPW_21_NC = getbits36_1 (p -> LPW, 21);
2375 p -> LPW_22_TAL = getbits36_1 (p -> LPW, 22);
2376 p -> LPW_23_REL = getbits36_1 (p -> LPW, 23);
2377 p -> LPW_TALLY = getbits36_12 (p -> LPW, 24);
2378
2379 if (chan == IOM_CONNECT_CHAN)
2380 {
2381 p -> LPWX = 0;
2382 p -> LPWX_BOUND = 0;
2383 p -> LPWX_SIZE = 0;
2384 }
2385 else
2386 {
2387 iom_core_read (iom_unit_idx, chanLoc + IOM_MBX_LPWX, (word36 *) & p -> LPWX, __func__);
2388 p -> LPWX_BOUND = getbits36_18 (p -> LPWX, 0);
2389 p -> LPWX_SIZE = getbits36_18 (p -> LPWX, 18);
2390 }
2391 update_chan_mode (iom_unit_idx, chan, false);
2392 }
2393
2394 static void unpack_DCW (uint iom_unit_idx, uint chan)
2395 {
2396 #if defined(TESTING)
2397 cpu_state_t * cpup = _cpup;
2398 #endif
2399 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2400 p -> DCW_18_20_CP = getbits36_3 (p -> DCW, 18);
2401
2402 if (IS_IDCW (p))
2403 {
2404 p -> IDCW_DEV_CMD = getbits36_6 (p -> DCW, 0);
2405 p -> IDCW_DEV_CODE = getbits36_6 (p -> DCW, 6);
2406 p -> IDCW_AE = getbits36_6 (p -> DCW, 12);
2407 if (p -> LPW_23_REL)
2408 p -> IDCW_EC = 0;
2409 else
2410 p -> IDCW_EC = getbits36_1 (p -> DCW, 21);
2411 if (p -> IDCW_EC)
2412 p -> SEG = 1;
2413 p -> IDCW_CHAN_CTRL = getbits36_2 (p -> DCW, 22);
2414 p -> IDCW_CHAN_CMD = getbits36_6 (p -> DCW, 24);
2415 p -> IDCW_COUNT = getbits36_6 (p -> DCW, 30);
2416 p->recordResidue = p->IDCW_COUNT;
2417 #if defined(TESTING)
2418 sim_debug (DBG_DEBUG, & iom_dev,
2419 "%s: IDCW %012llo cmd %02o (%s) dev %02o ctrl %o chancmd %o\n",
2420 __func__, p->DCW, p->IDCW_DEV_CMD, cmdNames[p->IDCW_DEV_CMD],
2421 p->IDCW_DEV_CODE, p->IDCW_CHAN_CTRL, p->IDCW_CHAN_CMD);
2422 #endif
2423 }
2424 else
2425 {
2426 p -> TDCW_DATA_ADDRESS = getbits36_18 (p -> DCW, 0);
2427 p -> TDCW_31_SEG = getbits36_1 (p -> DCW, 31);
2428 p -> TDCW_32_PDTA = getbits36_1 (p -> DCW, 32);
2429 p -> TDCW_33_PDCW = getbits36_1 (p -> DCW, 33);
2430 p -> TDCW_33_EC = getbits36_1 (p -> DCW, 33);
2431 p -> TDCW_34_RES = getbits36_1 (p -> DCW, 34);
2432 p -> TDCW_35_REL = getbits36_1 (p -> DCW, 35);
2433 p -> DDCW_TALLY = getbits36_12 (p -> DCW, 24);
2434 p -> DDCW_ADDR = getbits36_18 (p -> DCW, 0);
2435 p -> DDCW_22_23_TYPE = getbits36_2 (p -> DCW, 22);
2436 sim_debug (DBG_DEBUG, & iom_dev,
2437 "%s: TDCW/DDCW %012llo tally %04o addr %06o type %o\n",
2438 __func__, p->DCW, p->DDCW_TALLY, p->DDCW_ADDR, p->DDCW_22_23_TYPE);
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 static void pack_DCW (uint iom_unit_idx, uint chan)
2464 {
2465
2466 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2467 putbits36_3 ((word36 *) & p -> DCW, 18, p -> DCW_18_20_CP);
2468 }
2469
2470 static void pack_LPW (uint iom_unit_idx, uint chan)
2471 {
2472 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2473 putbits36_18 ((word36 *) & p-> LPW, 0, p -> LPW_DCW_PTR);
2474 putbits36_1 ((word36 *) & p-> LPW, 18, p -> LPW_18_RES);
2475 putbits36_1 ((word36 *) & p-> LPW, 19, p -> LPW_19_REL);
2476 putbits36_1 ((word36 *) & p-> LPW, 20, p -> LPW_20_AE);
2477 putbits36_1 ((word36 *) & p-> LPW, 21, p -> LPW_21_NC);
2478 putbits36_1 ((word36 *) & p-> LPW, 22, p -> LPW_22_TAL);
2479 putbits36_1 ((word36 *) & p-> LPW, 23, p -> LPW_23_REL);
2480 putbits36_12 ((word36 *) & p-> LPW, 24, p -> LPW_TALLY);
2481 putbits36_18 ((word36 *) & p-> LPWX, 0, p -> LPWX_BOUND);
2482 putbits36_18 ((word36 *) & p-> LPWX, 18, p -> LPWX_SIZE);
2483 }
2484
2485 static void fetch_and_parse_PCW (uint iom_unit_idx, uint chan)
2486 {
2487 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2488
2489 iom_core_read2 (iom_unit_idx, p -> LPW_DCW_PTR, (word36 *) & p -> PCW0, (word36 *) & p -> PCW1, __func__);
2490 p -> PCW_CHAN = getbits36_6 (p -> PCW1, 3);
2491 p -> PCW_AE = getbits36_6 (p -> PCW0, 12);
2492 p -> PCW_21_MSK = getbits36_1 (p -> PCW0, 21);
2493 p -> PCW_PAGE_TABLE_PTR = getbits36_18 (p -> PCW1, 9);
2494 p -> PCW_63_PTP = getbits36_1 (p -> PCW1, 27);
2495 p -> PCW_64_PGE = getbits36_1 (p -> PCW1, 28);
2496 p -> PCW_65_AUX = getbits36_1 (p -> PCW1, 29);
2497 if (p -> PCW_65_AUX)
2498 sim_warn ("PCW_65_AUX\n");
2499 p -> DCW = p -> PCW0;
2500 unpack_DCW (iom_unit_idx, chan);
2501 }
2502
2503 static void fetch_and_parse_DCW (uint iom_unit_idx, uint chan, UNUSED bool read_only)
2504 {
2505 #if defined(TESTING)
2506 cpu_state_t * cpup = _cpup;
2507 #endif
2508 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2509 word24 addr = p -> LPW_DCW_PTR & MASK18;
2510
2511 sim_debug (DBG_DEBUG, & iom_dev, "%s: addr %08o\n", __func__, addr);
2512 switch (p -> chanMode)
2513 {
2514
2515 case cm1:
2516 case cm1e:
2517 {
2518 iom_core_read (iom_unit_idx, addr, (word36 *) & p -> DCW, __func__);
2519 }
2520 break;
2521
2522
2523 case cm2e:
2524 {
2525
2526
2527 addr += ((word24) p -> LPWX_BOUND << 1);
2528 iom_core_read (iom_unit_idx, addr, (word36 *) & p -> DCW, __func__);
2529 }
2530 break;
2531
2532 case cm2:
2533 case cm3b:
2534 {
2535 sim_warn ("fetch_and_parse_DCW LPW paged\n");
2536 }
2537 break;
2538
2539 case cm3a:
2540 case cm4:
2541 case cm5:
2542 {
2543 fetch_LPWPTW (iom_unit_idx, chan);
2544
2545
2546 word24 addr_ = ((word24) (getbits36_14 (p -> PTW_LPW, 4) << 10)) | ((p -> LPW_DCW_PTR) & MASK10);
2547 iom_core_read (iom_unit_idx, addr_, (word36 *) & p -> DCW, __func__);
2548 }
2549 break;
2550 }
2551 unpack_DCW (iom_unit_idx, chan);
2552
2553 if (IS_IDCW (p))
2554 sim_debug (DBG_DEBUG, & iom_dev,
2555 "%s: chan %d idcw: dev_cmd %#o dev_code %#o ae %#o ec %d control %#o chan_cmd %#o data %#o\n",
2556 __func__, p -> PCW_CHAN, p -> IDCW_DEV_CMD, p -> IDCW_DEV_CODE, p -> IDCW_AE,
2557 p -> IDCW_EC, p -> IDCW_CHAN_CTRL, p -> IDCW_CHAN_CMD, p -> IDCW_COUNT);
2558 else
2559 if (p -> DDCW_22_23_TYPE == 02)
2560 sim_debug (DBG_DEBUG, & iom_dev,
2561 "%s: chan %d tdcw: address %#o seg %d pdta %d pdcw/ec %d res %d rel %d\n",
2562 __func__, p -> PCW_CHAN, p -> TDCW_DATA_ADDRESS, p -> TDCW_31_SEG,
2563 p -> TDCW_32_PDTA, p -> TDCW_33_PDCW, p -> TDCW_34_RES, p -> TDCW_35_REL);
2564 else
2565 sim_debug (DBG_DEBUG, & iom_dev,
2566 "%s: chan %d ddcw: address %#o char_pos %#o type %#o tally %#o\n",
2567 __func__, p -> PCW_CHAN, p -> DDCW_ADDR, p -> DCW_18_20_CP,
2568 p -> DDCW_22_23_TYPE, p -> DDCW_TALLY);
2569 }
2570
2571
2572
2573
2574
2575
2576
2577
2578 int send_general_interrupt (uint iom_unit_idx, uint chan, enum iomImwPics pic)
2579 {
2580 #if defined(TESTING)
2581 cpu_state_t * cpup = _cpup;
2582 #endif
2583 uint imw_addr;
2584 uint chan_group = chan < 32 ? 1 : 0;
2585 uint chan_in_group = chan & 037;
2586
2587 uint iomUnitNum =
2588 iom_unit_data[iom_unit_idx].configSwMultiplexBaseAddress & 3u;
2589 uint interrupt_num = iomUnitNum | (chan_group << 2) | ((uint) pic << 3);
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600 uint pi_base = iom_unit_data[iom_unit_idx].configSwMultiplexBaseAddress & ~3u;
2601 imw_addr = (pi_base << 3) | interrupt_num;
2602
2603 sim_debug (DBG_DEBUG, & iom_dev,
2604 "%s: IOM %c, channel %d (%#o), level %d; "
2605 "Interrupt %d (%#o).\n",
2606 __func__, iomChar (iom_unit_idx), chan, chan, pic, interrupt_num,
2607 interrupt_num);
2608 word36 imw;
2609 iom_core_read_lock (iom_unit_idx, imw_addr, &imw, __func__);
2610
2611
2612
2613
2614
2615 putbits36_1 (& imw, chan_in_group, 1);
2616 iom_core_write_unlock (iom_unit_idx, imw_addr, imw, __func__);
2617 return scu_set_interrupt (iom_unit_data[iom_unit_idx].invokingScuUnitIdx, interrupt_num);
2618 }
2619
2620 static void iom_fault (uint iom_unit_idx, uint chan, UNUSED const char * who,
2621 iomFaultServiceRequest req,
2622 iomSysFaults_t signal)
2623 {
2624 #if defined(TESTING)
2625 cpu_state_t * cpup = _cpup;
2626 #endif
2627 sim_warn ("iom_fault %s\n", who);
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654 sim_debug (DBG_DEBUG, & iom_dev,
2655 "%s: chan %d %s req %#o signal %#o\n",
2656 __func__, chan, who, req, signal);
2657
2658 word36 faultWord = 0;
2659 putbits36_9 (& faultWord, 9, (word9) chan);
2660 putbits36_5 (& faultWord, 18, (word5) req);
2661
2662 putbits36_6 (& faultWord, 30, (word6) signal);
2663
2664 uint chanloc = mbxLoc (iom_unit_idx, IOM_SYSTEM_FAULT_CHAN);
2665
2666 word36 lpw;
2667 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_LPW, & lpw, __func__);
2668
2669 word36 scw;
2670 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_SCW, & scw, __func__);
2671
2672 word36 dcw;
2673 iom_core_read_lock (iom_unit_idx, chanloc + IOM_MBX_DCW, & dcw, __func__);
2674
2675
2676
2677
2678
2679 iom_core_write (iom_unit_idx, (dcw >> 18) & MASK18, faultWord, __func__);
2680
2681 uint tally = dcw & MASK12;
2682 if (tally > 1)
2683 {
2684 dcw -= 01llu;
2685 dcw += 01000000llu;
2686 }
2687 else
2688 dcw = scw;
2689 iom_core_write_unlock (iom_unit_idx, chanloc + IOM_MBX_DCW, dcw, __func__);
2690
2691 send_general_interrupt (iom_unit_idx, IOM_SYSTEM_FAULT_CHAN, imwSystemFaultPic);
2692 }
2693
2694
2695
2696
2697
2698
2699 int iom_list_service (uint iom_unit_idx, uint chan,
2700 bool * ptro, bool * sendp, bool * uffp)
2701 {
2702 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2703
2704
2705
2706 bool isConnChan = chan == IOM_CONNECT_CHAN;
2707 * ptro = false;
2708 bool uff = false;
2709 bool send = false;
2710
2711
2712
2713
2714
2715
2716
2717 if (p -> lsFirst)
2718 {
2719
2720
2721 fetch_and_parse_LPW (iom_unit_idx, chan);
2722 p -> wasTDCW = false;
2723 p -> SEG = 0;
2724 }
2725
2726
2727
2728
2729 if (isConnChan)
2730 {
2731
2732
2733
2734 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 0)
2735 {
2736 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2737 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2738 iomIllTalCChnFlt);
2739 return -1;
2740 }
2741
2742 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 1)
2743 {
2744
2745
2746
2747 if (p -> LPW_TALLY == 0)
2748 {
2749 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2750 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2751 iomIllTalCChnFlt);
2752 return -1;
2753 }
2754
2755 if (p -> LPW_TALLY > 1)
2756 {
2757
2758
2759 if (p -> LPW_20_AE == 0 &&
2760 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
2761 01000000llu)
2762 {
2763 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2764 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2765 iom256KFlt);
2766 return -1;
2767 }
2768 }
2769 else if (p -> LPW_TALLY == 1)
2770 * ptro = true;
2771 }
2772 else
2773 * ptro = true;
2774
2775
2776
2777
2778
2779 fetch_and_parse_PCW (iom_unit_idx, chan);
2780
2781
2782 if (IS_NOT_IDCW (p))
2783 {
2784 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2785 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2786 iomNotPCWFlt);
2787 return -1;
2788 }
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801 send = true;
2802
2803 goto D;
2804 }
2805
2806
2807
2808
2809
2810 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 0)
2811 {
2812
2813
2814 if (p -> LPW_20_AE == 0 &&
2815 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
2816 01000000llu)
2817 {
2818 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2819 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2820 iom256KFlt);
2821 return -1;
2822 }
2823 }
2824 else if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 1)
2825 {
2826 A:;
2827
2828
2829 if (p -> LPW_TALLY == 0)
2830 {
2831 uff = true;
2832 }
2833 else if (p -> LPW_TALLY > 1)
2834 {
2835
2836
2837
2838 if (p -> LPW_20_AE == 0 &&
2839 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
2840 01000000llu)
2841 {
2842 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2843 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2844 iom256KFlt);
2845 return -1;
2846 }
2847 }
2848 }
2849
2850
2851
2852
2853 fetch_and_parse_DCW (iom_unit_idx, chan, false);
2854
2855
2856
2857
2858
2859 if (IS_IDCW (p))
2860 {
2861
2862
2863 if (p -> LPW_18_RES)
2864 {
2865
2866 uff = true;
2867
2868 }
2869 else
2870 {
2871
2872
2873 send = true;
2874 }
2875 p -> LPWX_SIZE = p -> LPW_DCW_PTR;
2876 goto D;
2877 }
2878
2879
2880
2881 if (p -> lsFirst)
2882 p -> LPWX_SIZE = p -> LPW_DCW_PTR;
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893 if (IS_TDCW (p))
2894 {
2895
2896 if (p -> wasTDCW)
2897 {
2898 uff = true;
2899 goto uffSet;
2900 }
2901 p -> wasTDCW = true;
2902
2903
2904
2905 p -> LPW_DCW_PTR = p -> TDCW_DATA_ADDRESS;
2906
2907
2908
2909
2910 p -> LPW_20_AE |= p -> TDCW_33_EC;
2911 p -> LPW_18_RES |= p -> TDCW_34_RES;
2912 p -> LPW_23_REL |= p -> TDCW_35_REL;
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945 if (p -> TDCW_31_SEG)
2946 sim_warn ("TDCW_31_SEG\n");
2947
2948 update_chan_mode (iom_unit_idx, chan, true);
2949
2950
2951 p -> LPW_TALLY = (p -> LPW_TALLY - 1u) & MASK12;
2952
2953 pack_LPW (iom_unit_idx, chan);
2954
2955
2956
2957 if (p -> LPW_18_RES && p -> TDCW_33_EC)
2958 {
2959 uff = true;
2960 goto uffSet;
2961 }
2962
2963 goto A;
2964 }
2965
2966 p -> wasTDCW = false;
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992 if (uff)
2993 {
2994 uffSet:;
2995
2996 p -> DCW_18_20_CP = 07u;
2997 pack_DCW (iom_unit_idx, chan);
2998 }
2999
3000
3001
3002
3003
3004
3005
3006
3007 send = true;
3008
3009
3010
3011 D:;
3012
3013
3014
3015 * uffp = uff;
3016 * sendp = send;
3017
3018
3019
3020 if (p -> LPW_21_NC == 0)
3021 {
3022
3023 if (isConnChan)
3024 p -> LPW_DCW_PTR = (p -> LPW_DCW_PTR + 2u) & MASK18;
3025 else
3026 p -> LPW_DCW_PTR = (p -> LPW_DCW_PTR + 1u) & MASK18;
3027
3028
3029 p->LPW_TALLY = ((word12) (((word12s) p->LPW_TALLY) - 1)) & MASK12;
3030 pack_LPW (iom_unit_idx, chan);
3031 }
3032
3033
3034 if (p -> DDCW_22_23_TYPE == 07u || p -> lsFirst)
3035 {
3036
3037
3038
3039
3040 write_LPW (iom_unit_idx, chan);
3041 }
3042 else
3043 {
3044 if (p -> LPW_21_NC == 0 ||
3045 (IS_TDCW (p)))
3046 {
3047
3048
3049
3050
3051 write_LPW (iom_unit_idx, chan);
3052 }
3053 }
3054
3055 p -> lsFirst = false;
3056
3057
3058 return 0;
3059 }
3060
3061
3062
3063 static int doPayloadChannel (uint iomUnitIdx, uint chan) {
3064 #if defined(TESTING)
3065 cpu_state_t * cpup = _cpup;
3066 sim_debug (DBG_DEBUG, & iom_dev, "%s: Payload channel %c%02o\n", __func__, iomChar (iomUnitIdx), chan);
3067 #endif
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
3086
3087 #if defined(TESTING)
3088 word36 PCW_DCW = p->DCW;
3089 word1 PCW_LPW_23_REL = p->LPW_23_REL;
3090 #endif
3091 p -> chanMode = cm1;
3092 p -> LPW_18_RES = 0;
3093 p -> LPW_20_AE = 0;
3094 p -> LPW_23_REL = 0;
3095
3096 unpack_DCW (iomUnitIdx, chan);
3097
3098 p->isPCW = true;
3099
3100
3101
3102 struct iom_to_ctlr_s * d = & cables->iom_to_ctlr[iomUnitIdx][chan];
3103
3104
3105
3106
3107 if (d->chan_type != chan_type_CPI && p -> IDCW_DEV_CMD == 051) {
3108 p->stati = 04501;
3109 send_terminate_interrupt (iomUnitIdx, chan);
3110 return 0;
3111 }
3112
3113 if ((!d->in_use) || (!d->iom_cmd)) {
3114 p -> stati = 06000;
3115 #if defined(POLTS_TESTING)
3116 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf \
3117 ("// terminate 10. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3118 #endif
3119 goto terminate;
3120 }
3121
3122
3123
3124
3125
3126 p -> ADDR_EXT = p -> PCW_AE;
3127
3128 p -> lsFirst = true;
3129
3130 p -> tallyResidue = 0;
3131 p -> isRead = true;
3132 p -> charPos = 0;
3133
3134
3135
3136 p -> initiate = true;
3137 p -> chanStatus = chanStatNormal;
3138
3139
3140
3141
3142 int rc = d->iom_cmd (iomUnitIdx, chan);
3143
3144 if (rc < 0) {
3145 p -> dev_code = getbits36_6 (p -> DCW, 6);
3146 #if defined(POLTS_TESTING)
3147 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3148 sim_printf ("// terminate 9. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3149 #endif
3150 goto terminate;
3151 }
3152
3153 if (IS_IDCW (p) && p->IDCW_CHAN_CTRL == CHAN_CTRL_MARKER) {
3154 send_marker_interrupt (iomUnitIdx, (int) chan);
3155 }
3156
3157 if (rc == IOM_CMD_DISCONNECT) {
3158 #if defined(POLTS_TESTING)
3159 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf \
3160 ("// terminate 8. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3161 #endif
3162 goto terminate;
3163 }
3164
3165 if (p->masked) {
3166 #if defined(POLTS_TESTING)
3167 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf \
3168 ("// terminate 7. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3169 #endif
3170 goto terminate;
3171 }
3172
3173 bool ptro, send, uff;
3174 bool terminate = false;
3175 p->isPCW = false;
3176
3177 #if defined(TESTING)
3178 bool first = true;
3179 #endif
3180
3181 (void)terminate;
3182 bool idcw_terminate = p -> IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE;
3183 do {
3184 int rc2 = iom_list_service (iomUnitIdx, chan, & ptro, & send, & uff);
3185 if (rc2 < 0) {
3186
3187 sim_warn ("%s list service failed\n", __func__);
3188 return -1;
3189 }
3190 if (uff) {
3191
3192 #if defined(POLTS_TESTING)
3193 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3194 sim_printf ("// terminate 6. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3195 #endif
3196 goto terminate;
3197 }
3198
3199 if (! send) {
3200 sim_warn ("%s nothing to send\n", __func__);
3201 return 1;
3202 }
3203
3204 #if defined(TESTING)
3205 # if defined(POLTS_TESTING)
3206 if (iomUnitIdx == 1 && chan == 020)
3207 # endif
3208 if_sim_debug (DBG_TRACE, & iom_dev) {
3209 if (first) {
3210 first = false;
3211 dumpLPW (iomUnitIdx, chan);
3212 sim_printf ("// DCW list dump: \r\n");
3213 dumpDCW (PCW_DCW, PCW_LPW_23_REL);
3214 for (int i = 0; i < 8; i ++)
3215 dumpDCW (M[p->LPW_DCW_PTR - 1 + i], p->LPW_23_REL);
3216 sim_printf ("// \r\n");
3217 }
3218 }
3219 #endif
3220
3221
3222
3223
3224
3225
3226 if (IS_IDCW (p)) {
3227 idcw_terminate = p -> IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE;
3228 if (p -> LPW_23_REL == 0 && p -> IDCW_EC == 1)
3229 p -> ADDR_EXT = getbits36_6 (p -> DCW, 12);
3230
3231 p -> tallyResidue = 0;
3232 p -> isRead = true;
3233 p -> charPos = 0;
3234 p -> chanStatus = chanStatNormal;
3235 }
3236
3237
3238
3239 rc2 = d->iom_cmd (iomUnitIdx, chan);
3240
3241 if (rc2 < 0) {
3242 p -> dev_code = getbits36_6 (p -> DCW, 6);
3243 #if defined(POLTS_TESTING)
3244 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3245 sim_printf ("// terminate 5. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3246 #endif
3247 goto terminate;
3248 }
3249
3250 if (rc2 == IOM_CMD_DISCONNECT) {
3251 terminate = true;
3252 #if defined(POLTS_TESTING)
3253 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf \
3254 ("// terminate 4. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3255 #endif
3256 }
3257
3258 if (rc2 == IOM_CMD_PENDING)
3259 goto pending;
3260
3261
3262 if (IS_IDCW (p) && p->IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE && p->IDCW_CHAN_CMD == CHAN_CMD_NONDATA) {
3263 #if defined(POLTS_TESTING)
3264 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3265 sim_printf ("// terminate 1. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3266 #endif
3267 goto terminate;
3268 }
3269
3270 if (IS_IOTD (p) && idcw_terminate && rc2 != IOM_CMD_RESIDUE) {
3271 #if defined(POLTS_TESTING)
3272
3273
3274 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3275 sim_printf ("// terminate 2. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3276 #endif
3277 goto terminate;
3278 }
3279
3280
3281
3282 if (IS_NOT_IDCW (p) && rc2 == IOM_CMD_RESIDUE) {
3283 if (p->recordResidue)
3284 p->recordResidue --;
3285 if (p->recordResidue == 0)
3286 goto terminate;
3287 }
3288 } while (! terminate);
3289
3290 terminate:;
3291 #if defined(POLTS_TESTING)
3292 if (iomUnitIdx == 1 && chan == 020) sim_printf ("stati %04o\r\n", p->stati);
3293 #endif
3294 send_terminate_interrupt (iomUnitIdx, chan);
3295 return 0;
3296
3297 pending:;
3298 return 0;
3299 }
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312 static int doConnectChan (uint iom_unit_idx) {
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324 #if defined(TESTING)
3325 cpu_state_t * cpup = _cpup;
3326 #endif
3327 sim_debug (DBG_DEBUG, & iom_dev, "%s: Connect channel\n", __func__);
3328 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][IOM_CONNECT_CHAN];
3329 p -> lsFirst = true;
3330 #if defined(TESTING) && defined(POLTS_TESTING)
3331 bool first = true;
3332 #endif
3333 bool ptro, send, uff;
3334 do {
3335
3336 int rc = iom_list_service (iom_unit_idx, IOM_CONNECT_CHAN, & ptro, & send, & uff);
3337 if (rc < 0) {
3338 sim_warn ("connect channel connect failed\n");
3339 return -1;
3340 }
3341 if (uff) {
3342 sim_warn ("connect channel ignoring uff\n");
3343 }
3344 if (! send) {
3345 sim_warn ("connect channel nothing to send\n");
3346 } else {
3347 #if defined(xTESTING)
3348 if_sim_debug (DBG_TRACE, & iom_dev) {
3349 if (first) {
3350 first = false;
3351 sim_printf ("// CIOC %lld\r\n", cpu.cycleCnt);
3352 dumpLPW (iom_unit_idx, IOM_CONNECT_CHAN);
3353 sim_printf ("// PCW %012llo %012llo\r\n", p->PCW0, p->PCW1);
3354 sim_printf ("// Chan info %04o\r\n", p->PCW_CHAN);
3355 sim_printf ("// Addr ext %02o\r\n", p->PCW_AE);
3356 sim_printf ("// 111 %o\r\n", getbits36_3 (p->PCW0, 18));
3357 sim_printf ("// M %o\r\n", p->PCW_21_MSK);
3358 sim_printf ("// Chan info %08o\r\n", getbits36_14 (p->PCW0, 22));
3359 sim_printf ("// Pg Tbl Ptr %06o\r\n", p->PCW_PAGE_TABLE_PTR);
3360 sim_printf ("// PTP %o\r\n", p->PCW_63_PTP);
3361 sim_printf ("// PGE %o\r\n", p->PCW_64_PGE);
3362 sim_printf ("// AUX %o\r\n", p->PCW_65_AUX);
3363 sim_printf ("//\r\n");
3364 }
3365 }
3366 #endif
3367
3368 iom_chan_data_t * q = & iom_chan_data[iom_unit_idx][p -> PCW_CHAN];
3369
3370 q -> PCW0 = p -> PCW0;
3371 q -> PCW1 = p -> PCW1;
3372 q -> PCW_CHAN = p -> PCW_CHAN;
3373 q -> PCW_AE = p -> PCW_AE;
3374 q -> PCW_PAGE_TABLE_PTR = p -> PCW_PAGE_TABLE_PTR;
3375 q -> PCW_63_PTP = p -> PCW_63_PTP;
3376 q -> PCW_64_PGE = p -> PCW_64_PGE;
3377 q -> PCW_65_AUX = p -> PCW_65_AUX;
3378 q -> PCW_21_MSK = p -> PCW_21_MSK;
3379 q -> DCW = p -> DCW;
3380
3381 sim_debug (DBG_DEBUG, & iom_dev, "%s: PCW %012llo %012llo chan %02o\n", __func__, q->PCW0, q->PCW1, q->PCW_CHAN);
3382
3383 q -> masked = p -> PCW_21_MSK;
3384 if (q -> masked) {
3385 if (q -> in_use)
3386 sim_warn ("%s: chan %d masked while in use\n", __func__, p -> PCW_CHAN);
3387 q -> in_use = false;
3388 q -> start = false;
3389 } else {
3390 if (q -> in_use)
3391 sim_warn ("%s: chan %d connect while in use\n", __func__, p -> PCW_CHAN);
3392 q -> in_use = true;
3393 q -> start = true;
3394 #if defined(IO_THREADZ)
3395 setChnConnect (iom_unit_idx, p -> PCW_CHAN);
3396 #else
3397 # if !defined(IO_ASYNC_PAYLOAD_CHAN) && !defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
3398 doPayloadChannel (iom_unit_idx, p -> PCW_CHAN);
3399 # endif
3400 # if defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
3401 pthread_cond_signal (& iomCond);
3402 # endif
3403 #endif
3404 }
3405 }
3406 } while (! ptro);
3407 return 0;
3408 }
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420 int send_marker_interrupt (uint iom_unit_idx, int chan)
3421 {
3422 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3423 return(0);
3424 status_service (iom_unit_idx, (uint) chan, true);
3425 return send_general_interrupt (iom_unit_idx, (uint) chan, imwMarkerPic);
3426 }
3427
3428
3429
3430
3431
3432
3433
3434
3435 int send_special_interrupt (uint iom_unit_idx, uint chan, uint devCode,
3436 word8 status0, word8 status1)
3437 {
3438
3439 uint chanloc = mbxLoc (iom_unit_idx, IOM_SPECIAL_STATUS_CHAN);
3440
3441 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3442 return(0);
3443
3444 #if defined(LOCKLESS)
3445 lock_iom();
3446 #endif
3447
3448
3449
3450
3451
3452
3453 word36 lpw;
3454 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_LPW, & lpw, __func__);
3455
3456 word36 scw;
3457 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_SCW, & scw, __func__);
3458
3459 word36 dcw;
3460 iom_core_read_lock (iom_unit_idx, chanloc + IOM_MBX_DCW, & dcw, __func__);
3461
3462 word36 status = 0400000000000ull;
3463 status |= (((word36) chan) & MASK6) << 27;
3464 status |= (((word36) devCode) & MASK8) << 18;
3465 status |= (((word36) status0) & MASK8) << 9;
3466 status |= (((word36) status1) & MASK8) << 0;
3467 iom_core_write (iom_unit_idx, (dcw >> 18) & MASK18, status, __func__);
3468
3469 uint tally = dcw & MASK12;
3470 if (tally > 1)
3471 {
3472 dcw -= 01llu;
3473 dcw += 01000000llu;
3474 }
3475 else
3476 dcw = scw;
3477 iom_core_write_unlock (iom_unit_idx, chanloc + IOM_MBX_DCW, dcw, __func__);
3478
3479 #if defined(LOCKLESS)
3480 unlock_iom();
3481 #endif
3482
3483 send_general_interrupt (iom_unit_idx, IOM_SPECIAL_STATUS_CHAN, imwSpecialPic);
3484 return 0;
3485 }
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496 int send_terminate_interrupt (uint iom_unit_idx, uint chan)
3497 {
3498 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3499 return 0;
3500 status_service (iom_unit_idx, chan, false);
3501 if (iom_chan_data [iom_unit_idx] [chan] . in_use == false)
3502 sim_warn ("%s: chan %d not in use\n", __func__, chan);
3503 iom_chan_data [iom_unit_idx] [chan] . in_use = false;
3504 send_general_interrupt (iom_unit_idx, chan, imwTerminatePic);
3505 return 0;
3506 }
3507
3508 void iom_interrupt (uint scu_unit_idx, uint iom_unit_idx)
3509 {
3510 cpu_state_t * cpup = _cpup;
3511 sim_debug (DBG_DEBUG, & iom_dev,
3512 "%s: IOM %c starting. [%"PRId64"] %05o:%08o\n",
3513 __func__, iomChar (iom_unit_idx), cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC);
3514
3515 iom_unit_data[iom_unit_idx].invokingScuUnitIdx = scu_unit_idx;
3516
3517 #if defined(IO_THREADZ)
3518 setIOMInterrupt (iom_unit_idx);
3519 iomDoneWait (iom_unit_idx);
3520 #else
3521 int ret = doConnectChan (iom_unit_idx);
3522
3523 sim_debug (DBG_DEBUG, & iom_dev,
3524 "%s: IOM %c finished; doConnectChan returned %d.\n",
3525 __func__, iomChar (iom_unit_idx), ret);
3526 #endif
3527
3528 }
3529
3530 #if defined(IO_THREADZ)
3531 void * chan_thread_main (void * arg)
3532 {
3533 uint myid = (uint) * (int *) arg;
3534 this_iom_idx = (uint) myid / MAX_CHANNELS;
3535 this_chan_num = (uint) myid % MAX_CHANNELS;
3536
3537
3538
3539 set_cpu_idx (0);
3540
3541 sim_msg ("\rIOM %c Channel %u thread created\r\n", this_iom_idx + 'a', this_chan_num);
3542 # if defined(TESTING)
3543 printPtid(pthread_self());
3544 # endif
3545 sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
3546
3547 setSignals ();
3548 while (1)
3549 {
3550
3551 chnConnectWait ();
3552
3553 doPayloadChannel (this_iom_idx, this_chan_num);
3554 chnConnectDone ();
3555 }
3556 }
3557
3558 void * iom_thread_main (void * arg)
3559 {
3560 int myid = * (int *) arg;
3561 this_iom_idx = (uint) myid;
3562
3563
3564
3565 set_cpu_idx (0);
3566
3567 sim_printf("IOM %c thread created\n", 'a' + myid);
3568
3569 setSignals ();
3570 while (1)
3571 {
3572
3573 iomInterruptWait ();
3574
3575 int ret = doConnectChan (this_iom_idx);
3576
3577 sim_debug (DBG_DEBUG, & iom_dev,
3578 "%s: IOM %c finished; doConnectChan returned %d.\n",
3579 __func__, iomChar (myid), ret);
3580 iomInterruptDone ();
3581 }
3582 }
3583 #endif
3584
3585
3586
3587
3588
3589
3590
3591 void iom_init (void)
3592 {
3593
3594 }
3595
3596 #if defined(PANEL68)
3597 void do_boot (void)
3598 {
3599 boot_svc (& boot_channel_unit[0]);
3600 }
3601 #endif
3602
3603 #if defined(IO_ASYNC_PAYLOAD_CHAN) || defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
3604 void iomProcess (void)
3605 {
3606 for (uint i = 0; i < N_IOM_UNITS_MAX; i++)
3607 for (uint j = 0; j < MAX_CHANNELS; j++)
3608 {
3609 iom_chan_data_t * p = &iom_chan_data [i] [j];
3610 if (p -> start)
3611 {
3612 p -> start = false;
3613 doPayloadChannel (i, j);
3614 }
3615 }
3616 }
3617 #endif
3618
3619 char iomChar (uint iomUnitIdx)
3620 {
3621 return (iom_unit_data[iomUnitIdx].configSwMultiplexBaseAddress & 3) + 'A';
3622 }