This source file includes following definitions.
- fnp_core_read_n
- l_putbits36_1
- dmpmbx
- wcd
- tun_write
- fnp_wtx_output
- wtx
- fnp_rtx_input_accepted
- interruptL66_CS_to_FNP
- interruptL66_FNP_to_CS
- interruptL66_CS_done
- interruptL66
- fnpcmdBootload
- getl6core
- processMBX
- fnpCmd
- fnp_iom_cmd
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 #define ASSUME0 0
38
39 #include <stdio.h>
40 #include <ctype.h>
41
42 #include "dps8.h"
43 #include "dps8_sys.h"
44 #include "dps8_scu.h"
45 #include "dps8_iom.h"
46 #include "dps8_cable.h"
47 #include "dps8_cpu.h"
48 #include "dps8_fnp2.h"
49 #include "dps8_fnp2_iomcmd.h"
50 #include "dps8_utils.h"
51 #include "fnpuv.h"
52
53 #define DBG_CTR 1
54
55 #if defined(THREADZ) || defined(LOCKLESS)
56 # include "threadz.h"
57 #endif
58
59 #ifdef TESTING
60 static inline void fnp_core_read_n (word24 addr, word36 *data, uint n, UNUSED const char * ctx)
61 {
62 # ifdef THREADZ
63 lock_mem_rd ();
64 # endif
65 for (uint i = 0; i < n; i ++)
66 data [i] = M [addr + i] & DMASK;
67 # ifdef THREADZ
68 unlock_mem ();
69 # endif
70 }
71 #endif
72
73 #ifdef THREADZ
74 static inline void l_putbits36_1 (vol word36 * x, uint p, word1 val)
75 {
76 const int n = 1;
77 int shift = 36 - (int) p - (int) n;
78 if (shift < 0 || shift > 35) {
79 sim_printf ("l_putbits36_1: bad args (%012"PRIo64",pos=%d)\n", *x, p);
80 return;
81 }
82 word36 mask = ~ (~0U<<n);
83 word36 smask = mask << (unsigned) shift;
84
85
86 lock_mem_wr ();
87 * x = (* x & ~ smask) | (((word36) val & mask) << shift);
88 unlock_mem ();
89 }
90 #else
91 # define l_putbits36_1 putbits36_1
92 #endif
93
94
95
96
97
98 struct decoded_t
99 {
100 uint devUnitIdx;
101 uint op_code;
102 uint slot_no;
103 uint iom_unit;
104 uint chan_num;
105 word24 smbx;
106 word24 fsmbx;
107 struct fnpUnitData_s * fudp;
108 uint cell;
109 };
110
111
112
113
114
115 #ifdef TESTING
116 static void dmpmbx (uint mailboxAddress)
117 {
118 struct mailbox mbx;
119 fnp_core_read_n (mailboxAddress, (word36 *) & mbx, MAILBOX_WORDS, "dmpmbx");
120 sim_printf ("dia_pcw %012llo\n", (long long unsigned int) mbx.dia_pcw);
121 sim_printf ("mailbox_requests %012llo\n", (long long unsigned int) mbx.mailbox_requests);
122 sim_printf ("term_inpt_mpx_wd %012llo\n", (long long unsigned int) mbx.term_inpt_mpx_wd);
123 sim_printf ("last_mbx_req_count %012llo\n", (long long unsigned int) mbx.last_mbx_req_count);
124 sim_printf ("num_in_use %012llo\n", (long long unsigned int) mbx.num_in_use);
125 sim_printf ("mbx_used_flags %012llo\n", (long long unsigned int) mbx.mbx_used_flags);
126 for (uint i = 0; i < 8; i ++)
127 {
128 sim_printf ("CS mbx %d\n", i);
129 sim_printf (" word1 %012llo\n",
130 (long long unsigned int) mbx.dn355_sub_mbxes[i].word1);
131 sim_printf (" word2 %012llo\n",
132 (long long unsigned int) mbx.dn355_sub_mbxes[i].word2);
133 sim_printf (" command_data %012llo\n",
134 (long long unsigned int) mbx.dn355_sub_mbxes[i].command_data [0]);
135 sim_printf (" %012llo\n",
136 (long long unsigned int) mbx.dn355_sub_mbxes[i].command_data [1]);
137 sim_printf (" %012llo\n",
138 (long long unsigned int) mbx.dn355_sub_mbxes[i].command_data [2]);
139 sim_printf (" word6 %012llo\n",
140 (long long unsigned int) mbx.dn355_sub_mbxes[i].word6);
141 }
142 for (uint i = 0; i < 4; i ++)
143 {
144 sim_printf ("FNP mbx %d\n", i);
145 sim_printf (" word1 %012llo\n",
146 (unsigned long long int)mbx.fnp_sub_mbxes[i].word1);
147 sim_printf (" word2 %012llo\n",
148 (unsigned long long int)mbx.fnp_sub_mbxes[i].word2);
149 sim_printf (" mystery %012llo\n",
150 (unsigned long long int)mbx.fnp_sub_mbxes[i].mystery [0]);
151 sim_printf (" %012llo\n",
152 (unsigned long long int)mbx.fnp_sub_mbxes[i].mystery [1]);
153 sim_printf (" %012llo\n",
154 (unsigned long long int)mbx.fnp_sub_mbxes[i].mystery [2]);
155 }
156
157 }
158 #endif
159
160
161
162
163
164 static int wcd (struct decoded_t *decoded_p)
165 {
166 struct t_line * linep = & decoded_p->fudp->MState.line[decoded_p->slot_no];
167 sim_debug (DBG_TRACE, & fnp_dev, "[%u] wcd op_code %u 0%o\n", decoded_p->slot_no, decoded_p->op_code, decoded_p->op_code);
168
169 word36 command_data[3];
170 for (uint i=0; i < 3; i++)
171 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->smbx+COMMAND_DATA + i, & command_data [i], direct_load);
172
173 switch (decoded_p->op_code)
174 {
175 case 1:
176 {
177 sim_debug (DBG_TRACE, & fnp_dev, "[%u] disconnect_this_line\n", decoded_p->slot_no);
178 if (linep->line_client && linep->service == service_login)
179 fnpuv_start_writestr (linep->line_client, (unsigned char *) "Multics has disconnected you\r\n");
180 #ifdef DISC_DELAY
181 linep -> line_disconnected = DISC_DELAY;
182 #else
183 linep -> line_disconnected = true;
184 #endif
185 linep -> listen = false;
186 if (linep->line_client)
187 {
188 close_connection ((uv_stream_t *) linep->line_client);
189 }
190
191 }
192 break;
193
194 case 3:
195 {
196 sim_debug (DBG_TRACE, & fnp_dev, "[%u] dont_accept_calls\n", decoded_p->slot_no);
197 decoded_p->fudp->MState.accept_calls = false;
198 }
199 break;
200
201 case 4:
202 {
203 sim_debug (DBG_TRACE, & fnp_dev, "[%u] accept_calls\n", decoded_p->slot_no);
204 decoded_p->fudp->MState.accept_calls = true;
205 }
206 break;
207
208 case 6:
209 {
210 linep->lineType = (word9) getbits36_18 (command_data[0], 0);
211 }
212 break;
213
214 case 8:
215 {
216 sim_debug (DBG_TRACE, & fnp_dev, "[%u] set_framing_chars\n", decoded_p->slot_no);
217
218 uint d1 = getbits36_9 (command_data[0], 0);
219 uint d2 = getbits36_9 (command_data[0], 9);
220 linep->frame_begin = d1;
221 linep->frame_end = d2;
222 }
223 break;
224
225 case 12:
226 {
227 sim_debug (DBG_TRACE, & fnp_dev, "[%u] dial out\n", decoded_p->slot_no);
228
229 fnpuv_dial_out (decoded_p->devUnitIdx, decoded_p->slot_no, command_data[0], command_data[1], command_data[2]);
230 }
231 break;
232
233 case 22:
234 {
235 sim_debug (DBG_TRACE, & fnp_dev, "[%u] line_control\n", decoded_p->slot_no);
236
237
238
239
240 word18 op = getbits36_18 (command_data[0], 0);
241
242
243
244
245 switch (op)
246 {
247 case 1:
248
249
250
251
252
253 break;
254 case 2:
255 sim_debug (DBG_TRACE, & fnp_dev, "ACCEPT_BID\n");
256 break;
257 case 3:
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272 break;
273 case 4:
274
275
276
277
278
279
280
281 break;
282 case 5:
283 sim_debug (DBG_TRACE, & fnp_dev, "REPORT_WRITE_STATUS\n");
284 break;
285 case 6:
286 sim_debug (DBG_TRACE, & fnp_dev, "SET_3270_MODE\n");
287 break;
288 case 7:
289 {
290 sim_debug (DBG_TRACE, & fnp_dev, "SET_POLLING_ADDR\n");
291
292
293
294 word9 c1 = getbits36_9 (command_data[0], 27);
295
296 word9 c3 = getbits36_9 (command_data[1], 9);
297
298 sim_debug (DBG_TRACE, & fnp_dev, " char1 %u\n", c1);
299 sim_debug (DBG_TRACE, & fnp_dev, " char3 %u\n", c3);
300 fnpData.ibm3270ctlr[ASSUME0].pollCtlrChar = (unsigned char) (c1 & 0xff);
301 fnpData.ibm3270ctlr[ASSUME0].pollDevChar = (unsigned char) (c3 & 0xff);
302 fnpData.
303 fnpUnitData[decoded_p->devUnitIdx].
304 MState.
305 line[decoded_p->slot_no].
306 line_client = NULL;
307 }
308 break;
309 case 8:
310 sim_debug (DBG_TRACE, & fnp_dev, "START_POLL\n");
311 fnpuv3270Poll (true);
312 break;
313 case 9:
314 {
315 sim_debug (DBG_TRACE, & fnp_dev, "SET_SELECT_ADDR\n");
316
317 word9 c1 = getbits36_9 (command_data[0], 27);
318
319 word9 c3 = getbits36_9 (command_data[1], 9);
320
321 sim_debug (DBG_TRACE, & fnp_dev, " char1 %u\n", c1);
322 sim_debug (DBG_TRACE, & fnp_dev, " char3 %u\n", c3);
323 fnpData.ibm3270ctlr[ASSUME0].selCtlrChar = (unsigned char) (c1 & 0xff);
324 fnpData.ibm3270ctlr[ASSUME0].selDevChar = (unsigned char) (c3 & 0xff);
325
326
327 if (fnpData.ibm3270ctlr[ASSUME0].selDevChar == 127)
328 {
329 fnpData.
330 fnpUnitData[decoded_p->devUnitIdx].
331 MState.
332 line[decoded_p->slot_no].
333 line_client = NULL;
334 break;
335 }
336
337
338
339
340 uint stn_no;
341 for (stn_no = 0; stn_no < ADDR_MAP_ENTRIES; stn_no ++)
342 if (addr_map [stn_no] == fnpData.ibm3270ctlr[ASSUME0].selDevChar)
343 break;
344 if (stn_no >= ADDR_MAP_ENTRIES)
345 {
346 sim_warn ("SET_POLLING_ADDR couldn't find selDevChar %02x\r\n", (unsigned int) fnpData.ibm3270ctlr[ASSUME0].selDevChar);
347 break;
348 }
349 fnpData.
350 fnpUnitData[decoded_p->devUnitIdx].
351 MState.
352 line[decoded_p->slot_no].
353 line_client =
354 fnpData.
355 ibm3270ctlr[ASSUME0].
356 stations[stn_no].
357 client;
358 }
359 break;
360 case 10:
361 sim_debug (DBG_TRACE, & fnp_dev, "STOP_AUTO_POLL\n");
362 break;
363 case 11:
364
365
366
367
368
369
370
371
372
373
374 break;
375 case 12:
376 sim_debug (DBG_TRACE, & fnp_dev, "SET_HASP_MODE\n");
377 break;
378 case 13:
379 sim_debug (DBG_TRACE, & fnp_dev, "SET_NAK_LIMIT\n");
380 break;
381 case 14:
382 sim_debug (DBG_TRACE, & fnp_dev, "SET_HASP_TIMERS\n");
383 break;
384 default:
385 sim_printf ("unknown %u. %o\n", op, op);
386 break;
387 }
388
389
390
391
392
393
394
395
396
397
398
399
400
401 }
402 break;
403
404 case 23:
405 {
406 linep->sync_msg_size = (uint) getbits36_18 (command_data[0], 0);
407
408 }
409 break;
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 case 24:
446 {
447 sim_debug (DBG_TRACE, & fnp_dev,
448 "[%u] set_echnego_break_table\n", decoded_p->slot_no);
449
450 #ifdef ECHNEGO_DEBUG
451 sim_printf ("set_echnego_break_table\r\n");
452 #endif
453
454 word36 word6;
455 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num,
456 decoded_p->smbx+WORD6, & word6,
457 direct_load);
458 uint data_addr = getbits36_18 (word6, 0);
459 uint data_len = getbits36_18 (word6, 18);
460
461
462
463
464
465
466
467 #define echoTableLen 8
468
469 if (data_len != echoTableLen && data_len != 0 &&
470 data_len != MASK18)
471 {
472 sim_printf ("set_echnego_break_table data_len !=8 (%d)\n", data_len);
473 break;
474 }
475
476 word36 echoTable [echoTableLen];
477 if (data_len == 0)
478 {
479 memset (linep->echnego_break_table, 0,
480 sizeof (linep->echnego_break_table));
481 }
482 else if (data_len == MASK18)
483 {
484 memset (linep->echnego_break_table, 1,
485 sizeof (linep->echnego_break_table));
486 }
487 else
488 {
489 for (uint i = 0; i < echoTableLen; i ++)
490 {
491 iom_direct_data_service (decoded_p->iom_unit,
492 decoded_p->chan_num, data_addr + i, & echoTable [i],
493 direct_load);
494
495 }
496
497
498 uint offset = 0;
499 for (uint i = 0; i < 8; i ++)
500 {
501 word36 w = echoTable [i];
502 for (uint j = 0; j < 16; j ++)
503 linep->echnego_break_table[offset++] =
504 !! getbits36_1 (w, j);
505 for (uint j = 0; j < 16; j ++)
506 linep->echnego_break_table[offset++] =
507 !! getbits36_1 (w, j + 18);
508 }
509 }
510
511
512
513
514
515
516
517
518
519
520
521 }
522 break;
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537 case 25:
538 {
539 sim_debug (DBG_TRACE, & fnp_dev,
540 "[%u] start_negotiated_echo\n", decoded_p->slot_no);
541
542 linep->echnego_sync_ctr =
543 getbits36_18 (command_data[0], 0);
544 linep->echnego_screen_left = getbits36_18 (command_data[0], 18);
545
546 #ifdef ECHNEGO_DEBUG
547 sim_printf ("start_negotiated_echo ctr %d screenleft %d "
548 "unechoed cnt %d\n", linep->echnego_sync_ctr,
549 linep->echnego_screen_left,linep->echnego_unechoed_cnt);
550 #endif
551
552
553
554
555
556 linep->echnego_on =
557 linep->echnego_sync_ctr == linep->echnego_unechoed_cnt;
558
559 #ifdef ECHNEGO_DEBUG
560 sim_printf ("echnego is %s\n", linep->echnego_on ? "on" : "off");
561 #endif
562
563 }
564 break;
565
566 case 26:
567 {
568 sim_debug (DBG_TRACE, & fnp_dev,
569 "[%u] stop_negotiated_echo\n", decoded_p->slot_no);
570 #ifdef ECHNEGO_DEBUG
571 sim_printf ("stop_negotiated_echo\r\n");
572 #endif
573 linep->echnego_on = false;
574
575 linep->ack_echnego_stop = true;
576 }
577 break;
578
579 case 27:
580 {
581 sim_debug (DBG_TRACE, & fnp_dev,
582 "[%u] init_echo_negotiation\n", decoded_p->slot_no);
583 #ifdef ECHNEGO_DEBUG
584 sim_printf ("init_echo_negotiation\r\n");
585 #endif
586
587
588
589
590
591
592
593 linep->echnego_unechoed_cnt = 0;
594
595
596 linep->ack_echnego_init = true;
597 }
598 break;
599
600 case 30:
601 {
602
603
604
605
606
607
608
609
610
611 sim_debug (DBG_TRACE, & fnp_dev, "[%u] input_fc_chars\n", decoded_p->slot_no);
612 word36 suspendStr = command_data[0];
613 linep->inputSuspendStr[0] = getbits36_8 (suspendStr, 10);
614 linep->inputSuspendStr[1] = getbits36_8 (suspendStr, 19);
615 linep->inputSuspendStr[2] = getbits36_8 (suspendStr, 28);
616 uint suspendLen = getbits36_9 (suspendStr, 0);
617 if (suspendLen > 3)
618 {
619
620 suspendLen = 3;
621 }
622 linep->inputSuspendLen = suspendLen;
623
624 word36 resumeStr = command_data[1];
625 linep->inputResumeStr[0] = getbits36_8 (resumeStr, 10);
626 linep->inputResumeStr[1] = getbits36_8 (resumeStr, 19);
627 linep->inputResumeStr[2] = getbits36_8 (resumeStr, 28);
628 uint resumeLen = getbits36_9 (resumeStr, 0);
629 if (resumeLen > 3)
630 {
631
632 resumeLen = 3;
633 }
634 linep->inputResumeLen = resumeLen;
635
636
637 }
638 break;
639
640 case 31:
641 {
642 sim_debug (DBG_TRACE, & fnp_dev, "[%u] output_fc_chars\n", decoded_p->slot_no);
643
644
645 word36 suspendStr = command_data[0];
646 linep->outputSuspendStr[0] = getbits36_8 (suspendStr, 10);
647 linep->outputSuspendStr[1] = getbits36_8 (suspendStr, 19);
648 linep->outputSuspendStr[2] = getbits36_8 (suspendStr, 28);
649 uint suspendLen = getbits36_9 (suspendStr, 0);
650 if (suspendLen > 3)
651 {
652
653 suspendLen = 3;
654 }
655 linep->outputSuspendLen = suspendLen;
656
657 word36 resumeStr = command_data[1];
658 linep->outputResumeStr[0] = getbits36_8 (resumeStr, 10);
659 linep->outputResumeStr[1] = getbits36_8 (resumeStr, 19);
660 linep->outputResumeStr[2] = getbits36_8 (resumeStr, 28);
661 uint resumeLen = getbits36_9 (resumeStr, 0);
662 if (resumeLen > 3)
663 {
664
665 resumeLen = 3;
666 }
667 linep->outputResumeLen = resumeLen;
668 }
669 break;
670
671 case 34:
672 {
673 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters\n", decoded_p->slot_no);
674
675
676
677 uint subtype = getbits36_9 (command_data[0], 0);
678 uint flag = getbits36_1 (command_data[0], 17);
679
680 switch (subtype)
681 {
682 case 3:
683 {
684 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters fullduplex %u\n", decoded_p->slot_no, flag);
685
686 linep->fullDuplex = !! flag;
687 }
688 break;
689
690 case 8:
691 {
692 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters crecho %u\n", decoded_p->slot_no, flag);
693
694 linep->crecho = !! flag;
695 }
696 break;
697
698 case 9:
699 {
700
701 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters lfecho %u\n", decoded_p->slot_no, flag);
702 linep->lfecho = !! flag;
703 }
704 break;
705
706 case 13:
707 {
708 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters dumpoutput\n", decoded_p->slot_no);
709
710
711
712 linep -> send_output = SEND_OUTPUT_DELAY;
713 }
714 break;
715
716 case 14:
717 {
718 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters tabecho %u\n", decoded_p->slot_no, flag);
719
720 linep->tabecho = !! flag;
721 }
722 break;
723
724 case 16:
725 {
726 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters listen %u\n", decoded_p->slot_no, flag);
727
728 uint bufsz = getbits36_18 (command_data[0], 18);
729 linep->listen = !! flag;
730 linep->inputBufferSize = bufsz;
731
732 if (linep->service == service_undefined)
733 linep->service = service_login;
734
735 if (linep->service == service_login && linep -> line_client)
736 {
737 fnpuv_start_writestr (linep->line_client,
738 linep->listen ?
739 (unsigned char *) "Multics is now listening to this line\r\n":
740 (unsigned char *) "Multics is no longer listening to this line\r\n");
741 }
742 if (linep->service == service_slave && ! linep -> line_client)
743 fnpuv_open_slave (decoded_p->devUnitIdx, decoded_p->slot_no);
744 }
745 break;
746
747 case 17:
748 {
749 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters handlequit%u \n", decoded_p->slot_no, flag);
750
751 linep->handleQuit = !! flag;
752 }
753 break;
754
755 case 18:
756 {
757
758 uint idx = getbits36_9 (command_data[0], 9);
759 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters chngstring %u\n", decoded_p->slot_no, flag);
760 linep->ctrlStrIdx = idx;
761 }
762 break;
763
764 case 19:
765 {
766 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters wru\n", decoded_p->slot_no);
767 linep -> wru_timeout = true;
768 }
769 break;
770
771 case 20:
772 {
773 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters echoplex %u\n", decoded_p->slot_no, flag);
774
775 linep->echoPlex = !! flag;
776 }
777 break;
778
779 case 22:
780 {
781 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters dumpinput\n", decoded_p->slot_no);
782
783
784
785
786
787
788
789
790 }
791 break;
792
793 case 23:
794 {
795 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters replay %u\n", decoded_p->slot_no, flag);
796
797 linep->replay = !! flag;
798 }
799 break;
800
801 case 24:
802 {
803 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters polite %u\n", decoded_p->slot_no, flag);
804
805 linep->polite = !! flag;
806 }
807 break;
808
809 case 25:
810 {
811 uint bufsiz1 = getbits36_18 (command_data[0], 18);
812 uint bufsiz2 = getbits36_18 (command_data[1], 0);
813 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters block_xfer %u %u\n", decoded_p->slot_no, bufsiz1, bufsiz2);
814 linep->block_xfer_out_frame_sz = bufsiz1;
815 linep->block_xfer_in_frame_sz = bufsiz2;
816
817
818 }
819 break;
820
821 case 26:
822 {
823
824
825
826
827
828 uint sz = getbits36_18 (command_data[0], 18);
829 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters set_buffer_size %u\n", decoded_p->slot_no, flag);
830 linep->inputBufferSize = sz;
831
832 }
833 break;
834
835 case 27:
836 {
837 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters breakall %u\n", decoded_p->slot_no, flag);
838
839 linep->breakAll = !! flag;
840 }
841 break;
842
843 case 28:
844 {
845 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters prefixnl %u\n", decoded_p->slot_no, flag);
846
847 linep->prefixnl = !! flag;
848 }
849 break;
850
851 case 29:
852 {
853 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters input_flow_control %u\n", decoded_p->slot_no, flag);
854
855 linep->input_flow_control = !! flag;
856 }
857 break;
858
859 case 30:
860 {
861 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters output_flow_control %u\n", decoded_p->slot_no, flag);
862
863 linep->output_flow_control = !! flag;
864 }
865 break;
866
867 case 31:
868 {
869 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters odd_parity %u\n", decoded_p->slot_no, flag);
870
871 linep->odd_parity = !! flag;
872 }
873 break;
874
875 case 32:
876 {
877 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters eight_bit_in %u\n", decoded_p->slot_no, flag);
878
879 linep->eight_bit_in = !! flag;
880 }
881 break;
882
883 case 33:
884 {
885 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters eight_bit_out %u\n", decoded_p->slot_no, flag);
886
887 linep->eight_bit_out = !! flag;
888 }
889 break;
890
891 case 1:
892 case 2:
893 case 4:
894 case 5:
895 case 6:
896 case 7:
897 case 10:
898 case 11:
899 case 12:
900 case 15:
901 case 21:
902 {
903 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters unimplemented\n", decoded_p->slot_no);
904 sim_printf ("fnp unimplemented subtype %d (%o)\n", subtype, subtype);
905
906 return -1;
907 }
908
909 default:
910 {
911 sim_debug (DBG_TRACE, & fnp_dev, "[%u] alter_parameters illegal\n", decoded_p->slot_no);
912 sim_printf ("fnp illegal subtype %d (%o)\n", subtype, subtype);
913
914 return -1;
915 }
916 }
917 }
918 break;
919
920 case 37:
921 {
922 sim_debug (DBG_TRACE, & fnp_dev, "[%u] set_delay_table\n", decoded_p->slot_no);
923
924 uint d1 = getbits36_18 (command_data[0], 0);
925 uint d2 = getbits36_18 (command_data[0], 18);
926
927 uint d3 = getbits36_18 (command_data[1], 0);
928 uint d4 = getbits36_18 (command_data[1], 18);
929
930 uint d5 = getbits36_18 (command_data[2], 0);
931 uint d6 = getbits36_18 (command_data[2], 18);
932
933 linep->delay_table[0] = d1;
934 linep->delay_table[1] = d2;
935 linep->delay_table[2] = d3;
936 linep->delay_table[3] = d4;
937 linep->delay_table[4] = d5;
938 linep->delay_table[5] = d6;
939 }
940 break;
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958 struct fnp_channel_meters
959 {
960
961 struct header
962 {
963
964 word36 dia_request_q_len;
965
966 word36 dia_rql_updates;
967
968 word36 pending_status;
969
970 word36 pending_status_updates;
971
972
973 word36 output_overlaps___parity_errors;
974
975
976 word36 software_status_overflows___hardware_status_overflows;
977
978
979 word36 input_alloc_failures___dia_current_q_len;
980
981 word36 exhaust;
982
983
984 word36 software_xte___sync_or_async;
985 } header;
986
987 word36 sync_or_async;
988 };
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003 struct fnp_async_meters
1004 {
1005
1006
1007 word36 pre_exhaust;
1008
1009 word36 echo_buf_overflow;
1010
1011
1012 word36 bell_quits___pad;
1013
1014 word36 pad;
1015 };
1016
1017 case 36:
1018 {
1019 sim_debug (DBG_TRACE, & fnp_dev, "[%u] report_meters\n", decoded_p->slot_no);
1020
1021
1022 }
1023 break;
1024
1025 case 0:
1026 case 2:
1027 case 5:
1028 case 7:
1029 case 9:
1030 case 10:
1031 case 11:
1032
1033 case 14:
1034
1035 case 16:
1036 case 17:
1037 case 18:
1038 case 19:
1039 case 20:
1040 case 21:
1041
1042
1043
1044
1045
1046 case 29:
1047
1048
1049 case 35:
1050 {
1051 sim_debug (DBG_TRACE, & fnp_dev, "[%u] unimplemented opcode\n", decoded_p->slot_no);
1052 sim_warn ("fnp unimplemented opcode %d (%o)\n", decoded_p->op_code, decoded_p->op_code);
1053
1054
1055
1056
1057 }
1058 break;
1059
1060 default:
1061 {
1062 sim_debug (DBG_TRACE, & fnp_dev, "[%u]fnp illegal opcode %d (%o)\n", decoded_p->slot_no, decoded_p->op_code, decoded_p->op_code);
1063
1064 return -1;
1065 }
1066 }
1067
1068 setTIMW (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fudp->mailboxAddress, (int) decoded_p->cell);
1069
1070 send_general_interrupt (decoded_p->iom_unit, decoded_p->chan_num, imwTerminatePic);
1071
1072 return 0;
1073 }
1074
1075 #ifdef TUN
1076 static void tun_write (struct t_line * linep, uint16_t * data, uint tally)
1077 {
1078
1079
1080
1081
1082
1083
1084
1085
1086 for (uint i = 0; i < tally; i ++)
1087 {
1088
1089 if (data [i] == 0x100)
1090 {
1091 linep->in_frame = true;
1092 linep->frameLen = 0;
1093 continue;
1094 }
1095
1096 if (! linep->in_frame)
1097 continue;
1098
1099 if (linep->frameLen >= 2+1500)
1100 {
1101 sim_printf ("inFrame overrun\n");
1102 break;
1103 }
1104 linep->frame[linep->frameLen ++] = (uint8_t) (data [i] & 0xff);
1105 }
1106
1107
1108
1109 if (linep->frameLen >= 2)
1110 {
1111 uint16_t target = (uint16_t) ((linep->frame[0] & 0xff) << 8) | (linep->frame[1]);
1112 if (target + 2 >= linep->frameLen)
1113 {
1114 sim_printf ("frame received\n");
1115 fnpuv_tun_write (linep);
1116 linep->in_frame = false;
1117 }
1118 }
1119 }
1120 #endif
1121
1122 static void fnp_wtx_output (struct decoded_t *decoded_p, uint tally, uint dataAddr)
1123 {
1124 sim_debug (DBG_TRACE, & fnp_dev, "[%u]rcd wtx_output\n", decoded_p->slot_no);
1125 struct t_line * linep = & decoded_p->fudp->MState.line[decoded_p->slot_no];
1126
1127 uint wordOff = 0;
1128 word36 word = 0;
1129 uint lastWordOff = (uint) -1;
1130 #ifdef TUN
1131 uint16_t data9 [tally];
1132 #endif
1133 unsigned char data [tally];
1134
1135 for (uint i = 0; i < tally; i ++)
1136 {
1137 uint byteOff = i % 4;
1138 uint byte = 0;
1139
1140 wordOff = i / 4;
1141
1142 if (wordOff != lastWordOff)
1143 {
1144 lastWordOff = wordOff;
1145 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, dataAddr + wordOff, & word, direct_load);
1146 }
1147 byte = getbits36_9 (word, byteOff * 9);
1148 data [i] = byte & 0377;
1149 #ifdef TUN
1150 data9 [i] = (uint16_t) byte;
1151 #endif
1152
1153
1154 }
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169 #ifdef TUN
1170 if (linep->is_tun && tally > 0)
1171 {
1172 tun_write (linep, data9, tally);
1173 return;
1174 }
1175 #endif
1176 if (tally > 0 && linep->line_client)
1177 {
1178 if (! linep->line_client || ! linep->line_client->data)
1179 {
1180 sim_warn ("fnp_wtx_output bad client data\r\n");
1181 return;
1182 }
1183 uvClientData * p = linep->line_client->data;
1184 (* p->write_cb) (linep->line_client, data, tally);
1185 }
1186 }
1187
1188 static int wtx (struct decoded_t *decoded_p)
1189 {
1190 sim_debug (DBG_TRACE, & fnp_dev, "[%u]wtx op_code %u 0%o\n", decoded_p->slot_no, decoded_p->op_code, decoded_p->op_code);
1191
1192 if (decoded_p->op_code != 012 && decoded_p->op_code != 014)
1193 {
1194 sim_debug (DBG_TRACE, & fnp_dev, "[%u] unimplemented opcode\n", decoded_p->slot_no);
1195 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp wtx unimplemented opcode %d (%o)\n", decoded_p->slot_no, decoded_p->op_code, decoded_p->op_code);
1196 sim_printf ("fnp wtx unimplemented opcode %d (%o)\n", decoded_p->op_code, decoded_p->op_code);
1197
1198 return -1;
1199 }
1200
1201 word36 data;
1202 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->smbx+WORD6, & data, direct_load);
1203 uint dcwAddr = getbits36_18 (data, 0);
1204 uint dcwCnt = getbits36_9 (data, 27);
1205
1206
1207
1208 for (uint i = 0; i < dcwCnt; i ++)
1209 {
1210
1211
1212 word36 dcw;
1213 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, dcwAddr + i, & dcw, direct_load);
1214
1215
1216 uint dataAddr = getbits36_18 (dcw, 0);
1217 uint tally = getbits36_9 (dcw, 27);
1218
1219 if (! tally)
1220 continue;
1221 fnp_wtx_output (decoded_p, tally, dataAddr);
1222
1223 }
1224
1225 setTIMW (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fudp->mailboxAddress, (int) decoded_p->cell);
1226
1227 send_general_interrupt (decoded_p->iom_unit, decoded_p->chan_num, imwTerminatePic);
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239 decoded_p->fudp->MState.line[decoded_p->slot_no].send_output = SEND_OUTPUT_DELAY;
1240
1241 return 0;
1242 }
1243
1244 static void fnp_rtx_input_accepted (struct decoded_t *decoded_p)
1245 {
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266 word36 word2;
1267 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+WORD2, & word2, direct_load);
1268 uint n_chars = getbits36_18 (word2, 0);
1269
1270 word36 n_buffers;
1271 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+N_BUFFERS, & n_buffers, direct_load);
1272
1273 struct t_line * linep = & decoded_p->fudp->MState.line[decoded_p->slot_no];
1274 unsigned char * data_p = linep -> buffer;
1275
1276 n_chars = min(n_chars, linep -> nPos);
1277
1278 uint off = 0;
1279 for (uint j = 0; j < n_buffers && off < n_chars; j++)
1280 {
1281 word36 data;
1282 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+DCWS+j, & data, direct_load);
1283 word24 addr = getbits36_24 (data, 0);
1284 word12 tally = getbits36_12 (data, 24);
1285
1286 if_sim_debug (DBG_TRACE, & fnp_dev) {
1287 { sim_printf ("[%u][FNP emulator: nPos %d long IN: '", decoded_p->slot_no, linep->nPos);
1288 for (uint i = 0; i < linep->nPos; i ++)
1289 {
1290 if (isgraph (linep->buffer [i]))
1291 sim_printf ("%c", linep->buffer [i]);
1292 else
1293 sim_printf ("\\%03o", linep->buffer [i]);
1294 }
1295 sim_printf ("']\n");
1296 }
1297 }
1298
1299
1300 uint n_chars_in_buf = min(n_chars-off, tally);
1301 for (uint i = 0; i < n_chars_in_buf; i += 4)
1302 {
1303 word36 v = 0;
1304 if (i < n_chars_in_buf)
1305 putbits36_9 (& v, 0, data_p [off++]);
1306 if (i + 1 < n_chars_in_buf)
1307 putbits36_9 (& v, 9, data_p [off++]);
1308 if (i + 2 < n_chars_in_buf)
1309 putbits36_9 (& v, 18, data_p [off++]);
1310 if (i + 3 < n_chars_in_buf)
1311 putbits36_9 (& v, 27, data_p [off++]);
1312 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, addr, & v, direct_store);
1313 addr ++;
1314 }
1315 }
1316
1317
1318
1319
1320
1321 word1 output_chain_present = 1;
1322
1323 word36 v;
1324 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+INP_COMMAND_DATA, &v, direct_load);
1325 l_putbits36_1 (& v, 16, output_chain_present);
1326 l_putbits36_1 (& v, 17, linep->input_break ? 1 : 0);
1327 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+INP_COMMAND_DATA, &v, direct_store);
1328
1329
1330 linep->input_reply_pending = false;
1331 linep->input_break = false;
1332 linep->nPos = 0;
1333
1334 setTIMW (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fudp->mailboxAddress, (int) decoded_p->cell);
1335
1336 send_general_interrupt (decoded_p->iom_unit, decoded_p->chan_num, imwTerminatePic);
1337 }
1338
1339 static int interruptL66_CS_to_FNP (struct decoded_t *decoded_p)
1340 {
1341 uint mbx = decoded_p->cell;
1342
1343 if (mbx >= 8)
1344 {
1345 sim_warn ("bad mbx number in interruptL66_CS_to_FNP; dropping\n");
1346 return -1;
1347 }
1348 decoded_p->smbx = decoded_p->fudp->mailboxAddress + DN355_SUB_MBXES + mbx*DN355_SUB_MBX_SIZE;
1349
1350 word36 word2;
1351 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->smbx+WORD2, & word2, direct_load);
1352
1353 decoded_p->op_code = getbits36_9 (word2, 18);
1354 uint io_cmd = getbits36_9 (word2, 27);
1355
1356 word36 word1;
1357 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->smbx+WORD1, & word1, direct_load);
1358 decoded_p->slot_no = getbits36_6 (word1, 12);
1359
1360 sim_debug (DBG_TRACE, & fnp_dev, "io_cmd %u\n", io_cmd);
1361 switch (io_cmd)
1362 {
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372 case 3:
1373 {
1374 int ret = wcd (decoded_p);
1375 if (ret)
1376 return ret;
1377 }
1378 break;
1379
1380 case 4:
1381 {
1382 int ret = wtx (decoded_p);
1383 if (ret)
1384 return ret;
1385 }
1386 break;
1387
1388 case 1:
1389 {
1390 sim_debug (DBG_TRACE, & fnp_dev, "[%u]rcd unimplemented\n", decoded_p->slot_no);
1391 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp unimplemented io_cmd %d\n", decoded_p->slot_no, io_cmd);
1392 sim_printf ("fnp unimplemented io_cmd %d\n", io_cmd);
1393
1394 return -1;
1395 }
1396 default:
1397 {
1398 sim_debug (DBG_TRACE, & fnp_dev, "[%u]rcd illegal opcode\n", decoded_p->slot_no);
1399 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp illegal io_cmd %d\n", decoded_p->slot_no, io_cmd);
1400 sim_printf ("fnp illegal io_cmd %d\n", io_cmd);
1401
1402 return -1;
1403 }
1404 }
1405 return 0;
1406 }
1407
1408 static int interruptL66_FNP_to_CS (struct decoded_t *decoded_p)
1409 {
1410
1411
1412
1413 uint mbx = decoded_p->cell - 8;
1414
1415 if (mbx >= 4)
1416 {
1417 sim_warn ("bad mbx number in interruptL66_FNP_to_CS; dropping\n");
1418 return -1;
1419 }
1420 decoded_p->fsmbx = decoded_p->fudp->mailboxAddress + FNP_SUB_MBXES + mbx*FNP_SUB_MBX_SIZE;
1421
1422
1423
1424
1425
1426
1427
1428
1429 word36 word2;
1430 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+WORD2, & word2, direct_load);
1431
1432 uint op_code = getbits36_9 (word2, 18);
1433 uint io_cmd = getbits36_9 (word2, 27);
1434
1435 word36 word1;
1436 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+WORD1, & word1, direct_load);
1437
1438
1439
1440 decoded_p->slot_no = getbits36_6 (word1, 12);
1441
1442
1443 sim_debug (DBG_TRACE, & fnp_dev, "[%u]fnp interrupt\n", decoded_p->slot_no);
1444 switch (io_cmd)
1445 {
1446 case 2:
1447 {
1448 sim_debug (DBG_TRACE, & fnp_dev, "[%u] rtx\n", decoded_p->slot_no);
1449 switch (op_code)
1450 {
1451 case 5:
1452 {
1453 sim_debug (DBG_TRACE, & fnp_dev, "[%u] input_accepted\n", decoded_p->slot_no);
1454 fnp_rtx_input_accepted (decoded_p);
1455 }
1456 break;
1457 default:
1458 sim_debug (DBG_TRACE, & fnp_dev, "[%u] illegal rtx ack\n", decoded_p->slot_no);
1459 sim_warn ("rtx %d. %o ack ignored\n", op_code, op_code);
1460 break;
1461 }
1462 break;
1463 }
1464 case 3:
1465 {
1466 sim_debug (DBG_TRACE, & fnp_dev, "[%u] wcd\n", decoded_p->slot_no);
1467 switch (op_code)
1468 {
1469 case 0:
1470 {
1471 sim_debug (DBG_TRACE, & fnp_dev, "[%u] terminal accepted\n", decoded_p->slot_no);
1472
1473
1474
1475
1476
1477
1478
1479 decoded_p->fudp->MState.line[decoded_p->slot_no].send_output = SEND_OUTPUT_DELAY;
1480
1481
1482
1483 decoded_p->fudp->MState.line[decoded_p->slot_no].waitForMbxDone = false;
1484 }
1485 break;
1486
1487 case 1:
1488 {
1489 sim_debug (DBG_TRACE, & fnp_dev, "[%u] disconnect_this_line\n", decoded_p->slot_no);
1490
1491 }
1492 break;
1493
1494 case 14:
1495 {
1496 sim_printf ("reject_request_temp\r\n");
1497 sim_debug (DBG_TRACE, & fnp_dev, "[%u] reject_request_temp\n", decoded_p->slot_no);
1498
1499
1500 decoded_p->fudp->MState.line[decoded_p->slot_no].accept_input = 100;
1501 }
1502 break;
1503
1504 case 2:
1505 case 3:
1506 case 4:
1507 case 5:
1508 case 6:
1509 case 7:
1510 case 8:
1511 case 9:
1512 case 10:
1513 case 11:
1514 case 12:
1515
1516
1517 case 16:
1518 case 17:
1519 case 18:
1520 case 19:
1521 case 20:
1522 case 21:
1523 case 22:
1524 case 23:
1525 case 24:
1526 case 25:
1527 case 26:
1528 case 27:
1529
1530 case 29:
1531 case 30:
1532 case 31:
1533
1534
1535 case 34:
1536 case 35:
1537 case 36:
1538 case 37:
1539 {
1540 sim_debug (DBG_TRACE, & fnp_dev, "[%u] unimplemented opcode\n", decoded_p->slot_no);
1541 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp reply unimplemented opcode %d (%o)\n", decoded_p->slot_no, op_code, op_code);
1542 sim_printf ("fnp reply unimplemented opcode %d (%o)\n", op_code, op_code);
1543
1544 return -1;
1545 }
1546
1547 default:
1548 {
1549 sim_debug (DBG_TRACE, & fnp_dev, "[%u] illegal opcode\n", decoded_p->slot_no);
1550 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp reply illegal opcode %d (%o)\n", decoded_p->slot_no, op_code, op_code);
1551 sim_printf ("fnp reply illegal opcode %d (%o)\n", op_code, op_code);
1552
1553 return -1;
1554 }
1555 }
1556
1557
1558
1559
1560
1561
1562
1563
1564 decoded_p->fudp->fnpMBXinUse [mbx] = false;
1565
1566 }
1567 break;
1568
1569 default:
1570 {
1571 sim_debug (DBG_TRACE, & fnp_dev, "[%u] illegal io_cmd\n", decoded_p->slot_no);
1572 sim_debug (DBG_ERR, & fnp_dev, "[%u]illegal/unimplemented io_cmd (%d) in fnp submbx\n", decoded_p->slot_no, io_cmd);
1573 sim_printf ("illegal/unimplemented io_cmd (%d) in fnp submbx\n", io_cmd);
1574
1575 return -1;
1576 }
1577 }
1578 return 0;
1579 }
1580
1581 static int interruptL66_CS_done (struct decoded_t *decoded_p)
1582 {
1583 uint mbx = decoded_p->cell - 12;
1584
1585 if (mbx >= 4)
1586 {
1587 sim_warn ("bad mbx number in interruptL66_CS_done; dropping\n");
1588 return -1;
1589 }
1590 if (! decoded_p->fudp -> fnpMBXinUse [mbx])
1591 {
1592 sim_debug (DBG_ERR, & fnp_dev, "odd -- Multics marked an unused mbx as unused? cell %d (mbx %d)\n", decoded_p->cell, mbx);
1593 sim_debug (DBG_ERR, & fnp_dev, " %d %d %d %d\n", decoded_p->fudp -> fnpMBXinUse [0], decoded_p->fudp -> fnpMBXinUse [1], decoded_p->fudp -> fnpMBXinUse [2], decoded_p->fudp -> fnpMBXinUse [3]);
1594 }
1595 else
1596 {
1597 sim_debug (DBG_TRACE, & fnp_dev, "Multics marked cell %d (mbx %d) as unused; was %o\n", decoded_p->cell, mbx, decoded_p->fudp -> fnpMBXinUse [mbx]);
1598 decoded_p->fudp -> fnpMBXinUse [mbx] = false;
1599 if (decoded_p->fudp->lineWaiting[mbx])
1600 {
1601 struct t_line * linep = & decoded_p->fudp->MState.line[decoded_p->fudp->fnpMBXlineno[mbx]];
1602 sim_debug (DBG_TRACE, & fnp_dev, "clearing wait; was %d\n", linep->waitForMbxDone);
1603 linep->waitForMbxDone = false;
1604 }
1605 sim_debug (DBG_TRACE, & fnp_dev, " %d %d %d %d\n", decoded_p->fudp->fnpMBXinUse [0], decoded_p->fudp->fnpMBXinUse [1], decoded_p->fudp->fnpMBXinUse [2], decoded_p->fudp->fnpMBXinUse [3]);
1606 }
1607 return 0;
1608 }
1609
1610 static int interruptL66 (uint iomUnitIdx, uint chan)
1611 {
1612 struct decoded_t decoded;
1613 struct decoded_t *decoded_p = &decoded;
1614 decoded_p->iom_unit = iomUnitIdx;
1615 decoded_p->chan_num = chan;
1616 decoded_p->devUnitIdx = get_ctlr_idx (iomUnitIdx, chan);
1617 decoded_p->fudp = & fnpData.fnpUnitData [decoded_p->devUnitIdx];
1618 word36 dia_pcw;
1619 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fudp->mailboxAddress+DIA_PCW, & dia_pcw, direct_load);
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654 decoded_p->cell = getbits36_6 (dia_pcw, 24);
1655 sim_debug (DBG_TRACE, & fnp_dev, "CS interrupt %u\n", decoded_p->cell);
1656 if (decoded_p->cell < 8)
1657 {
1658 interruptL66_CS_to_FNP (decoded_p);
1659 }
1660 else if (decoded_p->cell >= 8 && decoded_p->cell <= 11)
1661 {
1662 interruptL66_FNP_to_CS (decoded_p);
1663 }
1664 else if (decoded_p->cell >= 12 && decoded_p->cell <= 15)
1665 {
1666 interruptL66_CS_done (decoded_p);
1667 }
1668 else
1669 {
1670 sim_debug (DBG_ERR, & fnp_dev, "fnp illegal cell number %d\n", decoded_p->cell);
1671 sim_printf ("fnp illegal cell number %d\n", decoded_p->cell);
1672
1673 return -1;
1674 }
1675 return 0;
1676 }
1677
1678 static void fnpcmdBootload (uint devUnitIdx)
1679 {
1680 sim_printf("\r[FNP emulation: FNP %c received BOOTLOAD command]\r\n", (int)('a' + (int)devUnitIdx));
1681 fnpData.fnpUnitData[devUnitIdx].MState.accept_calls = false;
1682 bool have3270 = false;
1683 for (uint lineno = 0; lineno < MAX_LINES; lineno ++)
1684 {
1685 fnpData.fnpUnitData[devUnitIdx].MState.line [lineno] . listen = false;
1686 if (fnpData.fnpUnitData[devUnitIdx].MState.line [lineno].line_client)
1687 {
1688 fnpuv_start_writestr (fnpData.fnpUnitData[devUnitIdx].MState.line [lineno].line_client,
1689 (unsigned char *) "\r[FNP emulation: FNP restarted]\r\n");
1690 }
1691 if (fnpData.fnpUnitData[devUnitIdx].MState.line[lineno].service == service_3270)
1692 {
1693 sim_debug (DBG_TRACE, & fnp_dev, "3270 controller found at unit %u line %u\r\n", devUnitIdx, lineno);
1694
1695 if (fnpData.ibm3270ctlr[ASSUME0].configured)
1696 {
1697 sim_warn ("Too many 3270 controllers configured");
1698 }
1699 else
1700 {
1701 have3270 = true;
1702 memset (& fnpData.ibm3270ctlr[ASSUME0], 0, sizeof (struct ibm3270ctlr_s));
1703 fnpData.ibm3270ctlr[ASSUME0].configured = true;
1704 fnpData.ibm3270ctlr[ASSUME0].fnpno = devUnitIdx;
1705 fnpData.ibm3270ctlr[ASSUME0].lineno = lineno;
1706
1707
1708
1709
1710 if (fnpData.fnpUnitData[devUnitIdx].MState.line[lineno].lineType == 0)
1711 fnpData.fnpUnitData[devUnitIdx].MState.line[lineno].lineType = 7;
1712 fnpData.fnpUnitData[devUnitIdx].MState.line[lineno].accept_new_terminal = true;
1713 }
1714 }
1715 }
1716 (void)fnpuvInit (fnpData.telnet_port, fnpData.telnet_address);
1717 if (have3270)
1718 (void)fnpuv3270Init (fnpData.telnet3270_port);
1719 }
1720
1721
1722 static word18 getl6core (uint iom_unit_idx, uint chan, word24 l66addr, uint addr)
1723 {
1724 word24 wos = addr / 2;
1725 word36 word;
1726 iom_direct_data_service (iom_unit_idx, chan, l66addr + wos, & word, direct_load);
1727 if (addr & 1)
1728 return (word18) (word & MASK18);
1729 else
1730 return (word18) ((word >> 18) & MASK18);
1731 }
1732
1733
1734 static void processMBX (uint iomUnitIdx, uint chan)
1735 {
1736 uint fnp_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
1737 struct fnpUnitData_s * fudp = & fnpData.fnpUnitData [fnp_unit_idx];
1738
1739
1740
1741
1742
1743
1744
1745
1746 bool ok = true;
1747
1748 word36 dia_pcw;
1749 iom_direct_data_service (iomUnitIdx, chan, fudp->mailboxAddress+DIA_PCW, & dia_pcw, direct_load);
1750 sim_debug (DBG_TRACE, & fnp_dev,
1751 "%s: chan %d dia_pcw %012"PRIo64"\n", __func__, chan, dia_pcw);
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854 uint command = getbits36_6 (dia_pcw, 30);
1855 word36 bootloadStatus = 0;
1856
1857 if (command == 000)
1858 {
1859 sim_debug (DBG_TRACE, & fnp_dev,
1860 "%s: chan %d reset command\n", __func__, chan);
1861 send_general_interrupt (iomUnitIdx, chan, imwTerminatePic);
1862 }
1863 else if (command == 072)
1864 {
1865
1866 word24 l66addr = (((word24) getbits36_6 (dia_pcw, 24)) << 18) |
1867 (word24) getbits36_18 (dia_pcw, 0);
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879 word36 dcw;
1880 iom_direct_data_service (iomUnitIdx, chan, l66addr, & dcw, direct_load);
1881 word12 tally = getbits36_12 (dcw, 24);
1882
1883
1884
1885
1886 word24 image_off = (tally + 64) & 077777700;
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018 # ifdef VERBOSE_BOOT
2019 word18 crnls = getl6core (iomUnitIdx, chan, l66addr + image_off, 0655);
2020 sim_printf ("Number of LSLAs (crnls) %d\n", crnls);
2021 # endif
2022
2023
2024 word18 criom = getl6core (iomUnitIdx, chan, l66addr + image_off, 0653);
2025
2026
2027
2028
2029
2030
2031 bool hdr = false;
2032 # ifdef VERBOSE_BOOT
2033 uint nfound = 0;
2034 # endif
2035 for (uint lsla = 0; lsla < 6; lsla ++)
2036 {
2037 uint slot = lsla + 9;
2038 uint os = slot * 2;
2039
2040 word18 flags = getl6core (iomUnitIdx, chan, l66addr + image_off, criom + os);
2041 uint device_type_code = (flags >> 4) & 037;
2042 if (device_type_code == 4)
2043 {
2044 # ifdef VERBOSE_BOOT
2045 nfound ++;
2046 # endif
2047
2048 word18 tblp = getl6core (iomUnitIdx, chan, l66addr + image_off, criom + os + 1);
2049 for (uint slot = 0; slot < 52; slot ++)
2050 {
2051
2052
2053
2054
2055
2056
2057
2058 word3 slot_id = getl6core (iomUnitIdx, chan, l66addr + image_off, tblp + 2 * slot) & MASK3;
2059 if (slot_id != 7)
2060 {
2061 # ifdef VERBOSE_BOOT
2062 char * slot_ids [8] =
2063 {
2064 "10 cps",
2065 "30 cps, slot 1",
2066 "30 cps, slot 2",
2067 "30 cps, slot 3",
2068 "invalid",
2069 "15 cps, slot 1",
2070 "15 cps, slot 2",
2071 "unused"
2072 };
2073 char * id = slot_ids[slot_id];
2074 # endif
2075 if (! hdr)
2076 {
2077 hdr = true;
2078 # ifdef VERBOSE_BOOT
2079 sim_printf ("LSLA table: card number, slot, slot_id, slot_id string\n");
2080 # endif
2081 }
2082 # ifdef VERBOSE_BOOT
2083 sim_printf ("%d %2d %d %s\n", lsla, slot, slot_id, id);
2084 # endif
2085 }
2086 }
2087 }
2088 }
2089 # ifdef VERBOSE_BOOT
2090 if (nfound != crnls)
2091 sim_printf ("LSLAs configured %d found %d\n", crnls, nfound);
2092 # endif
2093
2094
2095 # ifdef VERBOSE_BOOT
2096 word18 crnhs = getl6core (iomUnitIdx, chan, l66addr + image_off, 0654);
2097 sim_printf ("Number of HSLAs (crnhs) %d\n", crnhs);
2098 # endif
2099
2100
2101
2102
2103
2104
2105 hdr = false;
2106 # ifdef VERBOSE_BOOT
2107 nfound = 0;
2108 # endif
2109 for (uint hsla = 0; hsla < 3; hsla ++)
2110 {
2111 uint slot = hsla + 6;
2112 uint os = slot * 2;
2113
2114 word18 flags = getl6core (iomUnitIdx, chan, l66addr + image_off, criom + os);
2115 uint device_type_code = (flags >> 4) & 037;
2116 if (device_type_code == 3)
2117 {
2118 # ifdef VERBOSE_BOOT
2119 nfound ++;
2120 # endif
2121
2122 word18 tblp = getl6core (iomUnitIdx, chan, l66addr + image_off, criom + os + 1);
2123 for (uint slot = 0; slot < 32; slot ++)
2124 {
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137 # ifdef VERBOSE_BOOT
2138 char * line_types[23] =
2139 {
2140 "none ",
2141 "ASCII ",
2142 "1050 ",
2143 "2741 ",
2144 "ARDS ",
2145 "Sync ",
2146 "G115 ",
2147 "BSC ",
2148 "202ETX ",
2149 "VIP ",
2150 "ASYNC1 ",
2151 "ASYNC2 ",
2152 "ASYNC3 ",
2153 "SYNC1 ",
2154 "SYNC2 ",
2155 "SYNC3 ",
2156 "POLLED_VIP",
2157 "X25LAP ",
2158 "HDLC ",
2159 "COLTS ",
2160 "DSA ",
2161 "HASP_OPR ",
2162 "invalid "
2163 };
2164 # endif
2165
2166 # ifdef VERBOSE_BOOT
2167 char * modem_types[8] =
2168 {
2169 "invalid ",
2170 "Bell 103A/113",
2171 "Bell 201C ",
2172 "Bell 202C5 ",
2173 "Bell 202C6 ",
2174 "Bell 208A ",
2175 "Bell 208B ",
2176 "Bell 209A "
2177 };
2178 # endif
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211 # ifdef VERBOSE_BOOT
2212 char * async_speeds[16] =
2213 {
2214 "invalid",
2215 "110 ",
2216 "133 ",
2217 "150 ",
2218 "300 ",
2219 "600 ",
2220 "1200 ",
2221 "1800 ",
2222 "2400 ",
2223 "4800 ",
2224 "7200 ",
2225 "9600 ",
2226 "19200 ",
2227 "40800 ",
2228 "50000 ",
2229 "72000 "
2230 };
2231
2232 char * sync_speeds[16] =
2233 {
2234 "invalid",
2235 "2000 ",
2236 "2400 ",
2237 "3600 ",
2238 "4800 ",
2239 "5400 ",
2240 "7200 ",
2241 "9600 ",
2242 "19200 ",
2243 "40800 ",
2244 "50000 ",
2245 "invalid",
2246 "invalid",
2247 "invalid",
2248 "invalid",
2249 "invalid"
2250 };
2251 # endif
2252 word18 subch_data = getl6core (iomUnitIdx, chan, l66addr + image_off, tblp + 2 * slot);
2253 # ifdef VERBOSE_BOOT
2254 word1 async = (subch_data >> 15) & 1;
2255 word1 option1 = (subch_data >> 14) & 1;
2256 # endif
2257 word5 line_type = (subch_data >> 4) & MASK5;
2258 if (line_type > 22)
2259 line_type = 22;
2260 word4 modem_type = (subch_data >> 9) & MASK4;
2261 if (modem_type > 7)
2262 modem_type = 0;
2263 # ifdef VERBOSE_BOOT
2264 word4 dev_speed = subch_data & MASK4;
2265
2266
2267 char * speed = async ? async_speeds[dev_speed] : sync_speeds[dev_speed];
2268 if (async && dev_speed == 4 && option1)
2269 speed = "auto ";
2270 # endif
2271 if (! hdr)
2272 {
2273 hdr = true;
2274 # ifdef VERBOSE_BOOT
2275 sim_printf ("HSLA table: card number, slot, "
2276 "sync/async, line type, modem_type, "
2277 "speed\n");
2278 # endif
2279 }
2280 # ifdef VERBOSE_BOOT
2281 sim_printf ("%d %2d %s %s %s %s\n",
2282 hsla, slot, async ? "async" :"sync ",
2283 line_types[line_type],
2284 modem_types[modem_type],
2285 speed);
2286 # endif
2287 uint lineno = hsla * 32u + slot;
2288 struct t_line * linep = & fudp->MState.line[lineno];
2289
2290
2291
2292
2293
2294
2295
2296
2297 linep->lineType = line_type;
2298 }
2299 }
2300 }
2301 # ifdef VERBOSE_BOOT
2302 if (nfound != crnls)
2303 sim_printf ("LSLAs configured %d found %d\n", crnls, nfound);
2304 # endif
2305
2306
2307 #if defined(THREADZ) || defined(LOCKLESS)
2308 lock_libuv ();
2309 #endif
2310 fnpcmdBootload (fnp_unit_idx);
2311 #if defined(THREADZ) || defined(LOCKLESS)
2312 unlock_libuv ();
2313 #endif
2314 send_general_interrupt (iomUnitIdx, chan, imwTerminatePic);
2315 fudp -> fnpIsRunning = true;
2316 }
2317 else if (command == 071)
2318 {
2319 #if defined(THREADZ) || defined(LOCKLESS)
2320 lock_libuv ();
2321 #endif
2322 ok = interruptL66 (iomUnitIdx, chan) == 0;
2323 #if defined(THREADZ) || defined(LOCKLESS)
2324 unlock_libuv ();
2325 #endif
2326 }
2327 else if (command == 075)
2328 {
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397 }
2398 else
2399 {
2400 sim_warn ("bogus fnp command %d (%o)\n", command, command);
2401 ok = false;
2402 }
2403
2404 if (ok)
2405 {
2406 #ifdef TESTING
2407 if_sim_debug (DBG_TRACE, & fnp_dev) dmpmbx (fudp->mailboxAddress);
2408 #endif
2409
2410 dia_pcw = 0;
2411 iom_direct_data_service (iomUnitIdx, chan, fudp -> mailboxAddress+DIA_PCW, & dia_pcw, direct_store);
2412 putbits36_1 (& bootloadStatus, 0, 1);
2413 putbits36_3 (& bootloadStatus, 3, 0);
2414 putbits36_8 (& bootloadStatus, 9, 0);
2415 putbits36_17 (& bootloadStatus, 17, 0);
2416 iom_direct_data_service (iomUnitIdx, chan, fudp -> mailboxAddress+CRASH_DATA, & bootloadStatus, direct_store);
2417 }
2418 else
2419 {
2420 #ifdef TESTING
2421 if_sim_debug (DBG_TRACE, & fnp_dev) dmpmbx (fudp->mailboxAddress);
2422 #endif
2423
2424
2425 putbits36_1 (& dia_pcw, 18, 1);
2426 iom_direct_data_service (iomUnitIdx, chan, fudp -> mailboxAddress+DIA_PCW, & dia_pcw, direct_store);
2427 }
2428 }
2429
2430 static int fnpCmd (uint iomUnitIdx, uint chan) {
2431 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
2432
2433 switch (p->IDCW_DEV_CMD) {
2434 case 000: {
2435 p->stati = 04000;
2436 processMBX (iomUnitIdx, chan);
2437
2438
2439 }
2440 return IOM_CMD_DISCONNECT;
2441
2442 default: {
2443 p->stati = 04501;
2444 p->chanStatus = chanStatIncorrectDCW;
2445 if (p->IDCW_DEV_CMD != 051)
2446 sim_warn ("%s: FNP unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
2447 }
2448 return IOM_CMD_ERROR;
2449 }
2450 }
2451
2452
2453
2454
2455
2456
2457 iom_cmd_rc_t fnp_iom_cmd (uint iomUnitIdx, uint chan) {
2458 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
2459
2460
2461 if (IS_IDCW (p)) {
2462 return fnpCmd (iomUnitIdx, chan);
2463 }
2464
2465 sim_warn ("%s expected IDCW\n", __func__);
2466 return IOM_CMD_ERROR;
2467 }