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
550
551
552 #include "dps8.h"
553 #include "dps8_cpu.h"
554 #include "dps8_sys.h"
555 #include "dps8_faults.h"
556 #include "dps8_scu.h"
557 #include "dps8_iom.h"
558 #include "dps8_cable.h"
559 #include "dps8_console.h"
560 #include "dps8_fnp2.h"
561 #include "dps8_utils.h"
562 #if defined(LOCKLESS)
563 # include "threadz.h"
564 #endif
565
566 #define DBG_CTR 1
567
568
569
570
571
572
573
574
575 #define N_IOM_UNITS 1
576
577 #define IOM_UNIT_IDX(uptr) ((uptr) - iom_unit)
578
579 #define IOM_SYSTEM_FAULT_CHAN 1U
580 #define IOM_CONNECT_CHAN 2U
581 #define IOM_SPECIAL_STATUS_CHAN 6U
582
583 iom_chan_data_t iom_chan_data[N_IOM_UNITS_MAX][MAX_CHANNELS];
584
585 typedef enum iom_status_t
586 {
587 iomStatNormal = 0,
588 iomStatLPWTRO = 1,
589 iomStat2TDCW = 2,
590 iomStatBoundaryError = 3,
591 iomStatAERestricted = 4,
592 iomStatIDCWRestricted = 5,
593 iomStatCPDiscrepancy = 6,
594 iomStatParityErr = 7
595 } iom_status_t;
596
597 enum config_sw_OS_t
598 {
599 CONFIG_SW_STD_GCOS,
600 CONFIG_SW_EXT_GCOS,
601 CONFIG_SW_MULTICS
602 };
603
604 enum config_sw_model_t
605 {
606 CONFIG_SW_MODEL_IOM,
607 CONFIG_SW_MODEL_IMU
608 };
609
610
611 enum config_sw_bootload_device_e { CONFIG_SW_BLCT_CARD, CONFIG_SW_BLCT_TAPE };
612
613 typedef struct
614 {
615
616
617
618 word12 configSwIomBaseAddress;
619
620
621
622
623
624
625
626
627
628
629
630
631 word9 configSwMultiplexBaseAddress;
632
633 enum config_sw_model_t config_sw_model;
634
635
636 enum config_sw_OS_t config_sw_OS;
637
638
639 enum config_sw_bootload_device_e configSwBootloadCardTape;
640
641
642 word6 configSwBootloadMagtapeChan;
643
644
645 word6 configSwBootloadCardrdrChan;
646
647
648
649
650
651
652
653
654 word3 configSwBootloadPort;
655
656
657
658
659 uint configSwPortAddress[N_IOM_PORTS];
660
661
662 uint configSwPortInterface[N_IOM_PORTS];
663
664
665 uint configSwPortEnable[N_IOM_PORTS];
666
667
668 uint configSwPortSysinitEnable[N_IOM_PORTS];
669
670
671 uint configSwPortHalfsize[N_IOM_PORTS];
672
673 uint configSwPortStoresize[N_IOM_PORTS];
674
675
676
677
678 iom_status_t iomStatus;
679
680 uint invokingScuUnitIdx;
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 #ifdef IO_THREADZ
738 __thread uint this_iom_idx;
739 __thread uint this_chan_num;
740 #endif
741
742 #ifdef 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 #ifdef LOCKLESS
815 # ifndef 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 #ifdef LOCKLESS
828 # ifndef SUNLINT
829 word36 v;
830 LOAD_ACQ_CORE_WORD(v, addr);
831 * even = v & DMASK;
832 # endif
833 addr++;
834 # ifndef 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 (UNUSED uint iom_unit_idx, word24 addr, word36 data, UNUSED const char * ctx)
845 {
846 #ifdef LOCKLESS
847 LOCK_CORE_WORD(addr);
848 # ifndef 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 #ifdef LOCKLESS
859 LOCK_CORE_WORD(addr);
860 # ifndef SUNLINT
861 STORE_REL_CORE_WORD(addr, even);
862 # endif
863 addr++;
864 LOCK_CORE_WORD(addr);
865 # ifndef 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 #ifdef LOCKLESS
877 LOCK_CORE_WORD(addr);
878 # ifndef 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 #ifdef LOCKLESS
891 # ifndef 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 #ifdef 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 #ifdef 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 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1718
1719
1720
1721
1722 word36 word1, word2;
1723 word1 = 0;
1724 putbits36_12 (& word1, 0, p -> stati);
1725
1726
1727
1728 putbits36_1 (& word1, 13, marker ? 1 : 0);
1729 putbits36_2 (& word1, 14, 0);
1730 putbits36_1 (& word1, 16, p -> initiate ? 1 : 0);
1731 putbits36_1 (& word1, 17, 0);
1732 putbits36_3 (& word1, 18, (word3) p -> chanStatus);
1733
1734 putbits36_3 (& word1, 21, 0);
1735
1736
1737
1738
1739 putbits36_6 (& word1, 30, p -> recordResidue);
1740
1741 word2 = 0;
1742
1743
1744
1745
1746
1747 putbits36_3 (& word2, 18, p -> charPos);
1748 putbits36_1 (& word2, 21, p -> isRead ? 1 : 0);
1749 putbits36_12 (& word2, 24, p -> tallyResidue);
1750
1751
1752
1753
1754
1755
1756 uint chanloc = mbxLoc (iom_unit_idx, chan);
1757 word24 scwAddr = chanloc + IOM_MBX_SCW;
1758 word36 scw;
1759 iom_core_read_lock (iom_unit_idx, scwAddr, & scw, __func__);
1760 word18 addr = getbits36_18 (scw, 0);
1761 uint lq = getbits36_2 (scw, 18);
1762 uint tally = getbits36_12 (scw, 24);
1763
1764 sim_debug (DBG_DEBUG, & iom_dev, "%s: Status: 0%012"PRIo64" 0%012"PRIo64"\n",
1765 __func__, word1, word2);
1766 if (lq == 3)
1767 {
1768 sim_debug (DBG_WARN, &iom_dev,
1769 "%s: SCW for channel %d has illegal LQ\n",
1770 __func__, chan);
1771 lq = 0;
1772 }
1773 iom_core_write2 (iom_unit_idx, addr, word1, word2, __func__);
1774
1775
1776 if (tally > 0 || (tally == 0 && lq != 0))
1777 {
1778 switch (lq)
1779 {
1780 case 0:
1781
1782 if (tally != 0)
1783 {
1784 tally --;
1785 addr += 2;
1786 }
1787 break;
1788
1789 case 1:
1790
1791 if (tally % 8 == 1 )
1792 addr -= 8;
1793 else
1794 addr += 2;
1795 tally --;
1796 break;
1797
1798 case 2:
1799
1800 if (tally % 32 == 1 )
1801 addr -= 32;
1802 else
1803 addr += 2;
1804 tally --;
1805 break;
1806 }
1807
1808
1809 if (tally & ~07777U)
1810 {
1811 sim_debug (DBG_WARN, & iom_dev,
1812 "%s: Tally SCW address 0%o under/over flow\n",
1813 __func__, tally);
1814 tally &= 07777;
1815 }
1816
1817 putbits36_12 (& scw, 24, (word12) tally);
1818 putbits36_18 (& scw, 0, addr);
1819 }
1820
1821 iom_core_write_unlock (iom_unit_idx, scwAddr, scw, __func__);
1822
1823
1824 return 0;
1825 }
1826
1827 static word24 UNUSED build_AUXPTW_address (uint iom_unit_idx, int chan)
1828 {
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838 word12 IOMBaseAddress = iom_unit_data[iom_unit_idx].configSwIomBaseAddress;
1839 word24 addr = (((word24) IOMBaseAddress) & MASK12) << 6;
1840 addr |= ((uint) chan & MASK6) << 2;
1841 addr |= 03;
1842 return addr;
1843 }
1844
1845 static word24 build_DDSPTW_address (word18 PCW_PAGE_TABLE_PTR, word8 pageNumber)
1846 {
1847
1848
1849
1850
1851
1852
1853
1854
1855 if (PCW_PAGE_TABLE_PTR & 3)
1856 sim_warn ("%s: pcw_ptp %#o page_no %#o\n", __func__, PCW_PAGE_TABLE_PTR, pageNumber);
1857 word24 addr = (((word24) PCW_PAGE_TABLE_PTR) & MASK18) << 6;
1858 addr |= pageNumber;
1859 return addr;
1860 }
1861
1862
1863
1864 static void fetch_DDSPTW (uint iom_unit_idx, int chan, word18 addr)
1865 {
1866 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1867 word24 pgte = build_DDSPTW_address (p -> PCW_PAGE_TABLE_PTR,
1868 (addr >> 10) & MASK8);
1869 iom_core_read (iom_unit_idx, pgte, (word36 *) & p -> PTW_DCW, __func__);
1870 if ((p -> PTW_DCW & 0740000777747) != 04llu)
1871 sim_warn ("%s: chan %ld addr %#llo pgte %08llo ptw %012llo\n",
1872 __func__, (long)chan, (unsigned long long)addr,
1873 (unsigned long long)pgte, (unsigned long long)p -> PTW_DCW);
1874 }
1875
1876 static word24 build_IDSPTW_address (word18 PCW_PAGE_TABLE_PTR, word1 seg, word8 pageNumber)
1877 {
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893 word24 addr = (((word24) PCW_PAGE_TABLE_PTR) & MASK18) << 6;
1894 addr += (((word24) seg) & 01) << 8;
1895 addr += pageNumber;
1896 return addr;
1897 }
1898
1899
1900
1901 static void fetch_IDSPTW (uint iom_unit_idx, int chan, word18 addr)
1902 {
1903 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1904 word24 pgte = build_IDSPTW_address (p -> PCW_PAGE_TABLE_PTR,
1905 p -> SEG,
1906 (addr >> 10) & MASK8);
1907 iom_core_read (iom_unit_idx, pgte, (word36 *) & p -> PTW_DCW, __func__);
1908 if ((p -> PTW_DCW & 0740000777747) != 04llu)
1909 sim_warn ("%s: chan %d addr %#o ptw %012llo\n",
1910 __func__, chan, addr, (unsigned long long)p -> PTW_DCW);
1911 }
1912
1913 static word24 build_LPWPTW_address (word18 PCW_PAGE_TABLE_PTR, word1 seg, word8 pageNumber)
1914 {
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931 word24 addr = (((word24) PCW_PAGE_TABLE_PTR) & MASK18) << 6;
1932 addr += (((word24) seg) & 01) << 8;
1933 addr += pageNumber;
1934 return addr;
1935 }
1936
1937 static void fetch_LPWPTW (uint iom_unit_idx, uint chan)
1938 {
1939 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1940 word24 addr = build_LPWPTW_address (p -> PCW_PAGE_TABLE_PTR,
1941 p -> SEG,
1942 (p -> LPW_DCW_PTR >> 10) & MASK8);
1943 iom_core_read (iom_unit_idx, addr, (word36 *) & p -> PTW_LPW, __func__);
1944 if ((p -> PTW_LPW & 0740000777747) != 04llu)
1945 sim_warn ("%s: chan %d addr %#o ptw %012llo\n",
1946 __func__, chan, addr, (unsigned long long)p -> PTW_LPW);
1947 }
1948
1949
1950
1951
1952 void iom_direct_data_service (uint iom_unit_idx, uint chan, word24 daddr, word36 * data,
1953 iom_direct_data_service_op op)
1954 {
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1968
1969 if (p -> masked)
1970 return;
1971
1972 if (p -> PCW_63_PTP && p -> PCW_64_PGE)
1973 {
1974 fetch_DDSPTW (iom_unit_idx, (int) chan, daddr);
1975 daddr = ((uint) getbits36_14 (p -> PTW_DCW, 4) << 10) | (daddr & MASK10);
1976 }
1977
1978 if (op == direct_store)
1979 iom_core_write (iom_unit_idx, daddr, * data, __func__);
1980 else if (op == direct_load)
1981 iom_core_read (iom_unit_idx, daddr, data, __func__);
1982 else if (op == direct_read_clear)
1983 {
1984 iom_core_read_lock (iom_unit_idx, daddr, data, __func__);
1985 iom_core_write_unlock (iom_unit_idx, daddr, 0, __func__);
1986 }
1987 }
1988
1989
1990
1991
1992
1993
1994 void iom_indirect_data_service (uint iom_unit_idx, uint chan, word36 * data, uint * cnt, bool write) {
1995 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1996
1997 if (p->masked)
1998 return;
1999
2000
2001
2002 p->initiate = false;
2003
2004 uint tally = p->DDCW_TALLY;
2005 uint daddr = p->DDCW_ADDR;
2006 if (tally == 0) {
2007 tally = 4096;
2008 }
2009 p->tallyResidue = (word12) tally;
2010
2011 if (write) {
2012 uint c = * cnt;
2013 while (p->tallyResidue) {
2014 if (c == 0)
2015 break;
2016
2017 if (! IS_IONTP (p)) {
2018 if (p->PCW_63_PTP && p->PCW_64_PGE) {
2019 fetch_IDSPTW (iom_unit_idx, (int) chan, daddr);
2020 word24 addr = ((word24) (getbits36_14 (p -> PTW_DCW, 4) << 10)) | (daddr & MASK10);
2021 iom_core_write (iom_unit_idx, addr, * data, __func__);
2022 } else {
2023 if (daddr > MASK18) {
2024 sim_warn ("%s 256K ovf\n", __func__);
2025 daddr &= MASK18;
2026 }
2027
2028
2029
2030 uint daddr2 = daddr | (uint) p->ADDR_EXT << 18;
2031 iom_core_write (iom_unit_idx, daddr2, * data, __func__);
2032 }
2033 }
2034 daddr ++;
2035 data ++;
2036 p->tallyResidue --;
2037 c --;
2038 }
2039 } else {
2040 uint c = 0;
2041 while (p -> tallyResidue) {
2042 if (IS_IONTP (p)) {
2043 * data = 0;
2044 } else {
2045 if (p -> PCW_63_PTP && p -> PCW_64_PGE) {
2046 fetch_IDSPTW (iom_unit_idx, (int) chan, daddr);
2047 word24 addr = ((word24) (getbits36_14 (p -> PTW_DCW, 4) << 10)) | (daddr & MASK10);
2048 iom_core_read (iom_unit_idx, addr, data, __func__);
2049 } else {
2050
2051 if (daddr > MASK18) {
2052 sim_warn ("%s 256K ovf\n", __func__);
2053 daddr &= MASK18;
2054 }
2055
2056
2057
2058 uint daddr2 = daddr | (uint) p -> ADDR_EXT << 18;
2059 iom_core_read (iom_unit_idx, daddr2, data, __func__);
2060 }
2061 }
2062 daddr ++;
2063 p->tallyResidue --;
2064 data ++;
2065 c ++;
2066 }
2067 * cnt = c;
2068 }
2069 }
2070
2071 static void update_chan_mode (uint iom_unit_idx, uint chan, bool tdcw)
2072 {
2073 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2074 if (chan == IOM_CONNECT_CHAN)
2075 {
2076 p -> chanMode = cm1;
2077 return;
2078 }
2079
2080 if (! tdcw)
2081 {
2082 if (p -> PCW_64_PGE == 0)
2083 {
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
2100 if (p -> LPW_23_REL == 0)
2101 {
2102 p -> chanMode = cm1;
2103 }
2104 else
2105 {
2106 p -> chanMode = cm3a;
2107 }
2108
2109 }
2110 else
2111 {
2112
2113 if (p -> LPW_23_REL == 0)
2114 {
2115 p -> chanMode = cm3b;
2116 }
2117 else
2118 {
2119 p -> chanMode = cm4;
2120 }
2121
2122 }
2123 }
2124 }
2125 else
2126 {
2127 switch (p -> chanMode)
2128 {
2129 case cm1:
2130 if (p -> TDCW_32_PDTA)
2131 {
2132 p -> chanMode = cm2;
2133 break;
2134 }
2135 if (p -> TDCW_33_PDCW)
2136 if (p -> TDCW_35_REL)
2137 p -> chanMode = cm4;
2138 else
2139 p -> chanMode = cm3b;
2140 else
2141 if (p -> TDCW_35_REL)
2142 p -> chanMode = cm3a;
2143 else
2144 p -> chanMode = cm2;
2145 break;
2146
2147 case cm2:
2148 if (p -> TDCW_33_PDCW)
2149 if (p -> TDCW_35_REL)
2150 p -> chanMode = cm4;
2151 else
2152 p -> chanMode = cm3b;
2153 else
2154 if (p -> TDCW_35_REL)
2155 p -> chanMode = cm3a;
2156 else
2157 p -> chanMode = cm2;
2158 break;
2159
2160 case cm3a:
2161 if (p -> TDCW_33_PDCW)
2162 p -> chanMode = cm4;
2163 break;
2164
2165 case cm3b:
2166 if (p -> TDCW_35_REL)
2167 p -> chanMode = cm4;
2168 break;
2169
2170 case cm4:
2171 p -> chanMode = cm5;
2172 break;
2173
2174 case cm5:
2175 break;
2176
2177 case cm1e:
2178 {
2179 if (p -> chanMode == cm1e && p -> TDCW_33_EC)
2180 p -> chanMode = cm2e;
2181 }
2182 break;
2183
2184 case cm2e:
2185 break;
2186 }
2187 }
2188 }
2189
2190 static void write_LPW (uint iom_unit_idx, uint chan)
2191 {
2192 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2193
2194 uint chanLoc = mbxLoc (iom_unit_idx, chan);
2195 iom_core_write (iom_unit_idx, chanLoc + IOM_MBX_LPW, p -> LPW, __func__);
2196
2197
2198
2199 if (chan != IOM_CONNECT_CHAN)
2200 {
2201 iom_core_write (iom_unit_idx, chanLoc + IOM_MBX_LPWX, p -> LPWX, __func__);
2202 }
2203 }
2204
2205 #ifdef TESTING
2206 void dumpDCW (word36 DCW, word1 LPW_23_REL) {
2207 static char * charCtrls[4] = {"terminate", "undefined", "proceed", "marker"};
2208 static char * chanCmds[16] = {"record", "undefined", "nondata", "undefined", "undefined", "undefined", "multirecord", "undefined", "character", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined"};
2209 word3 DCW_18_20_CP = getbits36_3 (DCW, 18);
2210
2211 if (DCW_18_20_CP == 07) {
2212 word6 IDCW_DEV_CMD = getbits36_6 (DCW, 0);
2213 word6 IDCW_DEV_CODE = getbits36_6 (DCW, 6);
2214
2215
2216
2217
2218
2219
2220 word2 IDCW_CHAN_CTRL = getbits36_2 (DCW, 22);
2221 word6 IDCW_CHAN_CMD = getbits36_6 (DCW, 24);
2222 word6 IDCW_COUNT = getbits36_6 (DCW, 30);
2223 sim_printf ("// IDCW %012llo\r\n", DCW);
2224 sim_printf ("// cmd %02o %s\r\n", IDCW_DEV_CMD, cmdNames[IDCW_DEV_CMD]);
2225 sim_printf ("// dev code %02o\r\n", IDCW_DEV_CODE);
2226 sim_printf ("// ctrl %o (%s)\r\n", IDCW_CHAN_CTRL, charCtrls[IDCW_CHAN_CTRL]);
2227 sim_printf ("// chancmd %o (%s)\r\n", IDCW_CHAN_CMD, IDCW_CHAN_CMD < 16 ? chanCmds[IDCW_CHAN_CMD] : "unknown");
2228 sim_printf ("// count %o\r\n", IDCW_COUNT);
2229 } else {
2230 word18 TDCW_DATA_ADDRESS = getbits36_18 (DCW, 0);
2231 word1 TDCW_31_SEG = getbits36_1 (DCW, 31);
2232 word1 TDCW_32_PDTA = getbits36_1 (DCW, 32);
2233 word1 TDCW_33_PDCW = getbits36_1 (DCW, 33);
2234 word1 TDCW_33_EC = getbits36_1 (DCW, 33);
2235 word1 TDCW_34_RES = getbits36_1 (DCW, 34);
2236 word1 TDCW_35_REL = getbits36_1 (DCW, 35);
2237
2238 word12 DDCW_TALLY = getbits36_12 (DCW, 24);
2239 word18 DDCW_ADDR = getbits36_18 (DCW, 0);
2240 word2 DDCW_22_23_TYPE = getbits36_2 (DCW, 22);
2241 static char * types[4] = { "IOTD", "IOTP", "TDCW", "IONTP" };
2242 if (DDCW_22_23_TYPE == 2) {
2243 sim_printf ("// TDCW (2) %012llo\r\n", DCW);
2244 sim_printf ("// dcw ptr %06o\r\n", TDCW_DATA_ADDRESS);
2245 sim_printf ("// seg %o\r\n", TDCW_31_SEG);
2246 sim_printf ("// pdta %o\r\n", TDCW_32_PDTA);
2247 sim_printf ("// pdcw %o\r\n", TDCW_33_PDCW);
2248 sim_printf ("// ec %o\r\n", TDCW_33_EC);
2249 sim_printf ("// res %o\r\n", TDCW_34_RES);
2250 sim_printf ("// rel %o\r\n", TDCW_35_REL);
2251 } else {
2252 sim_printf ("// %s (%o) %012llo\r\n", types[DDCW_22_23_TYPE], DDCW_22_23_TYPE, DCW);
2253 sim_printf ("// tally %04o\r\n", DDCW_TALLY);
2254 sim_printf ("// addr %02o\r\n", DDCW_ADDR);
2255 sim_printf ("// cp %o\r\n", getbits36_3 (DCW, 18));
2256 }
2257 }
2258 }
2259
2260 static void dumpLPW (uint iom_unit_idx, uint chan) {
2261 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2262 char updateCase;
2263 if (p->LPW_21_NC)
2264 updateCase = 'c';
2265 else if (p->LPW_22_TAL)
2266 updateCase = 'b';
2267 else
2268 updateCase = 'a';
2269 static char * chanName[64] = {
2270 "0.",
2271 "1.",
2272 "Connect",
2273 "3.",
2274 "4.",
2275 "5.",
2276 "6.",
2277 "7.",
2278 "8.",
2279 "9.",
2280 "MTP Tape",
2281 "IPC Disk",
2282 "MPC Disk",
2283 "Card reader",
2284 "Card punch",
2285 "Printer",
2286 "FNP",
2287 "FNP",
2288 "FNP",
2289 "FNP",
2290 "FNP",
2291 "FNP",
2292 "FNP",
2293 "FNP",
2294 "24.",
2295 "25.",
2296 "ABSI",
2297 "27.",
2298 "28.",
2299 "29.",
2300 "Console",
2301 "31.",
2302 "Socket",
2303 "Socket",
2304 "Socket",
2305 "Socket",
2306 "Socket",
2307 "Socket",
2308 "Socket",
2309 "39.",
2310 "40.",
2311 "41.",
2312 "42.",
2313 "43.",
2314 "44.",
2315 "45.",
2316 "46.",
2317 "47.",
2318 "48.",
2319 "49.",
2320 "50.",
2321 "51.",
2322 "52.",
2323 "53.",
2324 "54.",
2325 "55.",
2326 "56.",
2327 "57.",
2328 "58.",
2329 "59.",
2330 "60.",
2331 "61.",
2332 "62.",
2333 "63."
2334 };
2335 sim_printf ("// %s channel LPW %012llo (case %c)\r\n", chanName[chan], p->LPW, updateCase);
2336 sim_printf ("// DCW pointer %06o\r\n", p->LPW_DCW_PTR);
2337 sim_printf ("// RES %o\r\n", p->LPW_18_RES);
2338 sim_printf ("// REL %o\r\n", p->LPW_19_REL);
2339 sim_printf ("// AE %o\r\n", p->LPW_20_AE);
2340 sim_printf ("// NC 21 %o\r\n", p->LPW_21_NC);
2341 sim_printf ("// TAL 22 %o\r\n", p->LPW_22_TAL);
2342 sim_printf ("// REL %o\r\n", p->LPW_23_REL);
2343 sim_printf ("// TALLY %04o\r\n", p->LPW_TALLY);
2344 sim_printf ("// \r\n");
2345 }
2346 #endif
2347
2348 static void fetch_and_parse_LPW (uint iom_unit_idx, uint chan)
2349 {
2350 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2351 uint chanLoc = mbxLoc (iom_unit_idx, chan);
2352
2353 iom_core_read (iom_unit_idx, chanLoc + IOM_MBX_LPW, (word36 *) & p -> LPW, __func__);
2354 sim_debug (DBG_DEBUG, & iom_dev,
2355 "%s: lpw %08o %012"PRIo64"\n", __func__, chanLoc + IOM_MBX_LPW, p->LPW);
2356
2357 p -> LPW_DCW_PTR = getbits36_18 (p -> LPW, 0);
2358 p -> LPW_18_RES = getbits36_1 (p -> LPW, 18);
2359 p -> LPW_19_REL = getbits36_1 (p -> LPW, 19);
2360 p -> LPW_20_AE = getbits36_1 (p -> LPW, 20);
2361 p -> LPW_21_NC = getbits36_1 (p -> LPW, 21);
2362 p -> LPW_22_TAL = getbits36_1 (p -> LPW, 22);
2363 p -> LPW_23_REL = getbits36_1 (p -> LPW, 23);
2364 p -> LPW_TALLY = getbits36_12 (p -> LPW, 24);
2365
2366 if (chan == IOM_CONNECT_CHAN)
2367 {
2368 p -> LPWX = 0;
2369 p -> LPWX_BOUND = 0;
2370 p -> LPWX_SIZE = 0;
2371 }
2372 else
2373 {
2374 iom_core_read (iom_unit_idx, chanLoc + IOM_MBX_LPWX, (word36 *) & p -> LPWX, __func__);
2375 p -> LPWX_BOUND = getbits36_18 (p -> LPWX, 0);
2376 p -> LPWX_SIZE = getbits36_18 (p -> LPWX, 18);
2377 }
2378 update_chan_mode (iom_unit_idx, chan, false);
2379 }
2380
2381 static void unpack_DCW (uint iom_unit_idx, uint chan)
2382 {
2383 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2384 p -> DCW_18_20_CP = getbits36_3 (p -> DCW, 18);
2385
2386 if (IS_IDCW (p))
2387 {
2388 p -> IDCW_DEV_CMD = getbits36_6 (p -> DCW, 0);
2389 p -> IDCW_DEV_CODE = getbits36_6 (p -> DCW, 6);
2390 p -> IDCW_AE = getbits36_6 (p -> DCW, 12);
2391 if (p -> LPW_23_REL)
2392 p -> IDCW_EC = 0;
2393 else
2394 p -> IDCW_EC = getbits36_1 (p -> DCW, 21);
2395 if (p -> IDCW_EC)
2396 p -> SEG = 1;
2397 p -> IDCW_CHAN_CTRL = getbits36_2 (p -> DCW, 22);
2398 p -> IDCW_CHAN_CMD = getbits36_6 (p -> DCW, 24);
2399 p -> IDCW_COUNT = getbits36_6 (p -> DCW, 30);
2400 p->recordResidue = p->IDCW_COUNT;
2401 #ifdef TESTING
2402 sim_debug (DBG_DEBUG, & iom_dev,
2403 "%s: IDCW %012llo cmd %02o (%s) dev %02o ctrl %o chancmd %o\n",
2404 __func__, p->DCW, p->IDCW_DEV_CMD, cmdNames[p->IDCW_DEV_CMD],
2405 p->IDCW_DEV_CODE, p->IDCW_CHAN_CTRL, p->IDCW_CHAN_CMD);
2406 #endif
2407 }
2408 else
2409 {
2410 p -> TDCW_DATA_ADDRESS = getbits36_18 (p -> DCW, 0);
2411 p -> TDCW_31_SEG = getbits36_1 (p -> DCW, 31);
2412 p -> TDCW_32_PDTA = getbits36_1 (p -> DCW, 32);
2413 p -> TDCW_33_PDCW = getbits36_1 (p -> DCW, 33);
2414 p -> TDCW_33_EC = getbits36_1 (p -> DCW, 33);
2415 p -> TDCW_34_RES = getbits36_1 (p -> DCW, 34);
2416 p -> TDCW_35_REL = getbits36_1 (p -> DCW, 35);
2417 p -> DDCW_TALLY = getbits36_12 (p -> DCW, 24);
2418 p -> DDCW_ADDR = getbits36_18 (p -> DCW, 0);
2419 p -> DDCW_22_23_TYPE = getbits36_2 (p -> DCW, 22);
2420 sim_debug (DBG_DEBUG, & iom_dev,
2421 "%s: TDCW/DDCW %012llo tally %04o addr %06o type %o\n",
2422 __func__, p->DCW, p->DDCW_TALLY, p->DDCW_ADDR, p->DDCW_22_23_TYPE);
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444 }
2445 }
2446
2447 static void pack_DCW (uint iom_unit_idx, uint chan)
2448 {
2449
2450 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2451 putbits36_3 ((word36 *) & p -> DCW, 18, p -> DCW_18_20_CP);
2452 }
2453
2454 static void pack_LPW (uint iom_unit_idx, uint chan)
2455 {
2456 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2457 putbits36_18 ((word36 *) & p-> LPW, 0, p -> LPW_DCW_PTR);
2458 putbits36_1 ((word36 *) & p-> LPW, 18, p -> LPW_18_RES);
2459 putbits36_1 ((word36 *) & p-> LPW, 19, p -> LPW_19_REL);
2460 putbits36_1 ((word36 *) & p-> LPW, 20, p -> LPW_20_AE);
2461 putbits36_1 ((word36 *) & p-> LPW, 21, p -> LPW_21_NC);
2462 putbits36_1 ((word36 *) & p-> LPW, 22, p -> LPW_22_TAL);
2463 putbits36_1 ((word36 *) & p-> LPW, 23, p -> LPW_23_REL);
2464 putbits36_12 ((word36 *) & p-> LPW, 24, p -> LPW_TALLY);
2465 putbits36_18 ((word36 *) & p-> LPWX, 0, p -> LPWX_BOUND);
2466 putbits36_18 ((word36 *) & p-> LPWX, 18, p -> LPWX_SIZE);
2467 }
2468
2469 static void fetch_and_parse_PCW (uint iom_unit_idx, uint chan)
2470 {
2471 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2472
2473 iom_core_read2 (iom_unit_idx, p -> LPW_DCW_PTR, (word36 *) & p -> PCW0, (word36 *) & p -> PCW1, __func__);
2474 p -> PCW_CHAN = getbits36_6 (p -> PCW1, 3);
2475 p -> PCW_AE = getbits36_6 (p -> PCW0, 12);
2476 p -> PCW_21_MSK = getbits36_1 (p -> PCW0, 21);
2477 p -> PCW_PAGE_TABLE_PTR = getbits36_18 (p -> PCW1, 9);
2478 p -> PCW_63_PTP = getbits36_1 (p -> PCW1, 27);
2479 p -> PCW_64_PGE = getbits36_1 (p -> PCW1, 28);
2480 p -> PCW_65_AUX = getbits36_1 (p -> PCW1, 29);
2481 if (p -> PCW_65_AUX)
2482 sim_warn ("PCW_65_AUX\n");
2483 p -> DCW = p -> PCW0;
2484 unpack_DCW (iom_unit_idx, chan);
2485 }
2486
2487 static void fetch_and_parse_DCW (uint iom_unit_idx, uint chan, UNUSED bool read_only)
2488 {
2489 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2490 word24 addr = p -> LPW_DCW_PTR & MASK18;
2491
2492 sim_debug (DBG_DEBUG, & iom_dev, "%s: addr %08o\n", __func__, addr);
2493 switch (p -> chanMode)
2494 {
2495
2496 case cm1:
2497 case cm1e:
2498 {
2499 iom_core_read (iom_unit_idx, addr, (word36 *) & p -> DCW, __func__);
2500 }
2501 break;
2502
2503
2504 case cm2e:
2505 {
2506
2507
2508 addr += ((word24) p -> LPWX_BOUND << 1);
2509 iom_core_read (iom_unit_idx, addr, (word36 *) & p -> DCW, __func__);
2510 }
2511 break;
2512
2513 case cm2:
2514 case cm3b:
2515 {
2516 sim_warn ("fetch_and_parse_DCW LPW paged\n");
2517 }
2518 break;
2519
2520 case cm3a:
2521 case cm4:
2522 case cm5:
2523 {
2524 fetch_LPWPTW (iom_unit_idx, chan);
2525
2526
2527 word24 addr_ = ((word24) (getbits36_14 (p -> PTW_LPW, 4) << 10)) | ((p -> LPW_DCW_PTR) & MASK10);
2528 iom_core_read (iom_unit_idx, addr_, (word36 *) & p -> DCW, __func__);
2529 }
2530 break;
2531 }
2532 unpack_DCW (iom_unit_idx, chan);
2533
2534 if (IS_IDCW (p))
2535 sim_debug (DBG_DEBUG, & iom_dev,
2536 "%s: chan %d idcw: dev_cmd %#o dev_code %#o ae %#o ec %d control %#o chan_cmd %#o data %#o\n",
2537 __func__, p -> PCW_CHAN, p -> IDCW_DEV_CMD, p -> IDCW_DEV_CODE, p -> IDCW_AE,
2538 p -> IDCW_EC, p -> IDCW_CHAN_CTRL, p -> IDCW_CHAN_CMD, p -> IDCW_COUNT);
2539 else
2540 if (p -> DDCW_22_23_TYPE == 02)
2541 sim_debug (DBG_DEBUG, & iom_dev,
2542 "%s: chan %d tdcw: address %#o seg %d pdta %d pdcw/ec %d res %d rel %d\n",
2543 __func__, p -> PCW_CHAN, p -> TDCW_DATA_ADDRESS, p -> TDCW_31_SEG,
2544 p -> TDCW_32_PDTA, p -> TDCW_33_PDCW, p -> TDCW_34_RES, p -> TDCW_35_REL);
2545 else
2546 sim_debug (DBG_DEBUG, & iom_dev,
2547 "%s: chan %d ddcw: address %#o char_pos %#o type %#o tally %#o\n",
2548 __func__, p -> PCW_CHAN, p -> DDCW_ADDR, p -> DCW_18_20_CP,
2549 p -> DDCW_22_23_TYPE, p -> DDCW_TALLY);
2550 }
2551
2552
2553
2554
2555
2556
2557
2558
2559 int send_general_interrupt (uint iom_unit_idx, uint chan, enum iomImwPics pic)
2560 {
2561 uint imw_addr;
2562 uint chan_group = chan < 32 ? 1 : 0;
2563 uint chan_in_group = chan & 037;
2564
2565 uint iomUnitNum =
2566 iom_unit_data[iom_unit_idx].configSwMultiplexBaseAddress & 3u;
2567 uint interrupt_num = iomUnitNum | (chan_group << 2) | ((uint) pic << 3);
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578 uint pi_base = iom_unit_data[iom_unit_idx].configSwMultiplexBaseAddress & ~3u;
2579 imw_addr = (pi_base << 3) | interrupt_num;
2580
2581 sim_debug (DBG_DEBUG, & iom_dev,
2582 "%s: IOM %c, channel %d (%#o), level %d; "
2583 "Interrupt %d (%#o).\n",
2584 __func__, iomChar (iom_unit_idx), chan, chan, pic, interrupt_num,
2585 interrupt_num);
2586 word36 imw;
2587 iom_core_read_lock (iom_unit_idx, imw_addr, &imw, __func__);
2588
2589
2590
2591
2592
2593 putbits36_1 (& imw, chan_in_group, 1);
2594 iom_core_write_unlock (iom_unit_idx, imw_addr, imw, __func__);
2595 return scu_set_interrupt (iom_unit_data[iom_unit_idx].invokingScuUnitIdx, interrupt_num);
2596 }
2597
2598 static void iom_fault (uint iom_unit_idx, uint chan, UNUSED const char * who,
2599 iomFaultServiceRequest req,
2600 iomSysFaults_t signal)
2601 {
2602 sim_warn ("iom_fault %s\n", who);
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629 sim_debug (DBG_DEBUG, & iom_dev,
2630 "%s: chan %d %s req %#o signal %#o\n",
2631 __func__, chan, who, req, signal);
2632
2633 word36 faultWord = 0;
2634 putbits36_9 (& faultWord, 9, (word9) chan);
2635 putbits36_5 (& faultWord, 18, (word5) req);
2636
2637 putbits36_6 (& faultWord, 30, (word6) signal);
2638
2639 uint chanloc = mbxLoc (iom_unit_idx, IOM_SYSTEM_FAULT_CHAN);
2640
2641 word36 lpw;
2642 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_LPW, & lpw, __func__);
2643
2644 word36 scw;
2645 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_SCW, & scw, __func__);
2646
2647 word36 dcw;
2648 iom_core_read_lock (iom_unit_idx, chanloc + IOM_MBX_DCW, & dcw, __func__);
2649
2650
2651
2652
2653
2654 iom_core_write (iom_unit_idx, (dcw >> 18) & MASK18, faultWord, __func__);
2655
2656 uint tally = dcw & MASK12;
2657 if (tally > 1)
2658 {
2659 dcw -= 01llu;
2660 dcw += 01000000llu;
2661 }
2662 else
2663 dcw = scw;
2664 iom_core_write_unlock (iom_unit_idx, chanloc + IOM_MBX_DCW, dcw, __func__);
2665
2666 send_general_interrupt (iom_unit_idx, IOM_SYSTEM_FAULT_CHAN, imwSystemFaultPic);
2667 }
2668
2669
2670
2671
2672
2673
2674 int iom_list_service (uint iom_unit_idx, uint chan,
2675 bool * ptro, bool * sendp, bool * uffp)
2676 {
2677 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2678
2679
2680
2681 bool isConnChan = chan == IOM_CONNECT_CHAN;
2682 * ptro = false;
2683 bool uff = false;
2684 bool send = false;
2685
2686
2687
2688
2689
2690
2691
2692 if (p -> lsFirst)
2693 {
2694
2695
2696 fetch_and_parse_LPW (iom_unit_idx, chan);
2697 p -> wasTDCW = false;
2698 p -> SEG = 0;
2699 }
2700
2701
2702
2703
2704 if (isConnChan)
2705 {
2706
2707
2708
2709 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 0)
2710 {
2711 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2712 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2713 iomIllTalCChnFlt);
2714 return -1;
2715 }
2716
2717 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 1)
2718 {
2719
2720
2721
2722 if (p -> LPW_TALLY == 0)
2723 {
2724 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2725 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2726 iomIllTalCChnFlt);
2727 return -1;
2728 }
2729
2730 if (p -> LPW_TALLY > 1)
2731 {
2732
2733
2734 if (p -> LPW_20_AE == 0 &&
2735 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
2736 01000000llu)
2737 {
2738 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2739 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2740 iom256KFlt);
2741 return -1;
2742 }
2743 }
2744 else if (p -> LPW_TALLY == 1)
2745 * ptro = true;
2746 }
2747 else
2748 * ptro = true;
2749
2750
2751
2752
2753
2754 fetch_and_parse_PCW (iom_unit_idx, chan);
2755
2756
2757 if (IS_NOT_IDCW (p))
2758 {
2759 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2760 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2761 iomNotPCWFlt);
2762 return -1;
2763 }
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776 send = true;
2777
2778 goto D;
2779 }
2780
2781
2782
2783
2784
2785 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 0)
2786 {
2787
2788
2789 if (p -> LPW_20_AE == 0 &&
2790 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
2791 01000000llu)
2792 {
2793 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2794 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2795 iom256KFlt);
2796 return -1;
2797 }
2798 }
2799 else if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 1)
2800 {
2801 A:;
2802
2803
2804 if (p -> LPW_TALLY == 0)
2805 {
2806 uff = true;
2807 }
2808 else if (p -> LPW_TALLY > 1)
2809 {
2810
2811
2812
2813 if (p -> LPW_20_AE == 0 &&
2814 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
2815 01000000llu)
2816 {
2817 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2818 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2819 iom256KFlt);
2820 return -1;
2821 }
2822 }
2823 }
2824
2825
2826
2827
2828 fetch_and_parse_DCW (iom_unit_idx, chan, false);
2829
2830
2831
2832
2833
2834 if (IS_IDCW (p))
2835 {
2836
2837
2838
2839 if (p -> LPW_18_RES)
2840 {
2841
2842 uff = true;
2843
2844 }
2845 else
2846 {
2847
2848
2849 send = true;
2850 }
2851 p -> LPWX_SIZE = p -> LPW_DCW_PTR;
2852 goto D;
2853 }
2854
2855
2856
2857 if (p -> lsFirst)
2858 p -> LPWX_SIZE = p -> LPW_DCW_PTR;
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869 if (IS_TDCW (p))
2870 {
2871
2872 if (p -> wasTDCW)
2873 {
2874 uff = true;
2875 goto uffSet;
2876 }
2877 p -> wasTDCW = true;
2878
2879
2880
2881 p -> LPW_DCW_PTR = p -> TDCW_DATA_ADDRESS;
2882
2883
2884
2885
2886 p -> LPW_20_AE |= p -> TDCW_33_EC;
2887 p -> LPW_18_RES |= p -> TDCW_34_RES;
2888 p -> LPW_23_REL |= p -> TDCW_35_REL;
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921 if (p -> TDCW_31_SEG)
2922 sim_warn ("TDCW_31_SEG\n");
2923
2924 update_chan_mode (iom_unit_idx, chan, true);
2925
2926
2927 p -> LPW_TALLY = (p -> LPW_TALLY - 1u) & MASK12;
2928
2929 pack_LPW (iom_unit_idx, chan);
2930
2931
2932
2933 if (p -> LPW_18_RES && p -> TDCW_33_EC)
2934 {
2935 uff = true;
2936 goto uffSet;
2937 }
2938
2939 goto A;
2940 }
2941
2942 p -> wasTDCW = false;
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968 if (uff)
2969 {
2970 uffSet:;
2971
2972 p -> DCW_18_20_CP = 07u;
2973 pack_DCW (iom_unit_idx, chan);
2974 }
2975
2976
2977
2978
2979
2980
2981
2982
2983 send = true;
2984
2985
2986
2987 D:;
2988
2989
2990
2991 * uffp = uff;
2992 * sendp = send;
2993
2994
2995
2996 if (p -> LPW_21_NC == 0)
2997 {
2998
2999 if (isConnChan)
3000 p -> LPW_DCW_PTR = (p -> LPW_DCW_PTR + 2u) & MASK18;
3001 else
3002 p -> LPW_DCW_PTR = (p -> LPW_DCW_PTR + 1u) & MASK18;
3003
3004
3005 p->LPW_TALLY = ((word12) (((word12s) p->LPW_TALLY) - 1)) & MASK12;
3006 pack_LPW (iom_unit_idx, chan);
3007 }
3008
3009
3010 if (p -> DDCW_22_23_TYPE == 07u || p -> lsFirst)
3011 {
3012
3013
3014
3015
3016 write_LPW (iom_unit_idx, chan);
3017 }
3018 else
3019 {
3020 if (p -> LPW_21_NC == 0 ||
3021 (IS_TDCW (p)))
3022 {
3023
3024
3025
3026
3027 write_LPW (iom_unit_idx, chan);
3028 }
3029 }
3030
3031 p -> lsFirst = false;
3032
3033
3034 return 0;
3035 }
3036
3037
3038
3039 static int doPayloadChannel (uint iomUnitIdx, uint chan) {
3040 sim_debug (DBG_DEBUG, & iom_dev, "%s: Payload channel %c%02o\n", __func__, iomChar (iomUnitIdx), chan);
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
3059
3060 #ifdef TESTING
3061 word36 PCW_DCW = p->DCW;
3062 word1 PCW_LPW_23_REL = p->LPW_23_REL;
3063 #endif
3064 p -> chanMode = cm1;
3065 p -> LPW_18_RES = 0;
3066 p -> LPW_20_AE = 0;
3067 p -> LPW_23_REL = 0;
3068
3069 unpack_DCW (iomUnitIdx, chan);
3070
3071 p->isPCW = true;
3072
3073
3074
3075 struct iom_to_ctlr_s * d = & cables->iom_to_ctlr[iomUnitIdx][chan];
3076
3077
3078
3079
3080 if (d->chan_type != chan_type_CPI && p -> IDCW_DEV_CMD == 051) {
3081 p->stati = 04501;
3082 send_terminate_interrupt (iomUnitIdx, chan);
3083 return 0;
3084 }
3085
3086 if ((!d->in_use) || (!d->iom_cmd)) {
3087 p -> stati = 06000;
3088 #ifdef POLTS_TESTING
3089 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 10. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3090 #endif
3091 goto terminate;
3092 }
3093
3094
3095
3096
3097
3098 p -> ADDR_EXT = p -> PCW_AE;
3099
3100 p -> lsFirst = true;
3101
3102 p -> tallyResidue = 0;
3103 p -> isRead = true;
3104 p -> charPos = 0;
3105
3106
3107
3108 p -> initiate = true;
3109 p -> chanStatus = chanStatNormal;
3110
3111
3112
3113
3114 int rc = d->iom_cmd (iomUnitIdx, chan);
3115
3116 if (rc < 0) {
3117 p -> dev_code = getbits36_6 (p -> DCW, 6);
3118 #ifdef POLTS_TESTING
3119 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 9. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3120 #endif
3121 goto terminate;
3122 }
3123
3124 if (IS_IDCW (p) && p->IDCW_CHAN_CTRL == CHAN_CTRL_MARKER) {
3125 send_marker_interrupt (iomUnitIdx, (int) chan);
3126 }
3127
3128 if (rc == IOM_CMD_DISCONNECT) {
3129 #ifdef POLTS_TESTING
3130 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 8. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3131 #endif
3132 goto terminate;
3133 }
3134
3135 if (p->masked) {
3136 #ifdef POLTS_TESTING
3137 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 7. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3138 #endif
3139 goto terminate;
3140 }
3141
3142 bool ptro, send, uff;
3143 bool terminate = false;
3144 p->isPCW = false;
3145
3146 #ifdef TESTING
3147 bool first = true;
3148 #endif
3149
3150 (void)terminate;
3151 bool idcw_terminate = p -> IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE;
3152 do {
3153 int rc2 = iom_list_service (iomUnitIdx, chan, & ptro, & send, & uff);
3154 if (rc2 < 0) {
3155
3156 sim_warn ("%s list service failed\n", __func__);
3157 return -1;
3158 }
3159 if (uff) {
3160
3161 #ifdef POLTS_TESTING
3162 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 6. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3163 #endif
3164 goto terminate;
3165 }
3166
3167 if (! send) {
3168 sim_warn ("%s nothing to send\n", __func__);
3169 return 1;
3170 }
3171
3172 #ifdef TESTING
3173 # ifdef POLTS_TESTING
3174 if (iomUnitIdx == 1 && chan == 020)
3175 # endif
3176 if_sim_debug (DBG_TRACE, & iom_dev) {
3177 if (first) {
3178 first = false;
3179 dumpLPW (iomUnitIdx, chan);
3180 sim_printf ("// DCW list dump: \r\n");
3181 dumpDCW (PCW_DCW, PCW_LPW_23_REL);
3182 for (int i = 0; i < 8; i ++)
3183 dumpDCW (M[p->LPW_DCW_PTR - 1 + i], p->LPW_23_REL);
3184 sim_printf ("// \r\n");
3185 }
3186 }
3187 #endif
3188
3189
3190
3191
3192
3193
3194 if (IS_IDCW (p)) {
3195 idcw_terminate = p -> IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE;
3196 if (p -> LPW_23_REL == 0 && p -> IDCW_EC == 1)
3197 p -> ADDR_EXT = getbits36_6 (p -> DCW, 12);
3198
3199 p -> tallyResidue = 0;
3200 p -> isRead = true;
3201 p -> charPos = 0;
3202 p -> chanStatus = chanStatNormal;
3203 }
3204
3205
3206
3207 rc2 = d->iom_cmd (iomUnitIdx, chan);
3208
3209 if (rc2 < 0) {
3210 p -> dev_code = getbits36_6 (p -> DCW, 6);
3211 #ifdef POLTS_TESTING
3212 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 5. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3213 #endif
3214 goto terminate;
3215 }
3216
3217 if (rc2 == IOM_CMD_DISCONNECT) {
3218 terminate = true;
3219 #ifdef POLTS_TESTING
3220 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 4. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3221 #endif
3222 }
3223
3224 if (rc2 == IOM_CMD_PENDING)
3225 goto pending;
3226
3227
3228 if (IS_IDCW (p) && p->IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE && p->IDCW_CHAN_CMD == CHAN_CMD_NONDATA) {
3229 #ifdef POLTS_TESTING
3230 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 1. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3231 #endif
3232 goto terminate;
3233 }
3234
3235 if (IS_IOTD (p) && idcw_terminate && rc2 != IOM_CMD_RESIDUE) {
3236 #ifdef POLTS_TESTING
3237
3238 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf ("// terminate 2. ctrl == 0 in chan %d (%o) DCW\n", chan, chan);
3239 #endif
3240 goto terminate;
3241 }
3242
3243
3244
3245 if (IS_NOT_IDCW (p) && rc2 == IOM_CMD_RESIDUE) {
3246 if (p->recordResidue)
3247 p->recordResidue --;
3248 if (p->recordResidue == 0)
3249 goto terminate;
3250 }
3251 } while (! terminate);
3252
3253 terminate:;
3254 #ifdef POLTS_TESTING
3255 if (iomUnitIdx == 1 && chan == 020) sim_printf ("stati %04o\r\n", p->stati);
3256 #endif
3257 send_terminate_interrupt (iomUnitIdx, chan);
3258 return 0;
3259
3260 pending:;
3261 return 0;
3262 }
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275 static int doConnectChan (uint iom_unit_idx) {
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287 sim_debug (DBG_DEBUG, & iom_dev, "%s: Connect channel\n", __func__);
3288 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][IOM_CONNECT_CHAN];
3289 p -> lsFirst = true;
3290 #if defined(TESTING) && defined(POLTS_TESTING)
3291 bool first = true;
3292 #endif
3293 bool ptro, send, uff;
3294 do {
3295
3296 int rc = iom_list_service (iom_unit_idx, IOM_CONNECT_CHAN, & ptro, & send, & uff);
3297 if (rc < 0) {
3298 sim_warn ("connect channel connect failed\n");
3299 return -1;
3300 }
3301 if (uff) {
3302 sim_warn ("connect channel ignoring uff\n");
3303 }
3304 if (! send) {
3305 sim_warn ("connect channel nothing to send\n");
3306 } else {
3307 #ifdef xTESTING
3308 if_sim_debug (DBG_TRACE, & iom_dev) {
3309 if (first) {
3310 first = false;
3311 sim_printf ("// CIOC %lld\r\n", cpu.cycleCnt);
3312 dumpLPW (iom_unit_idx, IOM_CONNECT_CHAN);
3313 sim_printf ("// PCW %012llo %012llo\r\n", p->PCW0, p->PCW1);
3314 sim_printf ("// Chan info %04o\r\n", p->PCW_CHAN);
3315 sim_printf ("// Addr ext %02o\r\n", p->PCW_AE);
3316 sim_printf ("// 111 %o\r\n", getbits36_3 (p->PCW0, 18));
3317 sim_printf ("// M %o\r\n", p->PCW_21_MSK);
3318 sim_printf ("// Chan info %08o\r\n", getbits36_14 (p->PCW0, 22));
3319 sim_printf ("// Pg Tbl Ptr %06o\r\n", p->PCW_PAGE_TABLE_PTR);
3320 sim_printf ("// PTP %o\r\n", p->PCW_63_PTP);
3321 sim_printf ("// PGE %o\r\n", p->PCW_64_PGE);
3322 sim_printf ("// AUX %o\r\n", p->PCW_65_AUX);
3323 sim_printf ("//\r\n");
3324 }
3325 }
3326 #endif
3327
3328 iom_chan_data_t * q = & iom_chan_data[iom_unit_idx][p -> PCW_CHAN];
3329
3330 q -> PCW0 = p -> PCW0;
3331 q -> PCW1 = p -> PCW1;
3332 q -> PCW_CHAN = p -> PCW_CHAN;
3333 q -> PCW_AE = p -> PCW_AE;
3334 q -> PCW_PAGE_TABLE_PTR = p -> PCW_PAGE_TABLE_PTR;
3335 q -> PCW_63_PTP = p -> PCW_63_PTP;
3336 q -> PCW_64_PGE = p -> PCW_64_PGE;
3337 q -> PCW_65_AUX = p -> PCW_65_AUX;
3338 q -> PCW_21_MSK = p -> PCW_21_MSK;
3339 q -> DCW = p -> DCW;
3340
3341 sim_debug (DBG_DEBUG, & iom_dev, "%s: PCW %012llo %012llo chan %02o\n", __func__, q->PCW0, q->PCW1, q->PCW_CHAN);
3342
3343 q -> masked = p -> PCW_21_MSK;
3344 if (q -> masked) {
3345 if (q -> in_use)
3346 sim_warn ("%s: chan %d masked while in use\n", __func__, p -> PCW_CHAN);
3347 q -> in_use = false;
3348 q -> start = false;
3349 } else {
3350 if (q -> in_use)
3351 sim_warn ("%s: chan %d connect while in use\n", __func__, p -> PCW_CHAN);
3352 q -> in_use = true;
3353 q -> start = true;
3354 #ifdef IO_THREADZ
3355 setChnConnect (iom_unit_idx, p -> PCW_CHAN);
3356 #else
3357 # if !defined(IO_ASYNC_PAYLOAD_CHAN) && !defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
3358 doPayloadChannel (iom_unit_idx, p -> PCW_CHAN);
3359 # endif
3360 # ifdef IO_ASYNC_PAYLOAD_CHAN_THREAD
3361 pthread_cond_signal (& iomCond);
3362 # endif
3363 #endif
3364 }
3365 }
3366 } while (! ptro);
3367 return 0;
3368 }
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380 int send_marker_interrupt (uint iom_unit_idx, int chan)
3381 {
3382 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3383 return(0);
3384 status_service (iom_unit_idx, (uint) chan, true);
3385 return send_general_interrupt (iom_unit_idx, (uint) chan, imwMarkerPic);
3386 }
3387
3388
3389
3390
3391
3392
3393
3394
3395 int send_special_interrupt (uint iom_unit_idx, uint chan, uint devCode,
3396 word8 status0, word8 status1)
3397 {
3398
3399 uint chanloc = mbxLoc (iom_unit_idx, IOM_SPECIAL_STATUS_CHAN);
3400
3401 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3402 return(0);
3403
3404 #ifdef LOCKLESS
3405 lock_iom();
3406 #endif
3407
3408
3409
3410
3411
3412
3413 word36 lpw;
3414 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_LPW, & lpw, __func__);
3415
3416 word36 scw;
3417 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_SCW, & scw, __func__);
3418
3419 word36 dcw;
3420 iom_core_read_lock (iom_unit_idx, chanloc + IOM_MBX_DCW, & dcw, __func__);
3421
3422 word36 status = 0400000000000;
3423 status |= (((word36) chan) & MASK6) << 27;
3424 status |= (((word36) devCode) & MASK8) << 18;
3425 status |= (((word36) status0) & MASK8) << 9;
3426 status |= (((word36) status1) & MASK8) << 0;
3427 iom_core_write (iom_unit_idx, (dcw >> 18) & MASK18, status, __func__);
3428
3429 uint tally = dcw & MASK12;
3430 if (tally > 1)
3431 {
3432 dcw -= 01llu;
3433 dcw += 01000000llu;
3434 }
3435 else
3436 dcw = scw;
3437 iom_core_write_unlock (iom_unit_idx, chanloc + IOM_MBX_DCW, dcw, __func__);
3438
3439 #ifdef LOCKLESS
3440 unlock_iom();
3441 #endif
3442
3443 send_general_interrupt (iom_unit_idx, IOM_SPECIAL_STATUS_CHAN, imwSpecialPic);
3444 return 0;
3445 }
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456 int send_terminate_interrupt (uint iom_unit_idx, uint chan)
3457 {
3458 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3459 return 0;
3460 status_service (iom_unit_idx, chan, false);
3461 if (iom_chan_data [iom_unit_idx] [chan] . in_use == false)
3462 sim_warn ("%s: chan %d not in use\n", __func__, chan);
3463 iom_chan_data [iom_unit_idx] [chan] . in_use = false;
3464 send_general_interrupt (iom_unit_idx, chan, imwTerminatePic);
3465 return 0;
3466 }
3467
3468 void iom_interrupt (uint scu_unit_idx, uint iom_unit_idx)
3469 {
3470 sim_debug (DBG_DEBUG, & iom_dev,
3471 "%s: IOM %c starting. [%"PRId64"] %05o:%08o\n",
3472 __func__, iomChar (iom_unit_idx), cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC);
3473
3474 iom_unit_data[iom_unit_idx].invokingScuUnitIdx = scu_unit_idx;
3475
3476 #ifdef IO_THREADZ
3477 setIOMInterrupt (iom_unit_idx);
3478 iomDoneWait (iom_unit_idx);
3479 #else
3480 int ret = doConnectChan (iom_unit_idx);
3481
3482 sim_debug (DBG_DEBUG, & iom_dev,
3483 "%s: IOM %c finished; doConnectChan returned %d.\n",
3484 __func__, iomChar (iom_unit_idx), ret);
3485 #endif
3486
3487 }
3488
3489 #ifdef IO_THREADZ
3490 void * chan_thread_main (void * arg)
3491 {
3492 uint myid = (uint) * (int *) arg;
3493 this_iom_idx = (uint) myid / MAX_CHANNELS;
3494 this_chan_num = (uint) myid % MAX_CHANNELS;
3495
3496
3497
3498 set_cpu_idx (0);
3499
3500 sim_msg ("\rIOM %c Channel %u thread created\r\n", this_iom_idx + 'a', this_chan_num);
3501 # ifdef TESTING
3502 printPtid(pthread_self());
3503 # endif
3504 sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
3505
3506 setSignals ();
3507 while (1)
3508 {
3509
3510 chnConnectWait ();
3511
3512 doPayloadChannel (this_iom_idx, this_chan_num);
3513 chnConnectDone ();
3514 }
3515 }
3516
3517 void * iom_thread_main (void * arg)
3518 {
3519 int myid = * (int *) arg;
3520 this_iom_idx = (uint) myid;
3521
3522
3523
3524 set_cpu_idx (0);
3525
3526 sim_printf("IOM %c thread created\n", 'a' + myid);
3527
3528 setSignals ();
3529 while (1)
3530 {
3531
3532 iomInterruptWait ();
3533
3534 int ret = doConnectChan (this_iom_idx);
3535
3536 sim_debug (DBG_DEBUG, & iom_dev,
3537 "%s: IOM %c finished; doConnectChan returned %d.\n",
3538 __func__, iomChar (myid), ret);
3539 iomInterruptDone ();
3540 }
3541 }
3542 #endif
3543
3544
3545
3546
3547
3548
3549
3550 void iom_init (void)
3551 {
3552
3553 }
3554
3555 #ifdef PANEL68
3556 void do_boot (void)
3557 {
3558 boot_svc (& boot_channel_unit[0]);
3559 }
3560 #endif
3561
3562 #if defined(IO_ASYNC_PAYLOAD_CHAN) || defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
3563 void iomProcess (void)
3564 {
3565 for (uint i = 0; i < N_IOM_UNITS_MAX; i++)
3566 for (uint j = 0; j < MAX_CHANNELS; j++)
3567 {
3568 iom_chan_data_t * p = &iom_chan_data [i] [j];
3569 if (p -> start)
3570 {
3571 p -> start = false;
3572 doPayloadChannel (i, j);
3573 }
3574 }
3575 }
3576 #endif
3577
3578 char iomChar (uint iomUnitIdx)
3579 {
3580 return (iom_unit_data[iomUnitIdx].configSwMultiplexBaseAddress & 3) + 'A';
3581 }