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