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) + 1);
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 + 1];
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 #if defined(__GNUC__)
778 # if !defined(__clang_version__)
779 # if __GNUC__ > 7
780 # if !defined(__INTEL_COMPILER)
781 # pragma GCC diagnostic push
782 # pragma GCC diagnostic ignored "-Wstringop-truncation"
783 # endif
784 # endif
785 # endif
786 #endif
787 strncpy (rdr_state [readerIndex].fname, fname, sizeof(rdr_state [readerIndex].fname) - 1);
788 rdr_state [readerIndex].fname [sizeof(rdr_state [readerIndex].fname) - 1] = '\0';
789 #if defined(__GNUC__)
790 # if !defined(__clang_version__)
791 # if __GNUC__ > 7
792 # if !defined(__INTEL_COMPILER)
793 # pragma GCC diagnostic pop
794 # endif
795 # endif
796 # endif
797 #endif
798 rdr_state [readerIndex].deckfd = deckfd;
799 rdr_state [readerIndex].deckState = deckStart;
800 rdr_state [readerIndex].deckFormat = fmt;
801 if (deckfd >= 0)
802 rdrCardReady (readerIndex);
803 }
804
805 static void scanForCards(uint16 readerIndex)
806 {
807 char rdr_dir [2 * PATH_MAX + 8];
808
809 if (readerIndex >= N_RDR_UNITS_MAX) {
810 sim_warn("crdrdr: scanForCards called with invalid reader index %d\n", readerIndex);
811 return;
812 }
813
814 #if !defined(__MINGW64__) || !defined(__MINGW32__)
815 const char* r_tmpdir = getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp";
816 #else
817 const char* r_tmpdir = getenv("TEMP") ? getenv("TEMP") : \
818 getenv("TMP") ? getenv("TMP") : ".";
819 #endif
820 snprintf_truncat(rdr_dir, PATH_MAX + 1, "%s/%s%c",
821 r_tmpdir, rdr_name, 'a' + readerIndex);
822
823 if (rdr_path_prefix [0])
824 {
825 snprintf_truncat(rdr_dir, PATH_MAX + 1, "%s%s%c",
826 rdr_path_prefix, rdr_name, 'a' + readerIndex);
827 }
828
829 DIR * dp;
830 dp = opendir (rdr_dir);
831 if (! dp)
832 {
833 sim_warn ("crdrdr opendir '%s' fail.\n", rdr_dir);
834 perror ("opendir");
835 return;
836 }
837 struct dirent * entry;
838 struct stat info;
839 char fqname [2 * PATH_MAX + 8];
840 while ((entry = readdir (dp)))
841 {
842 strcpy (fqname, rdr_dir);
843 strcat (fqname, "/");
844 strcat (fqname, entry -> d_name);
845
846 if (stat(fqname, &info) != 0)
847 {
848 sim_warn("crdrdr: scanForCards stat() error for %s: %s\n", fqname, xstrerror_l(errno));
849 continue;
850 }
851
852 if (S_ISDIR(info.st_mode))
853 {
854
855 continue;
856 }
857
858 if (rdr_state [readerIndex] . deckfd < 0)
859 {
860 if (strncmp (entry -> d_name, "cdeck.", 6) == 0)
861 {
862 submit (cardDeck, fqname, readerIndex);
863 break;
864 }
865 if (strncmp (entry -> d_name, "7deck.", 6) == 0)
866 {
867 submit (sevenDeck, fqname, readerIndex);
868 break;
869 }
870 if (strncmp (entry -> d_name, "sdeck.", 6) == 0)
871 {
872 submit (streamDeck, fqname, readerIndex);
873 break;
874 }
875 }
876 if (strcmp (entry -> d_name, "discard") == 0)
877 {
878
879 int rc = unlink (fqname);
880 if (rc)
881 perror ("crdrdr discard unlink\n");
882 if (rdr_state [readerIndex] . deckfd >= 0)
883 {
884 close (rdr_state [readerIndex] . deckfd);
885 rc = unlink (rdr_state [readerIndex] . fname);
886 if (rc)
887 perror ("crdrdr deck unlink\n");
888 rdr_state [readerIndex] . deckfd = -1;
889 rdr_state [readerIndex] . deckState = deckStart;
890 break;
891 }
892 }
893 }
894 closedir (dp);
895 }
896
897 void rdrProcessEvent (void)
898 {
899 if (rdr_path_prefix [0])
900 {
901
902
903 for (uint16 reader_idx = 0; reader_idx < rdr_dev . numunits; reader_idx++)
904 {
905 if (rdr_state [reader_idx] . running)
906 scanForCards(reader_idx);
907 }
908 }
909 else
910 {
911
912
913 if (! rdr_state [0] . running)
914 return;
915
916 scanForCards(0);
917 }
918 }
919
920 void rdrCardReady (int unitNum)
921 {
922 uint ctlr_unit_idx = cables->rdr_to_urp [unitNum].ctlr_unit_idx;
923 uint ctlr_port_num = 0;
924 uint iom_unit_idx = cables->urp_to_iom[ctlr_unit_idx][ctlr_port_num].iom_unit_idx;
925 uint chan_num = cables->urp_to_iom[ctlr_unit_idx][ctlr_port_num].chan_num;
926 uint dev_code = cables->rdr_to_urp[unitNum].dev_code;
927 send_special_interrupt (iom_unit_idx, chan_num, dev_code, 0377, 0377 );
928 }
929
930 iom_cmd_rc_t rdr_iom_cmd (uint iomUnitIdx, uint chan) {
931 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
932 #if defined(TESTING)
933 uint dev_code = p->IDCW_DEV_CODE;
934 cpu_state_t * cpup = _cpup;
935
936 sim_debug (DBG_TRACE, & rdr_dev, "%s: RDR %c%02o_%02o\n",
937 __func__, iomChar (iomUnitIdx), chan, dev_code);
938 #endif
939
940 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
941 uint unitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
942 struct rdr_state * statep = & rdr_state[unitIdx];
943 statep->running = true;
944
945 iom_cmd_rc_t rc = IOM_CMD_PROCEED;
946
947 if (IS_IDCW (p)) {
948
949 statep->io_mode = rdr_no_mode;
950
951 switch (p->IDCW_DEV_CMD) {
952 case 000:
953 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Request Status\n", __func__);
954 p->stati = 04000;
955
956
957
958 #if defined(TESTING)
959 sim_printf ("Request status %04o\r\n", p->stati);
960 #endif
961 break;
962
963 case 001:
964 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Read Binary\n", __func__);
965 if (rdr_state [unitIdx].deckfd < 0) {
966 p->stati = 04201;
967 p->tallyResidue = 0;
968 #if defined(TESTING)
969 if (! empty)
970 sim_printf ("hopper empty\r\n");
971 empty = true;
972 #endif
973 return IOM_CMD_DISCONNECT;
974 }
975 statep->io_mode = rdr_rd_bin;
976 p->stati = 04000;
977
978
979
980 #if defined(TESTING)
981 sim_printf ("read binary %04o\r\n", p->stati);
982 #endif
983 break;
984
985 case 040:
986 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Request Status\n", __func__);
987 p->stati = 04000;
988 p->isRead = false;
989
990
991
992 #if defined(TESTING)
993 sim_printf ("reset status %04o\r\n", p->stati);
994 #endif
995 break;
996
997 default:
998 #if defined(TESTING)
999 sim_printf ("unknown %o\r\n", p->IDCW_DEV_CMD);
1000 #endif
1001 if (p->IDCW_DEV_CMD != 051)
1002 sim_warn ("%s: RDR unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
1003 p->stati = 04501;
1004 p->chanStatus = chanStatIncorrectDCW;
1005 return IOM_CMD_ERROR;
1006 }
1007
1008 sim_debug (DBG_DEBUG, & rdr_dev, "%s: stati %04o\n", __func__, p->stati);
1009 return IOM_CMD_PROCEED;
1010 }
1011
1012
1013 switch (statep->io_mode) {
1014 case rdr_no_mode:
1015 #if defined(TESTING)
1016 sim_printf ("%s: Unexpected IOTx\r\n", __func__);
1017 #endif
1018
1019
1020 break;
1021
1022 case rdr_rd_bin: {
1023 int rc = rdrReadRecord (iomUnitIdx, chan);
1024 #if defined(TESTING)
1025 sim_printf ("rdrReadRecord returned %d\r\n", rc);
1026 #endif
1027 if (rc)
1028 return IOM_CMD_DISCONNECT;
1029 }
1030 break;
1031
1032 default:
1033 sim_warn ("%s: Unrecognized io_mode %d\n", __func__, statep->io_mode);
1034 return IOM_CMD_ERROR;
1035 }
1036 return rc;
1037 }
1038
1039 static t_stat rdr_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr, UNUSED int val,
1040 UNUSED const void * desc)
1041 {
1042 sim_printf("Number of RDR units in system is %d\n", rdr_dev . numunits);
1043 return SCPE_OK;
1044 }
1045
1046 static t_stat rdr_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value, const char * cptr,
1047 UNUSED void * desc)
1048 {
1049 if (! cptr)
1050 return SCPE_ARG;
1051 int n = atoi (cptr);
1052 if (n < 1 || n > N_RDR_UNITS_MAX)
1053 return SCPE_ARG;
1054 rdr_dev . numunits = (uint32) n;
1055 return SCPE_OK;
1056 }
1057
1058 static t_stat rdr_show_device_name (UNUSED FILE * st, UNIT * uptr,
1059 UNUSED int val, UNUSED const void * desc)
1060 {
1061 long n = RDR_UNIT_NUM (uptr);
1062 if (n < 0 || n >= N_RDR_UNITS_MAX)
1063 return SCPE_ARG;
1064 sim_printf("name : %s", rdr_state [n] . device_name);
1065 return SCPE_OK;
1066 }
1067
1068 static t_stat rdr_set_device_name (UNUSED UNIT * uptr, UNUSED int32 value,
1069 UNUSED const char * cptr, UNUSED void * desc)
1070 {
1071 long n = RDR_UNIT_NUM (uptr);
1072 if (n < 0 || n >= N_RDR_UNITS_MAX)
1073 return SCPE_ARG;
1074 if (cptr)
1075 {
1076 strncpy (rdr_state [n] . device_name, cptr, MAX_DEV_NAME_LEN - 1);
1077 rdr_state [n] . device_name [MAX_DEV_NAME_LEN - 1] = 0;
1078 }
1079 else
1080 rdr_state [n] . device_name [0] = 0;
1081 return SCPE_OK;
1082 }
1083
1084 static t_stat rdr_set_path (UNUSED UNIT * uptr, UNUSED int32 value,
1085 const UNUSED char * cptr, UNUSED void * desc)
1086 {
1087 if (! cptr)
1088 return SCPE_ARG;
1089
1090 size_t len = strlen(cptr);
1091
1092
1093
1094 if (len >= (sizeof(rdr_path_prefix) - (strlen(rdr_name) + 3)))
1095 return SCPE_ARG;
1096
1097 strncpy(rdr_path_prefix, cptr, sizeof(rdr_path_prefix) -1);
1098 rdr_path_prefix[sizeof(rdr_path_prefix) - 1] = '\0';
1099 if (len > 0)
1100 {
1101 if (rdr_path_prefix[len - 1] != '/')
1102 {
1103 if (len == sizeof(rdr_path_prefix) - 1)
1104 return SCPE_ARG;
1105 rdr_path_prefix[len++] = '/';
1106 rdr_path_prefix[len] = 0;
1107 }
1108 }
1109 return SCPE_OK;
1110 }
1111
1112 static t_stat rdr_show_path (UNUSED FILE * st, UNUSED UNIT * uptr,
1113 UNUSED int val, UNUSED const void * desc)
1114 {
1115 if (rdr_path_prefix [0])
1116 {
1117 sim_printf("\rPath to card reader directories is \"%s\".\r\n", rdr_path_prefix);
1118 }
1119 else
1120 {
1121 sim_printf("\rPath to card reader directories is unset.\r\n");
1122 }
1123 return SCPE_OK;
1124 }