First Commit of my working state
[simh.git] / PDP11 / pdp11_pt.c
1 /* pdp11_pt.c: PC11 paper tape reader/punch simulator
2
3 Copyright (c) 1993-2005, Robert M Supnik
4
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:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
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.
21
22 Except as contained in this notice, the name of Robert M Supnik 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 Robert M Supnik.
25
26 ptr paper tape reader
27 ptp paper tape punch
28
29 07-Jul-05 RMS Removed extraneous externs
30 19-May-03 RMS Revised for new conditional compilation scheme
31 25-Apr-03 RMS Revised for extended file support
32 12-Sep-02 RMS Split off from pdp11_stddev.c
33 */
34
35 #if defined (VM_PDP10) /* PDP10 version */
36 #include "pdp10_defs.h"
37 #define PT_DIS DEV_DIS
38 extern int32 int_req;
39
40 #elif defined (VM_VAX) /* VAX version */
41 #include "vax_defs.h"
42 #define PT_DIS DEV_DIS
43 extern int32 int_req[IPL_HLVL];
44
45 #else /* PDP-11 version */
46 #include "pdp11_defs.h"
47 #define PT_DIS 0
48 extern int32 int_req[IPL_HLVL];
49 #endif
50
51 #define PTRCSR_IMP (CSR_ERR+CSR_BUSY+CSR_DONE+CSR_IE) /* paper tape reader */
52 #define PTRCSR_RW (CSR_IE)
53 #define PTPCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* paper tape punch */
54 #define PTPCSR_RW (CSR_IE)
55
56 int32 ptr_csr = 0; /* control/status */
57 int32 ptr_stopioe = 0; /* stop on error */
58 int32 ptp_csr = 0; /* control/status */
59 int32 ptp_stopioe = 0; /* stop on error */
60
61 DEVICE ptr_dev, ptp_dev;
62 t_stat ptr_rd (int32 *data, int32 PA, int32 access);
63 t_stat ptr_wr (int32 data, int32 PA, int32 access);
64 t_stat ptr_svc (UNIT *uptr);
65 t_stat ptr_reset (DEVICE *dptr);
66 t_stat ptr_attach (UNIT *uptr, char *ptr);
67 t_stat ptr_detach (UNIT *uptr);
68 t_stat ptp_rd (int32 *data, int32 PA, int32 access);
69 t_stat ptp_wr (int32 data, int32 PA, int32 access);
70 t_stat ptp_svc (UNIT *uptr);
71 t_stat ptp_reset (DEVICE *dptr);
72 t_stat ptp_attach (UNIT *uptr, char *ptr);
73 t_stat ptp_detach (UNIT *uptr);
74
75 /* PTR data structures
76
77 ptr_dev PTR device descriptor
78 ptr_unit PTR unit descriptor
79 ptr_reg PTR register list
80 */
81
82 DIB ptr_dib = {
83 IOBA_PTR, IOLN_PTR, &ptr_rd, &ptr_wr,
84 1, IVCL (PTR), VEC_PTR, { NULL }
85 };
86
87 UNIT ptr_unit = {
88 UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
89 SERIAL_IN_WAIT
90 };
91
92 REG ptr_reg[] = {
93 { GRDATA (BUF, ptr_unit.buf, DEV_RDX, 8, 0) },
94 { GRDATA (CSR, ptr_csr, DEV_RDX, 16, 0) },
95 { FLDATA (INT, int_req, INT_V_PTR) },
96 { FLDATA (ERR, ptr_csr, CSR_V_ERR) },
97 { FLDATA (BUSY, ptr_csr, CSR_V_BUSY) },
98 { FLDATA (DONE, ptr_csr, CSR_V_DONE) },
99 { FLDATA (IE, ptr_csr, CSR_V_IE) },
100 { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
101 { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
102 { FLDATA (STOP_IOE, ptr_stopioe, 0) },
103 { FLDATA (DEVDIS, ptr_dev.flags, DEV_V_DIS), REG_HRO },
104 { NULL }
105 };
106
107 MTAB ptr_mod[] = {
108 { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
109 NULL, &show_addr, NULL },
110 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
111 NULL, &show_vec, NULL },
112 { 0 }
113 };
114
115 DEVICE ptr_dev = {
116 "PTR", &ptr_unit, ptr_reg, ptr_mod,
117 1, 10, 31, 1, DEV_RDX, 8,
118 NULL, NULL, &ptr_reset,
119 NULL, &ptr_attach, &ptr_detach,
120 &ptr_dib, DEV_DISABLE | PT_DIS | DEV_UBUS | DEV_QBUS
121 };
122
123 /* PTP data structures
124
125 ptp_dev PTP device descriptor
126 ptp_unit PTP unit descriptor
127 ptp_reg PTP register list
128 */
129
130 DIB ptp_dib = {
131 IOBA_PTP, IOLN_PTP, &ptp_rd, &ptp_wr,
132 1, IVCL (PTP), VEC_PTP, { NULL }
133 };
134
135 UNIT ptp_unit = {
136 UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
137 };
138
139 REG ptp_reg[] = {
140 { GRDATA (BUF, ptp_unit.buf, DEV_RDX, 8, 0) },
141 { GRDATA (CSR, ptp_csr, DEV_RDX, 16, 0) },
142 { FLDATA (INT, int_req, INT_V_PTP) },
143 { FLDATA (ERR, ptp_csr, CSR_V_ERR) },
144 { FLDATA (DONE, ptp_csr, CSR_V_DONE) },
145 { FLDATA (IE, ptp_csr, CSR_V_IE) },
146 { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
147 { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
148 { FLDATA (STOP_IOE, ptp_stopioe, 0) },
149 { NULL }
150 };
151
152 MTAB ptp_mod[] = {
153 { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
154 NULL, &show_addr, NULL },
155 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
156 NULL, &show_vec, NULL },
157 { 0 }
158 };
159
160 DEVICE ptp_dev = {
161 "PTP", &ptp_unit, ptp_reg, ptp_mod,
162 1, 10, 31, 1, DEV_RDX, 8,
163 NULL, NULL, &ptp_reset,
164 NULL, &ptp_attach, &ptp_detach,
165 &ptp_dib, DEV_DISABLE | PT_DIS | DEV_UBUS | DEV_QBUS
166 };
167
168 /* Paper tape reader I/O address routines */
169
170 t_stat ptr_rd (int32 *data, int32 PA, int32 access)
171 {
172 switch ((PA >> 1) & 01) { /* decode PA<1> */
173
174 case 0: /* ptr csr */
175 *data = ptr_csr & PTRCSR_IMP;
176 return SCPE_OK;
177
178 case 1: /* ptr buf */
179 ptr_csr = ptr_csr & ~CSR_DONE;
180 CLR_INT (PTR);
181 *data = ptr_unit.buf & 0377;
182 return SCPE_OK;
183 }
184
185 return SCPE_NXM; /* can't get here */
186 }
187
188 t_stat ptr_wr (int32 data, int32 PA, int32 access)
189 {
190 switch ((PA >> 1) & 01) { /* decode PA<1> */
191
192 case 0: /* ptr csr */
193 if (PA & 1) return SCPE_OK;
194 if ((data & CSR_IE) == 0) CLR_INT (PTR);
195 else if (((ptr_csr & CSR_IE) == 0) && (ptr_csr & (CSR_ERR | CSR_DONE)))
196 SET_INT (PTR);
197 if (data & CSR_GO) {
198 ptr_csr = (ptr_csr & ~CSR_DONE) | CSR_BUSY;
199 CLR_INT (PTR);
200 if (ptr_unit.flags & UNIT_ATT) /* data to read? */
201 sim_activate (&ptr_unit, ptr_unit.wait);
202 else sim_activate (&ptr_unit, 0); /* error if not */
203 }
204 ptr_csr = (ptr_csr & ~PTRCSR_RW) | (data & PTRCSR_RW);
205 return SCPE_OK;
206
207 case 1: /* ptr buf */
208 return SCPE_OK;
209 } /* end switch PA */
210
211 return SCPE_NXM; /* can't get here */
212 }
213
214 /* Paper tape reader service */
215
216 t_stat ptr_svc (UNIT *uptr)
217 {
218 int32 temp;
219
220 ptr_csr = (ptr_csr | CSR_ERR) & ~CSR_BUSY;
221 if (ptr_csr & CSR_IE) SET_INT (PTR);
222 if ((ptr_unit.flags & UNIT_ATT) == 0)
223 return IORETURN (ptr_stopioe, SCPE_UNATT);
224 if ((temp = getc (ptr_unit.fileref)) == EOF) {
225 if (feof (ptr_unit.fileref)) {
226 if (ptr_stopioe) printf ("PTR end of file\n");
227 else return SCPE_OK;
228 }
229 else perror ("PTR I/O error");
230 clearerr (ptr_unit.fileref);
231 return SCPE_IOERR;
232 }
233 ptr_csr = (ptr_csr | CSR_DONE) & ~CSR_ERR;
234 ptr_unit.buf = temp & 0377;
235 ptr_unit.pos = ptr_unit.pos + 1;
236 return SCPE_OK;
237 }
238
239 /* Paper tape reader support routines */
240
241 t_stat ptr_reset (DEVICE *dptr)
242 {
243 ptr_unit.buf = 0;
244 ptr_csr = 0;
245 if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR;
246 CLR_INT (PTR);
247 sim_cancel (&ptr_unit);
248 return SCPE_OK;
249 }
250
251 t_stat ptr_attach (UNIT *uptr, char *cptr)
252 {
253 t_stat reason;
254
255 reason = attach_unit (uptr, cptr);
256 if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR;
257 else ptr_csr = ptr_csr & ~CSR_ERR;
258 return reason;
259 }
260
261 t_stat ptr_detach (UNIT *uptr)
262 {
263 ptr_csr = ptr_csr | CSR_ERR;
264 return detach_unit (uptr);
265 }
266
267 /* Paper tape punch I/O address routines */
268
269 t_stat ptp_rd (int32 *data, int32 PA, int32 access)
270 {
271 switch ((PA >> 1) & 01) { /* decode PA<1> */
272
273 case 0: /* ptp csr */
274 *data = ptp_csr & PTPCSR_IMP;
275 return SCPE_OK;
276
277 case 1: /* ptp buf */
278 *data = ptp_unit.buf;
279 return SCPE_OK;
280 }
281
282 return SCPE_NXM; /* can't get here */
283 }
284
285 t_stat ptp_wr (int32 data, int32 PA, int32 access)
286 {
287 switch ((PA >> 1) & 01) { /* decode PA<1> */
288
289 case 0: /* ptp csr */
290 if (PA & 1) return SCPE_OK;
291 if ((data & CSR_IE) == 0) CLR_INT (PTP);
292 else if (((ptp_csr & CSR_IE) == 0) && (ptp_csr & (CSR_ERR | CSR_DONE)))
293 SET_INT (PTP);
294 ptp_csr = (ptp_csr & ~PTPCSR_RW) | (data & PTPCSR_RW);
295 return SCPE_OK;
296
297 case 1: /* ptp buf */
298 if ((PA & 1) == 0) ptp_unit.buf = data & 0377;
299 ptp_csr = ptp_csr & ~CSR_DONE;
300 CLR_INT (PTP);
301 if (ptp_unit.flags & UNIT_ATT) /* file to write? */
302 sim_activate (&ptp_unit, ptp_unit.wait);
303 else sim_activate (&ptp_unit, 0); /* error if not */
304 return SCPE_OK;
305 } /* end switch PA */
306
307 return SCPE_NXM; /* can't get here */
308 }
309
310 /* Paper tape punch service */
311
312 t_stat ptp_svc (UNIT *uptr)
313 {
314 ptp_csr = ptp_csr | CSR_ERR | CSR_DONE;
315 if (ptp_csr & CSR_IE) SET_INT (PTP);
316 if ((ptp_unit.flags & UNIT_ATT) == 0)
317 return IORETURN (ptp_stopioe, SCPE_UNATT);
318 if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) {
319 perror ("PTP I/O error");
320 clearerr (ptp_unit.fileref);
321 return SCPE_IOERR;
322 }
323 ptp_csr = ptp_csr & ~CSR_ERR;
324 ptp_unit.pos = ptp_unit.pos + 1;
325 return SCPE_OK;
326 }
327
328 /* Paper tape punch support routines */
329
330 t_stat ptp_reset (DEVICE *dptr)
331 {
332 ptp_unit.buf = 0;
333 ptp_csr = CSR_DONE;
334 if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR;
335 CLR_INT (PTP);
336 sim_cancel (&ptp_unit); /* deactivate unit */
337 return SCPE_OK;
338 }
339
340 t_stat ptp_attach (UNIT *uptr, char *cptr)
341 {
342 t_stat reason;
343
344 reason = attach_unit (uptr, cptr);
345 if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR;
346 else ptp_csr = ptp_csr & ~CSR_ERR;
347 return reason;
348 }
349
350 t_stat ptp_detach (UNIT *uptr)
351 {
352 ptp_csr = ptp_csr | CSR_ERR;
353 return detach_unit (uptr);
354 }