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 };
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 #endif
471 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
472 sim_debug (DBG_NOTIFY, & rdr_dev, "Read binary\n");
473 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
474 uint unitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492 #if defined(TESTING)
493 sim_printf ("hopper not empty\r\n");
494 empty = false;
495 #endif
496 unsigned char cardImage [80] = "";
497 uint8_t rawCardImage [rawCardImageBytes + 2 ];
498 size_t l = 0;
499
500 enum deckFormat thisCard = cardDeck;
501
502 static int jobNo = 0;
503
504 switch (rdr_state [unitIdx].deckState) {
505 case deckStart: {
506 #if defined(TESTING)
507 sim_printf ("deckStart: sending ++EOF\r\n");
508 #endif
509 strcpy ((char *) cardImage, "++EOF");
510 l = strlen ((char *) cardImage);
511 thisCard = cardDeck;
512 rdr_state [unitIdx].deckState = eof1Sent;
513 jobNo ++;
514 }
515 break;
516
517 case eof1Sent: {
518 #if defined(TESTING)
519 sim_printf ("eof1Sent: sending ++UID\r\n");
520 #endif
521 (void)sprintf ((char *) cardImage, "++UID %d", jobNo);
522 l = strlen (((char *) cardImage) + 1);
523 thisCard = cardDeck;
524 rdr_state [unitIdx].deckState = uid1Sent;
525 }
526 break;
527
528 case uid1Sent: {
529 #if defined(TESTING)
530 sim_printf ("uid1Sent: sending data\r\n");
531 #endif
532 int rc = getCardLine (rdr_state [unitIdx].deckfd, cardImage);
533 if (rc) {
534 #if defined(TESTING)
535 sim_printf ("uid1Sent: getCardLine returned %d\r\n", rc);
536 #endif
537 close (rdr_state [unitIdx].deckfd);
538
539 rc = unlink (rdr_state [unitIdx].fname);
540 if (rc)
541 perror ("card reader deck unlink\n");
542 rdr_state [unitIdx].deckfd = -1;
543 rdr_state [unitIdx].deckState = deckStart;
544 p->stati = 04201;
545 return IOM_CMD_DISCONNECT;
546 }
547 #if defined(TESTING)
548 sim_printf ("uid1Sent: getCardLine returned <%s>\r\n", cardImage);
549 #endif
550 l = strlen ((char *) cardImage);
551 thisCard = cardDeck;
552 if (strncasecmp ((char *) cardImage, "++input", 7) == 0) {
553 #if defined(TESTING)
554 sim_printf ("uid1Sent: switching to inputSent <%s>\r\n", cardImage);
555 #endif
556 rdr_state [unitIdx].deckState = inputSent;
557 }
558 }
559 break;
560
561
562
563 case inputSent: {
564 #if defined(TESTING)
565 sim_printf ("inputSent: format %d\r\n", rdr_state [unitIdx].deckFormat);
566 #endif
567 switch (rdr_state [unitIdx].deckFormat) {
568 case cardDeck: {
569 #if defined(TESTING)
570 sim_printf ("inputSent: cardDeck\r\n");
571 #endif
572 int rc = getCardLine (rdr_state [unitIdx].deckfd, cardImage);
573 if (rc) {
574 strcpy ((char *) cardImage, "++EOF");
575 rdr_state [unitIdx].deckState = eof2Sent;
576 }
577 l = strlen ((char *) cardImage);
578 }
579 thisCard = cardDeck;
580 break;
581
582 case streamDeck: {
583 #if defined(TESTING)
584 sim_printf ("inputSent: streamDeck\r\n");
585 #endif
586 l = (size_t) getCardData (rdr_state [unitIdx].deckfd, (char *) cardImage);
587 if (l) {
588 thisCard = streamDeck;
589 } else {
590 strcpy ((char *) cardImage, "++EOF");
591 l = strlen ((char *) cardImage);
592 rdr_state [unitIdx].deckState = eof2Sent;
593 thisCard = cardDeck;
594 }
595 #if defined(TESTING)
596 sim_printf ("inputSent: getCardLine returned <%s>\r\n", cardImage);
597 #endif
598 }
599 break;
600
601 case sevenDeck: {
602 #if defined(TESTING)
603 sim_printf ("inputSent: 7Deck\r\n");
604 #endif
605 l = (size_t) getRawCardData (rdr_state [unitIdx].deckfd, rawCardImage);
606 if (l) {
607 thisCard = sevenDeck;
608 } else {
609 strcpy ((char *) cardImage, "++EOF");
610 l = strlen ((char *) cardImage);
611 rdr_state [unitIdx].deckState = eof2Sent;
612 thisCard = cardDeck;
613 }
614 }
615 break;
616
617 }
618 }
619 break;
620
621
622
623 case eof2Sent: {
624 # if defined(TESTING)
625 sim_printf ("eof2Sent\r\n");
626 # endif
627 (void)sprintf ((char *) cardImage, "++UID %d", jobNo);
628 l = strlen ((char *) cardImage);
629 thisCard = cardDeck;
630 rdr_state [unitIdx].deckState = deckStart;
631 close (rdr_state [unitIdx].deckfd);
632
633 int rc = unlink (rdr_state [unitIdx].fname);
634 if (rc)
635 perror ("card reader deck unlink\n");
636 rdr_state [unitIdx].deckfd = -1;
637 }
638 break;
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
672
673
674
675 #if defined(TESTING)
676 sim_printf ("\r\n");
677 sim_printf ("\r\n");
678 for (uint i = 0; i < 80; i ++) {
679 if (isprint (cardImage [i]))
680 sim_printf ("%c", cardImage [i]);
681 else
682 sim_printf ("\\%03o", cardImage [i]);
683 }
684 sim_printf ("\r\n");
685 sim_printf ("\r\n");
686 #endif
687 word36 buffer [27];
688 switch (thisCard) {
689 case sevenDeck: {
690
691
692 for (uint i = 0; i < 27; i ++)
693 buffer [i] = extr36 ((uint8 *) rawCardImage, i);
694
695
696 }
697 break;
698
699 case streamDeck:
700
701
702
703
704
705
706
707
708
709
710 case cardDeck: {
711 if (l > 80) {
712 sim_warn ("Whups. rdr l %lu > 80; truncating.\n", (unsigned long)l);
713 l = 80;
714
715 }
716
717 uint hbuf [l + 1];
718 asciiToH ((char *) cardImage, hbuf, l);
719
720
721 uint nbits = (uint) l * 12;
722
723 uint tally = (nbits + 35) / 36;
724
725 if (tally > 27) {
726 sim_warn ("Impossible rdr tally: %d > 27; truncating.\n", tally);
727 tally = 27;
728 }
729
730
731
732 (void)memset (buffer, 0, sizeof (buffer));
733 for (uint col = 0; col < l; col ++) {
734 uint wordno = col / 3;
735 uint fieldno = col % 3;
736 putbits36_12 (& buffer [wordno], fieldno * 12, (word12) hbuf [col]);
737 }
738 }
739 break;
740 }
741
742
743
744
745
746
747
748
749
750
751
752 p->stati = 04000;
753
754
755 uint tally = 27;
756
757 iom_indirect_data_service (iomUnitIdx, chan, buffer, & tally, true);
758 p->initiate = false;
759 p->stati = 04000;
760 p->tallyResidue = (word12) tally & MASK12;
761 p->charPos = 0;
762
763 return IOM_CMD_PROCEED;
764 }
765
766 static void submit (enum deckFormat fmt, char * fname, uint16 readerIndex)
767 {
768 if (readerIndex >= N_RDR_UNITS_MAX) {
769 sim_warn("crdrdr: submit called with invalid reader index %ld\n", (long) readerIndex);
770 return;
771 }
772
773 int deckfd = open (fname, O_RDONLY);
774 if (deckfd < 0)
775 perror ("card reader deck open\n");
776
777
778 #if defined(TESTING)
779 sim_printf ("submit %s\r\n", fname);
780 #endif
781 #if defined(__GNUC__)
782 # if !defined(__clang_version__)
783 # if __GNUC__ > 7
784 # if !defined(__INTEL_COMPILER)
785 # pragma GCC diagnostic push
786 # pragma GCC diagnostic ignored "-Wstringop-truncation"
787 # endif
788 # endif
789 # endif
790 #endif
791 strncpy (rdr_state [readerIndex].fname, fname, sizeof(rdr_state [readerIndex].fname) - 1);
792 rdr_state [readerIndex].fname [sizeof(rdr_state [readerIndex].fname) - 1] = '\0';
793 #if defined(__GNUC__)
794 # if !defined(__clang_version__)
795 # if __GNUC__ > 7
796 # if !defined(__INTEL_COMPILER)
797 # pragma GCC diagnostic pop
798 # endif
799 # endif
800 # endif
801 #endif
802 rdr_state [readerIndex].deckfd = deckfd;
803 rdr_state [readerIndex].deckState = deckStart;
804 rdr_state [readerIndex].deckFormat = fmt;
805 if (deckfd >= 0)
806 rdrCardReady (readerIndex);
807 }
808
809 static void scanForCards(uint16 readerIndex)
810 {
811 char rdr_dir [2 * PATH_MAX + 8];
812
813 if (readerIndex >= N_RDR_UNITS_MAX) {
814 sim_warn("crdrdr: scanForCards called with invalid reader index %d\n", readerIndex);
815 return;
816 }
817
818 #if !defined(__MINGW64__) || !defined(__MINGW32__)
819 const char* r_tmpdir = getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp";
820 #else
821 const char* r_tmpdir = getenv("TEMP") ? getenv("TEMP") : \
822 getenv("TMP") ? getenv("TMP") : ".";
823 #endif
824 snprintf_truncat(rdr_dir, PATH_MAX + 1, "%s/%s%c",
825 r_tmpdir, rdr_name, 'a' + readerIndex);
826
827 if (rdr_path_prefix [0])
828 {
829 snprintf_truncat(rdr_dir, PATH_MAX + 1, "%s%s%c",
830 rdr_path_prefix, rdr_name, 'a' + readerIndex);
831 }
832
833 DIR * dp;
834 dp = opendir (rdr_dir);
835 if (! dp)
836 {
837 sim_warn ("crdrdr opendir '%s' fail.\n", rdr_dir);
838 perror ("opendir");
839 return;
840 }
841 struct dirent * entry;
842 struct stat info;
843 char fqname [2 * PATH_MAX + 8];
844 while ((entry = readdir (dp)))
845 {
846 strcpy (fqname, rdr_dir);
847 strcat (fqname, "/");
848 strcat (fqname, entry -> d_name);
849
850 if (stat(fqname, &info) != 0)
851 {
852 sim_warn("crdrdr: scanForCards stat() error for %s: %s\n", fqname, xstrerror_l(errno));
853 continue;
854 }
855
856 if (S_ISDIR(info.st_mode))
857 {
858
859 continue;
860 }
861
862 if (rdr_state [readerIndex] . deckfd < 0)
863 {
864 if (strncmp (entry -> d_name, "cdeck.", 6) == 0)
865 {
866 submit (cardDeck, fqname, readerIndex);
867 break;
868 }
869 if (strncmp (entry -> d_name, "7deck.", 6) == 0)
870 {
871 submit (sevenDeck, fqname, readerIndex);
872 break;
873 }
874 if (strncmp (entry -> d_name, "sdeck.", 6) == 0)
875 {
876 submit (streamDeck, fqname, readerIndex);
877 break;
878 }
879 }
880 if (strcmp (entry -> d_name, "discard") == 0)
881 {
882
883 int rc = unlink (fqname);
884 if (rc)
885 perror ("crdrdr discard unlink\n");
886 if (rdr_state [readerIndex] . deckfd >= 0)
887 {
888 close (rdr_state [readerIndex] . deckfd);
889 rc = unlink (rdr_state [readerIndex] . fname);
890 if (rc)
891 perror ("crdrdr deck unlink\n");
892 rdr_state [readerIndex] . deckfd = -1;
893 rdr_state [readerIndex] . deckState = deckStart;
894 break;
895 }
896 }
897 }
898 closedir (dp);
899 }
900
901 void rdrProcessEvent (void)
902 {
903 if (rdr_path_prefix [0])
904 {
905
906
907 for (uint16 reader_idx = 0; reader_idx < rdr_dev . numunits; reader_idx++)
908 {
909 if (rdr_state [reader_idx] . running)
910 scanForCards(reader_idx);
911 }
912 }
913 else
914 {
915
916
917 if (! rdr_state [0] . running)
918 return;
919
920 scanForCards(0);
921 }
922 }
923
924 void rdrCardReady (int unitNum)
925 {
926 uint ctlr_unit_idx = cables->rdr_to_urp [unitNum].ctlr_unit_idx;
927 uint ctlr_port_num = 0;
928 uint iom_unit_idx = cables->urp_to_iom[ctlr_unit_idx][ctlr_port_num].iom_unit_idx;
929 uint chan_num = cables->urp_to_iom[ctlr_unit_idx][ctlr_port_num].chan_num;
930 uint dev_code = cables->rdr_to_urp[unitNum].dev_code;
931 send_special_interrupt (iom_unit_idx, chan_num, dev_code, 0377, 0377 );
932 }
933
934 iom_cmd_rc_t rdr_iom_cmd (uint iomUnitIdx, uint chan) {
935 iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
936 #if defined(TESTING)
937 uint dev_code = p->IDCW_DEV_CODE;
938 cpu_state_t * cpup = _cpup;
939
940 sim_debug (DBG_TRACE, & rdr_dev, "%s: RDR %c%02o_%02o\n",
941 __func__, iomChar (iomUnitIdx), chan, dev_code);
942 #endif
943
944 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
945 uint unitIdx = cables->urp_to_urd[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
946 struct rdr_state * statep = & rdr_state[unitIdx];
947 statep->running = true;
948
949 iom_cmd_rc_t rc = IOM_CMD_PROCEED;
950
951 if (IS_IDCW (p)) {
952
953 statep->io_mode = rdr_no_mode;
954
955 switch (p->IDCW_DEV_CMD) {
956 case 000:
957 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Request Status\n", __func__);
958 p->stati = 04000;
959
960
961
962 #if defined(TESTING)
963 sim_printf ("Request status %04o\r\n", p->stati);
964 #endif
965 break;
966
967 case 001:
968 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Read Binary\n", __func__);
969 if (rdr_state [unitIdx].deckfd < 0) {
970 p->stati = 04201;
971 p->tallyResidue = 0;
972 #if defined(TESTING)
973 if (! empty)
974 sim_printf ("hopper empty\r\n");
975 empty = true;
976 #endif
977 return IOM_CMD_DISCONNECT;
978 }
979 statep->io_mode = rdr_rd_bin;
980 p->stati = 04000;
981
982
983
984 #if defined(TESTING)
985 sim_printf ("read binary %04o\r\n", p->stati);
986 #endif
987 break;
988
989 case 040:
990 sim_debug (DBG_DEBUG, & rdr_dev, "%s: Request Status\n", __func__);
991 p->stati = 04000;
992 p->isRead = false;
993
994
995
996 #if defined(TESTING)
997 sim_printf ("reset status %04o\r\n", p->stati);
998 #endif
999 break;
1000
1001 default:
1002 #if defined(TESTING)
1003 sim_printf ("unknown %o\r\n", p->IDCW_DEV_CMD);
1004 #endif
1005 if (p->IDCW_DEV_CMD != 051)
1006 sim_warn ("%s: RDR unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
1007 p->stati = 04501;
1008 p->chanStatus = chanStatIncorrectDCW;
1009 return IOM_CMD_ERROR;
1010 }
1011
1012 sim_debug (DBG_DEBUG, & rdr_dev, "%s: stati %04o\n", __func__, p->stati);
1013 return IOM_CMD_PROCEED;
1014 }
1015
1016
1017 switch (statep->io_mode) {
1018 case rdr_no_mode:
1019 #if defined(TESTING)
1020 sim_printf ("%s: Unexpected IOTx\r\n", __func__);
1021 #endif
1022
1023
1024 break;
1025
1026 case rdr_rd_bin: {
1027 int rc = rdrReadRecord (iomUnitIdx, chan);
1028 #if defined(TESTING)
1029 sim_printf ("rdrReadRecord returned %d\r\n", rc);
1030 #endif
1031 if (rc)
1032 return IOM_CMD_DISCONNECT;
1033 }
1034 break;
1035
1036 default:
1037 sim_warn ("%s: Unrecognized io_mode %d\n", __func__, statep->io_mode);
1038 return IOM_CMD_ERROR;
1039 }
1040 return rc;
1041 }
1042
1043 static t_stat rdr_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr, UNUSED int val,
1044 UNUSED const void * desc)
1045 {
1046 sim_printf("Number of RDR units in system is %d\n", rdr_dev . numunits);
1047 return SCPE_OK;
1048 }
1049
1050 static t_stat rdr_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value, const char * cptr,
1051 UNUSED void * desc)
1052 {
1053 if (! cptr)
1054 return SCPE_ARG;
1055 int n = atoi (cptr);
1056 if (n < 1 || n > N_RDR_UNITS_MAX)
1057 return SCPE_ARG;
1058 rdr_dev . numunits = (uint32) n;
1059 return SCPE_OK;
1060 }
1061
1062 static t_stat rdr_show_device_name (UNUSED FILE * st, UNIT * uptr,
1063 UNUSED int val, UNUSED const void * desc)
1064 {
1065 long n = RDR_UNIT_NUM (uptr);
1066 if (n < 0 || n >= N_RDR_UNITS_MAX)
1067 return SCPE_ARG;
1068 sim_printf("name : %s", rdr_state [n] . device_name);
1069 return SCPE_OK;
1070 }
1071
1072 static t_stat rdr_set_device_name (UNUSED UNIT * uptr, UNUSED int32 value,
1073 UNUSED const char * cptr, UNUSED void * desc)
1074 {
1075 long n = RDR_UNIT_NUM (uptr);
1076 if (n < 0 || n >= N_RDR_UNITS_MAX)
1077 return SCPE_ARG;
1078 if (cptr)
1079 {
1080 strncpy (rdr_state [n] . device_name, cptr, MAX_DEV_NAME_LEN - 1);
1081 rdr_state [n] . device_name [MAX_DEV_NAME_LEN - 1] = 0;
1082 }
1083 else
1084 rdr_state [n] . device_name [0] = 0;
1085 return SCPE_OK;
1086 }
1087
1088 static t_stat rdr_set_path (UNUSED UNIT * uptr, UNUSED int32 value,
1089 const UNUSED char * cptr, UNUSED void * desc)
1090 {
1091 if (! cptr)
1092 return SCPE_ARG;
1093
1094 size_t len = strlen(cptr);
1095
1096
1097
1098 if (len >= (sizeof(rdr_path_prefix) - (strlen(rdr_name) + 3)))
1099 return SCPE_ARG;
1100
1101 strncpy(rdr_path_prefix, cptr, sizeof(rdr_path_prefix) -1);
1102 rdr_path_prefix[sizeof(rdr_path_prefix) - 1] = '\0';
1103 if (len > 0)
1104 {
1105 if (rdr_path_prefix[len - 1] != '/')
1106 {
1107 if (len == sizeof(rdr_path_prefix) - 1)
1108 return SCPE_ARG;
1109 rdr_path_prefix[len++] = '/';
1110 rdr_path_prefix[len] = 0;
1111 }
1112 }
1113 return SCPE_OK;
1114 }
1115
1116 static t_stat rdr_show_path (UNUSED FILE * st, UNUSED UNIT * uptr,
1117 UNUSED int val, UNUSED const void * desc)
1118 {
1119 if (rdr_path_prefix [0])
1120 {
1121 sim_printf("\rPath to card reader directories is \"%s\".\r\n", rdr_path_prefix);
1122 }
1123 else
1124 {
1125 sim_printf("\rPath to card reader directories is unset.\r\n");
1126 }
1127 return SCPE_OK;
1128 }