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