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