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 #include <stdio.h>
31 #include <ctype.h>
32
33 #include "dps8.h"
34 #include "dps8_dia.h"
35 #include "dps8_sys.h"
36 #include "dps8_cpu.h"
37 #include "dps8_faults.h"
38 #include "dps8_scu.h"
39 #include "dps8_iom.h"
40 #include "dps8_cable.h"
41 #include "dps8_utils.h"
42
43 #include "udplib.h"
44
45 #define DBG_CTR 1
46
47 #if defined(THREADZ)
48 # include "threadz.h"
49 #endif
50
51 #if defined(FREE)
52 # undef FREE
53 #endif
54 #define FREE(p) do \
55 { \
56 free((p)); \
57 (p) = NULL; \
58 } while(0)
59
60 static inline void fnp_core_read (word24 addr, word36 *data, UNUSED const char * ctx)
61 {
62 #if defined(THREADZ)
63 lock_mem_rd ();
64 #endif
65 * data = M [addr] & DMASK;
66 #if defined(THREADZ)
67 unlock_mem ();
68 #endif
69 }
70 #define N_DIA_UNITS 1
71 #define DIA_UNIT_IDX(uptr) ((uptr) - dia_unit)
72
73 static config_list_t dia_config_list [] =
74 {
75
76 { "mailbox", 0, 07777, NULL },
77 { NULL, 0, 0, NULL }
78 };
79
80 static t_stat set_config (UNIT * uptr, UNUSED int value, const char * cptr, UNUSED void * desc)
81 {
82 uint dia_unit_idx = (uint) DIA_UNIT_IDX (uptr);
83
84 if (dia_unit_idx >= N_DIA_UNITS_MAX)
85 {
86 sim_debug (DBG_ERR, & dia_dev, "DIA SET CONFIG: Invalid unit number %ld\n",
87 (long) dia_unit_idx);
88 sim_printf ("error: DIA SET CONFIG: Invalid unit number %ld\n",
89 (long) dia_unit_idx);
90 return SCPE_ARG;
91 }
92
93 struct dia_unit_data * dudp = dia_data.dia_unit_data + dia_unit_idx;
94
95 config_state_t cfg_state = { NULL, NULL };
96
97 for (;;)
98 {
99 int64_t v;
100 int rc = cfg_parse ("DIA SET CONFIG", cptr, dia_config_list, & cfg_state, & v);
101 switch (rc)
102 {
103 case -2:
104 cfg_parse_done (& cfg_state);
105 return SCPE_ARG;
106
107 case -1:
108 break;
109
110 case 0:
111 dudp -> mailbox_address = (uint) v;
112 break;
113
114 default:
115 sim_printf ("error: DIA SET CONFIG: Invalid cfg_parse rc <%ld>\n", (long) rc);
116 cfg_parse_done (& cfg_state);
117 return SCPE_ARG;
118 }
119 if (rc < 0)
120 break;
121 }
122 cfg_parse_done (& cfg_state);
123 return SCPE_OK;
124 }
125
126 static t_stat show_config (UNUSED FILE * st, UNIT * uptr, UNUSED int val,
127 UNUSED const void * desc)
128 {
129 long unit_idx = DIA_UNIT_IDX (uptr);
130 if (unit_idx >= (long) N_DIA_UNITS_MAX)
131 {
132 sim_debug (DBG_ERR, & dia_dev,
133 "DIA SHOW CONFIG: Invalid unit number %ld\n", (long) unit_idx);
134 sim_printf ("error: Invalid unit number %ld\n", (long) unit_idx);
135 return SCPE_ARG;
136 }
137
138 sim_printf ("DIA unit number %ld\n", (long) unit_idx);
139 struct dia_unit_data * dudp = dia_data.dia_unit_data + unit_idx;
140
141 sim_printf ("DIA Mailbox Address: %04o(8)\n", dudp -> mailbox_address);
142
143 return SCPE_OK;
144 }
145
146 static t_stat show_status (UNUSED FILE * st, UNIT * uptr, UNUSED int val,
147 UNUSED const void * desc)
148 {
149 long dia_unit_idx = DIA_UNIT_IDX (uptr);
150 if (dia_unit_idx >= (long) dia_dev.numunits)
151 {
152 sim_debug (DBG_ERR, & dia_dev,
153 "DIA SHOW STATUS: Invalid unit number %ld\n", (long) dia_unit_idx);
154 sim_printf ("error: Invalid unit number %ld\n", (long) dia_unit_idx);
155 return SCPE_ARG;
156 }
157
158 sim_printf ("DIA unit number %ld\n", (long) dia_unit_idx);
159 struct dia_unit_data * dudp = dia_data.dia_unit_data + dia_unit_idx;
160
161 sim_printf ("mailbox_address: %04o\n", dudp->mailbox_address);
162 return SCPE_OK;
163 }
164
165 static t_stat show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
166 UNUSED int val, UNUSED const void * desc)
167 {
168 sim_printf("Number of DIA units in system is %d\n", dia_dev.numunits);
169 return SCPE_OK;
170 }
171
172 static t_stat set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
173 const char * cptr, UNUSED void * desc)
174 {
175 if (! cptr)
176 return SCPE_ARG;
177 int n = atoi (cptr);
178 if (n < 1 || n > N_DIA_UNITS_MAX)
179 return SCPE_ARG;
180 dia_dev.numunits = (uint32) n;
181 return SCPE_OK;
182 }
183
184 static MTAB dia_mod [] =
185 {
186 {
187 MTAB_XTD | MTAB_VUN | \
188 MTAB_NMO | MTAB_VALR,
189 0,
190 "CONFIG",
191 "CONFIG",
192 set_config,
193 show_config,
194 NULL,
195 NULL
196 },
197
198 {
199 MTAB_XTD | MTAB_VUN | \
200 MTAB_NMO | MTAB_VALR,
201 0,
202 "STATUS",
203 "STATUS",
204 NULL,
205 show_status,
206 NULL,
207 NULL
208 },
209
210 {
211 MTAB_XTD | MTAB_VDV | \
212 MTAB_NMO | MTAB_VALR,
213 0,
214 "NUNITS",
215 "NUNITS",
216 set_nunits,
217 show_nunits,
218 "Number of DIA units in the system",
219 NULL
220 },
221 { 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }
222 };
223
224 UNIT dia_unit [N_DIA_UNITS_MAX] = {
225 {UDATA (NULL, UNIT_DISABLE | UNIT_IDLE, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL}
226 };
227
228 static DEBTAB dia_DT [] =
229 {
230 { "TRACE", DBG_TRACE, NULL },
231 { "NOTIFY", DBG_NOTIFY, NULL },
232 { "INFO", DBG_INFO, NULL },
233 { "ERR", DBG_ERR, NULL },
234 { "WARN", DBG_WARN, NULL },
235 { "DEBUG", DBG_DEBUG, NULL },
236 { "ALL", DBG_ALL, NULL },
237 { NULL, 0, NULL }
238 };
239
240 static t_stat reset (UNUSED DEVICE * dptr)
241 {
242 return SCPE_OK;
243 }
244
245 static t_stat attach (UNIT * uptr, const char * cptr)
246 {
247 if (! cptr)
248 return SCPE_ARG;
249 int unitno = (int) (uptr - dia_unit);
250
251
252
253 t_stat ret;
254 char * pfn;
255
256
257 if ((uptr->flags & UNIT_ATT) != 0)
258 detach_unit (uptr);
259
260
261
262
263 pfn = (char *) calloc (CBUFSIZE, sizeof (char));
264 if (pfn == NULL)
265 return SCPE_MEM;
266 strncpy (pfn, cptr, CBUFSIZE);
267
268
269 ret = udp_create (cptr, & dia_data.dia_unit_data[unitno].link);
270 if (ret != SCPE_OK)
271 {
272 FREE (pfn);
273 return ret;
274 }
275
276 uptr->flags |= UNIT_ATT;
277 uptr->filename = pfn;
278 return SCPE_OK;
279 }
280
281
282 static t_stat detach (UNIT * uptr)
283 {
284 int unitno = (int) (uptr - dia_unit);
285 t_stat ret;
286 if ((uptr->flags & UNIT_ATT) == 0)
287 return SCPE_OK;
288 if (dia_data.dia_unit_data[unitno].link == NOLINK)
289 return SCPE_OK;
290
291 ret = udp_release (dia_data.dia_unit_data[unitno].link);
292 if (ret != SCPE_OK)
293 return ret;
294 dia_data.dia_unit_data[unitno].link = NOLINK;
295 uptr->flags &= ~ (unsigned int) UNIT_ATT;
296 FREE (uptr->filename);
297 uptr->filename = NULL;
298 return SCPE_OK;
299 }
300
301 DEVICE dia_dev = {
302 "DIA",
303 dia_unit,
304 NULL,
305 dia_mod,
306 N_DIA_UNITS,
307 10,
308 31,
309 1,
310 8,
311 9,
312 NULL,
313 NULL,
314 reset,
315 NULL,
316 attach,
317 detach,
318 NULL,
319 DEV_DEBUG,
320 0,
321 dia_DT,
322 NULL,
323 NULL,
324 NULL,
325 NULL,
326 NULL,
327 NULL,
328 NULL
329 };
330
331 t_dia_data dia_data;
332
333 struct dn355_submailbox
334 {
335 word36 word1;
336 word36 word2;
337 word36 command_data [3];
338 word36 word6;
339 word36 pad3 [2];
340 };
341
342 struct fnp_submailbox
343 {
344
345 word36 word1;
346 word36 word2;
347 word36 mystery [26];
348 };
349
350 struct mailbox
351 {
352 word36 dia_pcw;
353 word36 mailbox_requests;
354 word36 term_inpt_mpx_wd;
355 word36 last_mbx_req_count;
356 word36 num_in_use;
357 word36 mbx_used_flags;
358 word36 crash_data [2];
359 struct dn355_submailbox dn355_sub_mbxes [8];
360 struct fnp_submailbox fnp_sub_mbxes [4];
361 };
362
363 #define MAILBOX_WORDS (sizeof (struct mailbox) / sizeof (word36))
364 #define TERM_INPT_MPX_WD (offsetof (struct mailbox, term_inpt_mpx_wd) / sizeof (word36))
365
366
367
368
369
370 void dia_init (void)
371 {
372
373 (void)memset(& dia_data, 0, sizeof(dia_data));
374 for (uint unit_num = 0; unit_num < N_DIA_UNITS_MAX; unit_num ++)
375 {
376 cables -> cables_from_iom_to_dia [unit_num].iomUnitIdx = -1;
377 dia_data.dia_unit_data[unit_num].link = -1;
378 }
379 }
380
381 static inline void fnp_core_write (word24 addr, word36 data, UNUSED const char * ctx)
382 {
383 #if defined(THREADZ)
384 lock_mem_wr ();
385 #endif
386 M [addr] = data & DMASK;
387 #if defined(THREADZ)
388 unlock_mem ();
389 #endif
390 }
391
392
393
394
395
396 static uint virtToPhys (uint ptPtr, uint l66Address)
397 {
398 uint pageTable = ptPtr * 64u;
399 uint l66AddressPage = l66Address / 1024u;
400
401 word36 ptw;
402 fnp_core_read (pageTable + l66AddressPage, & ptw, "fnpIOMCmd get ptw");
403 uint page = getbits36_14 (ptw, 4);
404 uint addr = page * 1024u + l66Address % 1024u;
405 return addr;
406 }
407
408
409
410
411
412
413
414
415 static void cmd_bootload (uint iom_unit_idx, uint dev_unit_idx, uint chan, word24 l66_addr)
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 (void)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
785
786 sim_debug (DBG_TRACE, & dia_dev, "FNP data xfer??\n");
787 }
788 else
789 {
790 sim_warn ("bogus fnp command %d (%o)\n", command, command);
791 ok = false;
792 }
793
794 if (ok)
795 {
796
797 fnp_core_write (dudp -> mailbox_address, 0, "dia_iom_cmd clear dia_pcw");
798 putbits36_1 (& bootloadStatus, 0, 1);
799 putbits36_3 (& bootloadStatus, 3, 0);
800 putbits36_8 (& bootloadStatus, 9, 0);
801 putbits36_17 (& bootloadStatus, 17, 0);
802 fnp_core_write (dudp -> mailbox_address + 6, bootloadStatus,
803 "dia_iom_cmd set bootload status");
804 }
805 else
806 {
807
808 sim_printf ("%s not ok\r\n", __func__);
809
810 putbits36_1 (& dia_pcw, 18, 1);
811 fnp_core_write (dudp -> mailbox_address, dia_pcw, "dia_iom_cmd set error bit");
812 }
813 }
814
815 static int dia_cmd (uint iom_unit_idx, uint chan)
816 {
817 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
818 p -> stati = 0;
819
820 switch (p -> IDCW_DEV_CMD)
821 {
822 case 000:
823 {
824 p -> stati = 04000;
825 sim_debug (DBG_NOTIFY, & dia_dev, "Request status\n");
826 }
827 break;
828
829 default:
830 {
831 p -> stati = 04501;
832 p -> chanStatus = chanStatIncorrectDCW;
833 if (p->IDCW_DEV_CMD != 051)
834 sim_warn ("dia daze %o\n", p->IDCW_DEV_CMD);
835 }
836 return IOM_CMD_ERROR;
837 }
838
839 processMBX (iom_unit_idx, chan);
840
841 return IOM_CMD_NO_DCW;
842 }
843
844
845
846
847
848
849
850
851
852
853 int dia_iom_cmd (uint iom_unit_idx, uint chan)
854 {
855 sim_printf ("dia_iom_cmd %u %u\r\n", iom_unit_idx, chan);
856 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
857
858
859 if (IS_IDCW (p))
860 {
861 return dia_cmd (iom_unit_idx, chan);
862 }
863
864 sim_printf ("%s expected IDCW\n", __func__);
865 return -1;
866 }
867
868 static void load_stored_boot (void)
869 {
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888 sim_printf ("got load_stored_boot\n");
889 }
890
891 #define psz 17000
892 static uint8_t pkt[psz];
893
894
895 static int poll_coupler (uint unitno, uint8_t * * pktp)
896 {
897 int sz = dn_udp_receive (dia_data.dia_unit_data[unitno].link, pkt, psz);
898 if (sz < 0)
899 {
900 sim_printf ("dn_udp_receive failed: %d\n", sz);
901 sz = 0;
902 }
903 * pktp = pkt;
904 return sz;
905 }
906
907 void dia_unit_process_events (uint unit_num)
908 {
909
910
911
912
913 uint8_t * pktp;
914 int sz = poll_coupler (unit_num, & pktp);
915
916 if (! sz)
917 {
918 return;
919 }
920
921 uint8_t cmd = pktp [0];
922 switch (cmd)
923 {
924
925 case dn_cmd_ISB_IOLD:
926 {
927 load_stored_boot ();
928 break;
929 }
930
931 default:
932 {
933 sim_printf ("%s got unhandled cmd %u\n", __func__, cmd);
934 break;
935 }
936 }
937 }
938
939 void dia_process_events (void)
940 {
941 for (uint unit_num = 0; unit_num < N_DIA_UNITS_MAX; unit_num ++)
942 {
943 if (dia_data.dia_unit_data[unit_num].link >= 0)
944 dia_unit_process_events (unit_num);
945 }
946 }