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 struct fnp_channel_meters
958 {
959
960 struct header
961 {
962
963 word36 dia_request_q_len;
964
965 word36 dia_rql_updates;
966
967 word36 pending_status;
968
969 word36 pending_status_updates;
970
971
972 word36 output_overlaps___parity_errors;
973
974
975 word36 software_status_overflows___hardware_status_overflows;
976
977
978 word36 input_alloc_failures___dia_current_q_len;
979
980 word36 exhaust;
981
982
983 word36 software_xte___sync_or_async;
984 } header;
985
986 word36 sync_or_async;
987 };
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002 struct fnp_async_meters
1003 {
1004
1005
1006 word36 pre_exhaust;
1007
1008 word36 echo_buf_overflow;
1009
1010
1011 word36 bell_quits___pad;
1012
1013 word36 pad;
1014 };
1015
1016 case 36:
1017 {
1018 sim_debug (DBG_TRACE, & fnp_dev, "[%u] report_meters\n", decoded_p->slot_no);
1019
1020
1021 }
1022 break;
1023
1024 case 0:
1025 case 2:
1026 case 5:
1027 case 7:
1028 case 9:
1029 case 10:
1030 case 11:
1031
1032 case 14:
1033
1034 case 16:
1035 case 17:
1036 case 18:
1037 case 19:
1038 case 20:
1039 case 21:
1040
1041
1042
1043
1044
1045 case 29:
1046
1047
1048 case 35:
1049 {
1050 sim_debug (DBG_TRACE, & fnp_dev, "[%u] unimplemented opcode\n", decoded_p->slot_no);
1051 sim_warn ("fnp unimplemented opcode %d (%o)\n", decoded_p->op_code, decoded_p->op_code);
1052
1053
1054
1055
1056 }
1057 break;
1058
1059 default:
1060 {
1061 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);
1062
1063 return -1;
1064 }
1065 }
1066
1067 setTIMW (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fudp->mailboxAddress, (int) decoded_p->cell);
1068
1069 send_general_interrupt (decoded_p->iom_unit, decoded_p->chan_num, imwTerminatePic);
1070
1071 return 0;
1072 }
1073
1074 #ifdef TUN
1075 static void tun_write (struct t_line * linep, uint16_t * data, uint tally)
1076 {
1077
1078
1079
1080
1081
1082
1083
1084
1085 for (uint i = 0; i < tally; i ++)
1086 {
1087
1088 if (data [i] == 0x100)
1089 {
1090 linep->in_frame = true;
1091 linep->frameLen = 0;
1092 continue;
1093 }
1094
1095 if (! linep->in_frame)
1096 continue;
1097
1098 if (linep->frameLen >= 2+1500)
1099 {
1100 sim_printf ("inFrame overrun\n");
1101 break;
1102 }
1103 linep->frame[linep->frameLen ++] = (uint8_t) (data [i] & 0xff);
1104 }
1105
1106
1107
1108 if (linep->frameLen >= 2)
1109 {
1110 uint16_t target = (uint16_t) ((linep->frame[0] & 0xff) << 8) | (linep->frame[1]);
1111 if (target + 2 >= linep->frameLen)
1112 {
1113 sim_printf ("frame received\n");
1114 fnpuv_tun_write (linep);
1115 linep->in_frame = false;
1116 }
1117 }
1118 }
1119 #endif
1120
1121 static void fnp_wtx_output (struct decoded_t *decoded_p, uint tally, uint dataAddr)
1122 {
1123 sim_debug (DBG_TRACE, & fnp_dev, "[%u]rcd wtx_output\n", decoded_p->slot_no);
1124 struct t_line * linep = & decoded_p->fudp->MState.line[decoded_p->slot_no];
1125
1126 uint wordOff = 0;
1127 word36 word = 0;
1128 uint lastWordOff = (uint) -1;
1129 #ifdef TUN
1130 uint16_t data9 [tally];
1131 #endif
1132 unsigned char data [tally];
1133
1134 for (uint i = 0; i < tally; i ++)
1135 {
1136 uint byteOff = i % 4;
1137 uint byte = 0;
1138
1139 wordOff = i / 4;
1140
1141 if (wordOff != lastWordOff)
1142 {
1143 lastWordOff = wordOff;
1144 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, dataAddr + wordOff, & word, direct_load);
1145 }
1146 byte = getbits36_9 (word, byteOff * 9);
1147 data [i] = byte & 0377;
1148 #ifdef TUN
1149 data9 [i] = (uint16_t) byte;
1150 #endif
1151
1152
1153 }
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 #ifdef TUN
1169 if (linep->is_tun && tally > 0)
1170 {
1171 tun_write (linep, data9, tally);
1172 return;
1173 }
1174 #endif
1175 if (tally > 0 && linep->line_client)
1176 {
1177 if (! linep->line_client || ! linep->line_client->data)
1178 {
1179 sim_warn ("fnp_wtx_output bad client data\r\n");
1180 return;
1181 }
1182 uvClientData * p = linep->line_client->data;
1183 (* p->write_cb) (linep->line_client, data, tally);
1184 }
1185 }
1186
1187 static int wtx (struct decoded_t *decoded_p)
1188 {
1189 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);
1190
1191 if (decoded_p->op_code != 012 && decoded_p->op_code != 014)
1192 {
1193 sim_debug (DBG_TRACE, & fnp_dev, "[%u] unimplemented opcode\n", decoded_p->slot_no);
1194 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);
1195 sim_printf ("fnp wtx unimplemented opcode %d (%o)\n", decoded_p->op_code, decoded_p->op_code);
1196
1197 return -1;
1198 }
1199
1200 word36 data;
1201 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->smbx+WORD6, & data, direct_load);
1202 uint dcwAddr = getbits36_18 (data, 0);
1203 uint dcwCnt = getbits36_9 (data, 27);
1204
1205
1206
1207 for (uint i = 0; i < dcwCnt; i ++)
1208 {
1209
1210
1211 word36 dcw;
1212 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, dcwAddr + i, & dcw, direct_load);
1213
1214
1215 uint dataAddr = getbits36_18 (dcw, 0);
1216 uint tally = getbits36_9 (dcw, 27);
1217
1218 if (! tally)
1219 continue;
1220 fnp_wtx_output (decoded_p, tally, dataAddr);
1221
1222 }
1223
1224 setTIMW (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fudp->mailboxAddress, (int) decoded_p->cell);
1225
1226 send_general_interrupt (decoded_p->iom_unit, decoded_p->chan_num, imwTerminatePic);
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238 decoded_p->fudp->MState.line[decoded_p->slot_no].send_output = SEND_OUTPUT_DELAY;
1239
1240 return 0;
1241 }
1242
1243 static void fnp_rtx_input_accepted (struct decoded_t *decoded_p)
1244 {
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265 word36 word2;
1266 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+WORD2, & word2, direct_load);
1267 uint n_chars = getbits36_18 (word2, 0);
1268
1269 word36 n_buffers;
1270 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+N_BUFFERS, & n_buffers, direct_load);
1271
1272 struct t_line * linep = & decoded_p->fudp->MState.line[decoded_p->slot_no];
1273 unsigned char * data_p = linep -> buffer;
1274
1275 n_chars = min(n_chars, linep -> nPos);
1276
1277 uint off = 0;
1278 for (uint j = 0; j < n_buffers && off < n_chars; j++)
1279 {
1280 word36 data;
1281 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+DCWS+j, & data, direct_load);
1282 word24 addr = getbits36_24 (data, 0);
1283 word12 tally = getbits36_12 (data, 24);
1284
1285 if_sim_debug (DBG_TRACE, & fnp_dev) {
1286 { sim_printf ("[%u][FNP emulator: nPos %d long IN: '", decoded_p->slot_no, linep->nPos);
1287 for (uint i = 0; i < linep->nPos; i ++)
1288 {
1289 if (isgraph (linep->buffer [i]))
1290 sim_printf ("%c", linep->buffer [i]);
1291 else
1292 sim_printf ("\\%03o", linep->buffer [i]);
1293 }
1294 sim_printf ("']\n");
1295 }
1296 }
1297
1298
1299 uint n_chars_in_buf = min(n_chars-off, tally);
1300 for (uint i = 0; i < n_chars_in_buf; i += 4)
1301 {
1302 word36 v = 0;
1303 if (i < n_chars_in_buf)
1304 putbits36_9 (& v, 0, data_p [off++]);
1305 if (i + 1 < n_chars_in_buf)
1306 putbits36_9 (& v, 9, data_p [off++]);
1307 if (i + 2 < n_chars_in_buf)
1308 putbits36_9 (& v, 18, data_p [off++]);
1309 if (i + 3 < n_chars_in_buf)
1310 putbits36_9 (& v, 27, data_p [off++]);
1311 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, addr, & v, direct_store);
1312 addr ++;
1313 }
1314 }
1315
1316
1317
1318
1319
1320 word1 output_chain_present = 1;
1321
1322 word36 v;
1323 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+INP_COMMAND_DATA, &v, direct_load);
1324 l_putbits36_1 (& v, 16, output_chain_present);
1325 l_putbits36_1 (& v, 17, linep->input_break ? 1 : 0);
1326 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+INP_COMMAND_DATA, &v, direct_store);
1327
1328
1329 linep->input_reply_pending = false;
1330 linep->input_break = false;
1331 linep->nPos = 0;
1332
1333 setTIMW (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fudp->mailboxAddress, (int) decoded_p->cell);
1334
1335 send_general_interrupt (decoded_p->iom_unit, decoded_p->chan_num, imwTerminatePic);
1336 }
1337
1338 static int interruptL66_CS_to_FNP (struct decoded_t *decoded_p)
1339 {
1340 uint mbx = decoded_p->cell;
1341
1342 if (mbx >= 8)
1343 {
1344 sim_warn ("bad mbx number in interruptL66_CS_to_FNP; dropping\n");
1345 return -1;
1346 }
1347 decoded_p->smbx = decoded_p->fudp->mailboxAddress + DN355_SUB_MBXES + mbx*DN355_SUB_MBX_SIZE;
1348
1349 word36 word2;
1350 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->smbx+WORD2, & word2, direct_load);
1351
1352 decoded_p->op_code = getbits36_9 (word2, 18);
1353 uint io_cmd = getbits36_9 (word2, 27);
1354
1355 word36 word1;
1356 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->smbx+WORD1, & word1, direct_load);
1357 decoded_p->slot_no = getbits36_6 (word1, 12);
1358
1359 sim_debug (DBG_TRACE, & fnp_dev, "io_cmd %u\n", io_cmd);
1360 switch (io_cmd)
1361 {
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371 case 3:
1372 {
1373 int ret = wcd (decoded_p);
1374 if (ret)
1375 return ret;
1376 }
1377 break;
1378
1379 case 4:
1380 {
1381 int ret = wtx (decoded_p);
1382 if (ret)
1383 return ret;
1384 }
1385 break;
1386
1387 case 1:
1388 {
1389 sim_debug (DBG_TRACE, & fnp_dev, "[%u]rcd unimplemented\n", decoded_p->slot_no);
1390 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp unimplemented io_cmd %d\n", decoded_p->slot_no, io_cmd);
1391 sim_printf ("fnp unimplemented io_cmd %d\n", io_cmd);
1392
1393 return -1;
1394 }
1395 default:
1396 {
1397 sim_debug (DBG_TRACE, & fnp_dev, "[%u]rcd illegal opcode\n", decoded_p->slot_no);
1398 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp illegal io_cmd %d\n", decoded_p->slot_no, io_cmd);
1399 sim_printf ("fnp illegal io_cmd %d\n", io_cmd);
1400
1401 return -1;
1402 }
1403 }
1404 return 0;
1405 }
1406
1407 static int interruptL66_FNP_to_CS (struct decoded_t *decoded_p)
1408 {
1409
1410
1411
1412 uint mbx = decoded_p->cell - 8;
1413
1414 if (mbx >= 4)
1415 {
1416 sim_warn ("bad mbx number in interruptL66_FNP_to_CS; dropping\n");
1417 return -1;
1418 }
1419 decoded_p->fsmbx = decoded_p->fudp->mailboxAddress + FNP_SUB_MBXES + mbx*FNP_SUB_MBX_SIZE;
1420
1421
1422
1423
1424
1425
1426
1427
1428 word36 word2;
1429 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+WORD2, & word2, direct_load);
1430
1431 uint op_code = getbits36_9 (word2, 18);
1432 uint io_cmd = getbits36_9 (word2, 27);
1433
1434 word36 word1;
1435 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fsmbx+WORD1, & word1, direct_load);
1436
1437
1438
1439 decoded_p->slot_no = getbits36_6 (word1, 12);
1440
1441
1442 sim_debug (DBG_TRACE, & fnp_dev, "[%u]fnp interrupt\n", decoded_p->slot_no);
1443 switch (io_cmd)
1444 {
1445 case 2:
1446 {
1447 sim_debug (DBG_TRACE, & fnp_dev, "[%u] rtx\n", decoded_p->slot_no);
1448 switch (op_code)
1449 {
1450 case 5:
1451 {
1452 sim_debug (DBG_TRACE, & fnp_dev, "[%u] input_accepted\n", decoded_p->slot_no);
1453 fnp_rtx_input_accepted (decoded_p);
1454 }
1455 break;
1456 default:
1457 sim_debug (DBG_TRACE, & fnp_dev, "[%u] illegal rtx ack\n", decoded_p->slot_no);
1458 sim_warn ("rtx %d. %o ack ignored\n", op_code, op_code);
1459 break;
1460 }
1461 break;
1462 }
1463 case 3:
1464 {
1465 sim_debug (DBG_TRACE, & fnp_dev, "[%u] wcd\n", decoded_p->slot_no);
1466 switch (op_code)
1467 {
1468 case 0:
1469 {
1470 sim_debug (DBG_TRACE, & fnp_dev, "[%u] terminal accepted\n", decoded_p->slot_no);
1471
1472
1473
1474
1475
1476
1477
1478 decoded_p->fudp->MState.line[decoded_p->slot_no].send_output = SEND_OUTPUT_DELAY;
1479
1480
1481
1482 decoded_p->fudp->MState.line[decoded_p->slot_no].waitForMbxDone = false;
1483 }
1484 break;
1485
1486 case 1:
1487 {
1488 sim_debug (DBG_TRACE, & fnp_dev, "[%u] disconnect_this_line\n", decoded_p->slot_no);
1489
1490 }
1491 break;
1492
1493 case 14:
1494 {
1495 sim_printf ("reject_request_temp\r\n");
1496 sim_debug (DBG_TRACE, & fnp_dev, "[%u] reject_request_temp\n", decoded_p->slot_no);
1497
1498
1499 decoded_p->fudp->MState.line[decoded_p->slot_no].accept_input = 100;
1500 }
1501 break;
1502
1503 case 2:
1504 case 3:
1505 case 4:
1506 case 5:
1507 case 6:
1508 case 7:
1509 case 8:
1510 case 9:
1511 case 10:
1512 case 11:
1513 case 12:
1514
1515
1516 case 16:
1517 case 17:
1518 case 18:
1519 case 19:
1520 case 20:
1521 case 21:
1522 case 22:
1523 case 23:
1524 case 24:
1525 case 25:
1526 case 26:
1527 case 27:
1528
1529 case 29:
1530 case 30:
1531 case 31:
1532
1533
1534 case 34:
1535 case 35:
1536 case 36:
1537 case 37:
1538 {
1539 sim_debug (DBG_TRACE, & fnp_dev, "[%u] unimplemented opcode\n", decoded_p->slot_no);
1540 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp reply unimplemented opcode %d (%o)\n", decoded_p->slot_no, op_code, op_code);
1541 sim_printf ("fnp reply unimplemented opcode %d (%o)\n", op_code, op_code);
1542
1543 return -1;
1544 }
1545
1546 default:
1547 {
1548 sim_debug (DBG_TRACE, & fnp_dev, "[%u] illegal opcode\n", decoded_p->slot_no);
1549 sim_debug (DBG_ERR, & fnp_dev, "[%u]fnp reply illegal opcode %d (%o)\n", decoded_p->slot_no, op_code, op_code);
1550 sim_printf ("fnp reply illegal opcode %d (%o)\n", op_code, op_code);
1551
1552 return -1;
1553 }
1554 }
1555
1556
1557
1558
1559
1560
1561
1562
1563 decoded_p->fudp->fnpMBXinUse [mbx] = false;
1564
1565 }
1566 break;
1567
1568 default:
1569 {
1570 sim_debug (DBG_TRACE, & fnp_dev, "[%u] illegal io_cmd\n", decoded_p->slot_no);
1571 sim_debug (DBG_ERR, & fnp_dev, "[%u]illegal/unimplemented io_cmd (%d) in fnp submbx\n", decoded_p->slot_no, io_cmd);
1572 sim_printf ("illegal/unimplemented io_cmd (%d) in fnp submbx\n", io_cmd);
1573
1574 return -1;
1575 }
1576 }
1577 return 0;
1578 }
1579
1580 static int interruptL66_CS_done (struct decoded_t *decoded_p)
1581 {
1582 uint mbx = decoded_p->cell - 12;
1583
1584 if (mbx >= 4)
1585 {
1586 sim_warn ("bad mbx number in interruptL66_CS_done; dropping\n");
1587 return -1;
1588 }
1589 if (! decoded_p->fudp -> fnpMBXinUse [mbx])
1590 {
1591 sim_debug (DBG_ERR, & fnp_dev, "odd -- Multics marked an unused mbx as unused? cell %d (mbx %d)\n", decoded_p->cell, mbx);
1592 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]);
1593 }
1594 else
1595 {
1596 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]);
1597 decoded_p->fudp -> fnpMBXinUse [mbx] = false;
1598 if (decoded_p->fudp->lineWaiting[mbx])
1599 {
1600 struct t_line * linep = & decoded_p->fudp->MState.line[decoded_p->fudp->fnpMBXlineno[mbx]];
1601 sim_debug (DBG_TRACE, & fnp_dev, "clearing wait; was %d\n", linep->waitForMbxDone);
1602 linep->waitForMbxDone = false;
1603 }
1604 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]);
1605 }
1606 return 0;
1607 }
1608
1609 static int interruptL66 (uint iomUnitIdx, uint chan)
1610 {
1611 struct decoded_t decoded;
1612 struct decoded_t *decoded_p = &decoded;
1613 decoded_p->iom_unit = iomUnitIdx;
1614 decoded_p->chan_num = chan;
1615 decoded_p->devUnitIdx = get_ctlr_idx (iomUnitIdx, chan);
1616 decoded_p->fudp = & fnpData.fnpUnitData [decoded_p->devUnitIdx];
1617 word36 dia_pcw;
1618 iom_direct_data_service (decoded_p->iom_unit, decoded_p->chan_num, decoded_p->fudp->mailboxAddress+DIA_PCW, & dia_pcw, direct_load);
1619
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 decoded_p->cell = getbits36_6 (dia_pcw, 24);
1654 sim_debug (DBG_TRACE, & fnp_dev, "CS interrupt %u\n", decoded_p->cell);
1655 if (decoded_p->cell < 8)
1656 {
1657 interruptL66_CS_to_FNP (decoded_p);
1658 }
1659 else if (decoded_p->cell >= 8 && decoded_p->cell <= 11)
1660 {
1661 interruptL66_FNP_to_CS (decoded_p);
1662 }
1663 else if (decoded_p->cell >= 12 && decoded_p->cell <= 15)
1664 {
1665 interruptL66_CS_done (decoded_p);
1666 }
1667 else
1668 {
1669 sim_debug (DBG_ERR, & fnp_dev, "fnp illegal cell number %d\n", decoded_p->cell);
1670 sim_printf ("fnp illegal cell number %d\n", decoded_p->cell);
1671
1672 return -1;
1673 }
1674 return 0;
1675 }
1676
1677 static void fnpcmdBootload (uint devUnitIdx)
1678 {
1679 sim_printf("\r[FNP emulation: FNP %c received BOOTLOAD command]\r\n", (int)('a' + (int)devUnitIdx));
1680 fnpData.fnpUnitData[devUnitIdx].MState.accept_calls = false;
1681 bool have3270 = false;
1682 for (uint lineno = 0; lineno < MAX_LINES; lineno ++)
1683 {
1684 fnpData.fnpUnitData[devUnitIdx].MState.line [lineno] . listen = false;
1685 if (fnpData.fnpUnitData[devUnitIdx].MState.line [lineno].line_client)
1686 {
1687 fnpuv_start_writestr (fnpData.fnpUnitData[devUnitIdx].MState.line [lineno].line_client,
1688 (unsigned char *) "\r[FNP emulation: FNP restarted]\r\n");
1689 }
1690 if (fnpData.fnpUnitData[devUnitIdx].MState.line[lineno].service == service_3270)
1691 {
1692 sim_debug (DBG_TRACE, & fnp_dev, "3270 controller found at unit %u line %u\r\n", devUnitIdx, lineno);
1693
1694 if (fnpData.ibm3270ctlr[ASSUME0].configured)
1695 {
1696 sim_warn ("Too many 3270 controllers configured");
1697 }
1698 else
1699 {
1700 have3270 = true;
1701 memset (& fnpData.ibm3270ctlr[ASSUME0], 0, sizeof (struct ibm3270ctlr_s));
1702 fnpData.ibm3270ctlr[ASSUME0].configured = true;
1703 fnpData.ibm3270ctlr[ASSUME0].fnpno = devUnitIdx;
1704 fnpData.ibm3270ctlr[ASSUME0].lineno = lineno;
1705
1706
1707
1708
1709 if (fnpData.fnpUnitData[devUnitIdx].MState.line[lineno].lineType == 0)
1710 fnpData.fnpUnitData[devUnitIdx].MState.line[lineno].lineType = 7;
1711 fnpData.fnpUnitData[devUnitIdx].MState.line[lineno].accept_new_terminal = true;
1712 }
1713 }
1714 }
1715 (void)fnpuvInit (fnpData.telnet_port, fnpData.telnet_address);
1716 if (have3270)
1717 (void)fnpuv3270Init (fnpData.telnet3270_port);
1718 }
1719
1720
1721 static word18 getl6core (uint iom_unit_idx, uint chan, word24 l66addr, uint addr)
1722 {
1723 word24 wos = addr / 2;
1724 word36 word;
1725 iom_direct_data_service (iom_unit_idx, chan, l66addr + wos, & word, direct_load);
1726 if (addr & 1)
1727 return (word18) (word & MASK18);
1728 else
1729 return (word18) ((word >> 18) & MASK18);
1730 }
1731
1732
1733 static void processMBX (uint iomUnitIdx, uint chan)
1734 {
1735 uint fnp_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
1736 struct fnpUnitData_s * fudp = & fnpData.fnpUnitData [fnp_unit_idx];
1737
1738
1739
1740
1741
1742
1743
1744
1745 bool ok = true;
1746
1747 word36 dia_pcw;
1748 iom_direct_data_service (iomUnitIdx, chan, fudp->mailboxAddress+DIA_PCW, & dia_pcw, direct_load);
1749 sim_debug (DBG_TRACE, & fnp_dev,
1750 "%s: chan %d dia_pcw %012"PRIo64"\n", __func__, chan, dia_pcw);
1751
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 uint command = getbits36_6 (dia_pcw, 30);
1854 word36 bootloadStatus = 0;
1855
1856 if (command == 000)
1857 {
1858 sim_debug (DBG_TRACE, & fnp_dev,
1859 "%s: chan %d reset command\n", __func__, chan);
1860 send_general_interrupt (iomUnitIdx, chan, imwTerminatePic);
1861 }
1862 else if (command == 072)
1863 {
1864
1865 word24 l66addr = (((word24) getbits36_6 (dia_pcw, 24)) << 18) |
1866 (word24) getbits36_18 (dia_pcw, 0);
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 word36 dcw;
1879 iom_direct_data_service (iomUnitIdx, chan, l66addr, & dcw, direct_load);
1880 word12 tally = getbits36_12 (dcw, 24);
1881
1882
1883
1884
1885 word24 image_off = (tally + 64) & 077777700;
1886
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 # ifdef VERBOSE_BOOT
2018 word18 crnls = getl6core (iomUnitIdx, chan, l66addr + image_off, 0655);
2019 sim_printf ("Number of LSLAs (crnls) %d\n", crnls);
2020 # endif
2021
2022
2023 word18 criom = getl6core (iomUnitIdx, chan, l66addr + image_off, 0653);
2024
2025
2026
2027
2028
2029
2030 bool hdr = false;
2031 # ifdef VERBOSE_BOOT
2032 uint nfound = 0;
2033 # endif
2034 for (uint lsla = 0; lsla < 6; lsla ++)
2035 {
2036 uint slot = lsla + 9;
2037 uint os = slot * 2;
2038
2039 word18 flags = getl6core (iomUnitIdx, chan, l66addr + image_off, criom + os);
2040 uint device_type_code = (flags >> 4) & 037;
2041 if (device_type_code == 4)
2042 {
2043 # ifdef VERBOSE_BOOT
2044 nfound ++;
2045 # endif
2046
2047 word18 tblp = getl6core (iomUnitIdx, chan, l66addr + image_off, criom + os + 1);
2048 for (uint slot = 0; slot < 52; slot ++)
2049 {
2050
2051
2052
2053
2054
2055
2056
2057 word3 slot_id = getl6core (iomUnitIdx, chan, l66addr + image_off, tblp + 2 * slot) & MASK3;
2058 if (slot_id != 7)
2059 {
2060 # ifdef VERBOSE_BOOT
2061 char * slot_ids [8] =
2062 {
2063 "10 cps",
2064 "30 cps, slot 1",
2065 "30 cps, slot 2",
2066 "30 cps, slot 3",
2067 "invalid",
2068 "15 cps, slot 1",
2069 "15 cps, slot 2",
2070 "unused"
2071 };
2072 char * id = slot_ids[slot_id];
2073 # endif
2074 if (! hdr)
2075 {
2076 hdr = true;
2077 # ifdef VERBOSE_BOOT
2078 sim_printf ("LSLA table: card number, slot, slot_id, slot_id string\n");
2079 # endif
2080 }
2081 # ifdef VERBOSE_BOOT
2082 sim_printf ("%d %2d %d %s\n", lsla, slot, slot_id, id);
2083 # endif
2084 }
2085 }
2086 }
2087 }
2088 # ifdef VERBOSE_BOOT
2089 if (nfound != crnls)
2090 sim_printf ("LSLAs configured %d found %d\n", crnls, nfound);
2091 # endif
2092
2093
2094 # ifdef VERBOSE_BOOT
2095 word18 crnhs = getl6core (iomUnitIdx, chan, l66addr + image_off, 0654);
2096 sim_printf ("Number of HSLAs (crnhs) %d\n", crnhs);
2097 # endif
2098
2099
2100
2101
2102
2103
2104 hdr = false;
2105 # ifdef VERBOSE_BOOT
2106 nfound = 0;
2107 # endif
2108 for (uint hsla = 0; hsla < 3; hsla ++)
2109 {
2110 uint slot = hsla + 6;
2111 uint os = slot * 2;
2112
2113 word18 flags = getl6core (iomUnitIdx, chan, l66addr + image_off, criom + os);
2114 uint device_type_code = (flags >> 4) & 037;
2115 if (device_type_code == 3)
2116 {
2117 # ifdef VERBOSE_BOOT
2118 nfound ++;
2119 # endif
2120
2121 word18 tblp = getl6core (iomUnitIdx, chan, l66addr + image_off, criom + os + 1);
2122 for (uint slot = 0; slot < 32; slot ++)
2123 {
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136 # ifdef VERBOSE_BOOT
2137 char * line_types[23] =
2138 {
2139 "none ",
2140 "ASCII ",
2141 "1050 ",
2142 "2741 ",
2143 "ARDS ",
2144 "Sync ",
2145 "G115 ",
2146 "BSC ",
2147 "202ETX ",
2148 "VIP ",
2149 "ASYNC1 ",
2150 "ASYNC2 ",
2151 "ASYNC3 ",
2152 "SYNC1 ",
2153 "SYNC2 ",
2154 "SYNC3 ",
2155 "POLLED_VIP",
2156 "X25LAP ",
2157 "HDLC ",
2158 "COLTS ",
2159 "DSA ",
2160 "HASP_OPR ",
2161 "invalid "
2162 };
2163 # endif
2164
2165 # ifdef VERBOSE_BOOT
2166 char * modem_types[8] =
2167 {
2168 "invalid ",
2169 "Bell 103A/113",
2170 "Bell 201C ",
2171 "Bell 202C5 ",
2172 "Bell 202C6 ",
2173 "Bell 208A ",
2174 "Bell 208B ",
2175 "Bell 209A "
2176 };
2177 # endif
2178
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 # ifdef VERBOSE_BOOT
2211 char * async_speeds[16] =
2212 {
2213 "invalid",
2214 "110 ",
2215 "133 ",
2216 "150 ",
2217 "300 ",
2218 "600 ",
2219 "1200 ",
2220 "1800 ",
2221 "2400 ",
2222 "4800 ",
2223 "7200 ",
2224 "9600 ",
2225 "19200 ",
2226 "40800 ",
2227 "50000 ",
2228 "72000 "
2229 };
2230
2231 char * sync_speeds[16] =
2232 {
2233 "invalid",
2234 "2000 ",
2235 "2400 ",
2236 "3600 ",
2237 "4800 ",
2238 "5400 ",
2239 "7200 ",
2240 "9600 ",
2241 "19200 ",
2242 "40800 ",
2243 "50000 ",
2244 "invalid",
2245 "invalid",
2246 "invalid",
2247 "invalid",
2248 "invalid"
2249 };
2250 # endif
2251 word18 subch_data = getl6core (iomUnitIdx, chan, l66addr + image_off, tblp + 2 * slot);
2252 # ifdef VERBOSE_BOOT
2253 word1 async = (subch_data >> 15) & 1;
2254 word1 option1 = (subch_data >> 14) & 1;
2255 # endif
2256 word5 line_type = (subch_data >> 4) & MASK5;
2257 if (line_type > 22)
2258 line_type = 22;
2259 word4 modem_type = (subch_data >> 9) & MASK4;
2260 if (modem_type > 7)
2261 modem_type = 0;
2262 # ifdef VERBOSE_BOOT
2263 word4 dev_speed = subch_data & MASK4;
2264
2265
2266 char * speed = async ? async_speeds[dev_speed] : sync_speeds[dev_speed];
2267 if (async && dev_speed == 4 && option1)
2268 speed = "auto ";
2269 # endif
2270 if (! hdr)
2271 {
2272 hdr = true;
2273 # ifdef VERBOSE_BOOT
2274 sim_printf ("HSLA table: card number, slot, "
2275 "sync/async, line type, modem_type, "
2276 "speed\n");
2277 # endif
2278 }
2279 # ifdef VERBOSE_BOOT
2280 sim_printf ("%d %2d %s %s %s %s\n",
2281 hsla, slot, async ? "async" :"sync ",
2282 line_types[line_type],
2283 modem_types[modem_type],
2284 speed);
2285 # endif
2286 uint lineno = hsla * 32u + slot;
2287 struct t_line * linep = & fudp->MState.line[lineno];
2288
2289
2290
2291
2292
2293
2294
2295
2296 linep->lineType = line_type;
2297 }
2298 }
2299 }
2300 # ifdef VERBOSE_BOOT
2301 if (nfound != crnls)
2302 sim_printf ("LSLAs configured %d found %d\n", crnls, nfound);
2303 # endif
2304
2305
2306 #if defined(THREADZ) || defined(LOCKLESS)
2307 lock_libuv ();
2308 #endif
2309 fnpcmdBootload (fnp_unit_idx);
2310 #if defined(THREADZ) || defined(LOCKLESS)
2311 unlock_libuv ();
2312 #endif
2313 send_general_interrupt (iomUnitIdx, chan, imwTerminatePic);
2314 fudp -> fnpIsRunning = true;
2315 }
2316 else if (command == 071)
2317 {
2318 #if defined(THREADZ) || defined(LOCKLESS)
2319 lock_libuv ();
2320 #endif
2321 ok = interruptL66 (iomUnitIdx, chan) == 0;
2322 #if defined(THREADZ) || defined(LOCKLESS)
2323 unlock_libuv ();
2324 #endif
2325 }
2326 else if (command == 075)
2327 {
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 else
2398 {
2399 sim_warn ("bogus fnp command %d (%o)\n", command, command);
2400 ok = false;
2401 }
2402
2403 if (ok)
2404 {
2405 #ifdef TESTING
2406 if_sim_debug (DBG_TRACE, & fnp_dev) dmpmbx (fudp->mailboxAddress);
2407 #endif
2408
2409 dia_pcw = 0;
2410 iom_direct_data_service (iomUnitIdx, chan, fudp -> mailboxAddress+DIA_PCW, & dia_pcw, direct_store);
2411 putbits36_1 (& bootloadStatus, 0, 1);
2412 putbits36_3 (& bootloadStatus, 3, 0);
2413 putbits36_8 (& bootloadStatus, 9, 0);
2414 putbits36_17 (& bootloadStatus, 17, 0);
2415 iom_direct_data_service (iomUnitIdx, chan, fudp -> mailboxAddress+CRASH_DATA, & bootloadStatus, direct_store);
2416 }
2417 else
2418 {
2419 #ifdef TESTING
2420 if_sim_debug (DBG_TRACE, & fnp_dev) dmpmbx (fudp->mailboxAddress);
2421 #endif
2422
2423
2424 putbits36_1 (& dia_pcw, 18, 1);
2425 iom_direct_data_service (iomUnitIdx, chan, fudp -> mailboxAddress+DIA_PCW, & dia_pcw, direct_store);
2426 }
2427 }
2428
2429 static int fnpCmd (uint iomUnitIdx, uint chan) {
2430 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
2431
2432 switch (p->IDCW_DEV_CMD) {
2433 case 000: {
2434 p->stati = 04000;
2435 processMBX (iomUnitIdx, chan);
2436
2437
2438 }
2439 return IOM_CMD_DISCONNECT;
2440
2441 default: {
2442 p->stati = 04501;
2443 p->chanStatus = chanStatIncorrectDCW;
2444 if (p->IDCW_DEV_CMD != 051)
2445 sim_warn ("%s: FNP unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
2446 }
2447 return IOM_CMD_ERROR;
2448 }
2449 }
2450
2451
2452
2453
2454
2455
2456 iom_cmd_rc_t fnp_iom_cmd (uint iomUnitIdx, uint chan) {
2457 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
2458
2459
2460 if (IS_IDCW (p)) {
2461 return fnpCmd (iomUnitIdx, chan);
2462 }
2463
2464 sim_warn ("%s expected IDCW\n", __func__);
2465 return IOM_CMD_ERROR;
2466 }