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