Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* ibm1130_ptrp.c: IBM 1130 paper tape reader/punch emulation\r |
2 | \r | |
3 | Based on the SIMH simulator package written by Robert M Supnik\r | |
4 | \r | |
5 | Brian Knittel\r | |
6 | Revision History\r | |
7 | \r | |
8 | 2004.10.22 - Written.\r | |
9 | \r | |
10 | * (C) Copyright 2004, Brian Knittel.\r | |
11 | * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN\r | |
12 | * RISK basis, there is no warranty of fitness for any purpose, and the rest of the\r | |
13 | * usual yada-yada. Please keep this notice and the copyright in any distributions\r | |
14 | * or modifications.\r | |
15 | *\r | |
16 | * This is not a supported product, but I welcome bug reports and fixes.\r | |
17 | * Mail to simh@ibm1130.org\r | |
18 | */\r | |
19 | \r | |
20 | #include "ibm1130_defs.h"\r | |
21 | \r | |
22 | /***************************************************************************************\r | |
23 | * 1134 Paper Tape Reader device PTR\r | |
24 | * 1055 Paper Tape Punch device PTP (shares DSW with PTR)\r | |
25 | ***************************************************************************************/\r | |
26 | \r | |
27 | #define PTR1134_DSW_READER_RESPONSE 0x4000\r | |
28 | #define PTR1134_DSW_PUNCH_RESPONSE 0x1000\r | |
29 | #define PTR1134_DSW_READER_BUSY 0x0800\r | |
30 | #define PTR1134_DSW_READER_NOT_READY 0x0400\r | |
31 | #define PTR1134_DSW_PUNCH_BUSY 0x0200\r | |
32 | #define PTR1134_DSW_PUNCH_NOT_READY 0x0100\r | |
33 | \r | |
34 | #define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)\r | |
35 | \r | |
36 | static t_stat ptr_svc (UNIT *uptr);\r | |
37 | static t_stat ptr_reset (DEVICE *dptr);\r | |
38 | static t_stat ptr_attach (UNIT *uptr, char *cptr);\r | |
39 | static t_stat ptr_detach (UNIT *uptr);\r | |
40 | static t_stat ptr_boot (int unitno, DEVICE *dptr);\r | |
41 | static t_stat ptp_svc (UNIT *uptr);\r | |
42 | static t_stat ptp_reset (DEVICE *dptr);\r | |
43 | static t_stat ptp_attach (UNIT *uptr, char *cptr);\r | |
44 | static t_stat ptp_detach (UNIT *uptr);\r | |
45 | \r | |
46 | static int16 ptr_dsw = 0; /* device status word */\r | |
47 | static int32 ptr_wait = 1000; /* character read wait */\r | |
48 | static uint8 ptr_char = 0; /* last character read */\r | |
49 | static int32 ptp_wait = 1000; /* character punch wait */\r | |
50 | \r | |
51 | UNIT ptr_unit[1] = {\r | |
52 | { UDATA (&ptr_svc, UNIT_ATTABLE, 0) },\r | |
53 | };\r | |
54 | \r | |
55 | REG ptr_reg[] = {\r | |
56 | { HRDATA (DSW, ptr_dsw, 16) }, /* device status word */\r | |
57 | { DRDATA (WTIME, ptr_wait, 24), PV_LEFT }, /* character read wait */\r | |
58 | { DRDATA (LASTCHAR, ptr_char, 8), PV_LEFT }, /* last character read */\r | |
59 | { NULL } };\r | |
60 | \r | |
61 | DEVICE ptr_dev = {\r | |
62 | "PTR", ptr_unit, ptr_reg, NULL,\r | |
63 | 1, 16, 16, 1, 16, 16,\r | |
64 | NULL, NULL, ptr_reset,\r | |
65 | ptr_boot, ptr_attach, ptr_detach};\r | |
66 | \r | |
67 | UNIT ptp_unit[1] = {\r | |
68 | { UDATA (&ptp_svc, UNIT_ATTABLE, 0) },\r | |
69 | };\r | |
70 | \r | |
71 | REG ptp_reg[] = {\r | |
72 | { HRDATA (DSW, ptr_dsw, 16) }, /* device status word (this is the same as the reader's!) */\r | |
73 | { DRDATA (WTIME, ptp_wait, 24), PV_LEFT }, /* character punch wait */\r | |
74 | { NULL } };\r | |
75 | \r | |
76 | DEVICE ptp_dev = {\r | |
77 | "PTP", ptp_unit, ptp_reg, NULL,\r | |
78 | 1, 16, 16, 1, 16, 16,\r | |
79 | NULL, NULL, ptp_reset,\r | |
80 | NULL, ptp_attach, ptp_detach};\r | |
81 | \r | |
82 | /* xio_1134_papertape - XIO command interpreter for the 1134 paper tape reader and 1055 paper tape punch */\r | |
83 | \r | |
84 | void xio_1134_papertape (int32 iocc_addr, int32 iocc_func, int32 iocc_mod)\r | |
85 | {\r | |
86 | char msg[80];\r | |
87 | \r | |
88 | switch (iocc_func) {\r | |
89 | case XIO_READ: /* read: return last character read */\r | |
90 | M[iocc_addr & mem_mask] = (uint16) (ptr_char << 8);\r | |
91 | break;\r | |
92 | \r | |
93 | case XIO_WRITE: /* write: initiate punch operation */\r | |
94 | if ((ptr_dsw & PTR1134_DSW_PUNCH_NOT_READY) == 0 && IS_ONLINE(ptp_unit)) {\r | |
95 | putc((M[iocc_addr & mem_mask] >> 8) & 0xFF, ptp_unit->fileref);\r | |
96 | ptp_unit->pos++;\r | |
97 | }\r | |
98 | sim_activate(ptp_unit, ptp_wait); /* schedule interrupt */\r | |
99 | SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY | PTR1134_DSW_PUNCH_BUSY);\r | |
100 | break;\r | |
101 | \r | |
102 | case XIO_SENSE_DEV: /* sense device status */\r | |
103 | ACC = ptr_dsw;\r | |
104 | if (iocc_mod & 0x01) { /* reset interrupts */\r | |
105 | CLRBIT(ptr_dsw, PTR1134_DSW_READER_RESPONSE | PTR1134_DSW_PUNCH_RESPONSE);\r | |
106 | CLRBIT(ILSW[4], ILSW_4_1134_TAPE);\r | |
107 | }\r | |
108 | break;\r | |
109 | \r | |
110 | case XIO_CONTROL: /* control: initiate character read */\r | |
111 | sim_activate(ptr_unit, ptr_wait); /* schedule interrupt */\r | |
112 | SETBIT(ptr_dsw, PTR1134_DSW_READER_BUSY | PTR1134_DSW_READER_NOT_READY);\r | |
113 | break;\r | |
114 | \r | |
115 | default:\r | |
116 | sprintf(msg, "Invalid 1134 reader/1055 punch XIO function %x", iocc_func);\r | |
117 | xio_error(msg);\r | |
118 | }\r | |
119 | }\r | |
120 | \r | |
121 | /* ptr_svc - emulated timeout - 1134 read operation complete */\r | |
122 | \r | |
123 | static t_stat ptr_svc (UNIT *uptr)\r | |
124 | {\r | |
125 | CLRBIT(ptr_dsw, PTR1134_DSW_READER_BUSY); /* clear reader busy flag */\r | |
126 | SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* assume at end of file */\r | |
127 | \r | |
128 | if (IS_ONLINE(uptr)) { /* fetch character from file */\r | |
129 | ptr_char = getc(uptr->fileref);\r | |
130 | uptr->pos++;\r | |
131 | \r | |
132 | if (! feof(uptr->fileref)) /* there's more left */\r | |
133 | CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY);\r | |
134 | }\r | |
135 | \r | |
136 | SETBIT(ptr_dsw, PTR1134_DSW_READER_RESPONSE); /* indicate read complete */\r | |
137 | \r | |
138 | SETBIT(ILSW[4], ILSW_4_1134_TAPE); /* initiate interrupt */\r | |
139 | calc_ints();\r | |
140 | \r | |
141 | return SCPE_OK;\r | |
142 | }\r | |
143 | \r | |
144 | /* ptp_svc - emulated timeout -- 1055 punch operation complete */\r | |
145 | \r | |
146 | static t_stat ptp_svc (UNIT *uptr)\r | |
147 | {\r | |
148 | CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_BUSY); /* clear punch busy flag */\r | |
149 | \r | |
150 | if (IS_ONLINE(uptr)) /* update punch ready status */\r | |
151 | CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);\r | |
152 | else\r | |
153 | SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);\r | |
154 | \r | |
155 | SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_RESPONSE); /* indicate punch complete */\r | |
156 | \r | |
157 | SETBIT(ILSW[4], ILSW_4_1134_TAPE); /* initiate interrupt */\r | |
158 | calc_ints();\r | |
159 | \r | |
160 | return SCPE_OK;\r | |
161 | }\r | |
162 | \r | |
163 | /* ptr_reset - reset emulated paper tape reader */\r | |
164 | \r | |
165 | static t_stat ptr_reset (DEVICE *dptr)\r | |
166 | {\r | |
167 | sim_cancel(ptr_unit);\r | |
168 | \r | |
169 | CLRBIT(ptr_dsw, PTR1134_DSW_READER_BUSY | PTR1134_DSW_READER_RESPONSE);\r | |
170 | SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY);\r | |
171 | \r | |
172 | if (IS_ONLINE(ptr_unit) && ! feof(ptr_unit->fileref))\r | |
173 | CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY);\r | |
174 | \r | |
175 | if ((ptr_dsw & PTR1134_DSW_PUNCH_RESPONSE) == 0) { /* punch isn't interrupting either */\r | |
176 | CLRBIT(ILSW[4], ILSW_4_1134_TAPE);\r | |
177 | calc_ints();\r | |
178 | }\r | |
179 | \r | |
180 | return SCPE_OK;\r | |
181 | }\r | |
182 | \r | |
183 | /* ptp_reset - reset emulated paper tape punch */\r | |
184 | \r | |
185 | static t_stat ptp_reset (DEVICE *dptr)\r | |
186 | {\r | |
187 | sim_cancel(ptp_unit);\r | |
188 | \r | |
189 | CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_BUSY | PTR1134_DSW_PUNCH_RESPONSE);\r | |
190 | SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);\r | |
191 | \r | |
192 | if (IS_ONLINE(ptp_unit))\r | |
193 | CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);\r | |
194 | \r | |
195 | if ((ptr_dsw & PTR1134_DSW_READER_RESPONSE) == 0) { /* reader isn't interrupting either */\r | |
196 | CLRBIT(ILSW[4], ILSW_4_1134_TAPE);\r | |
197 | calc_ints();\r | |
198 | }\r | |
199 | \r | |
200 | return SCPE_OK;\r | |
201 | }\r | |
202 | \r | |
203 | /* ptr_attach - attach file to simulated paper tape reader */\r | |
204 | \r | |
205 | static t_stat ptr_attach (UNIT *uptr, char *cptr)\r | |
206 | {\r | |
207 | t_stat rval;\r | |
208 | \r | |
209 | SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* assume failure */\r | |
210 | \r | |
211 | if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) /* use standard attach */\r | |
212 | return rval;\r | |
213 | \r | |
214 | if ((ptr_dsw & PTR1134_DSW_READER_BUSY) == 0 && ! feof(uptr->fileref))\r | |
215 | CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* we're in business */\r | |
216 | \r | |
217 | return SCPE_OK;\r | |
218 | }\r | |
219 | \r | |
220 | /* ptr_attach - detach file from simulated paper tape reader */\r | |
221 | \r | |
222 | static t_stat ptr_detach (UNIT *uptr)\r | |
223 | {\r | |
224 | SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY);\r | |
225 | \r | |
226 | return detach_unit(uptr);\r | |
227 | }\r | |
228 | \r | |
229 | /* ptr_attach - perform paper tape initial program load */\r | |
230 | \r | |
231 | static t_stat ptr_boot (int unitno, DEVICE *dptr)\r | |
232 | {\r | |
233 | int ch, nch, val, addr;\r | |
234 | t_bool leader = TRUE, start = FALSE;\r | |
235 | t_stat rval;\r | |
236 | \r | |
237 | addr = 0;\r | |
238 | nch = 0;\r | |
239 | val = 0;\r | |
240 | \r | |
241 | for (;;) {\r | |
242 | if ((ch = getc(ptr_unit->fileref)) == EOF) {\r | |
243 | printf("EOF on paper tape without finding Channel 5 end-of-load mark\n");\r | |
244 | break;\r | |
245 | }\r | |
246 | \r | |
247 | if (leader) {\r | |
248 | if ((ch & 0x7F) == 0x7F) /* ignore leading rubouts or "delete" characters */\r | |
249 | continue;\r | |
250 | \r | |
251 | leader = FALSE; /* after first nonrubout, any punch in channel 5 terminates load */\r | |
252 | }\r | |
253 | \r | |
254 | /* this is untested -- not sure of actual byte ordering */\r | |
255 | \r | |
256 | val = (val << 4) | (ch & 0x0F); /* get next nybble */\r | |
257 | \r | |
258 | if (++nch == 4) { /* if we now have four nybbles, store the word */\r | |
259 | M[addr & mem_mask] = (uint16) val;\r | |
260 | \r | |
261 | addr++; /* prepare for next word */\r | |
262 | nch = 0;\r | |
263 | val = 0;\r | |
264 | }\r | |
265 | \r | |
266 | if (ch & 0x10) { /* channel 5 punch terminates load */\r | |
267 | start = TRUE;\r | |
268 | break;\r | |
269 | }\r | |
270 | }\r | |
271 | \r | |
272 | if (! start) /* if we didn't get a valid load, report EOF error */\r | |
273 | return SCPE_EOF;\r | |
274 | \r | |
275 | if ((rval = reset_all(0)) != SCPE_OK) /* force a reset */\r | |
276 | return rval;\r | |
277 | \r | |
278 | IAR = 0; /* start running at address 0 */\r | |
279 | return SCPE_OK;\r | |
280 | }\r | |
281 | \r | |
282 | /* ptp_attach - attach file to simulated paper tape punch */\r | |
283 | \r | |
284 | static t_stat ptp_attach (UNIT *uptr, char *cptr)\r | |
285 | {\r | |
286 | t_stat rval;\r | |
287 | \r | |
288 | SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); /* assume failure */\r | |
289 | \r | |
290 | if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) /* use standard attach */\r | |
291 | return rval;\r | |
292 | \r | |
293 | fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */\r | |
294 | uptr->pos = ftell(uptr->fileref);\r | |
295 | \r | |
296 | if ((ptr_dsw & PTR1134_DSW_PUNCH_BUSY) == 0)\r | |
297 | CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); /* we're in business */\r | |
298 | \r | |
299 | return SCPE_OK;\r | |
300 | }\r | |
301 | \r | |
302 | /* ptp_detach - detach file from simulated paper tape punch */\r | |
303 | \r | |
304 | static t_stat ptp_detach (UNIT *uptr)\r | |
305 | {\r | |
306 | SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);\r | |
307 | \r | |
308 | return detach_unit(uptr);\r | |
309 | }\r |