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