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
- tdcw_chan_mode
- 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
- peek_list_word
- iom_peek_next_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
2077
2078
2079
2080 static int tdcw_chan_mode (int mode, word1 pdta, word1 pdcw, word1 rel)
2081 {
2082 switch (mode)
2083 {
2084 case cm1:
2085 if (pdta)
2086 {
2087 mode = cm2;
2088 break;
2089 }
2090 if (pdcw)
2091 if (rel)
2092 mode = cm4;
2093 else
2094 mode = cm3b;
2095 else
2096 if (rel)
2097 mode = cm3a;
2098 else
2099 mode = cm2;
2100 break;
2101
2102 case cm2:
2103 if (pdcw)
2104 if (rel)
2105 mode = cm4;
2106 else
2107 mode = cm3b;
2108 else
2109 if (rel)
2110 mode = cm3a;
2111 else
2112 mode = cm2;
2113 break;
2114
2115 case cm3a:
2116 if (pdcw)
2117 mode = cm4;
2118 break;
2119
2120 case cm3b:
2121 if (rel)
2122 mode = cm4;
2123 break;
2124
2125 case cm4:
2126 mode = cm5;
2127 break;
2128
2129 case cm5:
2130 break;
2131
2132 case cm1e:
2133 {
2134 if (pdcw)
2135 mode = cm2e;
2136 }
2137 break;
2138
2139 case cm2e:
2140 break;
2141 }
2142 return mode;
2143 }
2144
2145 static void update_chan_mode (uint iom_unit_idx, uint chan, bool tdcw)
2146 {
2147 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2148 if (chan == IOM_CONNECT_CHAN)
2149 {
2150 p -> chanMode = cm1;
2151 return;
2152 }
2153
2154 if (! tdcw)
2155 {
2156 if (p -> PCW_64_PGE == 0)
2157 {
2158 if (p -> LPW_20_AE == 0)
2159 {
2160 p -> chanMode = cm1e;
2161 }
2162 else
2163 {
2164 p -> chanMode = cm2e;
2165 }
2166
2167 }
2168 else
2169 {
2170 if (p -> LPW_20_AE == 0)
2171 {
2172 if (p -> LPW_23_REL == 0)
2173 {
2174 p -> chanMode = cm1;
2175 }
2176 else
2177 {
2178 p -> chanMode = cm3a;
2179 }
2180
2181 }
2182 else
2183 {
2184 if (p -> LPW_23_REL == 0)
2185 {
2186 p -> chanMode = cm3b;
2187 }
2188 else
2189 {
2190 p -> chanMode = cm4;
2191 }
2192
2193 }
2194 }
2195 }
2196 else
2197 {
2198 p -> chanMode = tdcw_chan_mode (p -> chanMode, p -> TDCW_32_PDTA,
2199 p -> TDCW_33_PDCW, p -> TDCW_35_REL);
2200 }
2201 }
2202
2203 static void write_LPW (uint iom_unit_idx, uint chan)
2204 {
2205 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2206
2207 uint chanLoc = mbxLoc (iom_unit_idx, chan);
2208 iom_core_write (iom_unit_idx, chanLoc + IOM_MBX_LPW, p -> LPW, __func__);
2209
2210
2211
2212 if (chan != IOM_CONNECT_CHAN)
2213 {
2214 iom_core_write (iom_unit_idx, chanLoc + IOM_MBX_LPWX, p -> LPWX, __func__);
2215 }
2216 }
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230 void iom_advance_lpw (uint iom_unit_idx, uint chan)
2231 {
2232 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2233 p -> LPW_DCW_PTR = (p -> LPW_DCW_PTR + 1u) & MASK18;
2234 putbits36_18 ((word36 *) & p -> LPW, 0, p -> LPW_DCW_PTR);
2235 write_LPW (iom_unit_idx, chan);
2236 }
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270 int iom_continue_channel (uint iom_unit_idx, uint chan)
2271 {
2272 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2273 struct iom_to_ctlr_s * d = & cables->iom_to_ctlr[iom_unit_idx][chan];
2274
2275 if ((! d->in_use) || (! d->iom_cmd))
2276 {
2277 sim_warn ("%s: channel %d not in use\r\n", __func__, chan);
2278 return -1;
2279 }
2280
2281
2282
2283 bool ptro, send, uff;
2284 int rc = iom_list_service (iom_unit_idx, chan, & ptro, & send, & uff);
2285 if (rc < 0)
2286 {
2287 sim_warn ("%s: list service failed for channel %d\r\n", __func__, chan);
2288 return -2;
2289 }
2290
2291
2292
2293
2294
2295
2296
2297 if (uff)
2298 {
2299 sim_warn ("%s: iom_list_service returned uff=%o for channel %d (proceeding)\r\n",
2300 __func__, uff, chan);
2301 }
2302
2303 if (! send)
2304 {
2305 sim_warn ("%s: iom_list_service returned send=%o for channel %d\r\n", __func__, send, chan);
2306 return -4;
2307 }
2308
2309
2310
2311
2312 if (! IS_IDCW (p))
2313 {
2314 sim_warn ("%s: expected IDCW, got non-IDCW for channel %d\r\n",
2315 __func__, chan);
2316 return -5;
2317 }
2318
2319
2320 p -> isPCW = false;
2321 p -> tallyResidue = 0;
2322 p -> isRead = true;
2323 p -> charPos = 0;
2324 p -> chanStatus = chanStatNormal;
2325
2326
2327
2328
2329
2330 int rc2 = d->iom_cmd (iom_unit_idx, chan);
2331
2332 if (rc2 < 0)
2333 {
2334 sim_warn ("%s: iom_cmd failed for channel %d\r\n", __func__, chan);
2335
2336 return -6;
2337 }
2338
2339 if (rc2 == IOM_CMD_DISCONNECT)
2340 {
2341
2342 return -7;
2343 }
2344
2345
2346
2347 send_marker_interrupt (iom_unit_idx, (int) chan);
2348 return 0;
2349 }
2350
2351 #if defined(TESTING)
2352 void dumpDCW (word36 DCW, word1 LPW_23_REL) {
2353 static char * charCtrls[4] =
2354 { "terminate", "undefined", "proceed", "marker" };
2355 static char * chanCmds[16] =
2356 { "record", "undefined", "nondata", "undefined",
2357 "undefined", "undefined", "multirecord", "undefined",
2358 "character", "undefined", "undefined", "undefined",
2359 "undefined", "undefined", "undefined", "undefined"
2360 };
2361 word3 DCW_18_20_CP = getbits36_3 (DCW, 18);
2362
2363 if (DCW_18_20_CP == 07) {
2364 word6 IDCW_DEV_CMD = getbits36_6 (DCW, 0);
2365 word6 IDCW_DEV_CODE = getbits36_6 (DCW, 6);
2366
2367
2368
2369
2370
2371
2372 word2 IDCW_CHAN_CTRL = getbits36_2 (DCW, 22);
2373 word6 IDCW_CHAN_CMD = getbits36_6 (DCW, 24);
2374 word6 IDCW_COUNT = getbits36_6 (DCW, 30);
2375 sim_printf ("// IDCW %012llo\r\n", DCW);
2376 sim_printf ("// cmd %02o %s\r\n", IDCW_DEV_CMD, cmdNames[IDCW_DEV_CMD]);
2377 sim_printf ("// dev code %02o\r\n", IDCW_DEV_CODE);
2378 sim_printf ("// ctrl %o (%s)\r\n", IDCW_CHAN_CTRL, charCtrls[IDCW_CHAN_CTRL]);
2379 sim_printf ("// chancmd %o (%s)\r\n", IDCW_CHAN_CMD, IDCW_CHAN_CMD < 16 ? chanCmds[IDCW_CHAN_CMD] : "unknown");
2380 sim_printf ("// count %o\r\n", IDCW_COUNT);
2381 } else {
2382 word18 TDCW_DATA_ADDRESS = getbits36_18 (DCW, 0);
2383 word1 TDCW_31_SEG = getbits36_1 (DCW, 31);
2384 word1 TDCW_32_PDTA = getbits36_1 (DCW, 32);
2385 word1 TDCW_33_PDCW = getbits36_1 (DCW, 33);
2386 word1 TDCW_33_EC = getbits36_1 (DCW, 33);
2387 word1 TDCW_34_RES = getbits36_1 (DCW, 34);
2388 word1 TDCW_35_REL = getbits36_1 (DCW, 35);
2389
2390 word12 DDCW_TALLY = getbits36_12 (DCW, 24);
2391 word18 DDCW_ADDR = getbits36_18 (DCW, 0);
2392 word2 DDCW_22_23_TYPE = getbits36_2 (DCW, 22);
2393 static char * types[4] = { "IOTD", "IOTP", "TDCW", "IONTP" };
2394 if (DDCW_22_23_TYPE == 2) {
2395 sim_printf ("// TDCW (2) %012llo\r\n", DCW);
2396 sim_printf ("// dcw ptr %06o\r\n", TDCW_DATA_ADDRESS);
2397 sim_printf ("// seg %o\r\n", TDCW_31_SEG);
2398 sim_printf ("// pdta %o\r\n", TDCW_32_PDTA);
2399 sim_printf ("// pdcw %o\r\n", TDCW_33_PDCW);
2400 sim_printf ("// ec %o\r\n", TDCW_33_EC);
2401 sim_printf ("// res %o\r\n", TDCW_34_RES);
2402 sim_printf ("// rel %o\r\n", TDCW_35_REL);
2403 } else {
2404 sim_printf ("// %s (%o) %012llo\r\n", types[DDCW_22_23_TYPE], DDCW_22_23_TYPE, DCW);
2405 sim_printf ("// tally %04o\r\n", DDCW_TALLY);
2406 sim_printf ("// addr %02o\r\n", DDCW_ADDR);
2407 sim_printf ("// cp %o\r\n", getbits36_3 (DCW, 18));
2408 }
2409 }
2410 }
2411
2412 static void dumpLPW (uint iom_unit_idx, uint chan) {
2413 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2414 char updateCase;
2415 if (p->LPW_21_NC)
2416 updateCase = 'c';
2417 else if (p->LPW_22_TAL)
2418 updateCase = 'b';
2419 else
2420 updateCase = 'a';
2421 static char * chanName[64] = {
2422 "0.",
2423 "1.",
2424 "Connect",
2425 "3.",
2426 "4.",
2427 "5.",
2428 "6.",
2429 "7.",
2430 "8.",
2431 "9.",
2432 "MTP Tape",
2433 "IPC Disk",
2434 "MPC Disk",
2435 "Card reader",
2436 "Card punch",
2437 "Printer",
2438 "FNP",
2439 "FNP",
2440 "FNP",
2441 "FNP",
2442 "FNP",
2443 "FNP",
2444 "FNP",
2445 "FNP",
2446 "24.",
2447 "25.",
2448 "ABSI",
2449 "27.",
2450 "28.",
2451 "29.",
2452 "Console",
2453 "31.",
2454 "Socket",
2455 "Socket",
2456 "Socket",
2457 "Socket",
2458 "Socket",
2459 "Socket",
2460 "Socket",
2461 "39.",
2462 "40.",
2463 "41.",
2464 "42.",
2465 "43.",
2466 "44.",
2467 "45.",
2468 "46.",
2469 "47.",
2470 "48.",
2471 "49.",
2472 "50.",
2473 "51.",
2474 "52.",
2475 "53.",
2476 "54.",
2477 "55.",
2478 "56.",
2479 "57.",
2480 "58.",
2481 "59.",
2482 "60.",
2483 "61.",
2484 "62.",
2485 "63."
2486 };
2487 sim_printf ("// %s channel LPW %012llo (case %c)\r\n", chanName[chan], p->LPW, updateCase);
2488 sim_printf ("// DCW pointer %06o\r\n", p->LPW_DCW_PTR);
2489 sim_printf ("// RES %o\r\n", p->LPW_18_RES);
2490 sim_printf ("// REL %o\r\n", p->LPW_19_REL);
2491 sim_printf ("// AE %o\r\n", p->LPW_20_AE);
2492 sim_printf ("// NC 21 %o\r\n", p->LPW_21_NC);
2493 sim_printf ("// TAL 22 %o\r\n", p->LPW_22_TAL);
2494 sim_printf ("// REL %o\r\n", p->LPW_23_REL);
2495 sim_printf ("// TALLY %04o\r\n", p->LPW_TALLY);
2496 sim_printf ("// \r\n");
2497 }
2498 #endif
2499
2500 static void fetch_and_parse_LPW (uint iom_unit_idx, uint chan)
2501 {
2502 #if defined(TESTING)
2503 cpu_state_t * cpup = _cpup;
2504 #endif
2505 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2506 uint chanLoc = mbxLoc (iom_unit_idx, chan);
2507
2508 iom_core_read (iom_unit_idx, chanLoc + IOM_MBX_LPW, (word36 *) & p -> LPW, __func__);
2509 sim_debug (DBG_DEBUG, & iom_dev,
2510 "%s: lpw %08o %012"PRIo64"\r\n", __func__, chanLoc + IOM_MBX_LPW, p->LPW);
2511
2512 p -> LPW_DCW_PTR = getbits36_18 (p -> LPW, 0);
2513 p -> LPW_18_RES = getbits36_1 (p -> LPW, 18);
2514 p -> LPW_19_REL = getbits36_1 (p -> LPW, 19);
2515 p -> LPW_20_AE = getbits36_1 (p -> LPW, 20);
2516 p -> LPW_21_NC = getbits36_1 (p -> LPW, 21);
2517 p -> LPW_22_TAL = getbits36_1 (p -> LPW, 22);
2518 p -> LPW_23_REL = getbits36_1 (p -> LPW, 23);
2519 p -> LPW_TALLY = getbits36_12 (p -> LPW, 24);
2520
2521 if (chan == IOM_CONNECT_CHAN)
2522 {
2523 p -> LPWX = 0;
2524 p -> LPWX_BOUND = 0;
2525 p -> LPWX_SIZE = 0;
2526 }
2527 else
2528 {
2529 iom_core_read (iom_unit_idx, chanLoc + IOM_MBX_LPWX, (word36 *) & p -> LPWX, __func__);
2530 p -> LPWX_BOUND = getbits36_18 (p -> LPWX, 0);
2531 p -> LPWX_SIZE = getbits36_18 (p -> LPWX, 18);
2532 }
2533 update_chan_mode (iom_unit_idx, chan, false);
2534 }
2535
2536 static void unpack_DCW (uint iom_unit_idx, uint chan)
2537 {
2538 #if defined(TESTING)
2539 cpu_state_t * cpup = _cpup;
2540 #endif
2541 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2542 p -> DCW_18_20_CP = getbits36_3 (p -> DCW, 18);
2543
2544 if (IS_IDCW (p))
2545 {
2546 p -> IDCW_DEV_CMD = getbits36_6 (p -> DCW, 0);
2547 p -> IDCW_DEV_CODE = getbits36_6 (p -> DCW, 6);
2548 p -> IDCW_AE = getbits36_6 (p -> DCW, 12);
2549 if (p -> LPW_23_REL)
2550 p -> IDCW_EC = 0;
2551 else
2552 p -> IDCW_EC = getbits36_1 (p -> DCW, 21);
2553 if (p -> IDCW_EC)
2554 p -> SEG = 1;
2555 p -> IDCW_CHAN_CTRL = getbits36_2 (p -> DCW, 22);
2556 p -> IDCW_CHAN_CMD = getbits36_6 (p -> DCW, 24);
2557 p -> IDCW_COUNT = getbits36_6 (p -> DCW, 30);
2558 p->recordResidue = p->IDCW_COUNT;
2559 #if defined(TESTING)
2560 sim_debug (DBG_DEBUG, & iom_dev,
2561 "%s: IDCW %012llo cmd %02o (%s) dev %02o ctrl %o chancmd %o\r\n",
2562 __func__, p->DCW, p->IDCW_DEV_CMD, cmdNames[p->IDCW_DEV_CMD],
2563 p->IDCW_DEV_CODE, p->IDCW_CHAN_CTRL, p->IDCW_CHAN_CMD);
2564 #endif
2565 }
2566 else
2567 {
2568 p -> TDCW_DATA_ADDRESS = getbits36_18 (p -> DCW, 0);
2569 p -> TDCW_31_SEG = getbits36_1 (p -> DCW, 31);
2570 p -> TDCW_32_PDTA = getbits36_1 (p -> DCW, 32);
2571 p -> TDCW_33_PDCW = getbits36_1 (p -> DCW, 33);
2572 p -> TDCW_33_EC = getbits36_1 (p -> DCW, 33);
2573 p -> TDCW_34_RES = getbits36_1 (p -> DCW, 34);
2574 p -> TDCW_35_REL = getbits36_1 (p -> DCW, 35);
2575 p -> DDCW_TALLY = getbits36_12 (p -> DCW, 24);
2576 p -> DDCW_ADDR = getbits36_18 (p -> DCW, 0);
2577 p -> DDCW_22_23_TYPE = getbits36_2 (p -> DCW, 22);
2578 sim_debug (DBG_DEBUG, & iom_dev,
2579 "%s: TDCW/DDCW %012llo tally %04o addr %06o type %o\r\n",
2580 __func__, p->DCW, p->DDCW_TALLY, p->DDCW_ADDR, p->DDCW_22_23_TYPE);
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602 }
2603 }
2604
2605 static void pack_DCW (uint iom_unit_idx, uint chan)
2606 {
2607
2608 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2609 putbits36_3 ((word36 *) & p -> DCW, 18, p -> DCW_18_20_CP);
2610 }
2611
2612 static void pack_LPW (uint iom_unit_idx, uint chan)
2613 {
2614 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2615 putbits36_18 ((word36 *) & p-> LPW, 0, p -> LPW_DCW_PTR);
2616 putbits36_1 ((word36 *) & p-> LPW, 18, p -> LPW_18_RES);
2617 putbits36_1 ((word36 *) & p-> LPW, 19, p -> LPW_19_REL);
2618 putbits36_1 ((word36 *) & p-> LPW, 20, p -> LPW_20_AE);
2619 putbits36_1 ((word36 *) & p-> LPW, 21, p -> LPW_21_NC);
2620 putbits36_1 ((word36 *) & p-> LPW, 22, p -> LPW_22_TAL);
2621 putbits36_1 ((word36 *) & p-> LPW, 23, p -> LPW_23_REL);
2622 putbits36_12 ((word36 *) & p-> LPW, 24, p -> LPW_TALLY);
2623 putbits36_18 ((word36 *) & p-> LPWX, 0, p -> LPWX_BOUND);
2624 putbits36_18 ((word36 *) & p-> LPWX, 18, p -> LPWX_SIZE);
2625 }
2626
2627 static void fetch_and_parse_PCW (uint iom_unit_idx, uint chan)
2628 {
2629 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2630
2631 iom_core_read2 (iom_unit_idx, p -> LPW_DCW_PTR, (word36 *) & p -> PCW0, (word36 *) & p -> PCW1, __func__);
2632 p -> PCW_CHAN = getbits36_6 (p -> PCW1, 3);
2633 p -> PCW_AE = getbits36_6 (p -> PCW0, 12);
2634 p -> PCW_21_MSK = getbits36_1 (p -> PCW0, 21);
2635 p -> PCW_PAGE_TABLE_PTR = getbits36_18 (p -> PCW1, 9);
2636 p -> PCW_63_PTP = getbits36_1 (p -> PCW1, 27);
2637 p -> PCW_64_PGE = getbits36_1 (p -> PCW1, 28);
2638 p -> PCW_65_AUX = getbits36_1 (p -> PCW1, 29);
2639 if (p -> PCW_65_AUX)
2640 sim_warn ("PCW_65_AUX\r\n");
2641 p -> DCW = p -> PCW0;
2642 unpack_DCW (iom_unit_idx, chan);
2643 }
2644
2645 static void fetch_and_parse_DCW (uint iom_unit_idx, uint chan, UNUSED bool read_only)
2646 {
2647 #if defined(TESTING)
2648 cpu_state_t * cpup = _cpup;
2649 #endif
2650 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2651 word24 addr = p -> LPW_DCW_PTR & MASK18;
2652
2653 sim_debug (DBG_DEBUG, & iom_dev, "%s: addr %08o\r\n", __func__, addr);
2654 switch (p -> chanMode)
2655 {
2656
2657 case cm1:
2658 case cm1e:
2659 {
2660 iom_core_read (iom_unit_idx, addr, (word36 *) & p -> DCW, __func__);
2661 }
2662 break;
2663
2664
2665 case cm2e:
2666 {
2667
2668
2669 addr += ((word24) p -> LPWX_BOUND << 1);
2670 iom_core_read (iom_unit_idx, addr, (word36 *) & p -> DCW, __func__);
2671 }
2672 break;
2673
2674 case cm2:
2675 case cm3b:
2676 {
2677 sim_warn ("fetch_and_parse_DCW LPW paged\r\n");
2678 }
2679 break;
2680
2681 case cm3a:
2682 case cm4:
2683 case cm5:
2684 {
2685 fetch_LPWPTW (iom_unit_idx, chan);
2686
2687
2688 word24 addr_ = ((word24) (getbits36_14 (p -> PTW_LPW, 4) << 10)) | ((p -> LPW_DCW_PTR) & MASK10);
2689 iom_core_read (iom_unit_idx, addr_, (word36 *) & p -> DCW, __func__);
2690 }
2691 break;
2692 }
2693 unpack_DCW (iom_unit_idx, chan);
2694
2695 if (IS_IDCW (p))
2696 sim_debug (DBG_DEBUG, & iom_dev,
2697 "%s: chan %d idcw: dev_cmd %#o dev_code %#o ae %#o ec %d control %#o chan_cmd %#o data %#o\r\n",
2698 __func__, p -> PCW_CHAN, p -> IDCW_DEV_CMD, p -> IDCW_DEV_CODE, p -> IDCW_AE,
2699 p -> IDCW_EC, p -> IDCW_CHAN_CTRL, p -> IDCW_CHAN_CMD, p -> IDCW_COUNT);
2700 else
2701 if (p -> DDCW_22_23_TYPE == 02)
2702 sim_debug (DBG_DEBUG, & iom_dev,
2703 "%s: chan %d tdcw: address %#o seg %d pdta %d pdcw/ec %d res %d rel %d\r\n",
2704 __func__, p -> PCW_CHAN, p -> TDCW_DATA_ADDRESS, p -> TDCW_31_SEG,
2705 p -> TDCW_32_PDTA, p -> TDCW_33_PDCW, p -> TDCW_34_RES, p -> TDCW_35_REL);
2706 else
2707 sim_debug (DBG_DEBUG, & iom_dev,
2708 "%s: chan %d ddcw: address %#o char_pos %#o type %#o tally %#o\r\n",
2709 __func__, p -> PCW_CHAN, p -> DDCW_ADDR, p -> DCW_18_20_CP,
2710 p -> DDCW_22_23_TYPE, p -> DDCW_TALLY);
2711 }
2712
2713
2714
2715
2716
2717
2718
2719 static int peek_list_word (uint iom_unit_idx, uint chan, int mode, word18 addr, word36 * data)
2720 {
2721 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2722 switch (mode)
2723 {
2724 case cm1:
2725 case cm1e:
2726 iom_core_read (iom_unit_idx, addr, data, __func__);
2727 return 0;
2728
2729 case cm2e:
2730 iom_core_read (iom_unit_idx, (word24) addr + ((word24) p -> LPWX_BOUND << 1), data, __func__);
2731 return 0;
2732
2733 case cm3a:
2734 case cm4:
2735 case cm5:
2736 {
2737 word36 ptw;
2738 word24 pgte = build_LPWPTW_address (p -> PCW_PAGE_TABLE_PTR, p -> SEG,
2739 (addr >> 10) & MASK8);
2740 iom_core_read (iom_unit_idx, pgte, & ptw, __func__);
2741 if ((ptw & 0740000777747) != 04llu)
2742 return -1;
2743 iom_core_read (iom_unit_idx,
2744 ((word24) (getbits36_14 (ptw, 4) << 10)) | (addr & MASK10),
2745 data, __func__);
2746 return 0;
2747 }
2748
2749 default:
2750 return -1;
2751 }
2752 }
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767 int iom_peek_next_dcw (uint iom_unit_idx, uint chan, word36 * dcw)
2768 {
2769 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2770 int mode = p -> chanMode;
2771 word18 addr = p -> LPW_DCW_PTR;
2772 word1 res = p -> LPW_18_RES;
2773 word36 w;
2774
2775 if (peek_list_word (iom_unit_idx, chan, mode, addr, & w) != 0)
2776 return -1;
2777 if (getbits36_3 (w, 18) != 07 && getbits36_2 (w, 22) == 02)
2778 {
2779 word1 seg = getbits36_1 (w, 31);
2780 word1 pdta = getbits36_1 (w, 32);
2781 word1 pdcw = getbits36_1 (w, 33);
2782 word1 tres = getbits36_1 (w, 34);
2783 word1 rel = getbits36_1 (w, 35);
2784 res |= tres;
2785 if (seg || (res && pdcw))
2786 return -1;
2787 mode = tdcw_chan_mode (mode, pdta, pdcw, rel);
2788 addr = getbits36_18 (w, 0);
2789 if (peek_list_word (iom_unit_idx, chan, mode, addr, & w) != 0)
2790 return -1;
2791 if (getbits36_3 (w, 18) != 07 && getbits36_2 (w, 22) == 02)
2792 return -1;
2793 }
2794 if (getbits36_3 (w, 18) == 07 && res)
2795 return -1;
2796 * dcw = w;
2797 return 0;
2798 }
2799
2800
2801
2802
2803
2804
2805
2806
2807 int send_general_interrupt (uint iom_unit_idx, uint chan, enum iomImwPics pic)
2808 {
2809 #if defined(TESTING)
2810 cpu_state_t * cpup = _cpup;
2811 #endif
2812 uint imw_addr;
2813 uint chan_group = chan < 32 ? 1 : 0;
2814 uint chan_in_group = chan & 037;
2815
2816 uint iomUnitNum =
2817 iom_unit_data[iom_unit_idx].configSwMultiplexBaseAddress & 3u;
2818 uint interrupt_num = iomUnitNum | (chan_group << 2) | ((uint) pic << 3);
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829 uint pi_base = iom_unit_data[iom_unit_idx].configSwMultiplexBaseAddress & ~3u;
2830 imw_addr = (pi_base << 3) | interrupt_num;
2831
2832 sim_debug (DBG_DEBUG, & iom_dev,
2833 "%s: IOM %c, channel %d (%#o), level %d; "
2834 "Interrupt %d (%#o).\r\n",
2835 __func__, iomChar (iom_unit_idx), chan, chan, pic, interrupt_num,
2836 interrupt_num);
2837 word36 imw;
2838 iom_core_read_lock (iom_unit_idx, imw_addr, &imw, __func__);
2839
2840
2841
2842
2843
2844 putbits36_1 (& imw, chan_in_group, 1);
2845 iom_core_write_unlock (iom_unit_idx, imw_addr, imw, __func__);
2846 return scu_set_interrupt (iom_unit_data[iom_unit_idx].invokingScuUnitIdx, interrupt_num);
2847 }
2848
2849 static void iom_fault (uint iom_unit_idx, uint chan, UNUSED const char * who,
2850 iomFaultServiceRequest req,
2851 iomSysFaults_t signal)
2852 {
2853 #if defined(TESTING)
2854 cpu_state_t * cpup = _cpup;
2855 #endif
2856
2857
2858
2859 if (! tandd_mode_any ())
2860 sim_warn ("iom_fault %s: IOM %c channel %o, fault %o\r\n", who,
2861 'A' + iom_unit_idx, chan, (uint) signal);
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888 sim_debug (DBG_DEBUG, & iom_dev,
2889 "%s: chan %d %s req %#o signal %#o\r\n",
2890 __func__, chan, who, req, signal);
2891
2892 word36 faultWord = 0;
2893 putbits36_9 (& faultWord, 9, (word9) chan);
2894 putbits36_5 (& faultWord, 18, (word5) req);
2895
2896 putbits36_6 (& faultWord, 30, (word6) signal);
2897
2898 uint chanloc = mbxLoc (iom_unit_idx, IOM_SYSTEM_FAULT_CHAN);
2899
2900 word36 lpw;
2901 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_LPW, & lpw, __func__);
2902
2903 word36 scw;
2904 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_SCW, & scw, __func__);
2905
2906 word36 dcw;
2907 iom_core_read_lock (iom_unit_idx, chanloc + IOM_MBX_DCW, & dcw, __func__);
2908
2909
2910
2911
2912
2913 iom_core_write (iom_unit_idx, (dcw >> 18) & MASK18, faultWord, __func__);
2914
2915 uint tally = dcw & MASK12;
2916 if (tally > 1)
2917 {
2918 dcw -= 01llu;
2919 dcw += 01000000llu;
2920 }
2921 else
2922 dcw = scw;
2923 iom_core_write_unlock (iom_unit_idx, chanloc + IOM_MBX_DCW, dcw, __func__);
2924
2925 send_general_interrupt (iom_unit_idx, IOM_SYSTEM_FAULT_CHAN, imwSystemFaultPic);
2926 }
2927
2928
2929
2930
2931
2932
2933 int iom_list_service (uint iom_unit_idx, uint chan,
2934 bool * ptro, bool * sendp, bool * uffp)
2935 {
2936 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
2937
2938
2939
2940 bool isConnChan = chan == IOM_CONNECT_CHAN;
2941 * ptro = false;
2942 bool uff = false;
2943 bool send = false;
2944
2945
2946
2947
2948
2949
2950
2951 if (p -> lsFirst)
2952 {
2953
2954
2955 fetch_and_parse_LPW (iom_unit_idx, chan);
2956 p -> wasTDCW = false;
2957 p -> SEG = 0;
2958 }
2959
2960
2961
2962
2963 if (isConnChan)
2964 {
2965
2966
2967
2968 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 0)
2969 {
2970 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2971 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2972 iomIllTalCChnFlt);
2973 return -1;
2974 }
2975
2976 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 1)
2977 {
2978
2979
2980
2981 if (p -> LPW_TALLY == 0)
2982 {
2983 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2984 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2985 iomIllTalCChnFlt);
2986 return -1;
2987 }
2988
2989 if (p -> LPW_TALLY > 1)
2990 {
2991
2992
2993 if (p -> LPW_20_AE == 0 &&
2994 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
2995 01000000llu)
2996 {
2997 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
2998 p -> lsFirst ? iomFsrFirstList : iomFsrList,
2999 iom256KFlt);
3000 return -1;
3001 }
3002 }
3003 else if (p -> LPW_TALLY == 1)
3004 * ptro = true;
3005 }
3006 else
3007 * ptro = true;
3008
3009
3010
3011
3012
3013 fetch_and_parse_PCW (iom_unit_idx, chan);
3014
3015
3016 if (IS_NOT_IDCW (p))
3017 {
3018 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
3019 p -> lsFirst ? iomFsrFirstList : iomFsrList,
3020 iomNotPCWFlt);
3021 return -1;
3022 }
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035 send = true;
3036
3037 goto D;
3038 }
3039
3040
3041
3042
3043
3044 if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 0)
3045 {
3046
3047
3048 if (p -> LPW_20_AE == 0 &&
3049 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
3050 01000000llu)
3051 {
3052 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
3053 p -> lsFirst ? iomFsrFirstList : iomFsrList,
3054 iom256KFlt);
3055 return -1;
3056 }
3057 }
3058 else if (p -> LPW_21_NC == 0 && p -> LPW_22_TAL == 1)
3059 {
3060 A:;
3061
3062
3063
3064
3065
3066
3067
3068
3069 if (p -> LPW_TALLY == 0 && p -> LPW_22_TAL)
3070 {
3071 sim_warn("%s: setting uff for chan %d because LPW_TALLY was 0. LPW=%llo.\r\n",
3072 __func__, chan, p -> LPW);
3073 uff = true;
3074 }
3075 else if (p -> LPW_TALLY > 1)
3076 {
3077
3078
3079
3080 if (p -> LPW_20_AE == 0 &&
3081 (((word36) p -> LPW_DCW_PTR) + ((word36) p -> LPW_TALLY)) >
3082 01000000llu)
3083 {
3084 iom_fault (iom_unit_idx, IOM_CONNECT_CHAN, __func__,
3085 p -> lsFirst ? iomFsrFirstList : iomFsrList,
3086 iom256KFlt);
3087 return -1;
3088 }
3089 }
3090 }
3091
3092
3093
3094
3095 fetch_and_parse_DCW (iom_unit_idx, chan, false);
3096
3097
3098
3099 if (p -> lsFirst)
3100 p -> LPWX_SIZE = p -> LPW_DCW_PTR;
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111 if (IS_TDCW (p))
3112 {
3113
3114 if (p -> wasTDCW)
3115 {
3116 sim_warn("%s: setting uff for chan %d because p->wasTDCW was %d\r\n",
3117 __func__, chan, p->wasTDCW);
3118 uff = true;
3119 goto uffSet;
3120 }
3121 p -> wasTDCW = true;
3122
3123
3124
3125 p -> LPW_DCW_PTR = p -> TDCW_DATA_ADDRESS;
3126
3127
3128
3129
3130 p -> LPW_20_AE |= p -> TDCW_33_EC;
3131 p -> LPW_18_RES |= p -> TDCW_34_RES;
3132 p -> LPW_23_REL |= p -> TDCW_35_REL;
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165 if (p -> TDCW_31_SEG)
3166 sim_warn ("TDCW_31_SEG\r\n");
3167
3168 update_chan_mode (iom_unit_idx, chan, true);
3169
3170
3171 p->LPW_TALLY = ((word12) (((word12s) p->LPW_TALLY) - 1)) & MASK12;
3172
3173 pack_LPW (iom_unit_idx, chan);
3174
3175
3176
3177 if (p -> LPW_18_RES && p -> TDCW_33_EC)
3178 {
3179 sim_warn("%s: setting uff for chan %d because p->LPW_18_RES and p->TDCW_33_EC were set\r\n",
3180 __func__, chan);
3181 uff = true;
3182 goto uffSet;
3183 }
3184
3185 goto A;
3186 }
3187 else if (IS_IDCW (p))
3188 {
3189
3190
3191 if (p -> LPW_18_RES)
3192 {
3193
3194 sim_warn("%s: setting uff for chan %d because LPW_18_RES was %o\r\n",
3195 __func__, chan, p->LPW_18_RES);
3196 uff = true;
3197
3198 }
3199 else
3200 {
3201
3202
3203 send = true;
3204 }
3205 p -> LPWX_SIZE = p -> LPW_DCW_PTR;
3206 goto D;
3207 }
3208
3209 p -> wasTDCW = false;
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235 if (uff)
3236 {
3237 uffSet:;
3238
3239 p -> DCW_18_20_CP = 07u;
3240 pack_DCW (iom_unit_idx, chan);
3241 }
3242
3243
3244
3245
3246
3247
3248
3249
3250 send = true;
3251
3252
3253
3254 D:;
3255
3256
3257
3258 * uffp = uff;
3259 * sendp = send;
3260
3261
3262
3263 if (p -> LPW_21_NC == 0)
3264 {
3265
3266 if (isConnChan)
3267 p -> LPW_DCW_PTR = (p -> LPW_DCW_PTR + 2u) & MASK18;
3268 else
3269 p -> LPW_DCW_PTR = (p -> LPW_DCW_PTR + 1u) & MASK18;
3270
3271 p->LPW_TALLY = ((word12) (((word12s) p->LPW_TALLY) - 1)) & MASK12;
3272 pack_LPW (iom_unit_idx, chan);
3273 }
3274
3275
3276 if (p -> DDCW_22_23_TYPE == 07u || p -> lsFirst)
3277 {
3278
3279
3280
3281
3282 write_LPW (iom_unit_idx, chan);
3283 }
3284 else
3285 {
3286 if (p -> LPW_21_NC == 0 ||
3287 (IS_TDCW (p)))
3288 {
3289
3290
3291
3292
3293 write_LPW (iom_unit_idx, chan);
3294 }
3295 }
3296
3297 p -> lsFirst = false;
3298
3299
3300 return 0;
3301 }
3302
3303
3304
3305 static int doPayloadChannel (uint iomUnitIdx, uint chan) {
3306 #if defined(TESTING)
3307 cpu_state_t * cpup = _cpup;
3308 sim_debug (DBG_DEBUG, & iom_dev, "%s: Payload channel %c%02o\r\n", __func__, iomChar (iomUnitIdx), chan);
3309 #endif
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
3328
3329 #if defined(TESTING)
3330 word36 PCW_DCW = p->DCW;
3331 word1 PCW_LPW_23_REL = p->LPW_23_REL;
3332 #endif
3333 p -> chanMode = cm1;
3334 p -> LPW_18_RES = 0;
3335 p -> LPW_20_AE = 0;
3336 p -> LPW_23_REL = 0;
3337
3338 unpack_DCW (iomUnitIdx, chan);
3339
3340 p->isPCW = true;
3341
3342
3343
3344 struct iom_to_ctlr_s * d = & cables->iom_to_ctlr[iomUnitIdx][chan];
3345
3346
3347
3348
3349 if (d->chan_type != chan_type_CPI && p -> IDCW_DEV_CMD == 051) {
3350 p->stati = 04501;
3351 send_terminate_interrupt (iomUnitIdx, chan);
3352 return 0;
3353 }
3354
3355 if ((!d->in_use) || (!d->iom_cmd)) {
3356 p -> stati = 06000;
3357 #if defined(POLTS_TESTING)
3358 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf \
3359 ("// terminate 10. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3360 #endif
3361 goto terminate;
3362 }
3363
3364
3365
3366
3367
3368 p -> ADDR_EXT = p -> PCW_AE;
3369
3370 p -> lsFirst = true;
3371
3372 p -> tallyResidue = 0;
3373 p -> isRead = true;
3374 p -> charPos = 0;
3375
3376
3377
3378 p -> initiate = true;
3379 p -> chanStatus = chanStatNormal;
3380
3381
3382
3383
3384 int rc = d->iom_cmd (iomUnitIdx, chan);
3385
3386 if (rc < 0) {
3387 p -> dev_code = getbits36_6 (p -> DCW, 6);
3388 #if defined(POLTS_TESTING)
3389 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3390 sim_printf ("// terminate 9. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3391 #endif
3392 goto terminate;
3393 }
3394
3395 if (IS_IDCW (p) && p->IDCW_CHAN_CTRL == CHAN_CTRL_MARKER) {
3396 send_marker_interrupt (iomUnitIdx, (int) chan);
3397 }
3398
3399 if (rc == IOM_CMD_DISCONNECT) {
3400 #if defined(POLTS_TESTING)
3401 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf \
3402 ("// terminate 8. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3403 #endif
3404 goto terminate;
3405 }
3406
3407 if (p->masked) {
3408 #if defined(POLTS_TESTING)
3409 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf \
3410 ("// terminate 7. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3411 #endif
3412 goto terminate;
3413 }
3414
3415 bool ptro, send, uff;
3416 bool terminate = false;
3417 p->isPCW = false;
3418
3419 #if defined(TESTING)
3420 bool first = true;
3421 #endif
3422
3423 (void)terminate;
3424 bool idcw_terminate = p -> IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE;
3425 do {
3426 int rc2 = iom_list_service (iomUnitIdx, chan, & ptro, & send, & uff);
3427 if (rc2 < 0) {
3428
3429 sim_warn ("%s list service failed\r\n", __func__);
3430 return -1;
3431 }
3432 if (uff) {
3433
3434 #if defined(POLTS_TESTING)
3435 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3436 sim_printf ("// terminate 6. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3437 #endif
3438 goto terminate;
3439 }
3440
3441 if (! send) {
3442 sim_warn ("%s nothing to send\r\n", __func__);
3443 return 1;
3444 }
3445
3446 #if defined(TESTING)
3447 # if defined(POLTS_TESTING)
3448 if (iomUnitIdx == 1 && chan == 020)
3449 # endif
3450 if_sim_debug (DBG_TRACE, & iom_dev) {
3451 if (first) {
3452 first = false;
3453 dumpLPW (iomUnitIdx, chan);
3454 sim_printf ("// DCW list dump: \r\n");
3455 dumpDCW (PCW_DCW, PCW_LPW_23_REL);
3456 for (int i = 0; i < 8; i ++)
3457 dumpDCW (M[p->LPW_DCW_PTR - 1 + i], p->LPW_23_REL);
3458 sim_printf ("// \r\n");
3459 }
3460 }
3461 #endif
3462
3463
3464
3465
3466
3467
3468 if (IS_IDCW (p)) {
3469 idcw_terminate = p -> IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE;
3470 if (p -> LPW_23_REL == 0 && p -> IDCW_EC == 1)
3471 p -> ADDR_EXT = getbits36_6 (p -> DCW, 12);
3472
3473
3474 p -> tallyResidue = 0;
3475 p -> isRead = true;
3476 p -> charPos = 0;
3477 p -> chanStatus = chanStatNormal;
3478 }
3479
3480
3481
3482 rc2 = d->iom_cmd (iomUnitIdx, chan);
3483
3484 if (rc2 < 0) {
3485 p -> dev_code = getbits36_6 (p -> DCW, 6);
3486 #if defined(POLTS_TESTING)
3487 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3488 sim_printf ("// terminate 5. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3489 #endif
3490 goto terminate;
3491 }
3492
3493 if (rc2 == IOM_CMD_DISCONNECT) {
3494 terminate = true;
3495 #if defined(POLTS_TESTING)
3496 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) sim_printf \
3497 ("// terminate 4. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3498 #endif
3499 }
3500
3501 if (rc2 == IOM_CMD_PENDING)
3502 goto pending;
3503
3504
3505 if (IS_IDCW (p) && p->IDCW_CHAN_CTRL == CHAN_CTRL_TERMINATE && p->IDCW_CHAN_CMD == CHAN_CMD_NONDATA) {
3506 #if defined(POLTS_TESTING)
3507 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3508 sim_printf ("// terminate 1. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3509 #endif
3510 goto terminate;
3511 }
3512
3513 if (IS_IOTD (p) && idcw_terminate && rc2 != IOM_CMD_RESIDUE) {
3514 #if defined(POLTS_TESTING)
3515
3516
3517 if (chan == 014) if_sim_debug (DBG_TRACE, & iom_dev) \
3518 sim_printf ("// terminate 2. ctrl == 0 in chan %d (%o) DCW\r\n", chan, chan);
3519 #endif
3520 goto terminate;
3521 }
3522
3523
3524
3525 if (IS_NOT_IDCW (p) && rc2 == IOM_CMD_RESIDUE) {
3526 if (p->recordResidue)
3527 p->recordResidue --;
3528 if (p->recordResidue == 0)
3529 goto terminate;
3530 }
3531 } while (! terminate);
3532
3533 terminate:;
3534 #if defined(POLTS_TESTING)
3535 if (iomUnitIdx == 1 && chan == 020) sim_printf ("stati %04o\r\n", p->stati);
3536 #endif
3537 send_terminate_interrupt (iomUnitIdx, chan);
3538 return 0;
3539
3540 pending:;
3541 return 0;
3542 }
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555 static int doConnectChan (uint iom_unit_idx) {
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567 #if defined(TESTING)
3568 cpu_state_t * cpup = _cpup;
3569 #endif
3570 sim_debug (DBG_DEBUG, & iom_dev, "%s: Connect channel\r\n", __func__);
3571 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][IOM_CONNECT_CHAN];
3572 p -> lsFirst = true;
3573 #if defined(TESTING) && defined(POLTS_TESTING)
3574 bool first = true;
3575 #endif
3576 bool ptro, send, uff;
3577 do {
3578
3579 int rc = iom_list_service (iom_unit_idx, IOM_CONNECT_CHAN, & ptro, & send, & uff);
3580 if (rc < 0) {
3581 if (! tandd_mode_any ())
3582 sim_warn ("connect channel connect failed\r\n");
3583 return -1;
3584 }
3585 if (uff) {
3586 sim_warn ("connect channel ignoring uff\r\n");
3587 }
3588 if (! send) {
3589 sim_warn ("connect channel nothing to send\r\n");
3590 } else {
3591 #if defined(xTESTING)
3592 if_sim_debug (DBG_TRACE, & iom_dev) {
3593 if (first) {
3594 first = false;
3595 sim_printf ("// CIOC %lld\r\n", cpu.cycleCnt);
3596 dumpLPW (iom_unit_idx, IOM_CONNECT_CHAN);
3597 sim_printf ("// PCW %012llo %012llo\r\n", p->PCW0, p->PCW1);
3598 sim_printf ("// Chan info %04o\r\n", p->PCW_CHAN);
3599 sim_printf ("// Addr ext %02o\r\n", p->PCW_AE);
3600 sim_printf ("// 111 %o\r\n", getbits36_3 (p->PCW0, 18));
3601 sim_printf ("// M %o\r\n", p->PCW_21_MSK);
3602 sim_printf ("// Chan info %08o\r\n", getbits36_14 (p->PCW0, 22));
3603 sim_printf ("// Pg Tbl Ptr %06o\r\n", p->PCW_PAGE_TABLE_PTR);
3604 sim_printf ("// PTP %o\r\n", p->PCW_63_PTP);
3605 sim_printf ("// PGE %o\r\n", p->PCW_64_PGE);
3606 sim_printf ("// AUX %o\r\n", p->PCW_65_AUX);
3607 sim_printf ("//\r\n");
3608 }
3609 }
3610 #endif
3611
3612 iom_chan_data_t * q = & iom_chan_data[iom_unit_idx][p -> PCW_CHAN];
3613
3614 q -> PCW0 = p -> PCW0;
3615 q -> PCW1 = p -> PCW1;
3616 q -> PCW_CHAN = p -> PCW_CHAN;
3617 q -> PCW_AE = p -> PCW_AE;
3618 q -> PCW_PAGE_TABLE_PTR = p -> PCW_PAGE_TABLE_PTR;
3619 q -> PCW_63_PTP = p -> PCW_63_PTP;
3620 q -> PCW_64_PGE = p -> PCW_64_PGE;
3621 q -> PCW_65_AUX = p -> PCW_65_AUX;
3622 q -> PCW_21_MSK = p -> PCW_21_MSK;
3623 q -> DCW = p -> DCW;
3624
3625 sim_debug (DBG_DEBUG, & iom_dev, "%s: PCW %012llo %012llo chan %02o\r\n", __func__, q->PCW0, q->PCW1, q->PCW_CHAN);
3626
3627 q -> masked = p -> PCW_21_MSK;
3628 if (q -> masked) {
3629 if (q -> in_use)
3630 sim_warn ("%s: chan %d masked while in use\r\n", __func__, p -> PCW_CHAN);
3631 q -> in_use = false;
3632 q -> start = false;
3633 } else {
3634 if (q -> in_use)
3635 sim_warn ("%s: chan %d connect while in use\r\n", __func__, p -> PCW_CHAN);
3636 q -> in_use = true;
3637 q -> start = true;
3638 #if defined(IO_THREADZ)
3639 setChnConnect (iom_unit_idx, p -> PCW_CHAN);
3640 #else
3641 # if !defined(IO_ASYNC_PAYLOAD_CHAN) && !defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
3642 doPayloadChannel (iom_unit_idx, p -> PCW_CHAN);
3643 # endif
3644 # if defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
3645 pthread_cond_signal (& iomCond);
3646 # endif
3647 #endif
3648 }
3649 }
3650 } while (! ptro);
3651 return 0;
3652 }
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664 int send_marker_interrupt (uint iom_unit_idx, int chan)
3665 {
3666 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3667 return(0);
3668 status_service (iom_unit_idx, (uint) chan, true);
3669 return send_general_interrupt (iom_unit_idx, (uint) chan, imwMarkerPic);
3670 }
3671
3672
3673
3674
3675
3676
3677
3678
3679 int send_special_interrupt (uint iom_unit_idx, uint chan, uint devCode,
3680 word8 status0, word8 status1)
3681 {
3682
3683 uint chanloc = mbxLoc (iom_unit_idx, IOM_SPECIAL_STATUS_CHAN);
3684
3685 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3686 return(0);
3687
3688 #if defined(LOCKLESS)
3689 lock_iom();
3690 #endif
3691
3692
3693
3694
3695
3696
3697 word36 lpw;
3698 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_LPW, & lpw, __func__);
3699
3700 word36 scw;
3701 iom_core_read (iom_unit_idx, chanloc + IOM_MBX_SCW, & scw, __func__);
3702
3703 word36 dcw;
3704 iom_core_read_lock (iom_unit_idx, chanloc + IOM_MBX_DCW, & dcw, __func__);
3705
3706 word36 status = 0400000000000ull;
3707 status |= (((word36) chan) & MASK6) << 27;
3708 status |= (((word36) devCode) & MASK8) << 18;
3709 status |= (((word36) status0) & MASK8) << 9;
3710 status |= (((word36) status1) & MASK8) << 0;
3711 iom_core_write (iom_unit_idx, (dcw >> 18) & MASK18, status, __func__);
3712
3713 uint tally = dcw & MASK12;
3714 if (tally > 1)
3715 {
3716 dcw -= 01llu;
3717 dcw += 01000000llu;
3718 }
3719 else
3720 dcw = scw;
3721 iom_core_write_unlock (iom_unit_idx, chanloc + IOM_MBX_DCW, dcw, __func__);
3722
3723 #if defined(LOCKLESS)
3724 unlock_iom();
3725 #endif
3726
3727 send_general_interrupt (iom_unit_idx, IOM_SPECIAL_STATUS_CHAN, imwSpecialPic);
3728 return 0;
3729 }
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740 int send_terminate_interrupt (uint iom_unit_idx, uint chan)
3741 {
3742 if (iom_chan_data [iom_unit_idx] [chan] . masked)
3743 return 0;
3744 status_service (iom_unit_idx, chan, false);
3745 if (iom_chan_data [iom_unit_idx] [chan] . in_use == false)
3746 sim_warn ("%s: chan %d not in use\r\n", __func__, chan);
3747 iom_chan_data [iom_unit_idx] [chan] . in_use = false;
3748 send_general_interrupt (iom_unit_idx, chan, imwTerminatePic);
3749 return 0;
3750 }
3751
3752 void iom_interrupt (uint scu_unit_idx, uint iom_unit_idx)
3753 {
3754 cpu_state_t * cpup = _cpup;
3755 sim_debug (DBG_DEBUG, & iom_dev,
3756 "%s: IOM %c starting. [%"PRId64"] %05o:%08o\r\n",
3757 __func__, iomChar (iom_unit_idx), cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC);
3758
3759 iom_unit_data[iom_unit_idx].invokingScuUnitIdx = scu_unit_idx;
3760
3761 #if defined(IO_THREADZ)
3762 setIOMInterrupt (iom_unit_idx);
3763 iomDoneWait (iom_unit_idx);
3764 #else
3765 int ret = doConnectChan (iom_unit_idx);
3766
3767 sim_debug (DBG_DEBUG, & iom_dev,
3768 "%s: IOM %c finished; doConnectChan returned %d.\r\n",
3769 __func__, iomChar (iom_unit_idx), ret);
3770 #endif
3771
3772 }
3773
3774 #if defined(IO_THREADZ)
3775 void * chan_thread_main (void * arg)
3776 {
3777 uint myid = (uint) * (int *) arg;
3778 this_iom_idx = (uint) myid / MAX_CHANNELS;
3779 this_chan_num = (uint) myid % MAX_CHANNELS;
3780
3781
3782
3783 set_cpu_idx (0);
3784
3785 sim_msg ("\rIOM %c Channel %u thread created\r\n", this_iom_idx + 'a', this_chan_num);
3786 # if defined(TESTING)
3787 printPtid(pthread_self());
3788 # endif
3789 if (realtime_ok) {
3790 set_realtime_priority (pthread_self(), realtime_max_priority() - 1);
3791 check_realtime_priority (pthread_self(), realtime_max_priority() - 1);
3792 } else {
3793 # if !defined(__QNX__)
3794 (void)sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
3795 # endif
3796 }
3797
3798 setSignals ();
3799 while (1)
3800 {
3801
3802 chnConnectWait ();
3803
3804 doPayloadChannel (this_iom_idx, this_chan_num);
3805 chnConnectDone ();
3806 }
3807 }
3808
3809 void * iom_thread_main (void * arg)
3810 {
3811 int myid = * (int *) arg;
3812 this_iom_idx = (uint) myid;
3813
3814
3815
3816 set_cpu_idx (0);
3817
3818 sim_printf("IOM %c thread created\r\n", 'a' + myid);
3819
3820 setSignals ();
3821 while (1)
3822 {
3823
3824 iomInterruptWait ();
3825
3826 int ret = doConnectChan (this_iom_idx);
3827
3828 sim_debug (DBG_DEBUG, & iom_dev,
3829 "%s: IOM %c finished; doConnectChan returned %d.\r\n",
3830 __func__, iomChar (myid), ret);
3831 iomInterruptDone ();
3832 }
3833 }
3834 #endif
3835
3836
3837
3838
3839
3840
3841
3842 void iom_init (void)
3843 {
3844
3845 }
3846
3847 #if defined(PANEL68)
3848 void do_boot (void)
3849 {
3850 boot_svc (& boot_channel_unit[0]);
3851 }
3852 #endif
3853
3854 #if defined(IO_ASYNC_PAYLOAD_CHAN) || defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
3855 void iomProcess (void)
3856 {
3857 for (uint i = 0; i < N_IOM_UNITS_MAX; i++)
3858 for (uint j = 0; j < MAX_CHANNELS; j++)
3859 {
3860 iom_chan_data_t * p = &iom_chan_data [i] [j];
3861 if (p -> start)
3862 {
3863 p -> start = false;
3864 doPayloadChannel (i, j);
3865 }
3866 }
3867 }
3868 #endif
3869
3870 char iomChar (uint iomUnitIdx)
3871 {
3872 return (iom_unit_data[iomUnitIdx].configSwMultiplexBaseAddress & 3) + 'A';
3873 }