This source file includes following definitions.
- fnp_core_read
- set_config
- show_config
- show_status
- show_nunits
- set_nunits
- reset
- attach
- detach
- dia_init
- fnp_core_write
- virtToPhys
- cmd_bootload
- interruptL66
- processMBX
- dia_cmd
- dia_iom_cmd
- load_stored_boot
- poll_coupler
- dia_unit_process_events
- dia_process_events
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 #include <stdio.h>
34 #include <ctype.h>
35
36 #include "dps8.h"
37 #include "dps8_dia.h"
38 #include "dps8_sys.h"
39 #include "dps8_faults.h"
40 #include "dps8_scu.h"
41 #include "dps8_cpu.h"
42 #include "dps8_iom.h"
43 #include "dps8_cable.h"
44 #include "dps8_utils.h"
45
46 #include "udplib.h"
47
48 #define DBG_CTR 1
49
50 #ifdef THREADZ
51 # include "threadz.h"
52 #endif
53
54 #ifdef TESTING
55 # undef FREE
56 # define FREE(p) free(p)
57 #endif
58
59 static inline void fnp_core_read (word24 addr, word36 *data, UNUSED const char * ctx)
60 {
61 #ifdef THREADZ
62 lock_mem_rd ();
63 #endif
64 * data = M [addr] & DMASK;
65 #ifdef THREADZ
66 unlock_mem ();
67 #endif
68 }
69 #define N_DIA_UNITS 1
70 #define DIA_UNIT_IDX(uptr) ((uptr) - dia_unit)
71
72 static config_list_t dia_config_list [] =
73 {
74
75 { "mailbox", 0, 07777, NULL },
76 { NULL, 0, 0, NULL }
77 };
78
79 static t_stat set_config (UNIT * uptr, UNUSED int value, const char * cptr, UNUSED void * desc)
80 {
81 uint dia_unit_idx = (uint) DIA_UNIT_IDX (uptr);
82
83 if (dia_unit_idx >= N_DIA_UNITS_MAX)
84 {
85 sim_debug (DBG_ERR, & dia_dev, "DIA SET CONFIG: Invalid unit number %ld\n",
86 (long) dia_unit_idx);
87 sim_printf ("error: DIA SET CONFIG: Invalid unit number %ld\n",
88 (long) dia_unit_idx);
89 return SCPE_ARG;
90 }
91
92 struct dia_unit_data * dudp = dia_data.dia_unit_data + dia_unit_idx;
93
94 config_state_t cfg_state = { NULL, NULL };
95
96 for (;;)
97 {
98 int64_t v;
99 int rc = cfg_parse ("DIA SET CONFIG", cptr, dia_config_list, & cfg_state, & v);
100 switch (rc)
101 {
102 case -2:
103 cfg_parse_done (& cfg_state);
104 return SCPE_ARG;
105
106 case -1:
107 break;
108
109 case 0:
110 dudp -> mailbox_address = (uint) v;
111 break;
112
113 default:
114 sim_printf ("error: DIA SET CONFIG: Invalid cfg_parse rc <%ld>\n", (long) rc);
115 cfg_parse_done (& cfg_state);
116 return SCPE_ARG;
117 }
118 if (rc < 0)
119 break;
120 }
121 cfg_parse_done (& cfg_state);
122 return SCPE_OK;
123 }
124
125 static t_stat show_config (UNUSED FILE * st, UNIT * uptr, UNUSED int val,
126 UNUSED const void * desc)
127 {
128 long unit_idx = DIA_UNIT_IDX (uptr);
129 if (unit_idx >= (long) N_DIA_UNITS_MAX)
130 {
131 sim_debug (DBG_ERR, & dia_dev,
132 "DIA SHOW CONFIG: Invalid unit number %ld\n", (long) unit_idx);
133 sim_printf ("error: Invalid unit number %ld\n", (long) unit_idx);
134 return SCPE_ARG;
135 }
136
137 sim_printf ("DIA unit number %ld\n", (long) unit_idx);
138 struct dia_unit_data * dudp = dia_data.dia_unit_data + unit_idx;
139
140 sim_printf ("DIA Mailbox Address: %04o(8)\n", dudp -> mailbox_address);
141
142 return SCPE_OK;
143 }
144
145 static t_stat show_status (UNUSED FILE * st, UNIT * uptr, UNUSED int val,
146 UNUSED const void * desc)
147 {
148 long dia_unit_idx = DIA_UNIT_IDX (uptr);
149 if (dia_unit_idx >= (long) dia_dev.numunits)
150 {
151 sim_debug (DBG_ERR, & dia_dev,
152 "DIA SHOW STATUS: Invalid unit number %ld\n", (long) dia_unit_idx);
153 sim_printf ("error: Invalid unit number %ld\n", (long) dia_unit_idx);
154 return SCPE_ARG;
155 }
156
157 sim_printf ("DIA unit number %ld\n", (long) dia_unit_idx);
158 struct dia_unit_data * dudp = dia_data.dia_unit_data + dia_unit_idx;
159
160 sim_printf ("mailbox_address: %04o\n", dudp->mailbox_address);
161 return SCPE_OK;
162 }
163
164 static t_stat show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
165 UNUSED int val, UNUSED const void * desc)
166 {
167 sim_printf("Number of DIA units in system is %d\n", dia_dev.numunits);
168 return SCPE_OK;
169 }
170
171 static t_stat set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
172 const char * cptr, UNUSED void * desc)
173 {
174 if (! cptr)
175 return SCPE_ARG;
176 int n = atoi (cptr);
177 if (n < 1 || n > N_DIA_UNITS_MAX)
178 return SCPE_ARG;
179 dia_dev.numunits = (uint32) n;
180 return SCPE_OK;
181 }
182
183 static MTAB dia_mod [] =
184 {
185 {
186 MTAB_XTD | MTAB_VUN | \
187 MTAB_NMO | MTAB_VALR,
188 0,
189 "CONFIG",
190 "CONFIG",
191 set_config,
192 show_config,
193 NULL,
194 NULL
195 },
196
197 {
198 MTAB_XTD | MTAB_VUN | \
199 MTAB_NMO | MTAB_VALR,
200 0,
201 "STATUS",
202 "STATUS",
203 NULL,
204 show_status,
205 NULL,
206 NULL
207 },
208
209 {
210 MTAB_XTD | MTAB_VDV | \
211 MTAB_NMO | MTAB_VALR,
212 0,
213 "NUNITS",
214 "NUNITS",
215 set_nunits,
216 show_nunits,
217 "Number of DIA units in the system",
218 NULL
219 },
220 { 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }
221 };
222
223 UNIT dia_unit [N_DIA_UNITS_MAX] = {
224 {UDATA (NULL, UNIT_DISABLE | UNIT_IDLE, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL}
225 };
226
227 static DEBTAB dia_DT [] =
228 {
229 { "TRACE", DBG_TRACE, NULL },
230 { "NOTIFY", DBG_NOTIFY, NULL },
231 { "INFO", DBG_INFO, NULL },
232 { "ERR", DBG_ERR, NULL },
233 { "WARN", DBG_WARN, NULL },
234 { "DEBUG", DBG_DEBUG, NULL },
235 { "ALL", DBG_ALL, NULL },
236 { NULL, 0, NULL }
237 };
238
239 static t_stat reset (UNUSED DEVICE * dptr)
240 {
241 return SCPE_OK;
242 }
243
244 static t_stat attach (UNIT * uptr, const char * cptr)
245 {
246 if (! cptr)
247 return SCPE_ARG;
248 int unitno = (int) (uptr - dia_unit);
249
250
251
252 t_stat ret;
253 char * pfn;
254
255
256 if ((uptr->flags & UNIT_ATT) != 0)
257 detach_unit (uptr);
258
259
260
261
262 pfn = (char *) calloc (CBUFSIZE, sizeof (char));
263 if (pfn == NULL)
264 return SCPE_MEM;
265 strncpy (pfn, cptr, CBUFSIZE);
266
267
268 ret = udp_create (cptr, & dia_data.dia_unit_data[unitno].link);
269 if (ret != SCPE_OK)
270 {
271 FREE (pfn);
272 return ret;
273 }
274
275 uptr->flags |= UNIT_ATT;
276 uptr->filename = pfn;
277 return SCPE_OK;
278 }
279
280
281 static t_stat detach (UNIT * uptr)
282 {
283 int unitno = (int) (uptr - dia_unit);
284 t_stat ret;
285 if ((uptr->flags & UNIT_ATT) == 0)
286 return SCPE_OK;
287 if (dia_data.dia_unit_data[unitno].link == NOLINK)
288 return SCPE_OK;
289
290 ret = udp_release (dia_data.dia_unit_data[unitno].link);
291 if (ret != SCPE_OK)
292 return ret;
293 dia_data.dia_unit_data[unitno].link = NOLINK;
294 uptr->flags &= ~ (unsigned int) UNIT_ATT;
295 FREE (uptr->filename);
296 uptr->filename = NULL;
297 return SCPE_OK;
298 }
299
300 DEVICE dia_dev = {
301 "DIA",
302 dia_unit,
303 NULL,
304 dia_mod,
305 N_DIA_UNITS,
306 10,
307 31,
308 1,
309 8,
310 9,
311 NULL,
312 NULL,
313 reset,
314 NULL,
315 attach,
316 detach,
317 NULL,
318 DEV_DEBUG,
319 0,
320 dia_DT,
321 NULL,
322 NULL,
323 NULL,
324 NULL,
325 NULL,
326 NULL,
327 NULL
328 };
329
330 t_dia_data dia_data;
331
332 struct dn355_submailbox
333 {
334 word36 word1;
335 word36 word2;
336 word36 command_data [3];
337 word36 word6;
338 word36 pad3 [2];
339 };
340
341 struct fnp_submailbox
342 {
343
344 word36 word1;
345 word36 word2;
346 word36 mystery [26];
347 };
348
349 struct mailbox
350 {
351 word36 dia_pcw;
352 word36 mailbox_requests;
353 word36 term_inpt_mpx_wd;
354 word36 last_mbx_req_count;
355 word36 num_in_use;
356 word36 mbx_used_flags;
357 word36 crash_data [2];
358 struct dn355_submailbox dn355_sub_mbxes [8];
359 struct fnp_submailbox fnp_sub_mbxes [4];
360 };
361
362 #define MAILBOX_WORDS (sizeof (struct mailbox) / sizeof (word36))
363 #define TERM_INPT_MPX_WD (offsetof (struct mailbox, term_inpt_mpx_wd) / sizeof (word36))
364
365
366
367
368
369 void dia_init (void)
370 {
371
372 memset(& dia_data, 0, sizeof(dia_data));
373 for (uint unit_num = 0; unit_num < N_DIA_UNITS_MAX; unit_num ++)
374 {
375 cables -> cables_from_iom_to_dia [unit_num].iomUnitIdx = -1;
376 dia_data.dia_unit_data[unit_num].link = -1;
377 }
378 }
379
380 static inline void fnp_core_write (word24 addr, word36 data, UNUSED const char * ctx)
381 {
382 #ifdef THREADZ
383 lock_mem_wr ();
384 #endif
385 M [addr] = data & DMASK;
386 #ifdef THREADZ
387 unlock_mem ();
388 #endif
389 }
390
391
392
393
394
395 static uint virtToPhys (uint ptPtr, uint l66Address)
396 {
397 uint pageTable = ptPtr * 64u;
398 uint l66AddressPage = l66Address / 1024u;
399
400 word36 ptw;
401 fnp_core_read (pageTable + l66AddressPage, & ptw, "fnpIOMCmd get ptw");
402 uint page = getbits36_14 (ptw, 4);
403 uint addr = page * 1024u + l66Address % 1024u;
404 return addr;
405 }
406
407
408
409
410
411
412
413
414 static void cmd_bootload (uint iom_unit_idx, uint dev_unit_idx, uint chan, word24 l66_addr)
415 {
416
417 uint fnpno = dev_unit_idx;
418
419 struct dia_unit_data * dudp = & dia_data.dia_unit_data[fnpno];
420 struct mailbox vol * mbxp = (struct mailbox vol *) & M[dudp->mailbox_address];
421
422 dia_data.dia_unit_data[dev_unit_idx].l66_addr = l66_addr;
423
424 dn_bootload pkt;
425 pkt.cmd = dn_cmd_bootload;
426
427
428 sim_printf ("XXXXXXXXXXXXXXXXXXXXXXXXXXX cmd_bootload\r\n");
429 int rc = dn_udp_send (dia_data.dia_unit_data[dev_unit_idx].link,
430 (uint8_t *) & pkt,
431 (uint16_t) sizeof (pkt), PFLG_FINAL);
432 if (rc < 0)
433 {
434 fprintf (stderr, "udp_send failed\n");
435 }
436 }
437
438 static int interruptL66 (uint iom_unit_idx, uint chan)
439 {
440 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
441 struct device * d = & cables->cablesFromIomToDev[iom_unit_idx].
442 devices[chan][p->IDCW_DEV_CODE];
443 uint dev_unit_idx = d->devUnitIdx;
444 struct dia_unit_data * dudp = &dia_data.dia_unit_data[dev_unit_idx];
445 struct mailbox vol * mbxp = (struct mailbox vol *) & M[dudp->mailbox_address];
446 word36 dia_pcw = mbxp -> dia_pcw;
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481 word6 cell = getbits36_6 (dia_pcw, 24);
482 sim_debug (DBG_TRACE, & dia_dev, "CS interrupt %u\n", cell);
483 if (cell < 8)
484 {
485
486 }
487 else if (cell >= 8 && cell <= 11)
488 {
489
490 }
491 else if (cell >= 12 && cell <= 15)
492 {
493
494 }
495 else
496 {
497 sim_debug (DBG_ERR, & dia_dev, "fnp illegal cell number %d\n", cell);
498 sim_printf ("fnp illegal cell number %d\n", cell);
499
500 return -1;
501 }
502 return 0;
503 }
504
505 static void processMBX (uint iom_unit_idx, uint chan)
506 {
507 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
508 struct device * d = & cables->cablesFromIomToDev[iom_unit_idx].
509 devices[chan][p->IDCW_DEV_CODE];
510 uint dev_unit_idx = d->devUnitIdx;
511 struct dia_unit_data * dudp = &dia_data.dia_unit_data[dev_unit_idx];
512
513
514
515
516
517
518
519
520 bool ok = true;
521 struct mailbox vol * mbxp = (struct mailbox vol *) & M [dudp -> mailbox_address];
522
523 word36 dia_pcw;
524 dia_pcw = mbxp -> dia_pcw;
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629 uint command = getbits36_6 (dia_pcw, 30);
630 word36 bootloadStatus = 0;
631
632 if (command == 000)
633 {
634 sim_debug (DBG_TRACE, & dia_dev, "FNP reset??\n");
635 }
636 else if (command == 072)
637 {
638
639
640
641
642
643
644
645
646
647
648
649 word24 l66_addr = (word24) getbits36_18 (dia_pcw, 0);
650 sim_printf ("l66_addr %08o\r\n", l66_addr);
651
652 uint phys_addr = virtToPhys (p->PCW_PAGE_TABLE_PTR, l66_addr);
653 sim_printf ("phys_addr %08o\r\n", phys_addr);
654
655 word36 tcw;
656 fnp_core_read (phys_addr, & tcw, "tcw fetch");
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697 cmd_bootload (iom_unit_idx, dev_unit_idx, chan, l66_addr);
698
699
700
701
702
703
704
705
706
707
708
709 }
710 else if (command == 071)
711 {
712 ok = interruptL66 (iom_unit_idx, chan) == 0;
713 }
714 else if (command == 075)
715 {
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784 sim_debug (DBG_TRACE, & dia_dev, "FNP data xfer??\n");
785 }
786 else
787 {
788 sim_warn ("bogus fnp command %d (%o)\n", command, command);
789 ok = false;
790 }
791
792 if (ok)
793 {
794
795 fnp_core_write (dudp -> mailbox_address, 0, "dia_iom_cmd clear dia_pcw");
796 putbits36_1 (& bootloadStatus, 0, 1);
797 putbits36_3 (& bootloadStatus, 3, 0);
798 putbits36_8 (& bootloadStatus, 9, 0);
799 putbits36_17 (& bootloadStatus, 17, 0);
800 fnp_core_write (dudp -> mailbox_address + 6, bootloadStatus,
801 "dia_iom_cmd set bootload status");
802 }
803 else
804 {
805
806 sim_printf ("%s not ok\r\n", __func__);
807
808 putbits36_1 (& dia_pcw, 18, 1);
809 fnp_core_write (dudp -> mailbox_address, dia_pcw, "dia_iom_cmd set error bit");
810 }
811 }
812
813 static int dia_cmd (uint iom_unit_idx, uint chan)
814 {
815 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
816 p -> stati = 0;
817
818 switch (p -> IDCW_DEV_CMD)
819 {
820 case 000:
821 {
822 p -> stati = 04000;
823 sim_debug (DBG_NOTIFY, & dia_dev, "Request status\n");
824 }
825 break;
826
827 default:
828 {
829 p -> stati = 04501;
830 p -> chanStatus = chanStatIncorrectDCW;
831 if (p->IDCW_DEV_CMD != 051)
832 sim_warn ("dia daze %o\n", p->IDCW_DEV_CMD);
833 }
834 return IOM_CMD_ERROR;
835 }
836
837 processMBX (iom_unit_idx, chan);
838
839 return IOM_CMD_NO_DCW;
840 }
841
842
843
844
845
846
847
848
849
850
851 int dia_iom_cmd (uint iom_unit_idx, uint chan)
852 {
853 sim_printf ("dia_iom_cmd %u %u\r\n", iom_unit_idx, chan);
854 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
855
856
857 if (IS_IDCW (p))
858 {
859 return dia_cmd (iom_unit_idx, chan);
860 }
861
862 sim_printf ("%s expected IDCW\n", __func__);
863 return -1;
864 }
865
866 static void load_stored_boot (void)
867 {
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886 sim_printf ("got load_stored_boot\n");
887 }
888
889 #define psz 17000
890 static uint8_t pkt[psz];
891
892
893 static int poll_coupler (uint unitno, uint8_t * * pktp)
894 {
895 int sz = dn_udp_receive (dia_data.dia_unit_data[unitno].link, pkt, psz);
896 if (sz < 0)
897 {
898 sim_printf ("dn_udp_receive failed: %d\n", sz);
899 sz = 0;
900 }
901 * pktp = pkt;
902 return sz;
903 }
904
905 void dia_unit_process_events (uint unit_num)
906 {
907
908
909
910
911 uint8_t * pktp;
912 int sz = poll_coupler (unit_num, & pktp);
913
914 if (! sz)
915 {
916 return;
917 }
918
919 uint8_t cmd = pktp [0];
920 switch (cmd)
921 {
922
923 case dn_cmd_ISB_IOLD:
924 {
925 load_stored_boot ();
926 break;
927 }
928
929 default:
930 {
931 sim_printf ("%s got unhandled cmd %u\n", __func__, cmd);
932 break;
933 }
934 }
935 }
936
937 void dia_process_events (void)
938 {
939 for (uint unit_num = 0; unit_num < N_DIA_UNITS_MAX; unit_num ++)
940 {
941 if (dia_data.dia_unit_data[unit_num].link >= 0)
942 dia_unit_process_events (unit_num);
943 }
944 }