0a7da16597b6d7b7b62d22c14fab02f3ea088bc0
1 /* id_pt.c: Interdata paper tape reader
3 Copyright (c) 2000-2005, Robert M. Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
26 pt paper tape reader and punch
28 25-Apr-03 RMS Revised for extended file support
29 10-Apr-03 RMS Fixed type problem in ptr service (from Mark Pizzolato)
35 /* Device definitions */
37 #define PTR 0 /* unit subscripts */
40 #define STA_OVR 0x80 /* overrun */
41 #define STA_NMTN 0x10 /* no motion */
42 #define STA_MASK (STA_BSY | STA_OVR | STA_DU) /* static bits */
43 #define SET_EX (STA_OVR | STA_NMTN) /* set EX */
45 #define CMD_V_RUN 4 /* run/stop */
46 #define CMD_V_SLEW 2 /* slew/step */
47 #define CMD_V_RD 0 /* read/write */
49 extern uint32 int_req
[INTSZ
], int_enb
[INTSZ
];
51 uint32 pt_run
= 0, pt_slew
= 0; /* ptr modes */
52 uint32 pt_rd
= 1, pt_chp
= 0; /* pt state */
53 uint32 pt_arm
= 0; /* int arm */
54 uint32 pt_sta
= STA_BSY
; /* status */
55 uint32 ptr_stopioe
= 0, ptp_stopioe
= 0; /* stop on error */
58 uint32
pt (uint32 dev
, uint32 op
, uint32 dat
);
59 t_stat
ptr_svc (UNIT
*uptr
);
60 t_stat
ptp_svc (UNIT
*uptr
);
61 t_stat
pt_boot (int32 unitno
, DEVICE
*dptr
);
62 t_stat
pt_reset (DEVICE
*dptr
);
66 pt_dev PT device descriptor
67 pt_unit PT unit descriptors
68 pt_reg PT register list
71 DIB pt_dib
= { d_PT
, -1, v_PT
, NULL
, &pt
, NULL
};
74 { UDATA (&ptr_svc
, UNIT_SEQ
+UNIT_ATTABLE
+UNIT_ROABLE
, 0),
76 { UDATA (&ptp_svc
, UNIT_SEQ
+UNIT_ATTABLE
, 0), SERIAL_OUT_WAIT
}
80 { HRDATA (STA
, pt_sta
, 8) },
81 { HRDATA (RBUF
, pt_unit
[PTR
].buf
, 8) },
82 { DRDATA (RPOS
, pt_unit
[PTR
].pos
, T_ADDR_W
), PV_LEFT
},
83 { DRDATA (RTIME
, pt_unit
[PTR
].wait
, 24), PV_LEFT
},
84 { FLDATA (RSTOP_IOE
, ptr_stopioe
, 0) },
85 { HRDATA (PBUF
, pt_unit
[PTP
].buf
, 8) },
86 { DRDATA (PPOS
, pt_unit
[PTP
].pos
, T_ADDR_W
), PV_LEFT
},
87 { DRDATA (PTIME
, pt_unit
[PTP
].wait
, 24), PV_LEFT
},
88 { FLDATA (PSTOP_IOE
, ptp_stopioe
, 0) },
89 { FLDATA (IREQ
, int_req
[l_PT
], i_PT
) },
90 { FLDATA (IENB
, int_enb
[l_PT
], i_PT
) },
91 { FLDATA (IARM
, pt_arm
, 0) },
92 { FLDATA (RD
, pt_rd
, 0) },
93 { FLDATA (RUN
, pt_run
, 0) },
94 { FLDATA (SLEW
, pt_slew
, 0) },
95 { FLDATA (CHP
, pt_chp
, 0) },
96 { HRDATA (DEVNO
, pt_dib
.dno
, 8), REG_HRO
},
101 { MTAB_XTD
|MTAB_VDV
, 0, "devno", "DEVNO",
102 &set_dev
, &show_dev
, NULL
},
107 "PT", pt_unit
, pt_reg
, pt_mod
,
109 NULL
, NULL
, &pt_reset
,
110 &pt_boot
, NULL
, NULL
,
114 /* Paper tape: IO routine */
116 uint32
pt (uint32 dev
, uint32 op
, uint32 dat
)
118 uint32 t
, old_rd
, old_run
;
120 switch (op
) { /* case IO op */
122 case IO_ADR
: /* select */
123 return BY
; /* byte only */
125 case IO_OC
: /* command */
126 old_rd
= pt_rd
; /* save curr rw */
127 old_run
= pt_run
; /* save curr run */
128 pt_arm
= int_chg (v_PT
, dat
, pt_arm
); /* upd int ctrl */
129 pt_rd
= io_2b (dat
, CMD_V_RD
, pt_rd
); /* upd read/wr */
130 if (old_rd
!= pt_rd
) { /* rw change? */
131 pt_sta
= pt_sta
& ~STA_OVR
; /* clr overrun */
132 if (sim_is_active (&pt_unit
[pt_rd
? PTR
: PTP
])) {
133 pt_sta
= pt_sta
| STA_BSY
; /* busy = 1 */
134 CLR_INT (v_PT
); /* clear int */
136 else { /* not active */
137 pt_sta
= pt_sta
& ~STA_BSY
; /* busy = 0 */
138 if (pt_arm
) SET_INT (v_PT
); /* no, set int */
141 if (pt_rd
) { /* reader? */
142 pt_run
= io_2b (dat
, CMD_V_RUN
, pt_run
); /* upd run/stop */
143 pt_slew
= io_2b (dat
, CMD_V_SLEW
, pt_slew
); /* upd slew/inc */
144 if (pt_run
) { /* run set? */
145 if (old_run
== 0) { /* run 0 -> 1? */
146 sim_activate (&pt_unit
[PTR
], pt_unit
[PTR
].wait
);
147 pt_sta
= pt_sta
& ~STA_DU
; /* clear eof */
150 else sim_cancel (&pt_unit
[PTR
]); /* clr, stop rdr */
152 else pt_sta
= pt_sta
& ~STA_DU
; /* punch, clr eof */
155 case IO_RD
: /* read */
156 if (pt_run
&& !pt_slew
) { /* incremental? */
157 sim_activate (&pt_unit
[PTR
], pt_unit
[PTR
].wait
);
158 pt_sta
= pt_sta
& ~STA_DU
; /* clr eof */
160 pt_chp
= 0; /* clr char pend */
161 if (pt_rd
) pt_sta
= pt_sta
| STA_BSY
; /* set busy */
162 return (pt_unit
[PTR
].buf
& 0xFF); /* return char */
164 case IO_WD
: /* write */
165 pt_unit
[PTP
].buf
= dat
& DMASK8
; /* save char */
166 if (!pt_rd
) pt_sta
= pt_sta
| STA_BSY
; /* set busy */
167 sim_activate (&pt_unit
[PTP
], pt_unit
[PTP
].wait
);
170 case IO_SS
: /* status */
171 t
= pt_sta
& STA_MASK
; /* get status */
172 if (pt_rd
&& !pt_run
&& !sim_is_active (&pt_unit
[PTR
]))
173 t
= t
| STA_NMTN
; /* stopped? */
174 if ((pt_unit
[pt_rd
? PTR
: PTP
].flags
& UNIT_ATT
) == 0)
175 t
= t
| STA_DU
; /* offline? */
176 if (t
& SET_EX
) t
= t
| STA_EX
; /* test for EX */
185 t_stat
ptr_svc (UNIT
*uptr
)
189 if ((uptr
->flags
& UNIT_ATT
) == 0) /* attached? */
190 return IORETURN (ptr_stopioe
, SCPE_UNATT
);
191 if (pt_rd
) { /* read mode? */
192 pt_sta
= pt_sta
& ~STA_BSY
; /* clear busy */
193 if (pt_arm
) SET_INT (v_PT
); /* if armed, intr */
194 if (pt_chp
) pt_sta
= pt_sta
| STA_OVR
; /* overrun? */
196 pt_chp
= 1; /* char pending */
197 if ((temp
= getc (uptr
->fileref
)) == EOF
) { /* error? */
198 if (feof (uptr
->fileref
)) { /* eof? */
199 pt_sta
= pt_sta
| STA_DU
; /* set DU */
200 if (ptr_stopioe
) printf ("PTR end of file\n");
203 else perror ("PTR I/O error");
204 clearerr (uptr
->fileref
);
207 uptr
->buf
= temp
& DMASK8
; /* store char */
208 uptr
->pos
= uptr
->pos
+ 1; /* incr pos */
209 if (pt_slew
) sim_activate (uptr
, uptr
->wait
); /* slew? continue */
213 t_stat
ptp_svc (UNIT
*uptr
)
215 if ((uptr
->flags
& UNIT_ATT
) == 0) /* attached? */
216 return IORETURN (ptp_stopioe
, SCPE_UNATT
);
217 if (!pt_rd
) { /* write mode? */
218 pt_sta
= pt_sta
& ~STA_BSY
; /* clear busy */
219 if (pt_arm
) SET_INT (v_PT
); /* if armed, intr */
221 if (putc (uptr
->buf
, uptr
-> fileref
) == EOF
) { /* write char */
222 perror ("PTP I/O error");
223 clearerr (uptr
-> fileref
);
226 uptr
-> pos
= uptr
-> pos
+ 1; /* incr pos */
232 t_stat
pt_reset (DEVICE
*dptr
)
234 sim_cancel (&pt_unit
[PTR
]); /* deactivate units */
235 sim_cancel (&pt_unit
[PTP
]);
236 pt_rd
= 1; /* read */
237 pt_chp
= pt_run
= pt_slew
= 0; /* stop, inc, disarm */
238 pt_sta
= STA_BSY
; /* buf empty */
239 CLR_INT (v_PT
); /* clear int */
240 CLR_ENB (v_PT
); /* disable int */
241 pt_arm
= 0; /* disarm int */
245 /* Bootstrap routine */
247 #define BOOT_START 0x50
248 #define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
249 #define BOOT3_START 0x3E
250 #define BOOT3_LEN (sizeof (boot_rom) / sizeof (uint8))
252 static uint8 boot_rom
[] = {
253 0xD5, 0x00, 0x00, 0xCF, /* ST AL CF */
254 0x43, 0x00, 0x00, 0x80 /* BR 80 */
257 static uint8 boot3_rom
[] = {
258 0xC8, 0x20, 0x00, 0x80, /* ST LHI 2,80 */
259 0xC8, 0x30, 0x00, 0x01, /* LHI 3,1 */
260 0xC8, 0x40, 0x00, 0xCF, /* LHI 4,CF */
261 0xD3, 0xA0, 0x00, 0x78, /* LB A,78 */
262 0xDE, 0xA0, 0x00, 0x79, /* OC A,79 */
263 0x9D, 0xAE, /* LP SSR A,E */
264 0x42, 0xF0, 0x00, 0x52, /* BTC F,LP */
265 0x9B, 0xAE, /* RDR A,E */
266 0x08, 0xEE, /* LHR E,E */
267 0x43, 0x30, 0x00, 0x52, /* BZ LP */
268 0x43, 0x00, 0x00, 0x6C, /* BR STO */
269 0x9D, 0xAE, /* LP1 SSR A,E */
270 0x42, 0xF0, 0x00, 0x64, /* BTC F,LP1 */
271 0x9B, 0xAE, /* RDR A,E */
272 0xD2, 0xE2, 0x00, 0x00, /* STO STB E,0(2) */
273 0xC1, 0x20, 0x00, 0x64, /* BXLE 2,LP1 */
274 0x43, 0x00, 0x00, 0x80 /* BR 80 */
277 t_stat
pt_boot (int32 unitno
, DEVICE
*dptr
)
279 extern uint32 PC
, dec_flgs
;
280 extern uint16 decrom
[];
282 if (decrom
[0xD5] & dec_flgs
) /* AL defined? */
283 IOWriteBlk (BOOT3_START
, BOOT3_LEN
, boot3_rom
); /* no, 50 seq */
284 else IOWriteBlk (BOOT_START
, BOOT_LEN
, boot_rom
); /* copy AL boot */
285 IOWriteB (AL_DEV
, pt_dib
.dno
); /* set dev no */
286 IOWriteB (AL_IOC
, 0x99); /* set dev cmd */
287 IOWriteB (AL_SCH
, 0); /* clr sch dev no */
294 #define LOAD_START 0x80
298 #define LOAD_LEN (sizeof (load_rom) / sizeof (uint8))
301 static uint8 load_rom
[] = {
302 0x24, 0x21, /* BOOT LIS R2,1 */
303 0x23, 0x03, /* BS BOOT */
304 0x00, 0x00, /* 32b psw pointer */
305 0x00, 0x00, /* 32b reg pointer */
306 0xC8, 0x10, /* ST LHI R1,lo */
308 0xC8, 0x30, /* LHI R3,hi */
310 0xC8, 0x60, /* LHI R3,cs */
312 0xD3, 0x40, /* LB R4,X'78' */
314 0xDE, 0x40, /* OC R4,X'79' */
316 0x9D, 0x45, /* LDR SSR R4,R5 */
317 0x20, 0x91, /* BTBS 9,.-2 */
318 0x9B, 0x45, /* RDR R4,R5 */
319 0x08, 0x55, /* L(H)R R5,R5 */
320 0x22, 0x34, /* BZS LDR */
321 0xD2, 0x51, /* LOOP STB R5,0(R1) */
323 0x07, 0x65, /* X(H)R R6,R5 */
324 0x9A, 0x26, /* WDR R2,R6 */
325 0x9D, 0x45, /* SSR R4,R5 */
326 0x20, 0x91, /* BTBS 9,.-2 */
327 0x9B, 0x45, /* RDR R4,R5 */
328 0xC1, 0x10, /* BXLE R1,LOOP */
330 0x24, 0x78, /* LIS R7,8 */
331 0x91, 0x7C, /* SLLS R7,12 */
332 0x95, 0x57, /* EPSR R5,R7 */
333 0x22, 0x03 /* BS .-6 */
336 t_stat
pt_dump (FILE *of
, char *cptr
, char *fnam
)
338 uint32 i
, lo
, hi
, cs
;
340 extern DEVICE cpu_dev
;
342 if ((cptr
== NULL
) || (*cptr
== 0)) return SCPE_2FARG
;
343 tptr
= get_range (NULL
, cptr
, &lo
, &hi
, cpu_dev
.aradix
, 0xFFFF, 0);
344 if ((tptr
== NULL
) || (lo
< INTSVT
)) return SCPE_ARG
;
345 if (*tptr
!= 0) return SCPE_2MARG
;
346 for (i
= lo
, cs
= 0; i
<= hi
; i
++) cs
= cs
^ IOReadB (i
);
347 IOWriteBlk (LOAD_START
, LOAD_LEN
, load_rom
);
348 IOWriteB (LOAD_LO
, (lo
>> 8) & 0xFF);
349 IOWriteB (LOAD_LO
+ 1, lo
& 0xFF);
350 IOWriteB (LOAD_HI
, (hi
>> 8) & 0xFF);
351 IOWriteB (LOAD_HI
+ 1, hi
& 0xFF);
352 IOWriteB (LOAD_CS
, cs
& 0xFF);
353 for (i
= 0; i
< LOAD_LDR
; i
++) fputc (0, of
);
354 for (i
= LOAD_START
; i
< (LOAD_START
+ LOAD_LEN
); i
++)
355 fputc (IOReadB (i
), of
);
356 for (i
= 0; i
< LOAD_LDR
; i
++) fputc (0, of
);
357 for (i
= lo
; i
<= hi
; i
++) fputc (IOReadB (i
), of
);
358 for (i
= 0; i
< LOAD_LDR
; i
++) fputc (0, of
);