First Commit of my working state
[simh.git] / Interdata / id_pt.c
CommitLineData
196ba1fc
PH
1/* id_pt.c: Interdata paper tape reader\r
2\r
3 Copyright (c) 2000-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 pt paper tape reader and punch\r
27\r
28 25-Apr-03 RMS Revised for extended file support\r
29 10-Apr-03 RMS Fixed type problem in ptr service (from Mark Pizzolato)\r
30*/\r
31\r
32#include "id_defs.h"\r
33#include <ctype.h>\r
34\r
35/* Device definitions */\r
36\r
37#define PTR 0 /* unit subscripts */\r
38#define PTP 1\r
39\r
40#define STA_OVR 0x80 /* overrun */\r
41#define STA_NMTN 0x10 /* no motion */\r
42#define STA_MASK (STA_BSY | STA_OVR | STA_DU) /* static bits */\r
43#define SET_EX (STA_OVR | STA_NMTN) /* set EX */\r
44\r
45#define CMD_V_RUN 4 /* run/stop */\r
46#define CMD_V_SLEW 2 /* slew/step */\r
47#define CMD_V_RD 0 /* read/write */\r
48\r
49extern uint32 int_req[INTSZ], int_enb[INTSZ];\r
50\r
51uint32 pt_run = 0, pt_slew = 0; /* ptr modes */\r
52uint32 pt_rd = 1, pt_chp = 0; /* pt state */\r
53uint32 pt_arm = 0; /* int arm */\r
54uint32 pt_sta = STA_BSY; /* status */\r
55uint32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */\r
56\r
57DEVICE pt_dev;\r
58uint32 pt (uint32 dev, uint32 op, uint32 dat);\r
59t_stat ptr_svc (UNIT *uptr);\r
60t_stat ptp_svc (UNIT *uptr);\r
61t_stat pt_boot (int32 unitno, DEVICE *dptr);\r
62t_stat pt_reset (DEVICE *dptr);\r
63\r
64/* PT data structures\r
65\r
66 pt_dev PT device descriptor\r
67 pt_unit PT unit descriptors\r
68 pt_reg PT register list\r
69*/\r
70\r
71DIB pt_dib = { d_PT, -1, v_PT, NULL, &pt, NULL };\r
72\r
73UNIT pt_unit[] = {\r
74 { UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),\r
75 SERIAL_IN_WAIT },\r
76 { UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }\r
77 };\r
78\r
79REG pt_reg[] = {\r
80 { HRDATA (STA, pt_sta, 8) },\r
81 { HRDATA (RBUF, pt_unit[PTR].buf, 8) },\r
82 { DRDATA (RPOS, pt_unit[PTR].pos, T_ADDR_W), PV_LEFT },\r
83 { DRDATA (RTIME, pt_unit[PTR].wait, 24), PV_LEFT },\r
84 { FLDATA (RSTOP_IOE, ptr_stopioe, 0) },\r
85 { HRDATA (PBUF, pt_unit[PTP].buf, 8) },\r
86 { DRDATA (PPOS, pt_unit[PTP].pos, T_ADDR_W), PV_LEFT },\r
87 { DRDATA (PTIME, pt_unit[PTP].wait, 24), PV_LEFT },\r
88 { FLDATA (PSTOP_IOE, ptp_stopioe, 0) },\r
89 { FLDATA (IREQ, int_req[l_PT], i_PT) },\r
90 { FLDATA (IENB, int_enb[l_PT], i_PT) },\r
91 { FLDATA (IARM, pt_arm, 0) },\r
92 { FLDATA (RD, pt_rd, 0) },\r
93 { FLDATA (RUN, pt_run, 0) },\r
94 { FLDATA (SLEW, pt_slew, 0) },\r
95 { FLDATA (CHP, pt_chp, 0) },\r
96 { HRDATA (DEVNO, pt_dib.dno, 8), REG_HRO },\r
97 { NULL }\r
98 };\r
99\r
100MTAB pt_mod[] = {\r
101 { MTAB_XTD|MTAB_VDV, 0, "devno", "DEVNO",\r
102 &set_dev, &show_dev, NULL },\r
103 { 0 }\r
104 };\r
105\r
106DEVICE pt_dev = {\r
107 "PT", pt_unit, pt_reg, pt_mod,\r
108 2, 10, 31, 1, 16, 8,\r
109 NULL, NULL, &pt_reset,\r
110 &pt_boot, NULL, NULL,\r
111 &pt_dib, DEV_DISABLE\r
112 };\r
113\r
114/* Paper tape: IO routine */\r
115\r
116uint32 pt (uint32 dev, uint32 op, uint32 dat)\r
117{\r
118uint32 t, old_rd, old_run;\r
119\r
120switch (op) { /* case IO op */\r
121\r
122 case IO_ADR: /* select */\r
123 return BY; /* byte only */\r
124\r
125 case IO_OC: /* command */\r
126 old_rd = pt_rd; /* save curr rw */\r
127 old_run = pt_run; /* save curr run */\r
128 pt_arm = int_chg (v_PT, dat, pt_arm); /* upd int ctrl */\r
129 pt_rd = io_2b (dat, CMD_V_RD, pt_rd); /* upd read/wr */\r
130 if (old_rd != pt_rd) { /* rw change? */\r
131 pt_sta = pt_sta & ~STA_OVR; /* clr overrun */\r
132 if (sim_is_active (&pt_unit[pt_rd? PTR: PTP])) {\r
133 pt_sta = pt_sta | STA_BSY; /* busy = 1 */\r
134 CLR_INT (v_PT); /* clear int */\r
135 }\r
136 else { /* not active */\r
137 pt_sta = pt_sta & ~STA_BSY; /* busy = 0 */\r
138 if (pt_arm) SET_INT (v_PT); /* no, set int */\r
139 }\r
140 }\r
141 if (pt_rd) { /* reader? */\r
142 pt_run = io_2b (dat, CMD_V_RUN, pt_run); /* upd run/stop */\r
143 pt_slew = io_2b (dat, CMD_V_SLEW, pt_slew); /* upd slew/inc */\r
144 if (pt_run) { /* run set? */\r
145 if (old_run == 0) { /* run 0 -> 1? */\r
146 sim_activate (&pt_unit[PTR], pt_unit[PTR].wait);\r
147 pt_sta = pt_sta & ~STA_DU; /* clear eof */\r
148 }\r
149 }\r
150 else sim_cancel (&pt_unit[PTR]); /* clr, stop rdr */\r
151 }\r
152 else pt_sta = pt_sta & ~STA_DU; /* punch, clr eof */\r
153 break;\r
154\r
155 case IO_RD: /* read */\r
156 if (pt_run && !pt_slew) { /* incremental? */\r
157 sim_activate (&pt_unit[PTR], pt_unit[PTR].wait);\r
158 pt_sta = pt_sta & ~STA_DU; /* clr eof */\r
159 }\r
160 pt_chp = 0; /* clr char pend */\r
161 if (pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */\r
162 return (pt_unit[PTR].buf & 0xFF); /* return char */\r
163\r
164 case IO_WD: /* write */\r
165 pt_unit[PTP].buf = dat & DMASK8; /* save char */\r
166 if (!pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */\r
167 sim_activate (&pt_unit[PTP], pt_unit[PTP].wait);\r
168 break;\r
169\r
170 case IO_SS: /* status */\r
171 t = pt_sta & STA_MASK; /* get status */\r
172 if (pt_rd && !pt_run && !sim_is_active (&pt_unit[PTR]))\r
173 t = t | STA_NMTN; /* stopped? */\r
174 if ((pt_unit[pt_rd? PTR: PTP].flags & UNIT_ATT) == 0)\r
175 t = t | STA_DU; /* offline? */\r
176 if (t & SET_EX) t = t | STA_EX; /* test for EX */\r
177 return t;\r
178 }\r
179\r
180return 0;\r
181}\r
182\r
183/* Unit service */\r
184\r
185t_stat ptr_svc (UNIT *uptr)\r
186{\r
187int32 temp;\r
188\r
189if ((uptr->flags & UNIT_ATT) == 0) /* attached? */\r
190 return IORETURN (ptr_stopioe, SCPE_UNATT);\r
191if (pt_rd) { /* read mode? */\r
192 pt_sta = pt_sta & ~STA_BSY; /* clear busy */\r
193 if (pt_arm) SET_INT (v_PT); /* if armed, intr */\r
194 if (pt_chp) pt_sta = pt_sta | STA_OVR; /* overrun? */\r
195 }\r
196pt_chp = 1; /* char pending */\r
197if ((temp = getc (uptr->fileref)) == EOF) { /* error? */\r
198 if (feof (uptr->fileref)) { /* eof? */\r
199 pt_sta = pt_sta | STA_DU; /* set DU */\r
200 if (ptr_stopioe) printf ("PTR end of file\n");\r
201 else return SCPE_OK;\r
202 }\r
203 else perror ("PTR I/O error");\r
204 clearerr (uptr->fileref);\r
205 return SCPE_IOERR;\r
206 }\r
207uptr->buf = temp & DMASK8; /* store char */\r
208uptr->pos = uptr->pos + 1; /* incr pos */\r
209if (pt_slew) sim_activate (uptr, uptr->wait); /* slew? continue */\r
210return SCPE_OK;\r
211}\r
212\r
213t_stat ptp_svc (UNIT *uptr)\r
214{\r
215if ((uptr->flags & UNIT_ATT) == 0) /* attached? */\r
216 return IORETURN (ptp_stopioe, SCPE_UNATT);\r
217if (!pt_rd) { /* write mode? */\r
218 pt_sta = pt_sta & ~STA_BSY; /* clear busy */\r
219 if (pt_arm) SET_INT (v_PT); /* if armed, intr */\r
220 }\r
221if (putc (uptr->buf, uptr -> fileref) == EOF) { /* write char */\r
222 perror ("PTP I/O error");\r
223 clearerr (uptr -> fileref);\r
224 return SCPE_IOERR;\r
225 }\r
226uptr -> pos = uptr -> pos + 1; /* incr pos */\r
227return SCPE_OK;\r
228}\r
229\r
230/* Reset routine */\r
231\r
232t_stat pt_reset (DEVICE *dptr)\r
233{\r
234sim_cancel (&pt_unit[PTR]); /* deactivate units */\r
235sim_cancel (&pt_unit[PTP]);\r
236pt_rd = 1; /* read */\r
237pt_chp = pt_run = pt_slew = 0; /* stop, inc, disarm */\r
238pt_sta = STA_BSY; /* buf empty */\r
239CLR_INT (v_PT); /* clear int */\r
240CLR_ENB (v_PT); /* disable int */\r
241pt_arm = 0; /* disarm int */\r
242return SCPE_OK;\r
243}\r
244\r
245/* Bootstrap routine */\r
246\r
247#define BOOT_START 0x50\r
248#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))\r
249#define BOOT3_START 0x3E\r
250#define BOOT3_LEN (sizeof (boot_rom) / sizeof (uint8))\r
251\r
252static uint8 boot_rom[] = {\r
253 0xD5, 0x00, 0x00, 0xCF, /* ST AL CF */\r
254 0x43, 0x00, 0x00, 0x80 /* BR 80 */\r
255 };\r
256\r
257static uint8 boot3_rom[] = {\r
258 0xC8, 0x20, 0x00, 0x80, /* ST LHI 2,80 */\r
259 0xC8, 0x30, 0x00, 0x01, /* LHI 3,1 */\r
260 0xC8, 0x40, 0x00, 0xCF, /* LHI 4,CF */\r
261 0xD3, 0xA0, 0x00, 0x78, /* LB A,78 */\r
262 0xDE, 0xA0, 0x00, 0x79, /* OC A,79 */\r
263 0x9D, 0xAE, /* LP SSR A,E */\r
264 0x42, 0xF0, 0x00, 0x52, /* BTC F,LP */\r
265 0x9B, 0xAE, /* RDR A,E */\r
266 0x08, 0xEE, /* LHR E,E */\r
267 0x43, 0x30, 0x00, 0x52, /* BZ LP */\r
268 0x43, 0x00, 0x00, 0x6C, /* BR STO */\r
269 0x9D, 0xAE, /* LP1 SSR A,E */\r
270 0x42, 0xF0, 0x00, 0x64, /* BTC F,LP1 */\r
271 0x9B, 0xAE, /* RDR A,E */\r
272 0xD2, 0xE2, 0x00, 0x00, /* STO STB E,0(2) */\r
273 0xC1, 0x20, 0x00, 0x64, /* BXLE 2,LP1 */\r
274 0x43, 0x00, 0x00, 0x80 /* BR 80 */\r
275 };\r
276\r
277t_stat pt_boot (int32 unitno, DEVICE *dptr)\r
278{\r
279extern uint32 PC, dec_flgs;\r
280extern uint16 decrom[];\r
281\r
282if (decrom[0xD5] & dec_flgs) /* AL defined? */\r
283 IOWriteBlk (BOOT3_START, BOOT3_LEN, boot3_rom); /* no, 50 seq */\r
284else IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy AL boot */\r
285IOWriteB (AL_DEV, pt_dib.dno); /* set dev no */\r
286IOWriteB (AL_IOC, 0x99); /* set dev cmd */\r
287IOWriteB (AL_SCH, 0); /* clr sch dev no */\r
288PC = BOOT_START;\r
289return SCPE_OK;\r
290}\r
291\r
292/* Dump routine */\r
293\r
294#define LOAD_START 0x80\r
295#define LOAD_LO 0x8A\r
296#define LOAD_HI 0x8E\r
297#define LOAD_CS 0x93\r
298#define LOAD_LEN (sizeof (load_rom) / sizeof (uint8))\r
299#define LOAD_LDR 50\r
300\r
301static uint8 load_rom[] = {\r
302 0x24, 0x21, /* BOOT LIS R2,1 */\r
303 0x23, 0x03, /* BS BOOT */\r
304 0x00, 0x00, /* 32b psw pointer */\r
305 0x00, 0x00, /* 32b reg pointer */\r
306 0xC8, 0x10, /* ST LHI R1,lo */\r
307 0x00, 0x00,\r
308 0xC8, 0x30, /* LHI R3,hi */\r
309 0x00, 0x00,\r
310 0xC8, 0x60, /* LHI R3,cs */\r
311 0x00, 0x00,\r
312 0xD3, 0x40, /* LB R4,X'78' */\r
313 0x00, 0x78,\r
314 0xDE, 0x40, /* OC R4,X'79' */\r
315 0x00, 0x79,\r
316 0x9D, 0x45, /* LDR SSR R4,R5 */\r
317 0x20, 0x91, /* BTBS 9,.-2 */\r
318 0x9B, 0x45, /* RDR R4,R5 */\r
319 0x08, 0x55, /* L(H)R R5,R5 */\r
320 0x22, 0x34, /* BZS LDR */\r
321 0xD2, 0x51, /* LOOP STB R5,0(R1) */\r
322 0x00, 0x00,\r
323 0x07, 0x65, /* X(H)R R6,R5 */\r
324 0x9A, 0x26, /* WDR R2,R6 */\r
325 0x9D, 0x45, /* SSR R4,R5 */\r
326 0x20, 0x91, /* BTBS 9,.-2 */\r
327 0x9B, 0x45, /* RDR R4,R5 */\r
328 0xC1, 0x10, /* BXLE R1,LOOP */\r
329 0x00, 0xA6,\r
330 0x24, 0x78, /* LIS R7,8 */\r
331 0x91, 0x7C, /* SLLS R7,12 */\r
332 0x95, 0x57, /* EPSR R5,R7 */\r
333 0x22, 0x03 /* BS .-6 */\r
334 };\r
335\r
336t_stat pt_dump (FILE *of, char *cptr, char *fnam)\r
337{\r
338uint32 i, lo, hi, cs;\r
339char *tptr;\r
340extern DEVICE cpu_dev;\r
341\r
342if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG;\r
343tptr = get_range (NULL, cptr, &lo, &hi, cpu_dev.aradix, 0xFFFF, 0);\r
344if ((tptr == NULL) || (lo < INTSVT)) return SCPE_ARG;\r
345if (*tptr != 0) return SCPE_2MARG;\r
346for (i = lo, cs = 0; i <= hi; i++) cs = cs ^ IOReadB (i);\r
347IOWriteBlk (LOAD_START, LOAD_LEN, load_rom);\r
348IOWriteB (LOAD_LO, (lo >> 8) & 0xFF);\r
349IOWriteB (LOAD_LO + 1, lo & 0xFF);\r
350IOWriteB (LOAD_HI, (hi >> 8) & 0xFF);\r
351IOWriteB (LOAD_HI + 1, hi & 0xFF);\r
352IOWriteB (LOAD_CS, cs & 0xFF);\r
353for (i = 0; i < LOAD_LDR; i++) fputc (0, of);\r
354for (i = LOAD_START; i < (LOAD_START + LOAD_LEN); i++)\r
355 fputc (IOReadB (i), of);\r
356for (i = 0; i < LOAD_LDR; i++) fputc (0, of);\r
357for (i = lo; i <= hi; i++) fputc (IOReadB (i), of);\r
358for (i = 0; i < LOAD_LDR; i++) fputc (0, of);\r
359return SCPE_OK;\r
360}\r