Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* pdp1_stddev.c: PDP-1 standard devices\r |
2 | \r | |
3 | Copyright (c) 1993-2006, 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 paper tape reader\r | |
27 | ptp paper tape punch\r | |
28 | tti keyboard\r | |
29 | tto teleprinter\r | |
30 | \r | |
31 | 21-Dec-06 RMS Added 16-channel sequence break support\r | |
32 | 29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne)\r | |
33 | 07-Sep-03 RMS Changed ioc to ios\r | |
34 | 30-Aug-03 RMS Revised PTR to conform to Maintenance Manual;\r | |
35 | added deadlock prevention on errors\r | |
36 | 23-Jul-03 RMS Revised to detect I/O wait hang\r | |
37 | 25-Apr-03 RMS Revised for extended file support\r | |
38 | 22-Dec-02 RMS Added break support\r | |
39 | 29-Nov-02 RMS Fixed output flag initialization (found by Derek Peschel)\r | |
40 | 21-Nov-02 RMS Changed typewriter to half duplex (found by Derek Peschel)\r | |
41 | 06-Oct-02 RMS Revised for V2.10\r | |
42 | 30-May-02 RMS Widened POS to 32b\r | |
43 | 29-Nov-01 RMS Added read only unit support\r | |
44 | 07-Sep-01 RMS Moved function prototypes\r | |
45 | 10-Jun-01 RMS Fixed comment\r | |
46 | 30-Oct-00 RMS Standardized device naming\r | |
47 | \r | |
48 | Note: PTP timeout must be >10X faster that TTY output timeout for Macro\r | |
49 | to work correctly!\r | |
50 | */\r | |
51 | \r | |
52 | #include "pdp1_defs.h"\r | |
53 | \r | |
54 | #define FIODEC_STOP 013 /* stop code */\r | |
55 | #define FIODEC_UC 074\r | |
56 | #define FIODEC_LC 072\r | |
57 | #define UC_V 6 /* upper case */\r | |
58 | #define UC (1 << UC_V)\r | |
59 | #define BOTH (1 << (UC_V + 1)) /* both cases */\r | |
60 | #define CW (1 << (UC_V + 2)) /* char waiting */\r | |
61 | #define TT_WIDTH 077\r | |
62 | #define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */\r | |
63 | #define UNIT_ASCII (1 << UNIT_V_ASCII)\r | |
64 | #define PTR_LEADER 20 /* ASCII leader chars */\r | |
65 | \r | |
66 | int32 ptr_state = 0;\r | |
67 | int32 ptr_wait = 0;\r | |
68 | int32 ptr_stopioe = 0;\r | |
69 | int32 ptr_uc = 0; /* upper/lower case */\r | |
70 | int32 ptr_hold = 0; /* holding buffer */\r | |
71 | int32 ptr_leader = PTR_LEADER; /* leader count */\r | |
72 | int32 ptr_sbs = 0; /* SBS level */\r | |
73 | int32 ptp_stopioe = 0;\r | |
74 | int32 ptp_sbs = 0; /* SBS level */\r | |
75 | int32 tti_hold = 0; /* tti hold buf */\r | |
76 | int32 tti_sbs = 0; /* SBS level */\r | |
77 | int32 tty_buf = 0; /* tty buffer */\r | |
78 | int32 tty_uc = 0; /* tty uc/lc */\r | |
79 | int32 tto_sbs = 0;\r | |
80 | \r | |
81 | extern int32 ios, ioh, cpls, iosta;\r | |
82 | extern int32 PF, IO, PC, TA;\r | |
83 | extern int32 M[];\r | |
84 | \r | |
85 | int ptr_get_ascii (UNIT *uptr);\r | |
86 | t_stat ptr_svc (UNIT *uptr);\r | |
87 | t_stat ptp_svc (UNIT *uptr);\r | |
88 | t_stat tti_svc (UNIT *uptr);\r | |
89 | t_stat tto_svc (UNIT *uptr);\r | |
90 | t_stat ptr_reset (DEVICE *dptr);\r | |
91 | t_stat ptp_reset (DEVICE *dptr);\r | |
92 | t_stat tty_reset (DEVICE *dptr);\r | |
93 | t_stat ptr_boot (int32 unitno, DEVICE *dptr);\r | |
94 | t_stat ptr_attach (UNIT *uptr, char *cptr);\r | |
95 | \r | |
96 | /* Character translation tables */\r | |
97 | \r | |
98 | int32 fiodec_to_ascii[128] = {\r | |
99 | ' ', '1', '2', '3', '4', '5', '6', '7', /* lower case */\r | |
100 | '8', '9', 0, 0, 0, 0, 0, 0,\r | |
101 | '0', '/', 's', 't', 'u', 'v', 'w', 'x',\r | |
102 | 'y', 'z', 0, ',', 0, 0, '\t', 0,\r | |
103 | '@', 'j', 'k', 'l', 'm', 'n', 'o', 'p',\r | |
104 | 'q', 'r', 0, 0, '-', ')', '\\', '(',\r | |
105 | 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',\r | |
106 | 'h', 'i', '{', '.', '}', '\b', 0, '\r',\r | |
107 | ' ', '"', '\'', '~', '#', '!', '&', '<', /* upper case */\r | |
108 | '>', '^', 0, 0, 0, 0, 0, 0,\r | |
109 | '`', '?', 'S', 'T', 'U', 'V', 'W', 'X',\r | |
110 | 'Y', 'Z', 0, '=', 0, 0, '\t', 0,\r | |
111 | '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\r | |
112 | 'Q', 'R', 0, 0, '+', ']', '|', '[',\r | |
113 | 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',\r | |
114 | 'H', 'I', '{', '*', '}', '\b', 0, '\r'\r | |
115 | };\r | |
116 | \r | |
117 | int32 ascii_to_fiodec[128] = {\r | |
118 | 0, 0, 0, 0, 0, 0, 0, 0,\r | |
119 | BOTH+075, BOTH+036, 0, 0, 0, BOTH+077, 0, 0,\r | |
120 | 0, 0, 0, 0, 0, 0, 0, 0,\r | |
121 | 0, 0, 0, 0, 0, 0, 0, 0,\r | |
122 | BOTH+0, UC+005, UC+001, UC+004, 0, 0, UC+006, UC+002,\r | |
123 | 057, 055, UC+073, UC+054, 033, 054, 073, 021,\r | |
124 | 020, 001, 002, 003, 004, 005, 006, 007,\r | |
125 | 010, 011, 0, 0, UC+007, UC+033, UC+010, UC+021,\r | |
126 | 040, UC+061, UC+062, UC+063, UC+064, UC+065, UC+066, UC+067,\r | |
127 | UC+070, UC+071, UC+041, UC+042, UC+043, UC+044, UC+045, UC+046,\r | |
128 | UC+047, UC+050, UC+051, UC+022, UC+023, UC+024, UC+025, UC+026,\r | |
129 | UC+027, UC+030, UC+031, UC+057, 056, UC+055, UC+011, UC+040,\r | |
130 | UC+020, 061, 062, 063, 064, 065, 066, 067,\r | |
131 | 070, 071, 041, 042, 043, 044, 045, 046,\r | |
132 | 047, 050, 051, 022, 023, 024, 025, 026,\r | |
133 | 027, 030, 031, 0, UC+056, 0, UC+003, BOTH+075\r | |
134 | };\r | |
135 | \r | |
136 | /* PTR data structures\r | |
137 | \r | |
138 | ptr_dev PTR device descriptor\r | |
139 | ptr_unit PTR unit\r | |
140 | ptr_reg PTR register list\r | |
141 | */\r | |
142 | \r | |
143 | UNIT ptr_unit = {\r | |
144 | UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),\r | |
145 | SERIAL_IN_WAIT\r | |
146 | };\r | |
147 | \r | |
148 | REG ptr_reg[] = {\r | |
149 | { ORDATA (BUF, ptr_unit.buf, 18) },\r | |
150 | { FLDATA (UC, ptr_uc, UC_V) },\r | |
151 | { FLDATA (DONE, iosta, IOS_V_PTR) },\r | |
152 | { FLDATA (RPLS, cpls, CPLS_V_PTR) },\r | |
153 | { ORDATA (HOLD, ptr_hold, 9), REG_HRO },\r | |
154 | { ORDATA (STATE, ptr_state, 5), REG_HRO },\r | |
155 | { FLDATA (WAIT, ptr_wait, 0), REG_HRO },\r | |
156 | { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },\r | |
157 | { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },\r | |
158 | { DRDATA (LEADER, ptr_leader, 6), REG_HRO },\r | |
159 | { FLDATA (STOP_IOE, ptr_stopioe, 0) },\r | |
160 | { DRDATA (SBSLVL, ptr_sbs, 4), REG_HRO },\r | |
161 | { NULL }\r | |
162 | };\r | |
163 | \r | |
164 | MTAB ptr_mod[] = {\r | |
165 | { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",\r | |
166 | &dev_set_sbs, &dev_show_sbs, (void *) &ptr_sbs },\r | |
167 | { UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL },\r | |
168 | { UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL },\r | |
169 | { 0 }\r | |
170 | };\r | |
171 | \r | |
172 | DEVICE ptr_dev = {\r | |
173 | "PTR", &ptr_unit, ptr_reg, ptr_mod,\r | |
174 | 1, 10, 31, 1, 8, 8,\r | |
175 | NULL, NULL, &ptr_reset,\r | |
176 | &ptr_boot, &ptr_attach, NULL,\r | |
177 | NULL, 0\r | |
178 | };\r | |
179 | \r | |
180 | /* PTP data structures\r | |
181 | \r | |
182 | ptp_dev PTP device descriptor\r | |
183 | ptp_unit PTP unit\r | |
184 | ptp_reg PTP register list\r | |
185 | */\r | |
186 | \r | |
187 | UNIT ptp_unit = {\r | |
188 | UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT\r | |
189 | };\r | |
190 | \r | |
191 | REG ptp_reg[] = {\r | |
192 | { ORDATA (BUF, ptp_unit.buf, 8) },\r | |
193 | { FLDATA (DONE, iosta, IOS_V_PTP) },\r | |
194 | { FLDATA (RPLS, cpls, CPLS_V_PTP) },\r | |
195 | { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },\r | |
196 | { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },\r | |
197 | { FLDATA (STOP_IOE, ptp_stopioe, 0) },\r | |
198 | { DRDATA (SBSLVL, ptp_sbs, 4), REG_HRO },\r | |
199 | { NULL }\r | |
200 | };\r | |
201 | \r | |
202 | MTAB ptp_mod[] = {\r | |
203 | { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",\r | |
204 | &dev_set_sbs, &dev_show_sbs, (void *) &ptp_sbs },\r | |
205 | { 0 }\r | |
206 | };\r | |
207 | \r | |
208 | DEVICE ptp_dev = {\r | |
209 | "PTP", &ptp_unit, ptp_reg, ptp_mod,\r | |
210 | 1, 10, 31, 1, 8, 8,\r | |
211 | NULL, NULL, &ptp_reset,\r | |
212 | NULL, NULL, NULL,\r | |
213 | NULL, 0\r | |
214 | };\r | |
215 | \r | |
216 | /* TTI data structures\r | |
217 | \r | |
218 | tti_dev TTI device descriptor\r | |
219 | tti_unit TTI unit\r | |
220 | tti_reg TTI register list\r | |
221 | */\r | |
222 | \r | |
223 | UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };\r | |
224 | \r | |
225 | REG tti_reg[] = {\r | |
226 | { ORDATA (BUF, tty_buf, 6) },\r | |
227 | { FLDATA (UC, tty_uc, UC_V) },\r | |
228 | { ORDATA (HOLD, tti_hold, 9), REG_HRO },\r | |
229 | { FLDATA (DONE, iosta, IOS_V_TTI) },\r | |
230 | { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },\r | |
231 | { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },\r | |
232 | { DRDATA (SBSLVL, tti_sbs, 4), REG_HRO },\r | |
233 | { NULL }\r | |
234 | };\r | |
235 | \r | |
236 | MTAB tti_mod[] = {\r | |
237 | { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",\r | |
238 | &dev_set_sbs, &dev_show_sbs, (void *) &tti_sbs },\r | |
239 | { 0 }\r | |
240 | };\r | |
241 | \r | |
242 | DEVICE tti_dev = {\r | |
243 | "TTI", &tti_unit, tti_reg, tti_mod,\r | |
244 | 1, 10, 31, 1, 8, 8,\r | |
245 | NULL, NULL, &tty_reset,\r | |
246 | NULL, NULL, NULL,\r | |
247 | NULL, 0\r | |
248 | };\r | |
249 | \r | |
250 | /* TTO data structures\r | |
251 | \r | |
252 | tto_dev TTO device descriptor\r | |
253 | tto_unit TTO unit\r | |
254 | tto_reg TTO register list\r | |
255 | */\r | |
256 | \r | |
257 | UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 };\r | |
258 | \r | |
259 | REG tto_reg[] = {\r | |
260 | { ORDATA (BUF, tty_buf, 6) },\r | |
261 | { FLDATA (UC, tty_uc, UC_V) },\r | |
262 | { FLDATA (RPLS, cpls, CPLS_V_TTO) },\r | |
263 | { FLDATA (DONE, iosta, IOS_V_TTO) },\r | |
264 | { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },\r | |
265 | { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },\r | |
266 | { DRDATA (SBSLVL, tto_sbs, 4), REG_HRO },\r | |
267 | { NULL }\r | |
268 | };\r | |
269 | \r | |
270 | MTAB tto_mod[] = {\r | |
271 | { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",\r | |
272 | &dev_set_sbs, &dev_show_sbs, (void *) &tto_sbs },\r | |
273 | { 0 }\r | |
274 | };\r | |
275 | \r | |
276 | DEVICE tto_dev = {\r | |
277 | "TTO", &tto_unit, tto_reg, tto_mod,\r | |
278 | 1, 10, 31, 1, 8, 8,\r | |
279 | NULL, NULL, &tty_reset,\r | |
280 | NULL, NULL, NULL,\r | |
281 | NULL, 0\r | |
282 | };\r | |
283 | \r | |
284 | /* Paper tape reader: IOT routine. Points to note:\r | |
285 | \r | |
286 | - RPA (but not RPB) complements the reader clutch control. Thus,\r | |
287 | if the reader is running, RPA will stop it.\r | |
288 | - The status bit indicates data in the reader buffer that has not\r | |
289 | been transfered to IO. It is cleared by any RB->IO operation,\r | |
290 | including RRB and the completion pulse.\r | |
291 | - A reader error on a wait mode operation could hang the simulator.\r | |
292 | IOH is set; any retry (without RESET) will be NOP'd. Accordingly,\r | |
293 | the PTR service routine clears IOH on any error during a rpa/rpb i.\r | |
294 | */\r | |
295 | \r | |
296 | int32 ptr (int32 inst, int32 dev, int32 dat)\r | |
297 | {\r | |
298 | if (dev == 0030) { /* RRB */\r | |
299 | iosta = iosta & ~IOS_PTR; /* clear status */\r | |
300 | return ptr_unit.buf; /* return data */\r | |
301 | }\r | |
302 | if (dev == 0002) ptr_state = 18; /* RPB, mode = binary */\r | |
303 | else if (sim_is_active (&ptr_unit)) { /* RPA, running? */\r | |
304 | sim_cancel (&ptr_unit); /* stop reader */\r | |
305 | return dat;\r | |
306 | }\r | |
307 | else ptr_state = 0; /* mode = alpha */\r | |
308 | ptr_unit.buf = 0; /* clear buffer */\r | |
309 | if (inst & IO_WAIT) ptr_wait = 1; /* set ptr wait */\r | |
310 | else ptr_wait = 0; /* from IR<5> */\r | |
311 | if (GEN_CPLS (inst)) { /* comp pulse? */\r | |
312 | ios = 0;\r | |
313 | cpls = cpls | CPLS_PTR;\r | |
314 | }\r | |
315 | else cpls = cpls & ~CPLS_PTR;\r | |
316 | sim_activate (&ptr_unit, ptr_unit.wait); /* start reader */\r | |
317 | return dat;\r | |
318 | }\r | |
319 | \r | |
320 | /* Unit service */\r | |
321 | \r | |
322 | t_stat ptr_svc (UNIT *uptr)\r | |
323 | {\r | |
324 | int32 temp;\r | |
325 | \r | |
326 | if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */\r | |
327 | if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */\r | |
328 | if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT;\r | |
329 | return SCPE_OK;\r | |
330 | }\r | |
331 | if ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */\r | |
332 | temp = ptr_get_ascii (uptr); /* get processed char */\r | |
333 | else if ((temp = getc (uptr->fileref)) != EOF) /* no, get raw char */\r | |
334 | uptr->pos = uptr->pos + 1; /* if not eof, count */\r | |
335 | if (temp == EOF) { /* end of file? */\r | |
336 | if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */\r | |
337 | if (feof (uptr->fileref)) {\r | |
338 | if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n");\r | |
339 | else return SCPE_OK;\r | |
340 | }\r | |
341 | else perror ("PTR I/O error");\r | |
342 | clearerr (uptr->fileref);\r | |
343 | return SCPE_IOERR;\r | |
344 | }\r | |
345 | if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */\r | |
346 | else if (temp & 0200) { /* binary */\r | |
347 | ptr_state = ptr_state - 6;\r | |
348 | uptr->buf = uptr->buf | ((temp & 077) << ptr_state);\r | |
349 | }\r | |
350 | if (ptr_state == 0) { /* done? */\r | |
351 | if (cpls & CPLS_PTR) { /* completion pulse? */\r | |
352 | iosta = iosta & ~IOS_PTR; /* clear flag */\r | |
353 | IO = uptr->buf; /* fill IO */\r | |
354 | ios = 1; /* restart */\r | |
355 | cpls = cpls & ~CPLS_PTR;\r | |
356 | }\r | |
357 | else { /* no, interrupt */\r | |
358 | iosta = iosta | IOS_PTR; /* set flag */\r | |
359 | dev_req_int (ptr_sbs); /* req interrupt */\r | |
360 | }\r | |
361 | }\r | |
362 | else sim_activate (uptr, uptr->wait); /* get next char */\r | |
363 | return SCPE_OK;\r | |
364 | }\r | |
365 | \r | |
366 | /* Read next ASCII character */\r | |
367 | \r | |
368 | int ptr_get_ascii (UNIT *uptr)\r | |
369 | {\r | |
370 | int c;\r | |
371 | int32 in;\r | |
372 | \r | |
373 | if (ptr_leader > 0) { /* leader? */\r | |
374 | ptr_leader = ptr_leader - 1; /* count down */\r | |
375 | return 0;\r | |
376 | }\r | |
377 | if (ptr_hold & CW) { /* char waiting? */\r | |
378 | in = ptr_hold & TT_WIDTH; /* return char */\r | |
379 | ptr_hold = 0; /* not waiting */\r | |
380 | }\r | |
381 | else {\r | |
382 | for (;;) { /* until valid char */\r | |
383 | if ((c = getc (uptr->fileref)) == EOF) /* get next char, EOF? */\r | |
384 | return FIODEC_STOP; /* return STOP */\r | |
385 | uptr->pos = uptr->pos + 1; /* count char */\r | |
386 | c = c & 0177; /* cut to 7b */\r | |
387 | if (c == '\n') c = '\r'; /* NL -> CR */\r | |
388 | else if (c == '\r') continue; /* ignore CR */\r | |
389 | in = ascii_to_fiodec[c]; /* convert char */\r | |
390 | if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */ \r | |
391 | if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */\r | |
392 | in = in & TT_WIDTH; /* cut to 6b */\r | |
393 | else { /* no, case shift */\r | |
394 | ptr_hold = in | CW; /* set char waiting */\r | |
395 | ptr_uc = in & UC; /* set case */\r | |
396 | in = ptr_uc? FIODEC_UC: FIODEC_LC; /* return case */\r | |
397 | } /* end else */\r | |
398 | break;\r | |
399 | } /* end for */\r | |
400 | } /* end else */\r | |
401 | in = in * 010040201; /* even parity from */\r | |
402 | in = in | 027555555400; /* HACKMEM 167 */\r | |
403 | in = in % (9 << 7);\r | |
404 | return in & 0377;\r | |
405 | }\r | |
406 | \r | |
407 | /* Reset routine */\r | |
408 | \r | |
409 | t_stat ptr_reset (DEVICE *dptr)\r | |
410 | {\r | |
411 | ptr_state = 0; /* clear state */\r | |
412 | ptr_wait = 0;\r | |
413 | ptr_hold = 0;\r | |
414 | ptr_uc = 0;\r | |
415 | ptr_unit.buf = 0;\r | |
416 | cpls = cpls & ~CPLS_PTR;\r | |
417 | iosta = iosta & ~IOS_PTR; /* clear flag */\r | |
418 | sim_cancel (&ptr_unit); /* deactivate unit */\r | |
419 | return SCPE_OK;\r | |
420 | }\r | |
421 | \r | |
422 | /* Attach routine */\r | |
423 | \r | |
424 | t_stat ptr_attach (UNIT *uptr, char *cptr)\r | |
425 | {\r | |
426 | ptr_leader = PTR_LEADER; /* set up leader */\r | |
427 | return attach_unit (uptr, cptr);\r | |
428 | }\r | |
429 | \r | |
430 | /* Bootstrap routine */\r | |
431 | \r | |
432 | int32 ptr_getw (UNIT *uptr)\r | |
433 | {\r | |
434 | int32 i, tmp, word;\r | |
435 | \r | |
436 | for (i = word = 0; i < 3;) {\r | |
437 | if ((tmp = getc (uptr->fileref)) == EOF) return -1;\r | |
438 | uptr->pos = uptr->pos + 1;\r | |
439 | if (tmp & 0200) {\r | |
440 | word = (word << 6) | (tmp & 077);\r | |
441 | i++;\r | |
442 | }\r | |
443 | }\r | |
444 | return word;\r | |
445 | }\r | |
446 | \r | |
447 | t_stat ptr_boot (int32 unitno, DEVICE *dptr)\r | |
448 | {\r | |
449 | int32 origin, val;\r | |
450 | int32 fld = TA & EPCMASK;\r | |
451 | \r | |
452 | for (;;) {\r | |
453 | if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT;\r | |
454 | if (((val & 0760000) == OP_DIO) || /* DIO? */\r | |
455 | ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */\r | |
456 | origin = val & DAMASK;\r | |
457 | if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT;\r | |
458 | M[fld | origin] = val;\r | |
459 | }\r | |
460 | else if ((val & 0760000) == OP_JMP) { /* JMP? */\r | |
461 | PC = fld | (val & DAMASK);\r | |
462 | break;\r | |
463 | }\r | |
464 | else return SCPE_FMT; /* bad instr */\r | |
465 | }\r | |
466 | return SCPE_OK; /* done */\r | |
467 | }\r | |
468 | \r | |
469 | /* Paper tape punch: IOT routine */\r | |
470 | \r | |
471 | int32 ptp (int32 inst, int32 dev, int32 dat)\r | |
472 | {\r | |
473 | iosta = iosta & ~IOS_PTP; /* clear flag */\r | |
474 | ptp_unit.buf = (dev == 0006)? ((dat >> 12) | 0200): (dat & 0377);\r | |
475 | if (GEN_CPLS (inst)) { /* comp pulse? */\r | |
476 | ios = 0;\r | |
477 | cpls = cpls | CPLS_PTP;\r | |
478 | }\r | |
479 | else cpls = cpls & ~CPLS_PTP;\r | |
480 | sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */\r | |
481 | return dat;\r | |
482 | }\r | |
483 | \r | |
484 | /* Unit service */\r | |
485 | \r | |
486 | t_stat ptp_svc (UNIT *uptr)\r | |
487 | {\r | |
488 | if (cpls & CPLS_PTP) { /* completion pulse? */\r | |
489 | ios = 1; /* restart */\r | |
490 | cpls = cpls & ~CPLS_PTP;\r | |
491 | }\r | |
492 | iosta = iosta | IOS_PTP; /* set flag */\r | |
493 | dev_req_int (ptp_sbs); /* req interrupt */\r | |
494 | if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */\r | |
495 | return IORETURN (ptp_stopioe, SCPE_UNATT);\r | |
496 | if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */\r | |
497 | perror ("PTP I/O error");\r | |
498 | clearerr (uptr->fileref);\r | |
499 | return SCPE_IOERR;\r | |
500 | }\r | |
501 | uptr->pos = uptr->pos + 1;\r | |
502 | return SCPE_OK;\r | |
503 | }\r | |
504 | \r | |
505 | /* Reset routine */\r | |
506 | \r | |
507 | t_stat ptp_reset (DEVICE *dptr)\r | |
508 | {\r | |
509 | ptp_unit.buf = 0; /* clear state */\r | |
510 | cpls = cpls & ~CPLS_PTP;\r | |
511 | iosta = iosta & ~IOS_PTP; /* clear flag */\r | |
512 | sim_cancel (&ptp_unit); /* deactivate unit */\r | |
513 | return SCPE_OK;\r | |
514 | }\r | |
515 | \r | |
516 | /* Typewriter IOT routines */\r | |
517 | \r | |
518 | int32 tti (int32 inst, int32 dev, int32 dat)\r | |
519 | {\r | |
520 | iosta = iosta & ~IOS_TTI; /* clear flag */\r | |
521 | if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */\r | |
522 | return (STOP_RSRV << IOT_V_REASON) | (tty_buf & 077);\r | |
523 | return tty_buf & 077;\r | |
524 | }\r | |
525 | \r | |
526 | int32 tto (int32 inst, int32 dev, int32 dat)\r | |
527 | {\r | |
528 | iosta = iosta & ~IOS_TTO; /* clear flag */\r | |
529 | tty_buf = dat & TT_WIDTH; /* load buffer */\r | |
530 | if (GEN_CPLS (inst)) { /* comp pulse? */\r | |
531 | ios = 0;\r | |
532 | cpls = cpls | CPLS_TTO;\r | |
533 | }\r | |
534 | else cpls = cpls & ~CPLS_TTO;\r | |
535 | sim_activate (&tto_unit, tto_unit.wait); /* activate unit */\r | |
536 | return dat;\r | |
537 | }\r | |
538 | \r | |
539 | /* Unit service routines */\r | |
540 | \r | |
541 | t_stat tti_svc (UNIT *uptr)\r | |
542 | {\r | |
543 | int32 in, temp;\r | |
544 | \r | |
545 | sim_activate (uptr, uptr->wait); /* continue poll */\r | |
546 | if (tti_hold & CW) { /* char waiting? */\r | |
547 | tty_buf = tti_hold & TT_WIDTH; /* return char */\r | |
548 | tti_hold = 0; /* not waiting */\r | |
549 | }\r | |
550 | else {\r | |
551 | if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;\r | |
552 | if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */\r | |
553 | temp = temp & 0177;\r | |
554 | if (temp == 0177) temp = '\b'; /* rubout? bs */\r | |
555 | sim_putchar (temp); /* echo */\r | |
556 | if (temp == '\r') sim_putchar ('\n'); /* cr? add nl */\r | |
557 | in = ascii_to_fiodec[temp]; /* translate char */\r | |
558 | if (in == 0) return SCPE_OK; /* no xlation? */\r | |
559 | if ((in & BOTH) || ((in & UC) == (tty_uc & UC)))\r | |
560 | tty_buf = in & TT_WIDTH;\r | |
561 | else { /* must shift */\r | |
562 | tty_uc = in & UC; /* new case */\r | |
563 | tty_buf = tty_uc? FIODEC_UC: FIODEC_LC;\r | |
564 | tti_hold = in | CW; /* set 2nd waiting */\r | |
565 | }\r | |
566 | }\r | |
567 | iosta = iosta | IOS_TTI; /* set flag */\r | |
568 | dev_req_int (tti_sbs); /* req interrupt */\r | |
569 | PF = PF | PF_SS_1; /* set prog flag 1 */\r | |
570 | uptr->pos = uptr->pos + 1;\r | |
571 | return SCPE_OK;\r | |
572 | }\r | |
573 | \r | |
574 | t_stat tto_svc (UNIT *uptr)\r | |
575 | {\r | |
576 | int32 c;\r | |
577 | t_stat r;\r | |
578 | \r | |
579 | if (tty_buf == FIODEC_UC) tty_uc = UC; /* upper case? */\r | |
580 | else if (tty_buf == FIODEC_LC) tty_uc = 0; /* lower case? */\r | |
581 | else {\r | |
582 | c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */\r | |
583 | if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) { /* output; error? */\r | |
584 | sim_activate (uptr, uptr->wait); /* retry */\r | |
585 | return ((r == SCPE_STALL)? SCPE_OK: r);\r | |
586 | }\r | |
587 | }\r | |
588 | if (cpls & CPLS_TTO) { /* completion pulse? */\r | |
589 | ios = 1; /* restart */\r | |
590 | cpls = cpls & ~CPLS_TTO;\r | |
591 | }\r | |
592 | iosta = iosta | IOS_TTO; /* set flag */\r | |
593 | dev_req_int (tto_sbs); /* req interrupt */\r | |
594 | uptr->pos = uptr->pos + 1;\r | |
595 | if (c == '\r') { /* cr? add lf */\r | |
596 | sim_putchar ('\n');\r | |
597 | uptr->pos = uptr->pos + 1;\r | |
598 | }\r | |
599 | return SCPE_OK;\r | |
600 | }\r | |
601 | \r | |
602 | /* Reset routine */\r | |
603 | \r | |
604 | t_stat tty_reset (DEVICE *dptr)\r | |
605 | {\r | |
606 | tty_buf = 0; /* clear buffer */\r | |
607 | tty_uc = 0; /* clear case */\r | |
608 | tti_hold = 0; /* clear hold buf */\r | |
609 | cpls = cpls & ~CPLS_TTO;\r | |
610 | iosta = (iosta & ~IOS_TTI) | IOS_TTO; /* clear flag */\r | |
611 | sim_activate (&tti_unit, tti_unit.wait); /* activate keyboard */\r | |
612 | sim_cancel (&tto_unit); /* stop printer */\r | |
613 | return SCPE_OK;\r | |
614 | }\r |