First Commit of my working state
[simh.git] / PDP8 / pdp8_pt.c
1 /* pdp8_pt.c: PDP-8 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,ptp PC8E paper tape reader/punch
27
28 25-Apr-03 RMS Revised for extended file support
29 04-Oct-02 RMS Added DIBs
30 30-May-02 RMS Widened POS to 32b
31 30-Nov-01 RMS Added read only unit support
32 30-Mar-98 RMS Added RIM loader as PTR bootstrap
33 */
34
35 #include "pdp8_defs.h"
36
37 extern int32 int_req, int_enable, dev_done, stop_inst;
38
39 int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
40
41 int32 ptr (int32 IR, int32 AC);
42 int32 ptp (int32 IR, int32 AC);
43 t_stat ptr_svc (UNIT *uptr);
44 t_stat ptp_svc (UNIT *uptr);
45 t_stat ptr_reset (DEVICE *dptr);
46 t_stat ptp_reset (DEVICE *dptr);
47 t_stat ptr_boot (int32 unitno, DEVICE *dptr);
48
49 /* PTR data structures
50
51 ptr_dev PTR device descriptor
52 ptr_unit PTR unit descriptor
53 ptr_reg PTR register list
54 */
55
56 DIB ptr_dib = { DEV_PTR, 1, { &ptr } };
57
58 UNIT ptr_unit = {
59 UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
60 SERIAL_IN_WAIT
61 };
62
63 REG ptr_reg[] = {
64 { ORDATA (BUF, ptr_unit.buf, 8) },
65 { FLDATA (DONE, dev_done, INT_V_PTR) },
66 { FLDATA (ENABLE, int_enable, INT_V_PTR) },
67 { FLDATA (INT, int_req, INT_V_PTR) },
68 { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
69 { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
70 { FLDATA (STOP_IOE, ptr_stopioe, 0) },
71 { NULL }
72 };
73
74 MTAB ptr_mod[] = {
75 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
76 { 0 }
77 };
78
79 DEVICE ptr_dev = {
80 "PTR", &ptr_unit, ptr_reg, ptr_mod,
81 1, 10, 31, 1, 8, 8,
82 NULL, NULL, &ptr_reset,
83 &ptr_boot, NULL, NULL,
84 &ptr_dib, 0 };
85
86 /* PTP data structures
87
88 ptp_dev PTP device descriptor
89 ptp_unit PTP unit descriptor
90 ptp_reg PTP register list
91 */
92
93 DIB ptp_dib = { DEV_PTP, 1, { &ptp } };
94
95 UNIT ptp_unit = {
96 UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
97 };
98
99 REG ptp_reg[] = {
100 { ORDATA (BUF, ptp_unit.buf, 8) },
101 { FLDATA (DONE, dev_done, INT_V_PTP) },
102 { FLDATA (ENABLE, int_enable, INT_V_PTP) },
103 { FLDATA (INT, int_req, INT_V_PTP) },
104 { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
105 { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
106 { FLDATA (STOP_IOE, ptp_stopioe, 0) },
107 { NULL }
108 };
109
110 MTAB ptp_mod[] = {
111 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
112 { 0 }
113 };
114
115 DEVICE ptp_dev = {
116 "PTP", &ptp_unit, ptp_reg, ptp_mod,
117 1, 10, 31, 1, 8, 8,
118 NULL, NULL, &ptp_reset,
119 NULL, NULL, NULL,
120 &ptp_dib, 0
121 };
122
123 /* Paper tape reader: IOT routine */
124
125 int32 ptr (int32 IR, int32 AC)
126 {
127 switch (IR & 07) { /* decode IR<9:11> */
128
129 case 0: /* RPE */
130 int_enable = int_enable | (INT_PTR+INT_PTP); /* set enable */
131 int_req = INT_UPDATE; /* update interrupts */
132 return AC;
133
134 case 1: /* RSF */
135 return (dev_done & INT_PTR)? IOT_SKP + AC: AC;
136
137 case 6: /* RFC!RRB */
138 sim_activate (&ptr_unit, ptr_unit.wait);
139 case 2: /* RRB */
140 dev_done = dev_done & ~INT_PTR; /* clear flag */
141 int_req = int_req & ~INT_PTR; /* clear int req */
142 return (AC | ptr_unit.buf); /* or data to AC */
143
144 case 4: /* RFC */
145 sim_activate (&ptr_unit, ptr_unit.wait);
146 dev_done = dev_done & ~INT_PTR; /* clear flag */
147 int_req = int_req & ~INT_PTR; /* clear int req */
148 return AC;
149
150 default:
151 return (stop_inst << IOT_V_REASON) + AC;
152 } /* end switch */
153 }
154
155 /* Unit service */
156
157 t_stat ptr_svc (UNIT *uptr)
158 {
159 int32 temp;
160
161 if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
162 return IORETURN (ptr_stopioe, SCPE_UNATT);
163 if ((temp = getc (ptr_unit.fileref)) == EOF) {
164 if (feof (ptr_unit.fileref)) {
165 if (ptr_stopioe) printf ("PTR end of file\n");
166 else return SCPE_OK;
167 }
168 else perror ("PTR I/O error");
169 clearerr (ptr_unit.fileref);
170 return SCPE_IOERR;
171 }
172 dev_done = dev_done | INT_PTR; /* set done */
173 int_req = INT_UPDATE; /* update interrupts */
174 ptr_unit.buf = temp & 0377;
175 ptr_unit.pos = ptr_unit.pos + 1;
176 return SCPE_OK;
177 }
178
179 /* Reset routine */
180
181 t_stat ptr_reset (DEVICE *dptr)
182 {
183 ptr_unit.buf = 0;
184 dev_done = dev_done & ~INT_PTR; /* clear done, int */
185 int_req = int_req & ~INT_PTR;
186 int_enable = int_enable | INT_PTR; /* set enable */
187 sim_cancel (&ptr_unit); /* deactivate unit */
188 return SCPE_OK;
189 }
190
191 /* Paper tape punch: IOT routine */
192
193 int32 ptp (int32 IR, int32 AC)
194 {
195 switch (IR & 07) { /* decode IR<9:11> */
196
197 case 0: /* PCE */
198 int_enable = int_enable & ~(INT_PTR+INT_PTP); /* clear enables */
199 int_req = INT_UPDATE; /* update interrupts */
200 return AC;
201
202 case 1: /* PSF */
203 return (dev_done & INT_PTP)? IOT_SKP + AC: AC;
204
205 case 2: /* PCF */
206 dev_done = dev_done & ~INT_PTP; /* clear flag */
207 int_req = int_req & ~INT_PTP; /* clear int req */
208 return AC;
209
210 case 6: /* PLS */
211 dev_done = dev_done & ~INT_PTP; /* clear flag */
212 int_req = int_req & ~INT_PTP; /* clear int req */
213 case 4: /* PPC */
214 ptp_unit.buf = AC & 0377; /* load punch buf */
215 sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */
216 return AC;
217
218 default:
219 return (stop_inst << IOT_V_REASON) + AC;
220 } /* end switch */
221 }
222
223 /* Unit service */
224
225 t_stat ptp_svc (UNIT *uptr)
226 {
227 dev_done = dev_done | INT_PTP; /* set done */
228 int_req = INT_UPDATE; /* update interrupts */
229 if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */
230 return IORETURN (ptp_stopioe, SCPE_UNATT);
231 if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) {
232 perror ("PTP I/O error");
233 clearerr (ptp_unit.fileref);
234 return SCPE_IOERR;
235 }
236 ptp_unit.pos = ptp_unit.pos + 1;
237 return SCPE_OK;
238 }
239
240 /* Reset routine */
241
242 t_stat ptp_reset (DEVICE *dptr)
243 {
244 ptp_unit.buf = 0;
245 dev_done = dev_done & ~INT_PTP; /* clear done, int */
246 int_req = int_req & ~INT_PTP;
247 int_enable = int_enable | INT_PTP; /* set enable */
248 sim_cancel (&ptp_unit); /* deactivate unit */
249 return SCPE_OK;
250 }
251
252 /* Bootstrap routine */
253
254 #define BOOT_START 07756
255 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int16))
256
257 static const uint16 boot_rom[] = {
258 06014, /* 7756, RFC */
259 06011, /* 7757, LOOP, RSF */
260 05357, /* JMP .-1 */
261 06016, /* RFC RRB */
262 07106, /* CLL RTL*/
263 07006, /* RTL */
264 07510, /* SPA*/
265 05374, /* JMP 7774 */
266 07006, /* RTL */
267 06011, /* RSF */
268 05367, /* JMP .-1 */
269 06016, /* RFC RRB */
270 07420, /* SNL */
271 03776, /* DCA I 7776 */
272 03376, /* 7774, DCA 7776 */
273 05357, /* JMP 7757 */
274 00000, /* 7776, 0 */
275 05301 /* 7777, JMP 7701 */
276 };
277
278 t_stat ptr_boot (int32 unitno, DEVICE *dptr)
279 {
280 int32 i;
281 extern int32 saved_PC;
282 extern uint16 M[];
283
284 if (ptr_dib.dev != DEV_PTR) return STOP_NOTSTD; /* only std devno */
285 for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
286 saved_PC = BOOT_START;
287 return SCPE_OK;
288 }