This source file includes following definitions.
- prt_init
- prt_reset
- gc
- parseID
- openPrtFile
- eoj
- print_buf
- loadImageBuffer
- readStatusRegister
- loadVFCImage
- print_cmd
- prt_cmd_202
- prt_cmd_300
- prt_cmd_300a
- prt_cmd_400
- prt_iom_cmd
- prt_show_nunits
- prt_set_nunits
- prt_show_device_name
- prt_set_device_model
- prt_show_device_model
- prt_set_device_name
- prt_show_path
- prt_set_path
- burst_printer
- signal_prt_ready
- prt_set_ready
- prt_set_config
- prt_show_config
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 #include <stdio.h>
32 #include <ctype.h>
33 #include <unistd.h>
34
35 #include "dps8.h"
36 #include "dps8_iom.h"
37 #include "dps8_prt.h"
38 #include "dps8_sys.h"
39 #include "dps8_cable.h"
40 #include "dps8_cpu.h"
41 #include "dps8_faults.h"
42 #include "dps8_scu.h"
43 #include "dps8_utils.h"
44 #include "utfile.h"
45
46 #define DBG_CTR 1
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 #define N_PRT_UNITS 1
81
82 static t_stat prt_reset (DEVICE * dptr);
83 static t_stat prt_show_nunits (FILE *st, UNIT *uptr, int val, const void *desc);
84 static t_stat prt_set_nunits (UNIT * uptr, int32 value, const char * cptr, void * desc);
85 static t_stat prt_show_device_name (FILE *st, UNIT *uptr, int val, const void *desc);
86 static t_stat prt_set_device_name (UNIT * uptr, int32 value, const char * cptr, void * desc);
87 static t_stat prt_set_config (UNUSED UNIT * uptr, UNUSED int32 value,
88 const char * cptr, UNUSED void * desc);
89 static t_stat prt_show_config (UNUSED FILE * st, UNUSED UNIT * uptr,
90 UNUSED int val, UNUSED const void * desc);
91 static t_stat prt_show_path (UNUSED FILE * st, UNIT * uptr,
92 UNUSED int val, UNUSED const void * desc);
93 static t_stat prt_set_path (UNUSED UNIT * uptr, UNUSED int32 value,
94 const UNUSED char * cptr, UNUSED void * desc);
95 static t_stat prt_set_ready (UNIT * uptr, UNUSED int32 value,
96 UNUSED const char * cptr,
97 UNUSED void * desc);
98
99 static t_stat prt_show_device_model (FILE *st, UNIT *uptr, int val, const void *desc);
100 static t_stat prt_set_device_model (UNIT * uptr, int32 value, const char * cptr, void * desc);
101
102 #define UNIT_FLAGS ( UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | \
103 UNIT_IDLE )
104 UNIT prt_unit[N_PRT_UNITS_MAX] =
105 {
106 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
107 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
108 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
109 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
110 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
111 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
112 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
113 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
114 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
115 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
116 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
117 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
118 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
119 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
120 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
121 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
122 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
123 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
124 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
125 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
126 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
127 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
128 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
129 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
130 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
131 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
132 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
133 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
134 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
135 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
136 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
137 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
138 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
139 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL}
140 };
141
142 #define PRT_UNIT_NUM(uptr) ((uptr) - prt_unit)
143
144 static DEBTAB prt_dt[] =
145 {
146 { "NOTIFY", DBG_NOTIFY, NULL },
147 { "INFO", DBG_INFO, NULL },
148 { "ERR", DBG_ERR, NULL },
149 { "WARN", DBG_WARN, NULL },
150 { "DEBUG", DBG_DEBUG, NULL },
151 { "ALL", DBG_ALL, NULL },
152 { NULL, 0, NULL }
153 };
154
155 #define UNIT_WATCH UNIT_V_UF
156
157 static MTAB prt_mod[] =
158 {
159 #if !defined(SPEED)
160 { UNIT_WATCH, 1, "WATCH", "WATCH", 0, 0, NULL, NULL },
161 { UNIT_WATCH, 0, "NOWATCH", "NOWATCH", 0, 0, NULL, NULL },
162 #endif
163 {
164 MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_VALR,
165 0,
166 "NUNITS",
167 "NUNITS",
168 prt_set_nunits,
169 prt_show_nunits,
170 "Number of PRT units in the system",
171 NULL
172 },
173 {
174 MTAB_XTD | MTAB_VDV | MTAB_NMO | \
175 MTAB_VALR | MTAB_NC,
176 0,
177 "PATH",
178 "PATH",
179 prt_set_path,
180 prt_show_path,
181 "Path to write PRT files",
182 NULL
183 },
184 {
185 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
186 0,
187 "NAME",
188 "NAME",
189 prt_set_device_name,
190 prt_show_device_name,
191 "Select the printer name",
192 NULL
193 },
194
195 {
196 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
197 0,
198 "MODEL",
199 "MODEL",
200 prt_set_device_model,
201 prt_show_device_model,
202 "Select the printer model",
203 NULL
204 },
205 {
206 MTAB_XTD | MTAB_VUN,
207 0,
208 (char *) "CONFIG",
209 (char *) "CONFIG",
210 prt_set_config,
211 prt_show_config,
212 NULL,
213 NULL,
214 },
215 {
216 MTAB_XTD | MTAB_VUN | MTAB_NMO | MTAB_VALR,
217 0,
218 "READY",
219 "READY",
220 prt_set_ready,
221 NULL,
222 NULL,
223 NULL
224 },
225 { 0, 0, NULL, NULL, 0, 0, NULL, NULL }
226 };
227
228 DEVICE prt_dev = {
229 "PRT",
230 prt_unit,
231 NULL,
232 prt_mod,
233 N_PRT_UNITS,
234 10,
235 24,
236 1,
237 8,
238 36,
239 NULL,
240 NULL,
241 prt_reset,
242 NULL,
243 NULL,
244 NULL,
245 NULL,
246 DEV_DEBUG,
247 0,
248 prt_dt,
249 NULL,
250 NULL,
251 NULL,
252 NULL,
253 NULL,
254 NULL,
255 NULL
256 };
257
258 typedef struct
259 {
260 enum prt_mode
261 {
262 prtNoMode, prtPrt, prtLdImgBuf, prtRdStatReg, prtLdVFCImg
263 } ioMode;
264 int prtUnitNum;
265 bool isBCD;
266 bool isEdited;
267 int slew;
268 char device_name[MAX_DEV_NAME_LEN];
269 int prtfile;
270
271 bool cachedFF;
272 bool split;
273 int model;
274 } prt_state_t;
275
276 static prt_state_t prt_state[N_PRT_UNITS_MAX];
277
278 static char prt_path[1025];
279
280 #define N_MODELS 13
281
282 static const char * model_names[N_MODELS] =
283 {
284 "202", "300", "301", "302", "303", "304",
285 "401", "402", "901", "1000", "1200", "1201",
286 "1600"
287 };
288
289 #define MODEL_1600 12
290
291 static const int model_type[N_MODELS] =
292 { 1, 2, 2, 2, 3, 3,
293 4, 4, 4, 4, 4, 4,
294 4
295 };
296
297 #if defined(NO_C_ELLIPSIS)
298 static const uint8 newlines[128] = {
299 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
300 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
301 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
302 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
303 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
304 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
305 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
306 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
307 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
308 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
309 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
310 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
311 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
312 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
313 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
314 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'
315 };
316
317 static const uint8 spaces[128] = {
318 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
319 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
320 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
321 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
322 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
323 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
324 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
325 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
326 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
327 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
328 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
329 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
330 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
331 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
332 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
333 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
334 };
335 #else
336 static const uint8 newlines[128] = { [0 ... 127] = '\n' };
337 static const uint8 spaces[128] = { [0 ... 127] = ' ' };
338 #endif
339 static const uint8 formfeed[1] = { '\f' };
340 static const uint8 crlf[4] = { '\r', '\n', '\r', '\n' };
341 static const uint8 cr[2] = { '\r', '\n' };
342
343
344
345
346
347
348
349
350 void prt_init (void)
351 {
352 (void)memset (prt_path, 0, sizeof (prt_path));
353 (void)memset (prt_state, 0, sizeof (prt_state));
354 for (int i = 0; i < N_PRT_UNITS_MAX; i ++)
355 {
356 prt_state[i].prtfile = -1;
357 prt_state[i].model = MODEL_1600;
358 }
359 }
360
361 static t_stat prt_reset (UNUSED DEVICE * dptr)
362 {
363
364
365
366
367
368
369
370 return SCPE_OK;
371 }
372
373
374
375 static word9 gc (word36 * b, uint os)
376 {
377 uint wordno = os / 4;
378 uint charno = os % 4;
379 return (word9) getbits36_9 (b[wordno], charno * 9);
380 }
381
382
383 #define LONGEST 128
384
385
386
387
388
389
390
391 static int parseID (word36 * b, uint tally, char * qno, char * name)
392 {
393 if (tally < 3)
394 return 0;
395 if (gc (b, 0) != 040)
396 return 0;
397 if (gc (b, 1) != 040)
398 return 0;
399 uint i;
400 for (i = 0; i < 5; i ++)
401 {
402 word9 ch = gc (b, 2 + i);
403 if (ch < '0' || ch > '9')
404 return 0;
405 qno[i] = (char) ch;
406 }
407 qno[5] = 0;
408 if (gc (b, 7) != 037)
409 return 0;
410
411
412 for (i = 0; i < LONGEST; i ++)
413 {
414 word9 ch = gc (b, 9 + i);
415 if (ch == 037)
416 break;
417 if (! isprint (ch))
418 return 0;
419 name[i] = (char) ch;
420 }
421 name[i] = 0;
422 return -1;
423 }
424
425
426
427
428
429
430 static int openPrtFile (int prt_unit_num, word36 * buffer, uint tally)
431 {
432 if (prt_state[prt_unit_num].prtfile != -1)
433 return 0;
434
435
436
437
438 if (tally == 1 && buffer[0] == 0014013000000llu)
439 {
440 prt_state[prt_unit_num].cachedFF = true;
441 return -3;
442 }
443
444 char qno[6], name[LONGEST + 1];
445 int rc = parseID (buffer, tally, qno, name);
446 char template[1024 + 129 + LONGEST];
447 char unit_designator = 'a' + (char) prt_unit_num;
448 char split_prefix[6];
449 split_prefix[0] = 0;
450 if (prt_state [prt_unit_num] . split) {
451 (void)sprintf(split_prefix, "prt%c/", unit_designator);
452 }
453 if (rc == 0)
454 (void)sprintf (template, "%s%sprt%c.spool.XXXXXX.prt", prt_path, split_prefix, unit_designator);
455 else
456 (void)sprintf (template, "%s%sprt%c.spool.%s.%s.XXXXXX.prt", prt_path, split_prefix, unit_designator, qno, name);
457
458 prt_state[prt_unit_num].prtfile = utfile_mkstemps (template, 4);
459 if (prt_state[prt_unit_num].prtfile == -1)
460 {
461 sim_warn ("Unable to open printer file '%s', errno %d\n", template, errno);
462 return -1;
463 }
464 if (prt_state[prt_unit_num].cachedFF)
465 {
466 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, formfeed, 1);
467 if (n_write != 1)
468 {
469 return -2;
470 }
471 prt_state[prt_unit_num].cachedFF = false;
472 }
473 return 0;
474 }
475
476
477 static int eoj (word36 * buffer, uint tally)
478 {
479 if (tally < 3)
480 return 0;
481 if (getbits36_9 (buffer[0], 0) != 037)
482 return 0;
483 if (getbits36_9 (buffer[0], 9) != 014)
484 return 0;
485 word9 ch = getbits36_9 (buffer[0], 18);
486 if (ch < '0' || ch > '9')
487 return 0;
488 ch = getbits36_9 (buffer[0], 27);
489 if (ch < '0' || ch > '9')
490 return 0;
491 ch = getbits36_9 (buffer[1], 0);
492 if (ch < '0' || ch > '9')
493 return 0;
494 ch = getbits36_9 (buffer[1], 9);
495 if (ch < '0' || ch > '9')
496 return 0;
497 ch = getbits36_9 (buffer[1], 18);
498 if (ch < '0' || ch > '9')
499 return 0;
500 if (getbits36_9 (buffer[1], 27) != 037)
501 return 0;
502 if (getbits36_9 (buffer[2], 0) != 005)
503 return 0;
504 return -1;
505 }
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
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 static int print_buf (int prt_unit_num, bool isBCD, bool is_edited, int slew, word36 * buffer, uint tally)
617 {
618
619
620
621
622
623
624
625
626
627
628
629
630 static char * bcd_lc =
631 "01234567"
632 "89{#?;>?"
633 " abcdefg"
634 "hi|.}(<\\"
635 "^jklmnop"
636 "qr_$*);'"
637 "+/stuvwx"
638 "yz~,!=\"!";
639
640
641
642
643
644
645
646
647
648
649
650
651 static char * bcd_uc =
652 "01234567"
653 "89[#@;>?"
654 " ABCDEFG"
655 "HI&.](<\\"
656 "^JKLMNOP"
657 "QR-$*);'"
658 "+/STUVWX"
659 "YZ_,%=\"!";
660
661
662 static char * bcd =
663 "01234567"
664 "89[#@;> "
665 " ABCDEFG"
666 "HI&.](<\\"
667 "^JKLMNOP"
668 "QR-$*);'"
669 "+/STUVWX"
670 "YZ_,%=\"!";
671
672 if (prt_state[prt_unit_num].prtfile == -1)
673 {
674 int rc = openPrtFile (prt_unit_num, buffer, tally);
675 if (rc < 0)
676 {
677 return rc == -3 ? 0 : rc;
678 }
679 }
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710 if (slew == -1)
711 {
712 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, formfeed, 1);
713 if (n_write != 1)
714 {
715 return -2;
716 }
717 }
718 else if (slew)
719 {
720 for (int i = 0; i < slew; i ++)
721 {
722 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, crlf, 2);
723 if (n_write != 2)
724 {
725 return -2;
726 }
727 }
728 }
729
730
731
732
733
734
735 if (tally)
736 {
737 if (isBCD)
738 {
739 uint nchars = tally * 6;
740 #define get_BCD_char(i) ((uint8_t) ((buffer[i / 6] >> ((5 - i % 6) * 6)) & 077))
741
742 if (! is_edited)
743 {
744 uint8 bytes[nchars];
745 for (uint i = 0; i < nchars; i ++)
746 {
747 bytes[i] = (uint8_t) bcd_uc [get_BCD_char (i)];
748 }
749 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, bytes, nchars);
750 if (n_write != nchars)
751 {
752 return -2;
753 }
754 }
755 else
756 {
757
758
759
760
761
762 int BCD_cset = 0;
763 char * table[3] = { bcd, bcd_lc, bcd_uc };
764
765 for (uint i = 0; i < nchars; i ++)
766 {
767 uint8_t ch = get_BCD_char (i);
768
769
770
771
772
773
774
775
776 if (ch == 077)
777 {
778 i ++;
779 uint8_t n = get_BCD_char (i);
780
781 if (n == 077)
782 {
783
784 switch (BCD_cset)
785 {
786 case 0: BCD_cset = 1; break;
787 case 1: BCD_cset = 2; break;
788 case 2: BCD_cset = 1; break;
789 }
790 }
791 else if (n >= 041 && n <= 057)
792 {
793 int nchars = (n - 040) * 8;
794 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, spaces, (size_t)nchars);
795 if (n_write != nchars)
796 {
797 return -2;
798 }
799 }
800 else if (n >= 020 && n <= 022)
801 {
802
803 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, formfeed, 1);
804 if (n_write != 1)
805 {
806 return -2;
807 }
808 }
809 else if (n == 0)
810 {
811 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, cr, 1);
812 if (n_write != 1)
813 {
814 return -2;
815 }
816 }
817 else if (n <= 017)
818 {
819 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, newlines, n);
820 if (n_write != n)
821 {
822 return -2;
823 }
824 }
825 #if defined(TESTING)
826 else
827 {
828 sim_warn ("Printer BCD edited ESC %u. %o ignored\n", n, n);
829 }
830 #endif
831 }
832 else
833 {
834 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, table[BCD_cset] + ch, 1);
835 if (n_write != 1)
836 {
837 return -2;
838 }
839 }
840 }
841 }
842 }
843 else
844 {
845 uint nchars = tally * 4;
846 #define get_ASCII_char(i) ((uint8_t) ((buffer[i / 4] >> ((3 - i % 4) * 9)) & 0377))
847
848 if (! is_edited)
849 {
850 uint8 bytes[nchars];
851 uint nbytes = 0;
852 for (uint i = 0; i < nchars; i ++)
853 {
854 uint8_t ch = get_ASCII_char (i);
855 if (isprint (ch))
856 bytes[nbytes ++] = ch;
857 }
858 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, bytes, nbytes);
859 if (n_write != nbytes)
860 {
861 return -2;
862 }
863 }
864 else
865 {
866 uint col = 0;
867 for (uint i = 0; i < tally * 4; i ++)
868 {
869 uint8_t ch = get_ASCII_char (i);
870 if (ch == 037)
871 {
872 i ++;
873 uint8_t n = get_ASCII_char (i);
874 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, spaces, n);
875 if (n_write != n)
876 {
877 return -2;
878 }
879 col += n;
880 }
881 else if (ch == 013)
882 {
883 i ++;
884 uint8_t n = get_ASCII_char (i);
885 if (n)
886 {
887 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, newlines, n);
888 if (n_write != n)
889 {
890 return -2;
891 }
892 }
893 else
894 {
895 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, cr, 1);
896 if (n_write != 1)
897 {
898 return -2;
899 }
900 }
901 col = 0;
902 }
903 else if (ch == 014)
904 {
905 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, formfeed, 1);
906 if (n_write != 1)
907 {
908 return -2;
909 }
910 col = 0;
911 }
912 else if (ch == 011)
913 {
914 i ++;
915 uint8_t n = get_ASCII_char (i);
916 if (col < n)
917 {
918 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, spaces, n - col);
919 if (n_write != n - col)
920 {
921 return -2;
922 }
923 col += n;
924 }
925 }
926 else if (isprint (ch))
927 {
928 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, & ch, 1);
929 if (n_write != 1)
930 {
931 return -2;
932 }
933 col ++;
934 }
935 }
936 }
937 }
938 }
939
940
941 ssize_t n_write = write (prt_state[prt_unit_num].prtfile, cr, 1);
942 if (n_write != 1)
943 {
944 return -2;
945 }
946
947 if ((! isBCD) && eoj (buffer, tally))
948 {
949 close (prt_state[prt_unit_num].prtfile);
950 prt_state[prt_unit_num].prtfile = -1;
951 }
952 return 0;
953 }
954
955 static int loadImageBuffer (uint iom_unit_idx, uint chan)
956 {
957 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
958
959 p->stati = 04000;
960 return 0;
961 }
962
963 static int readStatusRegister (uint iom_unit_idx, uint chan)
964 {
965 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
966
967 uint tally = p -> DDCW_TALLY;
968
969 if (tally != 4)
970 {
971 sim_warn ("%s: expected tally of 4, is %d\n", __func__, tally);
972 }
973 if (tally == 0)
974 {
975 tally = 4096;
976 }
977
978
979
980 word36 buffer[tally];
981 (void)memset (buffer, 0, sizeof (buffer));
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003 uint wordsProcessed = tally;
1004 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1005 & wordsProcessed, true);
1006 p->charPos = 0;
1007 p->stati = 04000;
1008 return 0;
1009 }
1010
1011 static int loadVFCImage (uint iom_unit_idx, uint chan)
1012 {
1013 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1014
1015 p->stati = 04000;
1016 return 0;
1017 }
1018
1019 static iom_cmd_rc_t print_cmd (uint iom_unit_idx, uint chan, int prt_unit_num, bool isBCD, bool is_edited, int slew)
1020 {
1021 #if defined(TESTING)
1022 cpu_state_t * cpup = _cpup;
1023 #endif
1024 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1025 p->isRead = false;
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 uint tally = p -> DDCW_TALLY;
1062 sim_debug (DBG_DEBUG, & prt_dev,
1063 "%s: Tally %d (%o)\n", __func__, tally, tally);
1064
1065 if (tally == 0)
1066 tally = 4096;
1067
1068
1069 word36 buffer[tally];
1070 uint wordsProcessed = 0;
1071 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1072 & wordsProcessed, false);
1073 p -> initiate = false;
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 int rc = print_buf (prt_unit_num, isBCD, is_edited, slew, buffer, tally);
1095 if (rc == -1)
1096 {
1097 p->stati = 04201;
1098 return IOM_CMD_ERROR;
1099 }
1100 if (rc == -2)
1101 {
1102 p->stati = 04210;
1103 return IOM_CMD_ERROR;
1104 }
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116 p -> tallyResidue = 0;
1117 p -> stati = 04000;
1118
1119 return IOM_CMD_RESIDUE;
1120 }
1121
1122 iom_cmd_rc_t prt_cmd_202 (uint iomUnitIdx, uint chan) {
1123 #if defined(TESTING)
1124 cpu_state_t * cpup = _cpup;
1125 #endif
1126 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
1127 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
1128 uint devUnitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
1129 UNIT * unitp = & prt_unit[devUnitIdx];
1130 int prt_unit_num = (int) PRT_UNIT_NUM (unitp);
1131 prt_state_t * statep = & prt_state[devUnitIdx];
1132
1133
1134 if (IS_IDCW (p)) {
1135
1136 statep->ioMode = prtNoMode;
1137
1138 switch (p->IDCW_DEV_CMD) {
1139 case 000:
1140 sim_debug (DBG_DEBUG, & prt_dev, "%s: Request Status\n", __func__);
1141 p->stati = 04000;
1142 break;
1143
1144 case 010:
1145 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited BCD, Slew One Line\n", __func__);
1146 statep->ioMode = prtPrt;
1147 statep->prtUnitNum = prt_unit_num;
1148 statep->isBCD = true;
1149 statep->isEdited = false;
1150 statep->slew = 1;
1151 p->stati = 04000;
1152 break;
1153
1154 case 030:
1155 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited BCD, Slew Zero Lines\n", __func__);
1156 statep->ioMode = prtPrt;
1157 statep->prtUnitNum = prt_unit_num;
1158 statep->isBCD = true;
1159 statep->isEdited = true;
1160 statep->slew = 0;
1161 p->stati = 04000;
1162 break;
1163
1164 case 040:
1165 sim_debug (DBG_DEBUG, & prt_dev, "%s: Reset Status\n", __func__);
1166 p->stati = 04000;
1167 p->isRead = false;
1168 break;
1169
1170 default:
1171 p->stati = 04501;
1172 p->chanStatus = chanStatIncorrectDCW;
1173 if (p->IDCW_DEV_CMD != 051)
1174 sim_warn ("%s: PRT unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
1175 return IOM_CMD_ERROR;
1176 }
1177
1178 sim_debug (DBG_DEBUG, & prt_dev, "%s: stati %04o\n", __func__, p->stati);
1179 return IOM_CMD_PROCEED;
1180 }
1181
1182
1183 switch (statep->ioMode) {
1184 case prtNoMode:
1185
1186
1187
1188 break;
1189
1190 case prtPrt: {
1191 iom_cmd_rc_t rc = print_cmd (iomUnitIdx, chan, statep->prtUnitNum, statep->isBCD,
1192 statep->isEdited, statep->slew);
1193 if (rc)
1194 return rc;
1195 }
1196 break;
1197
1198 default:
1199 sim_warn ("%s: Unrecognized ioMode %d\n", __func__, statep->ioMode);
1200 return IOM_CMD_ERROR;
1201 }
1202
1203 return IOM_CMD_PROCEED;
1204 }
1205
1206 iom_cmd_rc_t prt_cmd_300 (uint iomUnitIdx, uint chan) {
1207 #if defined(TESTING)
1208 cpu_state_t * cpup = _cpup;
1209 #endif
1210 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
1211 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
1212 uint devUnitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
1213 UNIT * unitp = & prt_unit[devUnitIdx];
1214 int prt_unit_num = (int) PRT_UNIT_NUM (unitp);
1215 prt_state_t * statep = & prt_state[devUnitIdx];
1216
1217
1218 if (IS_IDCW (p)) {
1219
1220 statep->ioMode = prtNoMode;
1221
1222 switch (p->IDCW_DEV_CMD) {
1223 case 000:
1224 sim_debug (DBG_DEBUG, & prt_dev, "%s: Request Status\n", __func__);
1225 p->stati = 04000;
1226 break;
1227
1228 case 011:
1229 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited ASCII, Slew One Line\n", __func__);
1230 statep->ioMode = prtPrt;
1231 statep->prtUnitNum = prt_unit_num;
1232 statep->isBCD = false;
1233 statep->isEdited = false;
1234 statep->slew = 1;
1235 p->stati = 04000;
1236 break;
1237
1238 case 014:
1239 sim_debug (DBG_DEBUG, & prt_dev, "%s: Load Image Buffer\n", __func__);
1240 statep->ioMode = prtLdImgBuf;
1241 p->stati = 04000;
1242 break;
1243
1244 case 030:
1245 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited ASCII, Slew Zero Lines\n", __func__);
1246 statep->ioMode = prtPrt;
1247 statep->prtUnitNum = prt_unit_num;
1248 statep->isBCD = false;
1249 statep->isEdited = true;
1250 statep->slew = 0;
1251 p->stati = 04000;
1252 break;
1253
1254 case 040:
1255 sim_debug (DBG_DEBUG, & prt_dev, "%s: Reset Status\n", __func__);
1256 p->stati = 04000;
1257 p->isRead = false;
1258 break;
1259
1260 default:
1261 p->stati = 04501;
1262 p->chanStatus = chanStatIncorrectDCW;
1263 if (p->IDCW_DEV_CMD != 051)
1264 sim_warn ("%s: PRT unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
1265 return IOM_CMD_ERROR;
1266 }
1267
1268 sim_debug (DBG_DEBUG, & prt_dev, "%s: stati %04o\n", __func__, p->stati);
1269 return IOM_CMD_PROCEED;
1270 }
1271
1272
1273 switch (statep->ioMode) {
1274 case prtNoMode:
1275
1276
1277
1278 break;
1279
1280 case prtPrt: {
1281 iom_cmd_rc_t rc = print_cmd (iomUnitIdx, chan, statep->prtUnitNum, statep->isBCD,
1282 statep->isEdited, statep->slew);
1283 if (rc)
1284 return rc;
1285 }
1286 break;
1287
1288 case prtLdImgBuf: {
1289 int rc = loadImageBuffer (iomUnitIdx, chan);
1290 if (rc)
1291 return IOM_CMD_ERROR;
1292 }
1293 break;
1294
1295 default:
1296 sim_warn ("%s: Unrecognized ioMode %d\n", __func__, statep->ioMode);
1297 return IOM_CMD_ERROR;
1298 }
1299 return IOM_CMD_PROCEED;
1300 }
1301
1302 iom_cmd_rc_t prt_cmd_300a (uint iomUnitIdx, uint chan) {
1303 #if defined(TESTING)
1304 cpu_state_t * cpup = _cpup;
1305 #endif
1306 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
1307 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
1308 uint devUnitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
1309 UNIT * unitp = & prt_unit[devUnitIdx];
1310 int prt_unit_num = (int) PRT_UNIT_NUM (unitp);
1311 prt_state_t * statep = & prt_state[devUnitIdx];
1312
1313
1314 if (IS_IDCW (p)) {
1315
1316 statep->ioMode = prtNoMode;
1317
1318 switch (p->IDCW_DEV_CMD) {
1319 case 000:
1320 sim_debug (DBG_DEBUG, & prt_dev, "%s: Request Status\n", __func__);
1321 p->stati = 04000;
1322 break;
1323
1324 case 001:
1325 sim_debug (DBG_DEBUG, & prt_dev, "%s: Load Image Buffer\n", __func__);
1326 statep->ioMode = prtLdImgBuf;
1327 p->stati = 04000;
1328 break;
1329
1330 case 015:
1331 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited ASCII, Slew One Line\n", __func__);
1332 statep->ioMode = prtPrt;
1333 statep->prtUnitNum = prt_unit_num;
1334 statep->isBCD = false;
1335 statep->isEdited = false;
1336 statep->slew = 1;
1337 p->stati = 04000;
1338 break;
1339
1340 case 034:
1341 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited ASCII, Slew Zero Lines\n", __func__);
1342 statep->ioMode = prtPrt;
1343 statep->prtUnitNum = prt_unit_num;
1344 statep->isBCD = false;
1345 statep->isEdited = true;
1346 statep->slew = 0;
1347 p->stati = 04000;
1348 break;
1349
1350 case 040:
1351 sim_debug (DBG_DEBUG, & prt_dev, "%s: Reset Status\n", __func__);
1352 p->stati = 04000;
1353 p->isRead = false;
1354 break;
1355
1356 default:
1357 p->stati = 04501;
1358 p->chanStatus = chanStatIncorrectDCW;
1359 if (p->IDCW_DEV_CMD != 051)
1360 sim_warn ("%s: PRT unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
1361 return IOM_CMD_ERROR;
1362 }
1363
1364 sim_debug (DBG_DEBUG, & prt_dev, "%s: stati %04o\n", __func__, p->stati);
1365 return IOM_CMD_PROCEED;
1366 }
1367
1368
1369 switch (statep->ioMode) {
1370 case prtNoMode:
1371
1372
1373
1374 break;
1375
1376 case prtPrt: {
1377 iom_cmd_rc_t rc = print_cmd (iomUnitIdx, chan, statep->prtUnitNum, statep->isBCD,
1378 statep->isEdited, statep->slew);
1379 if (rc)
1380 return rc;
1381 }
1382 break;
1383
1384 case prtLdImgBuf: {
1385 int rc = loadImageBuffer (iomUnitIdx, chan);
1386 if (rc)
1387 return IOM_CMD_ERROR;
1388 }
1389 break;
1390
1391 default:
1392 sim_warn ("%s: Unrecognized ioMode %d\n", __func__, statep->ioMode);
1393 return IOM_CMD_ERROR;
1394 }
1395 return IOM_CMD_PROCEED;
1396 }
1397
1398 iom_cmd_rc_t prt_cmd_400 (uint iomUnitIdx, uint chan) {
1399 #if defined(TESTING)
1400 cpu_state_t * cpup = _cpup;
1401 #endif
1402 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
1403 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
1404 uint devUnitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
1405 UNIT * unitp = & prt_unit[devUnitIdx];
1406 int prt_unit_num = (int) PRT_UNIT_NUM (unitp);
1407 prt_state_t * statep = & prt_state[devUnitIdx];
1408
1409
1410 if (IS_IDCW (p)) {
1411
1412 statep->ioMode = prtNoMode;
1413
1414 switch (p->IDCW_DEV_CMD) {
1415 case 000:
1416 sim_debug (DBG_DEBUG, & prt_dev, "%s: Request Status\n", __func__);
1417 p->stati = 04000;
1418 break;
1419
1420 case 001:
1421 sim_debug (DBG_DEBUG, & prt_dev, "%s: Load Image Buffer\n", __func__);
1422 statep->ioMode = prtLdImgBuf;
1423 p->stati = 04000;
1424 break;
1425
1426 case 003:
1427 sim_debug (DBG_DEBUG, & prt_dev, "%s: Load Image Buffer\n", __func__);
1428 statep->ioMode = prtRdStatReg;
1429 p->stati = 04000;
1430 break;
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456 case 005:
1457 sim_debug (DBG_DEBUG, & prt_dev, "%s: Load VFC Image\n", __func__);
1458 statep->ioMode = prtLdVFCImg;
1459 p->stati = 04000;
1460 break;
1461
1462 case 010:
1463 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited BCD, Slew Zero Lines\n", __func__);
1464 statep->ioMode = prtPrt;
1465 statep->prtUnitNum = prt_unit_num;
1466 statep->isBCD = true;
1467 statep->isEdited = false;
1468 statep->slew = 0;
1469 p->stati = 04000;
1470 break;
1471
1472 case 011:
1473 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited BCD, Slew One Line\n", __func__);
1474 statep->ioMode = prtPrt;
1475 statep->prtUnitNum = prt_unit_num;
1476 statep->isBCD = true;
1477 statep->isEdited = false;
1478 statep->slew = 1;
1479 p->stati = 04000;
1480 break;
1481
1482 case 012:
1483 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited BCD, Slew Two Lines\n", __func__);
1484 statep->ioMode = prtPrt;
1485 statep->prtUnitNum = prt_unit_num;
1486 statep->isBCD = true;
1487 statep->isEdited = false;
1488 statep->slew = 2;
1489 p->stati = 04000;
1490 break;
1491
1492 case 013:
1493 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited BCD, Slew Top Of Page\n", __func__);
1494 statep->ioMode = prtPrt;
1495 statep->prtUnitNum = prt_unit_num;
1496 statep->isBCD = true;
1497 statep->isEdited = false;
1498 statep->slew = -1;
1499 p->stati = 04000;
1500 break;
1501
1502 case 014:
1503 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited ASCII, Slew Zero Lines\n", __func__);
1504 statep->ioMode = prtPrt;
1505 statep->prtUnitNum = prt_unit_num;
1506 statep->isBCD = false;
1507 statep->isEdited = false;
1508 statep->slew = 0;
1509 p->stati = 04000;
1510 break;
1511
1512 case 015:
1513 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited ASCII, Slew One Line\n", __func__);
1514 statep->ioMode = prtPrt;
1515 statep->prtUnitNum = prt_unit_num;
1516 statep->isBCD = false;
1517 statep->isEdited = false;
1518 statep->slew = 1;
1519 p->stati = 04000;
1520 break;
1521
1522 case 016:
1523 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited ASCII, Slew Two Lines\n", __func__);
1524 statep->ioMode = prtPrt;
1525 statep->prtUnitNum = prt_unit_num;
1526 statep->isBCD = false;
1527 statep->isEdited = false;
1528 statep->slew = 2;
1529 p->stati = 04000;
1530 break;
1531
1532 case 017:
1533 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Nonedited ASCII, Slew Top Of Page\n", __func__);
1534 statep->ioMode = prtPrt;
1535 statep->prtUnitNum = prt_unit_num;
1536 statep->isBCD = false;
1537 statep->isEdited = false;
1538 statep->slew = -1;
1539 p->stati = 04000;
1540 break;
1541
1542 case 030:
1543 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited BCD, Slew Zero Lines\n", __func__);
1544 statep->ioMode = prtPrt;
1545 statep->prtUnitNum = prt_unit_num;
1546 statep->isBCD = true;
1547 statep->isEdited = true;
1548 statep->slew = 0;
1549 p->stati = 04000;
1550 break;
1551
1552 case 031:
1553 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited BCD, Slew One Line\n", __func__);
1554 statep->ioMode = prtPrt;
1555 statep->prtUnitNum = prt_unit_num;
1556 statep->isBCD = true;
1557 statep->isEdited = true;
1558 statep->slew = 1;
1559 p->stati = 04000;
1560 break;
1561
1562 case 032:
1563 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited BCD, Slew Two Lines\n", __func__);
1564 statep->ioMode = prtPrt;
1565 statep->prtUnitNum = prt_unit_num;
1566 statep->isBCD = true;
1567 statep->isEdited = true;
1568 statep->slew = 2;
1569 p->stati = 04000;
1570 break;
1571
1572 case 033:
1573 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited BCD, Slew Top Of Page\n", __func__);
1574 statep->ioMode = prtPrt;
1575 statep->prtUnitNum = prt_unit_num;
1576 statep->isBCD = true;
1577 statep->isEdited = true;
1578 statep->slew = -1;
1579 p->stati = 04000;
1580 break;
1581
1582 case 034:
1583 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited ASCII, Slew Zero Lines\n", __func__);
1584 statep->ioMode = prtPrt;
1585 statep->prtUnitNum = prt_unit_num;
1586 statep->isBCD = false;
1587 statep->isEdited = true;
1588 statep->slew = 0;
1589 p->stati = 04000;
1590 break;
1591
1592 case 035:
1593 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited ASCII, Slew One Line\n", __func__);
1594 statep->ioMode = prtPrt;
1595 statep->prtUnitNum = prt_unit_num;
1596 statep->isBCD = false;
1597 statep->isEdited = true;
1598 statep->slew = 1;
1599 p->stati = 04000;
1600 break;
1601
1602 case 036:
1603 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited ASCII, Slew Two Lines\n", __func__);
1604 statep->ioMode = prtPrt;
1605 statep->prtUnitNum = prt_unit_num;
1606 statep->isBCD = false;
1607 statep->isEdited = true;
1608 statep->slew = 2;
1609 p->stati = 04000;
1610 break;
1611
1612 case 037:
1613 sim_debug (DBG_DEBUG, & prt_dev, "%s: Print Edited ASCII, Slew Top Of Page\n", __func__);
1614 statep->ioMode = prtPrt;
1615 statep->prtUnitNum = prt_unit_num;
1616 statep->isBCD = false;
1617 statep->isEdited = true;
1618 statep->slew = -1;
1619 p->stati = 04000;
1620 break;
1621
1622 case 040:
1623 sim_debug (DBG_DEBUG, & prt_dev, "%s: Reset Status\n", __func__);
1624 p->stati = 04000;
1625 p->isRead = false;
1626 break;
1627
1628 case 061: {
1629 sim_debug (DBG_DEBUG, & prt_dev, "%s: Slew One Line\n", __func__);
1630 int rc = print_buf (prt_unit_num, false, false, 1, NULL, 0);
1631 if (rc == -1) {
1632 p->stati = 04201;
1633 return IOM_CMD_ERROR;
1634 }
1635 if (rc == -2) {
1636 p->stati = 04210;
1637 return IOM_CMD_ERROR;
1638 }
1639 p->stati = 04000;
1640 p->isRead = false;
1641 }
1642 break;
1643
1644 case 062: {
1645 sim_debug (DBG_DEBUG, & prt_dev, "%s: Slew Two Lines\n", __func__);
1646 int rc = print_buf (prt_unit_num, false, false, 2, NULL, 0);
1647 if (rc == -1) {
1648 p->stati = 04201;
1649 return IOM_CMD_ERROR;
1650 }
1651 if (rc == -2) {
1652 p->stati = 04210;
1653 return IOM_CMD_ERROR;
1654 }
1655 p->stati = 04000;
1656 p->isRead = false;
1657 }
1658 break;
1659
1660 case 063: {
1661 sim_debug (DBG_DEBUG, & prt_dev, "%s: Slew To Top Of Page\n", __func__);
1662 int rc = print_buf (prt_unit_num, false, false, -1, NULL, 0);
1663 if (rc == -1) {
1664 p->stati = 04201;
1665 return IOM_CMD_ERROR;
1666 }
1667 if (rc == -2) {
1668 p->stati = 04210;
1669 return IOM_CMD_ERROR;
1670 }
1671 p->stati = 04000;
1672 p->isRead = false;
1673 }
1674 break;
1675
1676 case 066:
1677 sim_debug (DBG_DEBUG, & prt_dev, "%s: Reserve Device\n", __func__);
1678 p->stati = 04000;
1679 p->isRead = false;
1680 break;
1681
1682 case 067:
1683 sim_debug (DBG_DEBUG, & prt_dev, "%s: Release Device\n", __func__);
1684 p->stati = 04000;
1685 p->isRead = false;
1686 break;
1687
1688 default:
1689 p->stati = 04501;
1690 p->chanStatus = chanStatIncorrectDCW;
1691 if (p->IDCW_DEV_CMD != 051)
1692 sim_warn ("%s: PRT unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
1693 return IOM_CMD_ERROR;
1694 }
1695
1696 sim_debug (DBG_DEBUG, & prt_dev, "%s: stati %04o\n", __func__, p->stati);
1697 return IOM_CMD_PROCEED;
1698 }
1699
1700
1701 switch (statep->ioMode) {
1702 case prtNoMode:
1703
1704
1705
1706 break;
1707
1708 case prtPrt: {
1709 iom_cmd_rc_t rc = print_cmd (iomUnitIdx, chan, statep->prtUnitNum, statep->isBCD,
1710 statep->isEdited, statep->slew);
1711 if (rc)
1712 return rc;
1713 }
1714 break;
1715
1716 case prtLdImgBuf: {
1717 int rc = loadImageBuffer (iomUnitIdx, chan);
1718 if (rc)
1719 return IOM_CMD_ERROR;
1720 }
1721 break;
1722
1723 case prtRdStatReg: {
1724 int rc = readStatusRegister (iomUnitIdx, chan);
1725 if (rc)
1726 return IOM_CMD_ERROR;
1727 }
1728 break;
1729
1730 case prtLdVFCImg: {
1731 int rc = loadVFCImage (iomUnitIdx, chan);
1732 if (rc)
1733 return IOM_CMD_ERROR;
1734 }
1735 break;
1736
1737 default:
1738 sim_warn ("%s: Unrecognized ioMode %d\n", __func__, statep->ioMode);
1739 return IOM_CMD_ERROR;
1740 }
1741 return IOM_CMD_PROCEED;
1742 }
1743
1744 iom_cmd_rc_t prt_iom_cmd (uint iomUnitIdx, uint chan) {
1745 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
1746 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
1747 uint devUnitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
1748 UNIT * unitp = & prt_unit[devUnitIdx];
1749 int prt_unit_num = (int) PRT_UNIT_NUM (unitp);
1750
1751 switch (model_type [prt_state[prt_unit_num].model]) {
1752 case 1:
1753 return prt_cmd_202 (iomUnitIdx, chan);
1754
1755 case 2:
1756 return prt_cmd_300 (iomUnitIdx, chan);
1757
1758 case 3:
1759 return prt_cmd_300a (iomUnitIdx, chan);
1760
1761
1762 case 4:
1763 return prt_cmd_400 (iomUnitIdx, chan);
1764 }
1765 p->stati = 04502;
1766 return IOM_CMD_DISCONNECT;
1767 }
1768
1769 static t_stat prt_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr, UNUSED int val,
1770 UNUSED const void * desc)
1771 {
1772 sim_printf("Number of PRT units in system is %d\n", prt_dev.numunits);
1773 return SCPE_OK;
1774 }
1775
1776 static t_stat prt_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value, const char * cptr,
1777 UNUSED void * desc)
1778 {
1779 if (! cptr)
1780 return SCPE_ARG;
1781 int n = atoi (cptr);
1782 if (n < 1 || n > N_PRT_UNITS_MAX)
1783 return SCPE_ARG;
1784 prt_dev.numunits = (uint) n;
1785 return SCPE_OK;
1786 }
1787
1788 static t_stat prt_show_device_name (UNUSED FILE * st, UNIT * uptr,
1789 UNUSED int val, UNUSED const void * desc)
1790 {
1791 int n = (int) PRT_UNIT_NUM (uptr);
1792 if (n < 0 || n >= N_PRT_UNITS_MAX)
1793 return SCPE_ARG;
1794 sim_printf("name : %s", prt_state[n].device_name);
1795 return SCPE_OK;
1796 }
1797
1798 static t_stat prt_set_device_model (UNUSED UNIT * uptr, UNUSED int32 value,
1799 const UNUSED char * cptr, UNUSED void * desc)
1800 {
1801 int n = (int) PRT_UNIT_NUM (uptr);
1802 if (n < 0 || n >= N_PRT_UNITS_MAX)
1803 return SCPE_ARG;
1804 if (cptr)
1805 {
1806 for (int i = 0; i < N_MODELS; i ++)
1807 {
1808 if (strcmp (cptr, model_names[i]) == 0)
1809 {
1810 prt_state[n].model = i;
1811 return SCPE_OK;
1812 }
1813 }
1814 sim_printf ("Model '%s' not known (202 300 301 302 303 304 401 402 901 1000 1200 1201 1600)\n", cptr);
1815 return SCPE_ARG;
1816 }
1817 sim_printf ("Specify model from 202 300 301 302 303 304 401 402 901 1000 1200 1201 1600\n");
1818 return SCPE_ARG;
1819 }
1820
1821 static t_stat prt_show_device_model (UNUSED FILE * st, UNIT * uptr,
1822 UNUSED int val, UNUSED const void * desc)
1823 {
1824 int n = (int) PRT_UNIT_NUM (uptr);
1825 if (n < 0 || n >= N_PRT_UNITS_MAX)
1826 return SCPE_ARG;
1827 sim_printf("model : %s", model_names[prt_state[n].model]);
1828 return SCPE_OK;
1829 }
1830
1831 static t_stat prt_set_device_name (UNUSED UNIT * uptr, UNUSED int32 value,
1832 const UNUSED char * cptr, UNUSED void * desc)
1833 {
1834 int n = (int) PRT_UNIT_NUM (uptr);
1835 if (n < 0 || n >= N_PRT_UNITS_MAX)
1836 return SCPE_ARG;
1837 if (cptr)
1838 {
1839 strncpy (prt_state[n].device_name, cptr, MAX_DEV_NAME_LEN - 1);
1840 prt_state[n].device_name[MAX_DEV_NAME_LEN - 1] = 0;
1841 }
1842 else
1843 {
1844 prt_state[n].device_name[0] = 0;
1845 }
1846 return SCPE_OK;
1847 }
1848
1849 static t_stat prt_show_path (UNUSED FILE * st, UNUSED UNUSED UNIT * uptr,
1850 UNUSED int val, UNUSED const void * desc)
1851 {
1852 if (prt_path[1] != '\0')
1853 {
1854 sim_printf("Path to PRT files is %s\n", prt_path);
1855 }
1856 else
1857 {
1858 char cwd_path[PATH_MAX+1];
1859 if (getcwd(cwd_path, sizeof(cwd_path)) != NULL)
1860 {
1861 sim_printf("Path to PRT files is %s\n", cwd_path);
1862 }
1863 else
1864 {
1865 if (errno)
1866 {
1867 sim_printf("Path to PRT files is unavailable (%s)\n",
1868 xstrerror_l(errno));
1869 }
1870 else
1871 {
1872 sim_printf("Path to PRT files is undefined\n");
1873 }
1874 }
1875 }
1876 return SCPE_OK;
1877 }
1878
1879 static t_stat prt_set_path (UNUSED UNIT * uptr, UNUSED int32 value,
1880 const UNUSED char * cptr, UNUSED void * desc)
1881 {
1882 if (! cptr)
1883 return SCPE_ARG;
1884
1885 size_t len = strlen(cptr);
1886
1887 if (len >= sizeof(prt_path))
1888 return SCPE_ARG;
1889 strncpy(prt_path, cptr, sizeof(prt_path));
1890 if (len > 0)
1891 {
1892 if (prt_path[len - 1] != '/')
1893 {
1894 if (len == sizeof(prt_path) - 1)
1895 return SCPE_ARG;
1896 prt_path[len++] = '/';
1897 prt_path[len] = 0;
1898 }
1899 }
1900 return SCPE_OK;
1901 }
1902
1903 t_stat burst_printer (UNUSED int32 arg, const char * buf)
1904 {
1905 for (int i = 0; i < N_PRT_UNITS_MAX; i ++)
1906 {
1907 if (strcmp (buf, prt_state[i].device_name) == 0)
1908 {
1909 if (prt_state[i].prtfile != -1)
1910 {
1911 close (prt_state[i].prtfile);
1912 prt_state[i].prtfile = -1;
1913 return SCPE_OK;
1914 }
1915 sim_printf ("burst sees nothing to burst\n");
1916 return SCPE_OK;
1917 }
1918 }
1919 sim_printf ("burst can't find printer named '%s'\n", buf);
1920 return SCPE_ARG;
1921 }
1922
1923 static t_stat signal_prt_ready (uint prt_unit_idx) {
1924
1925 if (! sim_is_running)
1926 return SCPE_OK;
1927 uint ctlr_unit_idx = cables->prt_to_urp[prt_unit_idx].ctlr_unit_idx;
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 for (uint ctlr_port_num = 0; ctlr_port_num < MAX_CTLR_PORTS; ctlr_port_num ++) {
1953 struct ctlr_to_iom_s * urp_to_iom = & cables->urp_to_iom[ctlr_unit_idx][ctlr_port_num];
1954 if (urp_to_iom->in_use) {
1955 uint iom_unit_idx = urp_to_iom->iom_unit_idx;
1956 uint chan_num = urp_to_iom->chan_num;
1957 uint dev_code = cables->prt_to_urp[prt_unit_idx].dev_code;
1958
1959 send_special_interrupt (iom_unit_idx, chan_num, dev_code, 0x40, 01 );
1960 return SCPE_OK;
1961 }
1962 }
1963 return SCPE_ARG;
1964
1965 }
1966
1967 static t_stat prt_set_ready (UNIT * uptr, UNUSED int32 value,
1968 UNUSED const char * cptr,
1969 UNUSED void * desc)
1970 {
1971 #if defined(TESTING)
1972 cpu_state_t * cpup = _cpup;
1973 #endif
1974 int n = (int) PRT_UNIT_NUM (uptr);
1975 if (n < 0 || n >= N_PRT_UNITS_MAX)
1976 {
1977 sim_debug (DBG_ERR, & prt_dev,
1978 "Printer set ready: Invalid unit number %ld\n", (long) n);
1979 sim_printf ("error: Invalid unit number %ld\n", (long) n);
1980 return SCPE_ARG;
1981 }
1982 return signal_prt_ready ((uint) n);
1983 }
1984
1985 static config_value_list_t cfg_on_off[] =
1986 {
1987 { "off", 0 },
1988 { "on", 1 },
1989 { "disable", 0 },
1990 { "enable", 1 },
1991 { NULL, 0 }
1992 };
1993
1994 static config_list_t prt_config_list[] =
1995 {
1996 { "split", 0, 1, cfg_on_off },
1997 { NULL, 0, 0, NULL }
1998 };
1999
2000 static t_stat prt_set_config (UNUSED UNIT * uptr, UNUSED int32 value,
2001 const char * cptr, UNUSED void * desc)
2002 {
2003 int devUnitIdx = (int) PRT_UNIT_NUM (uptr);
2004 prt_state_t * psp = prt_state + devUnitIdx;
2005
2006 config_state_t cfg_state = { NULL, NULL };
2007
2008 for (;;)
2009 {
2010 int64_t v;
2011 int rc = cfg_parse (__func__, cptr, prt_config_list,
2012 & cfg_state, & v);
2013 if (rc == -1)
2014 break;
2015
2016 if (rc == -2)
2017 {
2018 cfg_parse_done (& cfg_state);
2019 return SCPE_ARG;
2020 }
2021 const char * p = prt_config_list[rc].name;
2022
2023 if (strcmp (p, "split") == 0)
2024 {
2025 psp->split = v != 0;
2026 continue;
2027 }
2028
2029 sim_warn ("error: prt_set_config: Invalid cfg_parse rc <%ld>\n",
2030 (long) rc);
2031 cfg_parse_done (& cfg_state);
2032 return SCPE_ARG;
2033 }
2034 cfg_parse_done (& cfg_state);
2035 return SCPE_OK;
2036 }
2037
2038 static t_stat prt_show_config (UNUSED FILE * st, UNUSED UNIT * uptr,
2039 UNUSED int val, UNUSED const void * desc)
2040 {
2041 int devUnitIdx = (int) PRT_UNIT_NUM (uptr);
2042 prt_state_t * psp = prt_state + devUnitIdx;
2043 sim_msg ("split : %d", psp->split);
2044 return SCPE_OK;
2045 }