This source file includes following definitions.
- rdr_init
- rdr_reset
- asciiToH
- getCardLine
- getCardData
- getRawCardData
- rdrReadRecord
- submit
- scanForCards
- rdrProcessEvent
- rdrCardReady
- rdr_iom_cmd
- rdr_show_nunits
- rdr_set_nunits
- rdr_show_device_name
- rdr_set_device_name
- rdr_set_path
- rdr_show_path
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <signal.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <dirent.h>
38 #include <unistd.h>
39 #include <errno.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include <stdint.h>
43
44 #include "dps8.h"
45 #include "dps8_iom.h"
46 #include "dps8_crdrdr.h"
47 #include "dps8_sys.h"
48 #include "dps8_cable.h"
49 #include "dps8_cpu.h"
50 #include "dps8_faults.h"
51 #include "dps8_scu.h"
52 #include "dps8_utils.h"
53
54 #define DBG_CTR 1
55 #define N_RDR_UNITS 1
56
57 #define snprintf_truncat(dst, size, ...) \
58 do \
59 { \
60 volatile size_t n = size; \
61 (void)snprintf (dst, n, __VA_ARGS__); \
62 } \
63 while (0)
64
65 static t_stat rdr_reset (DEVICE * dptr);
66 static t_stat rdr_show_nunits (FILE *st, UNIT *uptr, int val, const void *desc);
67 static t_stat rdr_set_nunits (UNIT * uptr, int32 value, const char * cptr, void * desc);
68 static t_stat rdr_show_device_name (FILE *st, UNIT *uptr, int val, const void *desc);
69 static t_stat rdr_set_device_name (UNIT * uptr, int32 value, const char * cptr, void * desc);
70 static t_stat rdr_show_path (UNUSED FILE * st, UNIT * uptr, UNUSED int val,
71 UNUSED const void * desc);
72 static t_stat rdr_set_path (UNUSED UNIT * uptr, UNUSED int32 value, const UNUSED char * cptr,
73 UNUSED void * desc);
74
75 #define UNIT_FLAGS ( UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | \
76 UNIT_IDLE )
77 UNIT rdr_unit [N_RDR_UNITS_MAX] =
78 {
79 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
80 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
81 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
82 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
83 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
84 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
85 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
86 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
87 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
88 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
89 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
90 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
91 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
92 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
93 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL},
94 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL}
95 };
96
97 #define RDR_UNIT_NUM(uptr) ((uptr) - rdr_unit)
98
99 static DEBTAB rdr_dt [] =
100 {
101 { "NOTIFY", DBG_NOTIFY, NULL },
102 { "INFO", DBG_INFO, NULL },
103 { "ERR", DBG_ERR, NULL },
104 { "WARN", DBG_WARN, NULL },
105 { "DEBUG", DBG_DEBUG, NULL },
106 { "ALL", DBG_ALL, NULL },
107 { NULL, 0, NULL }
108 };
109
110 #define UNIT_WATCH UNIT_V_UF
111
112 static MTAB rdr_mod [] =
113 {
114 #if !defined(SPEED)
115 { UNIT_WATCH, 1, "WATCH", "WATCH", 0, 0, NULL, NULL },
116 { UNIT_WATCH, 0, "NOWATCH", "NOWATCH", 0, 0, NULL, NULL },
117 #endif
118 {
119 MTAB_XTD | MTAB_VDV | \
120 MTAB_NMO | MTAB_VALR,
121 0,
122 "NUNITS",
123 "NUNITS",
124 rdr_set_nunits,
125 rdr_show_nunits,
126 "Number of RDR units in the system",
127 NULL
128 },
129 {
130 MTAB_XTD | MTAB_VUN | \
131 MTAB_VALR | MTAB_NC,
132 0,
133 "NAME",
134 "NAME",
135 rdr_set_device_name,
136 rdr_show_device_name,
137 "Select the boot drive",
138 NULL
139 },
140 {
141 MTAB_XTD | MTAB_VDV | MTAB_NMO | \
142 MTAB_VALR | MTAB_NC,
143 0,
144 "PATH",
145 "PATH",
146 rdr_set_path,
147 rdr_show_path,
148 "Path to card reader directories",
149 NULL
150 },
151
152 { 0, 0, NULL, NULL, 0, 0, NULL, NULL }
153 };
154
155 DEVICE rdr_dev = {
156 "RDR",
157 rdr_unit,
158 NULL,
159 rdr_mod,
160 N_RDR_UNITS,
161 10,
162 24,
163 1,
164 8,
165 36,
166 NULL,
167 NULL,
168 rdr_reset,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 DEV_DEBUG,
174 0,
175 rdr_dt,
176 NULL,
177 NULL,
178 NULL,
179 NULL,
180 NULL,
181 NULL,
182 NULL
183 };
184
185 enum deckFormat { sevenDeck, cardDeck, streamDeck };
186
187
188
189
190
191 static struct rdr_state
192 {
193 enum rdr_mode
194 {
195 rdr_no_mode, rdr_rd_bin
196 } io_mode;
197 int deckfd;
198
199
200 enum { deckStart = 0, eof1Sent, uid1Sent, inputSent, eof2Sent} deckState;
201 enum deckFormat deckFormat;
202 bool running;
203 char device_name [MAX_DEV_NAME_LEN];
204 char fname [PATH_MAX+1];
205 } rdr_state [N_RDR_UNITS_MAX];
206
207 static char* rdr_name = "rdr";
208 static char rdr_path_prefix[PATH_MAX+1];
209
210
211
212
213
214
215
216 void rdr_init (void)
217 {
218 (void)memset (rdr_path_prefix, 0, sizeof (rdr_path_prefix));
219 (void)memset (rdr_state, 0, sizeof (rdr_state));
220 for (uint i = 0; i < N_RDR_UNITS_MAX; i ++)
221 rdr_state [i] . deckfd = -1;
222 }
223
224 static t_stat rdr_reset (UNUSED DEVICE * dptr)
225 {
226
227
228
229
230
231
232
233 return SCPE_OK;
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358 static uint16 table [128] =
359 {
360 05403, 04401, 04201, 04101, 00005, 01023, 01013, 01007,
361 02011, 04021, 02021, 04103, 04043, 04023, 04013, 04007,
362 06403, 02401, 02201, 02101, 00043, 00023, 00201, 01011,
363 02003, 02403, 00007, 01005, 02043, 02023, 02013, 02007,
364 00000, 02202, 00006, 00102, 02102, 01042, 04000, 00022,
365 04022, 02022, 02042, 04012, 01102, 02000, 04102, 01400,
366 01000, 00400, 00200, 00100, 00040, 00020, 00010, 00004,
367 00002, 00001, 00202, 02012, 04042, 00012, 01012, 01006,
368 00042, 04400, 04200, 04100, 04040, 04020, 04010, 04004,
369 04002, 04001, 02400, 02200, 02100, 02040, 02020, 02010,
370 02004, 02002, 02001, 01200, 01100, 01040, 01020, 01010,
371 01004, 01002, 01001, 05022, 04202, 06022, 02006, 01022,
372 00402, 05400, 05200, 05100, 05040, 05020, 05010, 05004,
373 05002, 05001, 06400, 06200, 06100, 06040, 06020, 06010,
374 06004, 06002, 06001, 03200, 03100, 03040, 03020, 03010,
375 03004, 03002, 03001, 05000, 04006, 03000, 03400, 00000
376 };
377
378 static void asciiToH (char * str, uint * hstr, size_t l)
379 {
380 char * p = str;
381 for (size_t i = 0; i < l; i ++)
382
383 {
384 * hstr ++ = table [(* p) & 0177];
385 p ++;
386 }
387 }
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 static int getCardLine (int fd, unsigned char * buffer)
418 {
419 uint n = 0;
420 buffer [n] = 0;
421 while (1)
422 {
423 uint8 ch;
424 ssize_t rc = read (fd, & ch, 1);
425 if (rc <= 0)
426 return n == 0;
427 if (ch == '\n')
428 return 0;
429 buffer [n ++] = ch;
430 buffer [n] = 0;
431 if (n > 79)
432 return 0;
433 }
434 #if defined(SUNLINT) || !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
435
436 return 0;
437 #endif
438 }
439
440 static int getCardData (int fd, char * buffer)
441 {
442 (void)memset (buffer, 0, 80);
443 ssize_t rc = read (fd, buffer, 80);
444 if (rc < 0)
445 return 0;
446 return (int) rc;
447 }
448
449 #define rawCardImageBytes (80 * 12 / 8)
450 static int getRawCardData (int fd, uint8_t * buffer)
451 {
452 (void)memset (buffer, 0, rawCardImageBytes + 2);
453 ssize_t rc = read (fd, buffer, rawCardImageBytes);
454 if (rc < 0)
455 return 0;
456 return (int) rc;
457 }
458
459 #if defined(TESTING)
460 static bool empty = false;
461 #endif
462
463 static int rdrReadRecord (uint iomUnitIdx, uint chan) {
464 #if defined(TESTING)
465 cpu_state_t * cpup = _cpup;
466 #endif
467 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
468 sim_debug (DBG_NOTIFY, & rdr_dev, "Read binary\n");
469 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
470 uint unitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488 #if defined(TESTING)
489 sim_printf ("hopper not empty\r\n");
490 empty = false;
491 #endif
492 unsigned char cardImage [80] = "";
493 uint8_t rawCardImage [rawCardImageBytes + 2 ];
494 size_t l = 0;
495
496 enum deckFormat thisCard = cardDeck;
497
498 static int jobNo = 0;
499
500 switch (rdr_state [unitIdx].deckState) {
501 case deckStart: {
502 #if defined(TESTING)
503 sim_printf ("deckStart: sending ++EOF\r\n");
504 #endif
505 strcpy ((char *) cardImage, "++EOF");
506 l = strlen ((char *) cardImage);
507 thisCard = cardDeck;
508 rdr_state [unitIdx].deckState = eof1Sent;
509 jobNo ++;
510 }
511 break;
512
513 case eof1Sent: {
514 #if defined(TESTING)
515 sim_printf ("eof1Sent: sending ++UID\r\n");
516 #endif
517 (void)sprintf ((char *) cardImage, "++UID %d", jobNo);
518 l = strlen ((char *) cardImage);
519 thisCard = cardDeck;
520 rdr_state [unitIdx].deckState = uid1Sent;
521 }
522 break;
523
524 case uid1Sent: {
525 #if defined(TESTING)
526 sim_printf ("uid1Sent: sending data\r\n");
527 #endif
528 int rc = getCardLine (rdr_state [unitIdx].deckfd, cardImage);
529 if (rc) {
530 #if defined(TESTING)
531 sim_printf ("uid1Sent: getCardLine returned %d\r\n", rc);
532 #endif
533 close (rdr_state [unitIdx].deckfd);
534
535 rc = unlink (rdr_state [unitIdx].fname);
536 if (rc)
537 perror ("card reader deck unlink\n");
538 rdr_state [unitIdx].deckfd = -1;
539 rdr_state [unitIdx].deckState = deckStart;
540 p->stati = 04201;
541 return IOM_CMD_DISCONNECT;
542 }
543 #if defined(TESTING)
544 sim_printf ("uid1Sent: getCardLine returned <%s>\r\n", cardImage);
545 #endif
546 l = strlen ((char *) cardImage);
547 thisCard = cardDeck;
548 if (strncasecmp ((char *) cardImage, "++input", 7) == 0) {
549 #if defined(TESTING)
550 sim_printf ("uid1Sent: switching to inputSent <%s>\r\n", cardImage);
551 #endif
552 rdr_state [unitIdx].deckState = inputSent;
553 }
554 }
555 break;
556
557
558
559 case inputSent: {
560 #if defined(TESTING)
561 sim_printf ("inputSent: format %d\r\n", rdr_state [unitIdx].deckFormat);
562 #endif
563 switch (rdr_state [unitIdx].deckFormat) {
564 case cardDeck: {
565 #if defined(TESTING)
566 sim_printf ("inputSent: cardDeck\r\n");
567 #endif
568 int rc = getCardLine (rdr_state [unitIdx].deckfd, cardImage);
569 if (rc) {
570 strcpy ((char *) cardImage, "++EOF");
571 rdr_state [unitIdx].deckState = eof2Sent;
572 }
573 l = strlen ((char *) cardImage);
574 }
575 thisCard = cardDeck;
576 break;
577
578 case streamDeck: {
579 #if defined(TESTING)
580 sim_printf ("inputSent: streamDeck\r\n");
581 #endif
582 l = (size_t) getCardData (rdr_state [unitIdx].deckfd, (char *) cardImage);
583 if (l) {
584 thisCard = streamDeck;
585 } else {
586 strcpy ((char *) cardImage, "++EOF");
587 l = strlen ((char *) cardImage);
588 rdr_state [unitIdx].deckState = eof2Sent;
589 thisCard = cardDeck;
590 }
591 #if defined(TESTING)
592 sim_printf ("inputSent: getCardLine returned <%s>\r\n", cardImage);
593 #endif
594 }
595 break;
596
597 case sevenDeck: {
598 #if defined(TESTING)
599 sim_printf ("inputSent: 7Deck\r\n");
600 #endif
601 l = (size_t) getRawCardData (rdr_state [unitIdx].deckfd, rawCardImage);
602 if (l) {
603 thisCard = sevenDeck;
604 } else {
605 strcpy ((char *) cardImage, "++EOF");
606 l = strlen ((char *) cardImage);
607 rdr_state [unitIdx].deckState = eof2Sent;
608 thisCard = cardDeck;
609 }
610 }
611 break;
612
613 }
614 }
615 break;
616
617
618
619 case eof2Sent: {
620 # if defined(TESTING)
621 sim_printf ("eof2Sent\r\n");
622 # endif
623 (void)sprintf ((char *) cardImage, "++UID %d", jobNo);
624 l = strlen ((char *) cardImage);
625 thisCard = cardDeck;
626 rdr_state [unitIdx].deckState = deckStart;
627 close (rdr_state [unitIdx].deckfd);
628
629 int rc = unlink (rdr_state [unitIdx].fname);
630 if (rc)
631 perror ("card reader deck unlink\n");
632 rdr_state [unitIdx].deckfd = -1;
633 }
634 break;
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664 }
665
666
667
668
669
670
671 #if defined(TESTING)
672 sim_printf ("\r\n");
673 sim_printf ("\r\n");
674 for (uint i = 0; i < 80; i ++) {
675 if (isprint (cardImage [i]))
676 sim_printf ("%c", cardImage [i]);
677 else
678 sim_printf ("\\%03o", cardImage [i]);
679 }
680 sim_printf ("\r\n");
681 sim_printf ("\r\n");
682 #endif
683 word36 buffer [27];
684 switch (thisCard) {
685 case sevenDeck: {
686
687
688 for (uint i = 0; i < 27; i ++)
689 buffer [i] = extr36 ((uint8 *) rawCardImage, i);
690
691
692 }
693 break;
694
695 case streamDeck:
696
697
698
699
700
701
702
703
704
705
706 case cardDeck: {
707 if (l > 80) {
708 sim_warn ("Whups. rdr l %lu > 80; truncating.\n", (unsigned long)l);
709 l = 80;
710
711 }
712
713 uint hbuf [l];
714 asciiToH ((char *) cardImage, hbuf, l);
715
716
717 uint nbits = (uint) l * 12;
718
719 uint tally = (nbits + 35) / 36;
720
721 if (tally > 27) {
722 sim_warn ("Impossible rdr tally: %d > 27; truncating.\n", tally);
723 tally = 27;
724 }
725
726
727
728 (void)memset (buffer, 0, sizeof (buffer));
729 for (uint col = 0; col < l; col ++) {
730 uint wordno = col / 3;
731 uint fieldno = col % 3;
732 putbits36_12 (& buffer [wordno], fieldno * 12, (word12) hbuf [col]);
733 }
734 }
735 break;
736 }
737
738
739
740
741
742
743
744
745
746
747
748 p->stati = 04000;
749
750
751 uint tally = 27;
752
753 iom_indirect_data_service (iomUnitIdx, chan, buffer, & tally, true);
754 p->initiate = false;
755 p->stati = 04000;
756 p->tallyResidue = (word12) tally & MASK12;
757 p->charPos = 0;
758
759 return IOM_CMD_PROCEED;
760 }
761
762 static void submit (enum deckFormat fmt, char * fname, uint16 readerIndex)
763 {
764 if (readerIndex >= N_RDR_UNITS_MAX) {
765 sim_warn("crdrdr: submit called with invalid reader index %ld\n", (long) readerIndex);
766 return;
767 }
768
769 int deckfd = open (fname, O_RDONLY);
770 if (deckfd < 0)
771 perror ("card reader deck open\n");
772
773
774 #if defined(TESTING)
775 sim_printf ("submit %s\r\n", fname);
776 #endif
777 strcpy (rdr_state [readerIndex].fname, fname);
778 rdr_state [readerIndex].deckfd = deckfd;
779 rdr_state [readerIndex].deckState = deckStart;
780 rdr_state [readerIndex].deckFormat = fmt;
781 if (deckfd >= 0)
782 rdrCardReady (readerIndex);
783 }
784
785 static void scanForCards(uint16 readerIndex)
786 {
787 char rdr_dir [2 * PATH_MAX + 8];
788
789 if (readerIndex >= N_RDR_UNITS_MAX) {
790 sim_warn("crdrdr: scanForCards called with invalid reader index %d\n", readerIndex);
791 return;
792 }
793
794 #if !defined(__MINGW64__) || !defined(__MINGW32__)
795 const char* r_tmpdir = getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp";
796 #else
797 const char* r_tmpdir = getenv("TEMP") ? getenv("TEMP") : \
798 getenv("TMP") ? getenv("TMP") : ".";
799 #endif
800 snprintf_truncat(rdr_dir, PATH_MAX + 1, "%s/%s%c",
801 r_tmpdir, rdr_name, 'a' + readerIndex);
802
803 if (rdr_path_prefix [0])
804 {
805 snprintf_truncat(rdr_dir, PATH_MAX + 1, "%s%s%c",
806 rdr_path_prefix, rdr_name, 'a' + readerIndex);
807 }
808
809 DIR * dp;
810 dp = opendir (rdr_dir);
811 if (! dp)
812 {
813 sim_warn ("crdrdr opendir '%s' fail.\n", rdr_dir);
814 perror ("opendir");
815 return;
816 }
817 struct dirent * entry;
818 struct stat info;
819 char fqname [2 * PATH_MAX + 8];
820 while ((entry = readdir (dp)))
821 {
822 strcpy (fqname, rdr_dir);
823 strcat (fqname, "/");
824 strcat (fqname, entry -> d_name);
825
826 if (stat(fqname, &info) != 0)
827 {
828 sim_warn("crdrdr: scanForCards stat() error for %s: %s\n", fqname, xstrerror_l(errno));
829 continue;
830 }
831
832 if (S_ISDIR(info.st_mode))
833 {
834
835 continue;
836 }
837
838 if (rdr_state [readerIndex] . deckfd < 0)
839 {
840 if (strncmp (entry -> d_name, "cdeck.", 6) == 0)
841 {
842 submit (cardDeck, fqname, readerIndex);
843 break;
844 }
845 if (strncmp (entry -> d_name, "7deck.", 6) == 0)
846 {
847 submit (sevenDeck, fqname, readerIndex);
848 break;
849 }
850 if (strncmp (entry -> d_name, "sdeck.", 6) == 0)
851 {
852 submit (streamDeck, fqname, readerIndex);
853 break;
854 }
855 }
856 if (strcmp (entry -> d_name, "discard") == 0)
857 {
858
859 int rc = unlink (fqname);
860 if (rc)
861 perror ("crdrdr discard unlink\n");
862 if (rdr_state [readerIndex] . deckfd >= 0)
863 {
864 close (rdr_state [readerIndex] . deckfd);
865 rc = unlink (rdr_state [readerIndex] . fname);
866 if (rc)
867 perror ("crdrdr deck unlink\n");
868 rdr_state [readerIndex] . deckfd = -1;
869 rdr_state [readerIndex] . deckState = deckStart;
870 break;
871 }
872 }
873 }
874 closedir (dp);
875 }
876
877 void rdrProcessEvent (void)
878 {
879 if (rdr_path_prefix [0])
880 {
881
882
883 for (uint16 reader_idx = 0; reader_idx < rdr_dev . numunits; reader_idx++)
884 {
885 if (rdr_state [reader_idx] . running)
886 scanForCards(reader_idx);
887 }
888 }
889 else
890 {
891
892
893 if (! rdr_state [0] . running)
894 return;
895
896 scanForCards(0);
897 }
898 }
899
900 void rdrCardReady (int unitNum)
901 {
902 uint ctlr_unit_idx = cables->rdr_to_urp [unitNum].ctlr_unit_idx;
903 uint ctlr_port_num = 0;
904 uint iom_unit_idx = cables->urp_to_iom[ctlr_unit_idx][ctlr_port_num].iom_unit_idx;
905 uint chan_num = cables->urp_to_iom[ctlr_unit_idx][ctlr_port_num].chan_num;
906 uint dev_code = cables->rdr_to_urp[unitNum].dev_code;
907 send_special_interrupt (iom_unit_idx, chan_num, dev_code, 0377, 0377 );
908 }
909
910 iom_cmd_rc_t rdr_iom_cmd (uint iomUnitIdx, uint chan) {
911 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
912 #if defined(TESTING)
913 uint dev_code = p->IDCW_DEV_CODE;
914 cpu_state_t * cpup = _cpup;
915
916 sim_debug (DBG_TRACE, & rdr_dev, "%s: RDR %c%02o_%02o\n",
917 __func__, iomChar (iomUnitIdx), chan, dev_code);
918 #endif
919
920 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
921 uint unitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
922 struct rdr_state * statep = & rdr_state[unitIdx];
923 statep->running = true;
924
925 iom_cmd_rc_t rc = IOM_CMD_PROCEED;
926
927 if (IS_IDCW (p)) {
928
929 statep->io_mode = rdr_no_mode;
930
931 switch (p->IDCW_DEV_CMD) {
932 case 000:
933 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Request Status\n", __func__);
934 p->stati = 04000;
935
936
937
938 #if defined(TESTING)
939 sim_printf ("Request status %04o\r\n", p->stati);
940 #endif
941 break;
942
943 case 001:
944 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Read Binary\n", __func__);
945 if (rdr_state [unitIdx].deckfd < 0) {
946 p->stati = 04201;
947 p->tallyResidue = 0;
948 #if defined(TESTING)
949 if (! empty)
950 sim_printf ("hopper empty\r\n");
951 empty = true;
952 #endif
953 return IOM_CMD_DISCONNECT;
954 }
955 statep->io_mode = rdr_rd_bin;
956 p->stati = 04000;
957
958
959
960 #if defined(TESTING)
961 sim_printf ("read binary %04o\r\n", p->stati);
962 #endif
963 break;
964
965 case 040:
966 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Request Status\n", __func__);
967 p->stati = 04000;
968 p->isRead = false;
969
970
971
972 #if defined(TESTING)
973 sim_printf ("reset status %04o\r\n", p->stati);
974 #endif
975 break;
976
977 default:
978 #if defined(TESTING)
979 sim_printf ("unknown %o\r\n", p->IDCW_DEV_CMD);
980 #endif
981 if (p->IDCW_DEV_CMD != 051)
982 sim_warn ("%s: RDR unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
983 p->stati = 04501;
984 p->chanStatus = chanStatIncorrectDCW;
985 return IOM_CMD_ERROR;
986 }
987
988 sim_debug (DBG_DEBUG, & rdr_dev, "%s: stati %04o\n", __func__, p->stati);
989 return IOM_CMD_PROCEED;
990 }
991
992
993 switch (statep->io_mode) {
994 case rdr_no_mode:
995 #if defined(TESTING)
996 sim_printf ("%s: Unexpected IOTx\r\n", __func__);
997 #endif
998
999
1000 break;
1001
1002 case rdr_rd_bin: {
1003 int rc = rdrReadRecord (iomUnitIdx, chan);
1004 #if defined(TESTING)
1005 sim_printf ("rdrReadRecord returned %d\r\n", rc);
1006 #endif
1007 if (rc)
1008 return IOM_CMD_DISCONNECT;
1009 }
1010 break;
1011
1012 default:
1013 sim_warn ("%s: Unrecognized io_mode %d\n", __func__, statep->io_mode);
1014 return IOM_CMD_ERROR;
1015 }
1016 return rc;
1017 }
1018
1019 static t_stat rdr_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr, UNUSED int val,
1020 UNUSED const void * desc)
1021 {
1022 sim_printf("Number of RDR units in system is %d\n", rdr_dev . numunits);
1023 return SCPE_OK;
1024 }
1025
1026 static t_stat rdr_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value, const char * cptr,
1027 UNUSED void * desc)
1028 {
1029 if (! cptr)
1030 return SCPE_ARG;
1031 int n = atoi (cptr);
1032 if (n < 1 || n > N_RDR_UNITS_MAX)
1033 return SCPE_ARG;
1034 rdr_dev . numunits = (uint32) n;
1035 return SCPE_OK;
1036 }
1037
1038 static t_stat rdr_show_device_name (UNUSED FILE * st, UNIT * uptr,
1039 UNUSED int val, UNUSED const void * desc)
1040 {
1041 long n = RDR_UNIT_NUM (uptr);
1042 if (n < 0 || n >= N_RDR_UNITS_MAX)
1043 return SCPE_ARG;
1044 sim_printf("name : %s", rdr_state [n] . device_name);
1045 return SCPE_OK;
1046 }
1047
1048 static t_stat rdr_set_device_name (UNUSED UNIT * uptr, UNUSED int32 value,
1049 UNUSED const char * cptr, UNUSED void * desc)
1050 {
1051 long n = RDR_UNIT_NUM (uptr);
1052 if (n < 0 || n >= N_RDR_UNITS_MAX)
1053 return SCPE_ARG;
1054 if (cptr)
1055 {
1056 strncpy (rdr_state [n] . device_name, cptr, MAX_DEV_NAME_LEN - 1);
1057 rdr_state [n] . device_name [MAX_DEV_NAME_LEN - 1] = 0;
1058 }
1059 else
1060 rdr_state [n] . device_name [0] = 0;
1061 return SCPE_OK;
1062 }
1063
1064 static t_stat rdr_set_path (UNUSED UNIT * uptr, UNUSED int32 value,
1065 const UNUSED char * cptr, UNUSED void * desc)
1066 {
1067 if (! cptr)
1068 return SCPE_ARG;
1069
1070 size_t len = strlen(cptr);
1071
1072
1073
1074 if (len >= (sizeof(rdr_path_prefix) - (strlen(rdr_name) + 3)))
1075 return SCPE_ARG;
1076
1077 strncpy(rdr_path_prefix, cptr, sizeof(rdr_path_prefix));
1078 if (len > 0)
1079 {
1080 if (rdr_path_prefix[len - 1] != '/')
1081 {
1082 if (len == sizeof(rdr_path_prefix) - 1)
1083 return SCPE_ARG;
1084 rdr_path_prefix[len++] = '/';
1085 rdr_path_prefix[len] = 0;
1086 }
1087 }
1088 return SCPE_OK;
1089 }
1090
1091 static t_stat rdr_show_path (UNUSED FILE * st, UNUSED UNIT * uptr,
1092 UNUSED int val, UNUSED const void * desc)
1093 {
1094 if (rdr_path_prefix [0])
1095 {
1096 sim_printf("\rPath to card reader directories is \"%s\".\r\n", rdr_path_prefix);
1097 }
1098 else
1099 {
1100 sim_printf("\rPath to card reader directories is unset.\r\n");
1101 }
1102 return SCPE_OK;
1103 }