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