5221c7751d1237acf92ff9cbc06c77725ef4fbe9
1 /* s3_cd.c: IBM 1442 card reader/punch
3 Copyright (c) 2001-2005, Charles E. Owen
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of Charles E. Owen shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Charles E. Owen.
28 cdp2 card punch stacker 2
30 25-Apr-03 RMS Revised for extended file support
31 08-Oct-02 RMS Added impossible function catcher
33 Normally, cards are represented as ASCII text streams terminated by newlines.
34 This allows cards to be created and edited as normal files. Set the EBCDIC
35 flag on the card unit allows cards to be read or punched in EBCDIC format,
36 suitable for binary data.
43 extern char ebcdic_to_ascii
[256];
44 extern char ascii_to_ebcdic
[256];
46 char rbuf
[CBUFSIZE
]; /* > CDR_WIDTH */
47 t_stat
cdr_svc (UNIT
*uptr
);
48 t_stat
cdr_boot (int32 unitno
, DEVICE
*dptr
);
49 t_stat
cdr_attach (UNIT
*uptr
, char *cptr
);
50 t_stat
cd_reset (DEVICE
*dptr
);
51 t_stat
read_card (int32 ilnt
, int32 mod
);
52 t_stat
punch_card (int32 ilnt
, int32 mod
);
54 int32 DAR
; /* Data address register */
55 int32 LCR
; /* Length Count Register */
56 int32 lastcard
= 0; /* Last card switch */
57 int32 carderr
= 0; /* Error switch */
58 int32 pcherror
= 0; /* Punch error */
59 int32 notready
= 0; /* Not ready error */
60 int32 cdr_ebcdic
= 0; /* EBCDIC mode on reader */
61 int32 cdp_ebcdic
= 0; /* EBCDIC mode on punch */
63 extern int32
GetMem(int32 addr
);
64 extern int32
PutMem(int32 addr
, int32 data
);
66 /* Card reader data structures
68 cdr_dev CDR descriptor
69 cdr_unit CDR unit descriptor
70 cdr_reg CDR register list
73 UNIT cdr_unit
= { UDATA (&cdr_svc
, UNIT_SEQ
+UNIT_ATTABLE
, 0), 100 };
76 { FLDATA (LAST
, lastcard
, 0) },
77 { FLDATA (ERR
, carderr
, 0) },
78 { FLDATA (NOTRDY
, notready
, 0) },
79 { HRDATA (DAR
, DAR
, 16) },
80 { HRDATA (LCR
, LCR
, 16) },
81 { FLDATA (EBCDIC
, cdr_ebcdic
, 0) },
82 { FLDATA (S2
, s2sel
, 0) },
83 { DRDATA (POS
, cdr_unit
.pos
, T_ADDR_W
), PV_LEFT
},
84 { DRDATA (TIME
, cdr_unit
.wait
, 24), PV_LEFT
},
85 { BRDATA (BUF
, rbuf
, 8, 8, CDR_WIDTH
) },
90 "CDR", &cdr_unit
, cdr_reg
, NULL
,
92 NULL
, NULL
, &cd_reset
,
93 &cdr_boot
, &cdr_attach
, NULL
96 /* CDP data structures
98 cdp_dev CDP device descriptor
99 cdp_unit CDP unit descriptor
100 cdp_reg CDP register list
103 UNIT cdp_unit
= { UDATA (NULL
, UNIT_SEQ
+UNIT_ATTABLE
, 0) };
106 { FLDATA (ERR
, pcherror
, 0) },
107 { FLDATA (EBCDIC
, cdp_ebcdic
, 0) },
108 { FLDATA (S2
, s2sel
, 0) },
109 { FLDATA (NOTRDY
, notready
, 0) },
110 { HRDATA (DAR
, DAR
, 16) },
111 { HRDATA (LCR
, LCR
, 16) },
112 { DRDATA (POS
, cdp_unit
.pos
, T_ADDR_W
), PV_LEFT
},
117 "CDP", &cdp_unit
, cdp_reg
, NULL
,
119 NULL
, NULL
, &cd_reset
,
123 /* Stacker data structures
125 stack_dev STACK device descriptor
126 stack_unit STACK unit descriptors
127 stack_reg STACK register list
130 UNIT stack_unit
[] = {
131 { UDATA (NULL
, UNIT_SEQ
+UNIT_ATTABLE
, 0) }
135 { DRDATA (POS0
, stack_unit
[0].pos
, 32), PV_LEFT
},
140 "CDP2", stack_unit
, stack_reg
, NULL
,
142 NULL
, NULL
, &cd_reset
,
147 /* -------------------------------------------------------------------- */
149 /* 1442: master routine */
151 int32
crd (int32 op
, int32 m
, int32 n
, int32 data
)
155 case 0: /* SIO 1442 */
157 return STOP_IBKPT; */
158 switch (data
) { /* Select stacker */
168 case 0x00: /* Feed */
171 case 0x01: /* Read only */
173 iodata
= read_card(0, 1);
175 iodata
= read_card(0, 0);
177 case 0x02: /* Punch and feed */
178 iodata
= punch_card(0, 0);
180 case 0x03: /* Read Col Binary */
181 iodata
= read_card(0, 1);
183 case 0x04: /* Punch no feed */
184 iodata
= punch_card(0, 1);
190 case 1: /* LIO 1442 */
192 case 0x00: /* Load LCR */
202 case 2: /* TIO 1442 */
205 case 0x00: /* Error */
206 if (carderr
|| pcherror
|| notready
)
208 if ((cdr_unit
.flags
& UNIT_ATT
) == 0)
209 iodata
= 1; /* attached? */
211 case 0x02: /* Busy */
212 if (sim_is_active (&cdr_unit
))
216 return (STOP_INVDEV
<< 16);
218 return ((SCPE_OK
<< 16) | iodata
);
219 case 3: /* SNS 1442 */
233 if ((cdr_unit
.flags
& UNIT_ATT
) == 0)
242 return (STOP_INVDEV
<< 16);
244 iodata
|= ((SCPE_OK
<< 16) & 0xffff0000);
246 case 4: /* APL 1442 */
249 case 0x00: /* Error */
250 if (carderr
|| pcherror
|| notready
)
252 if ((cdr_unit
.flags
& UNIT_ATT
) == 0)
253 iodata
= 1; /* attached? */
255 case 0x02: /* Busy */
256 if (sim_is_active (&cdr_unit
))
260 return (STOP_INVDEV
<< 16);
262 return ((SCPE_OK
<< 16) | iodata
);
266 printf (">>CRD non-existent function %d\n", op
);
275 t_stat
read_card (int32 ilnt
, int32 mod
)
280 if (sim_is_active (&cdr_unit
)) { /* busy? */
281 sim_cancel (&cdr_unit
); /* cancel */
282 if (r
= cdr_svc (&cdr_unit
)) return r
; /* process */
285 if (((cdp_unit
.flags
& UNIT_ATT
) != 0 ||
286 (stack_unit
[0].flags
& UNIT_ATT
) != 0) && /* Punch is attached and */
287 (cdr_unit
.flags
& UNIT_ATT
) == 0) { /* reader is not --- */
288 for (i
= 0; i
< 80; i
++) { /* Assume blank cards in hopper */
292 sim_activate (&cdr_unit
, cdr_unit
.wait
); /* activate */
296 if ((cdr_unit
.flags
& UNIT_ATT
) == 0) return SCPE_UNATT
; /* attached? */
298 lastcard
= carderr
= notready
= s1sel
= s2sel
= 0; /* default stacker */
300 for (i
= 0; i
< CBUFSIZE
; i
++) rbuf
[i
] = 0x20; /* clear buffer */
302 for (i
= 0; i
< 80; i
++) {
303 rbuf
[i
] = fgetc(cdr_unit
.fileref
); /* Read EBCDIC */
306 fgets (rbuf
, CBUFSIZE
, cdr_unit
.fileref
); /* read Ascii */
308 if (feof (cdr_unit
.fileref
)) { /* eof? */
312 if (ferror (cdr_unit
.fileref
)) { /* error? */
313 perror ("Card reader I/O error");
314 clearerr (cdr_unit
.fileref
);
317 cdr_unit
.pos
= ftell (cdr_unit
.fileref
); /* update position */
318 i
= getc (cdr_unit
.fileref
); /* see if more */
319 if (feof (cdr_unit
.fileref
)) lastcard
= 1; /* eof? set flag */
320 fseek (cdr_unit
.fileref
, cdr_unit
.pos
, SEEK_SET
);
321 for (i
= 0; i
< 80; i
++) {
322 if (mod
== 0) { /* If ASCII mode... */
323 if (rbuf
[i
] == '\n' || /* remove ASCII CR/LF */
327 rbuf
[i
] = ascii_to_ebcdic
[rbuf
[i
]]; /* convert to EBCDIC */
329 PutMem(DAR
, rbuf
[i
]); /* Copy to main memory */
332 sim_activate (&cdr_unit
, cdr_unit
.wait
); /* activate */
336 /* Card reader service. If a stacker select is active, copy to the
337 selected stacker. Otherwise, copy to the normal stacker. If the
338 unit is unattached, simply exit.
341 t_stat
cdr_svc (UNIT
*uptr
)
345 if (s2sel
) uptr
= &stack_unit
[0]; /* stacker 1? */
346 else uptr
= &stack_unit
[0]; /* then default */
347 if ((uptr
-> flags
& UNIT_ATT
) == 0) return SCPE_OK
; /* attached? */
348 for (i
= 0; i
< CDR_WIDTH
; i
++) rbuf
[i
] = ebcdic_to_ascii
[rbuf
[i
]];
349 for (i
= CDR_WIDTH
- 1; (i
>= 0) && (rbuf
[i
] == ' '); i
--) rbuf
[i
] = 0;
350 rbuf
[CDR_WIDTH
] = 0; /* null at end */
351 fputs (rbuf
, uptr
-> fileref
); /* write card */
352 fputc ('\n', uptr
-> fileref
); /* plus new line */
353 if (ferror (uptr
-> fileref
)) { /* error? */
354 perror ("Card stacker I/O error");
355 clearerr (uptr
-> fileref
);
357 uptr
-> pos
= ftell (uptr
-> fileref
); /* update position */
361 /* Card punch routine
366 t_stat
punch_card (int32 ilnt
, int32 mod
)
369 static char pbuf
[CDP_WIDTH
+ 1]; /* + null */
372 if (s2sel
) uptr
= &stack_unit
[0]; /* stack 2? */
373 else uptr
= &cdp_unit
; /* normal output */
374 if ((uptr
-> flags
& UNIT_ATT
) == 0) { /* Attached? */
378 pcherror
= s1sel
= notready
= 0; /* clear flags */
380 colcount
= 128 - LCR
;
381 for (i
= 0; i
< colcount
; i
++) { /* Fetch data */
383 pbuf
[i
] = GetMem(DAR
) & 0xff;
385 pbuf
[i
] = ebcdic_to_ascii
[GetMem(DAR
)];
388 for (i
= CDP_WIDTH
- 1; (i
>= 0) && (pbuf
[i
] == ' '); i
--) pbuf
[i
] = 0;
389 pbuf
[CDP_WIDTH
] = 0; /* trailing null */
391 fputs (pbuf
, uptr
-> fileref
); /* output card */
392 fputc ('\n', uptr
-> fileref
); /* plus new line */
394 for (i
= 0; i
< 80; i
++) {
395 fputc(pbuf
[i
], uptr
-> fileref
);
398 if (ferror (uptr
-> fileref
)) { /* error? */
399 perror ("Card punch I/O error");
400 clearerr (uptr
-> fileref
);
403 uptr
-> pos
= ftell (uptr
-> fileref
); /* update position */
407 /* Select stack routine
409 Modifiers have been checked by the caller
410 Modifiers are 1, 2, for the respective stack
413 t_stat
select_stack (int32 ilnt
, int32 mod
)
415 if (mod
== 1) s1sel
= 1;
416 else if (mod
== 2) s2sel
= 1;
420 /* Card reader/punch reset */
422 t_stat
cd_reset (DEVICE
*dptr
)
424 lastcard
= carderr
= notready
= pcherror
= 0; /* clear indicators */
425 s1sel
= s2sel
= 0; /* clear stacker sel */
426 sim_cancel (&cdr_unit
); /* clear reader event */
430 /* Card reader attach */
432 t_stat
cdr_attach (UNIT
*uptr
, char *cptr
)
434 carderr
= lastcard
= notready
= 0; /* clear last card */
435 return attach_unit (uptr
, cptr
);
438 /* Bootstrap routine */
440 t_stat
cdr_boot (int32 unitno
, DEVICE
*dptr
)