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