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