First Commit of my working state
[simh.git] / S3 / s3_cd.c
CommitLineData
196ba1fc
PH
1/* s3_cd.c: IBM 1442 card reader/punch\r
2\r
3 Copyright (c) 2001-2005, Charles E. Owen\r
4\r
5 Permission is hereby granted, free of charge, to any person obtaining a\r
6 copy of this software and associated documentation files (the "Software"),\r
7 to deal in the Software without restriction, including without limitation\r
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
9 and/or sell copies of the Software, and to permit persons to whom the\r
10 Software is furnished to do so, subject to the following conditions:\r
11\r
12 The above copyright notice and this permission notice shall be included in\r
13 all copies or substantial portions of the Software.\r
14\r
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21\r
22 Except as contained in this notice, the name of Charles E. Owen shall not be\r
23 used in advertising or otherwise to promote the sale, use or other dealings\r
24 in this Software without prior written authorization from Charles E. Owen.\r
25\r
26 cdr card reader\r
27 cdp card punch\r
28 cdp2 card punch stacker 2\r
29\r
30 25-Apr-03 RMS Revised for extended file support\r
31 08-Oct-02 RMS Added impossible function catcher\r
32\r
33 Normally, cards are represented as ASCII text streams terminated by newlines.\r
34 This allows cards to be created and edited as normal files. Set the EBCDIC\r
35 flag on the card unit allows cards to be read or punched in EBCDIC format,\r
36 suitable for binary data.\r
37*/\r
38\r
39#include "s3_defs.h"\r
40#include <ctype.h>\r
41\r
42extern uint8 M[];\r
43extern char ebcdic_to_ascii[256];\r
44extern char ascii_to_ebcdic[256];\r
45int32 s1sel, s2sel;\r
46char rbuf[CBUFSIZE]; /* > CDR_WIDTH */\r
47t_stat cdr_svc (UNIT *uptr);\r
48t_stat cdr_boot (int32 unitno, DEVICE *dptr);\r
49t_stat cdr_attach (UNIT *uptr, char *cptr);\r
50t_stat cd_reset (DEVICE *dptr);\r
51t_stat read_card (int32 ilnt, int32 mod);\r
52t_stat punch_card (int32 ilnt, int32 mod);\r
53\r
54int32 DAR; /* Data address register */ \r
55int32 LCR; /* Length Count Register */\r
56int32 lastcard = 0; /* Last card switch */\r
57int32 carderr = 0; /* Error switch */\r
58int32 pcherror = 0; /* Punch error */\r
59int32 notready = 0; /* Not ready error */\r
60int32 cdr_ebcdic = 0; /* EBCDIC mode on reader */\r
61int32 cdp_ebcdic = 0; /* EBCDIC mode on punch */\r
62\r
63extern int32 GetMem(int32 addr);\r
64extern int32 PutMem(int32 addr, int32 data);\r
65\r
66/* Card reader data structures\r
67\r
68 cdr_dev CDR descriptor\r
69 cdr_unit CDR unit descriptor\r
70 cdr_reg CDR register list\r
71*/\r
72\r
73UNIT cdr_unit = { UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 100 };\r
74\r
75REG cdr_reg[] = {\r
76 { FLDATA (LAST, lastcard, 0) },\r
77 { FLDATA (ERR, carderr, 0) },\r
78 { FLDATA (NOTRDY, notready, 0) },\r
79 { HRDATA (DAR, DAR, 16) },\r
80 { HRDATA (LCR, LCR, 16) },\r
81 { FLDATA (EBCDIC, cdr_ebcdic, 0) },\r
82 { FLDATA (S2, s2sel, 0) },\r
83 { DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT },\r
84 { DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT },\r
85 { BRDATA (BUF, rbuf, 8, 8, CDR_WIDTH) },\r
86 { NULL }\r
87};\r
88\r
89DEVICE cdr_dev = {\r
90 "CDR", &cdr_unit, cdr_reg, NULL,\r
91 1, 10, 31, 1, 8, 7,\r
92 NULL, NULL, &cd_reset,\r
93 &cdr_boot, &cdr_attach, NULL\r
94};\r
95\r
96/* CDP data structures\r
97\r
98 cdp_dev CDP device descriptor\r
99 cdp_unit CDP unit descriptor\r
100 cdp_reg CDP register list\r
101*/\r
102\r
103UNIT cdp_unit = { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) };\r
104\r
105REG cdp_reg[] = {\r
106 { FLDATA (ERR, pcherror, 0) },\r
107 { FLDATA (EBCDIC, cdp_ebcdic, 0) },\r
108 { FLDATA (S2, s2sel, 0) },\r
109 { FLDATA (NOTRDY, notready, 0) },\r
110 { HRDATA (DAR, DAR, 16) },\r
111 { HRDATA (LCR, LCR, 16) },\r
112 { DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT },\r
113 { NULL }\r
114};\r
115\r
116DEVICE cdp_dev = {\r
117 "CDP", &cdp_unit, cdp_reg, NULL,\r
118 1, 10, 31, 1, 8, 7,\r
119 NULL, NULL, &cd_reset,\r
120 NULL, NULL, NULL\r
121};\r
122\r
123/* Stacker data structures\r
124\r
125 stack_dev STACK device descriptor\r
126 stack_unit STACK unit descriptors\r
127 stack_reg STACK register list\r
128*/\r
129\r
130UNIT stack_unit[] = {\r
131 { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }\r
132};\r
133\r
134REG stack_reg[] = {\r
135 { DRDATA (POS0, stack_unit[0].pos, 32), PV_LEFT },\r
136 { NULL }\r
137};\r
138\r
139DEVICE stack_dev = {\r
140 "CDP2", stack_unit, stack_reg, NULL,\r
141 1, 10, 31, 1, 8, 7,\r
142 NULL, NULL, &cd_reset,\r
143 NULL, NULL, NULL\r
144};\r
145\r
146\r
147/* -------------------------------------------------------------------- */\r
148\r
149/* 1442: master routine */\r
150\r
151int32 crd (int32 op, int32 m, int32 n, int32 data)\r
152{\r
153 int32 iodata;\r
154 switch (op) {\r
155 case 0: /* SIO 1442 */\r
156 /* if (n == 1)\r
157 return STOP_IBKPT; */\r
158 switch (data) { /* Select stacker */\r
159 case 0x00:\r
160 break;\r
161 case 0x01:\r
162 s2sel = 1;\r
163 break;\r
164 default:\r
165 break;\r
166 } \r
167 switch (n) {\r
168 case 0x00: /* Feed */\r
169 iodata = SCPE_OK;\r
170 break; \r
171 case 0x01: /* Read only */\r
172 if (cdr_ebcdic)\r
173 iodata = read_card(0, 1);\r
174 else\r
175 iodata = read_card(0, 0);\r
176 break;\r
177 case 0x02: /* Punch and feed */\r
178 iodata = punch_card(0, 0);\r
179 break;\r
180 case 0x03: /* Read Col Binary */\r
181 iodata = read_card(0, 1);\r
182 break;\r
183 case 0x04: /* Punch no feed */\r
184 iodata = punch_card(0, 1);\r
185 break;\r
186 default:\r
187 return STOP_INVDEV;\r
188 }\r
189 return iodata;\r
190 case 1: /* LIO 1442 */\r
191 switch (n) {\r
192 case 0x00: /* Load LCR */\r
193 LCR = data & 0xffff;\r
194 break;\r
195 case 0x04:\r
196 DAR = data & 0xffff;\r
197 break;\r
198 default:\r
199 return STOP_INVDEV;\r
200 }\r
201 return SCPE_OK;\r
202 case 2: /* TIO 1442 */\r
203 iodata = 0;\r
204 switch (n) {\r
205 case 0x00: /* Error */\r
206 if (carderr || pcherror || notready)\r
207 iodata = 1;\r
208 if ((cdr_unit.flags & UNIT_ATT) == 0) \r
209 iodata = 1; /* attached? */\r
210 break;\r
211 case 0x02: /* Busy */\r
212 if (sim_is_active (&cdr_unit)) \r
213 iodata = 1;\r
214 break; \r
215 default:\r
216 return (STOP_INVDEV << 16);\r
217 } \r
218 return ((SCPE_OK << 16) | iodata);\r
219 case 3: /* SNS 1442 */\r
220 iodata = 0;\r
221 switch (n) {\r
222 case 0x01:\r
223 break;\r
224 case 0x02:\r
225 break;\r
226 case 0x03:\r
227 if (carderr)\r
228 iodata |= 0x80;\r
229 if (lastcard)\r
230 iodata |= 0x40;\r
231 if (pcherror)\r
232 iodata |= 0x20;\r
233 if ((cdr_unit.flags & UNIT_ATT) == 0) \r
234 iodata |= 0x08;\r
235 if (notready)\r
236 iodata |= 0x08; \r
237 break;\r
238 case 0x04:\r
239 iodata = DAR;\r
240 break; \r
241 default:\r
242 return (STOP_INVDEV << 16);\r
243 }\r
244 iodata |= ((SCPE_OK << 16) & 0xffff0000); \r
245 return (iodata);\r
246 case 4: /* APL 1442 */\r
247 iodata = 0;\r
248 switch (n) {\r
249 case 0x00: /* Error */\r
250 if (carderr || pcherror || notready)\r
251 iodata = 1;\r
252 if ((cdr_unit.flags & UNIT_ATT) == 0) \r
253 iodata = 1; /* attached? */\r
254 break;\r
255 case 0x02: /* Busy */\r
256 if (sim_is_active (&cdr_unit)) \r
257 iodata = 1;\r
258 break; \r
259 default:\r
260 return (STOP_INVDEV << 16);\r
261 } \r
262 return ((SCPE_OK << 16) | iodata);\r
263 default:\r
264 break;\r
265 } \r
266 printf (">>CRD non-existent function %d\n", op);\r
267 return SCPE_OK; \r
268}\r
269\r
270/* Card read routine\r
271 mod 0 = ASCII read\r
272 mod 1 = EBCDIC read\r
273*/\r
274\r
275t_stat read_card (int32 ilnt, int32 mod)\r
276{\r
277int32 i;\r
278t_stat r;\r
279\r
280if (sim_is_active (&cdr_unit)) { /* busy? */\r
281 sim_cancel (&cdr_unit); /* cancel */\r
282 if (r = cdr_svc (&cdr_unit)) return r; /* process */\r
283} \r
284\r
285if (((cdp_unit.flags & UNIT_ATT) != 0 ||\r
286 (stack_unit[0].flags & UNIT_ATT) != 0) && /* Punch is attached and */\r
287 (cdr_unit.flags & UNIT_ATT) == 0) { /* reader is not --- */\r
288 for (i = 0; i < 80; i++) { /* Assume blank cards in hopper */\r
289 PutMem(DAR, 0x40);\r
290 DAR++;\r
291 }\r
292 sim_activate (&cdr_unit, cdr_unit.wait); /* activate */\r
293 return SCPE_OK;\r
294}\r
295 \r
296if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */\r
297\r
298lastcard = carderr = notready = s1sel = s2sel = 0; /* default stacker */\r
299\r
300for (i = 0; i < CBUFSIZE; i++) rbuf[i] = 0x20; /* clear buffer */\r
301if (mod) {\r
302 for (i = 0; i < 80; i++) {\r
303 rbuf[i] = fgetc(cdr_unit.fileref); /* Read EBCDIC */\r
304 } \r
305} else { \r
306 fgets (rbuf, CBUFSIZE, cdr_unit.fileref); /* read Ascii */\r
307} \r
308if (feof (cdr_unit.fileref)) { /* eof? */\r
309 notready = 1;\r
310 return STOP_NOCD;\r
311} \r
312if (ferror (cdr_unit.fileref)) { /* error? */\r
313 perror ("Card reader I/O error");\r
314 clearerr (cdr_unit.fileref);\r
315 carderr = 1; \r
316 return SCPE_OK; }\r
317cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */\r
318i = getc (cdr_unit.fileref); /* see if more */\r
319if (feof (cdr_unit.fileref)) lastcard = 1; /* eof? set flag */\r
320fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET);\r
321for (i = 0; i < 80; i++) { \r
322 if (mod == 0) { /* If ASCII mode... */\r
323 if (rbuf[i] == '\n' || /* remove ASCII CR/LF */\r
324 rbuf[i] == '\r' ||\r
325 rbuf[i] == 0x00)\r
326 rbuf[i] = ' ';\r
327 rbuf[i] = ascii_to_ebcdic[rbuf[i]]; /* convert to EBCDIC */\r
328 } \r
329 PutMem(DAR, rbuf[i]); /* Copy to main memory */\r
330 DAR++;\r
331}\r
332sim_activate (&cdr_unit, cdr_unit.wait); /* activate */\r
333return SCPE_OK;\r
334}\r
335\r
336/* Card reader service. If a stacker select is active, copy to the\r
337 selected stacker. Otherwise, copy to the normal stacker. If the\r
338 unit is unattached, simply exit.\r
339*/\r
340\r
341t_stat cdr_svc (UNIT *uptr)\r
342{\r
343int32 i;\r
344\r
345if (s2sel) uptr = &stack_unit[0]; /* stacker 1? */\r
346else uptr = &stack_unit[0]; /* then default */\r
347if ((uptr -> flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */\r
348for (i = 0; i < CDR_WIDTH; i++) rbuf[i] = ebcdic_to_ascii[rbuf[i]];\r
349for (i = CDR_WIDTH - 1; (i >= 0) && (rbuf[i] == ' '); i--) rbuf[i] = 0;\r
350rbuf[CDR_WIDTH] = 0; /* null at end */\r
351fputs (rbuf, uptr -> fileref); /* write card */\r
352fputc ('\n', uptr -> fileref); /* plus new line */\r
353if (ferror (uptr -> fileref)) { /* error? */\r
354 perror ("Card stacker I/O error");\r
355 clearerr (uptr -> fileref);\r
356}\r
357uptr -> pos = ftell (uptr -> fileref); /* update position */\r
358return SCPE_OK;\r
359}\r
360\r
361/* Card punch routine\r
362\r
363 mod: not used\r
364*/\r
365\r
366t_stat punch_card (int32 ilnt, int32 mod)\r
367{\r
368int32 i, colcount;\r
369static char pbuf[CDP_WIDTH + 1]; /* + null */\r
370UNIT *uptr;\r
371\r
372if (s2sel) uptr = &stack_unit[0]; /* stack 2? */\r
373else uptr = &cdp_unit; /* normal output */\r
374if ((uptr -> flags & UNIT_ATT) == 0) { /* Attached? */\r
375 notready = 1;\r
376 return SCPE_OK; \r
377}\r
378pcherror = s1sel = notready = 0; /* clear flags */\r
379\r
380colcount = 128 - LCR;\r
381for (i = 0; i < colcount; i++) { /* Fetch data */\r
382 if (cdp_ebcdic)\r
383 pbuf[i] = GetMem(DAR) & 0xff;\r
384 else\r
385 pbuf[i] = ebcdic_to_ascii[GetMem(DAR)];\r
386 DAR++;\r
387} \r
388for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) pbuf[i] = 0;\r
389pbuf[CDP_WIDTH] = 0; /* trailing null */\r
390if (!cdp_ebcdic) {\r
391 fputs (pbuf, uptr -> fileref); /* output card */\r
392 fputc ('\n', uptr -> fileref); /* plus new line */\r
393} else {\r
394 for (i = 0; i < 80; i++) {\r
395 fputc(pbuf[i], uptr -> fileref);\r
396 } \r
397} \r
398if (ferror (uptr -> fileref)) { /* error? */\r
399 perror ("Card punch I/O error");\r
400 clearerr (uptr -> fileref);\r
401 pcherror = 1;\r
402}\r
403uptr -> pos = ftell (uptr -> fileref); /* update position */\r
404return SCPE_OK;\r
405}\r
406\r
407/* Select stack routine\r
408\r
409 Modifiers have been checked by the caller\r
410 Modifiers are 1, 2, for the respective stack\r
411*/\r
412\r
413t_stat select_stack (int32 ilnt, int32 mod)\r
414{\r
415if (mod == 1) s1sel = 1;\r
416else if (mod == 2) s2sel = 1;\r
417return SCPE_OK;\r
418}\r
419\r
420/* Card reader/punch reset */\r
421\r
422t_stat cd_reset (DEVICE *dptr)\r
423{\r
424lastcard = carderr = notready = pcherror = 0; /* clear indicators */\r
425s1sel = s2sel = 0; /* clear stacker sel */\r
426sim_cancel (&cdr_unit); /* clear reader event */\r
427return SCPE_OK;\r
428}\r
429\r
430/* Card reader attach */\r
431\r
432t_stat cdr_attach (UNIT *uptr, char *cptr)\r
433{\r
434carderr = lastcard = notready = 0; /* clear last card */\r
435return attach_unit (uptr, cptr);\r
436}\r
437\r
438/* Bootstrap routine */\r
439\r
440t_stat cdr_boot (int32 unitno, DEVICE *dptr)\r
441{\r
442cdr_ebcdic = 1;\r
443DAR = 0;\r
444LCR = 80;\r
445read_card(0, 1);\r
446return SCPE_OK;\r
447}\r