First Commit of my working state
[simh.git] / H316 / h316_stddev.c
CommitLineData
196ba1fc
PH
1/* h316_stddev.c: Honeywell 316/516 standard devices\r
2\r
3 Copyright (c) 1999-2007, 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 316/516-50 paper tape reader\r
27 ptp 316/516-52 paper tape punch\r
28 tty 316/516-33 teleprinter\r
29 clk/options 316/516-12 real time clocks/internal options\r
30\r
31 09-Jun-07 RMS Fixed bug in clock increment (found by Theo Engel)\r
32 30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode\r
33 03-Apr-06 RMS Fixed bugs in punch state handling (from Theo Engel)\r
34 22-Nov-05 RMS Revised for new terminal processing routines\r
35 05-Feb-05 RMS Fixed bug in OCP '0001 (found by Philipp Hachtmann)\r
36 31-Jan-05 RMS Fixed bug in TTY print (found by Philipp Hachtmann)\r
37 01-Dec-04 RMS Fixed problem in SKS '104 (reported by Philipp Hachtmann)\r
38 Fixed bug in SKS '504\r
39 Added PTR detach routine, stops motion\r
40 Added PTR/PTP ASCII file support\r
41 Added TTR/TTP support\r
42 24-Oct-03 RMS Added DMA/DMC support\r
43 25-Apr-03 RMS Revised for extended file support\r
44 01-Mar-03 RMS Added SET/SHOW CLK FREQ support\r
45 22-Dec-02 RMS Added break support\r
46 01-Nov-02 RMS Added 7b/8b support to terminal\r
47 30-May-02 RMS Widened POS to 32b\r
48 03-Nov-01 RMS Implemented upper case for console output\r
49 29-Nov-01 RMS Added read only unit support\r
50 07-Sep-01 RMS Moved function prototypes\r
51\r
52 The ASR-33/35 reader/punch logic, and the ASCII file support for all paper tape\r
53 devices, logic is taken, with grateful thanks, from Adrian Wise's H316 emulator.\r
54\r
55 Teletype reader transitions:\r
56\r
57 - SET TTY2 START puts the reader in RUN\r
58 - XOFF from keyboard/reader stops the reader after 1-2 more characters are read\r
59 - XON from program starts the reader\r
60 - Detach, SET TTY2 STOP, or end of file stops the reader\r
61\r
62 Teletype punch transitions:\r
63\r
64 - SET TTY3 START puts the punch in RUN\r
65 - XOFF from program stops the punch after 1 more character is punched\r
66 - TAPE from program starts the punch after 1 character delay\r
67 - Detach or SET TTY3 STOP stops the punch\r
68*/\r
69\r
70#include "h316_defs.h"\r
71#include <ctype.h>\r
72\r
73#define UNIT_V_ASC (TTUF_V_UF + 0) /* ASCII */\r
74#define UNIT_V_UASC (TTUF_V_UF + 1) /* Unix ASCII */\r
75#define UNIT_ASC (1 << UNIT_V_ASC)\r
76#define UNIT_UASC (1 << UNIT_V_UASC)\r
77#define STA u3 /* state bits */\r
78#define LF_PEND 01 /* lf pending */\r
79#define RUNNING 02 /* tape running */\r
80\r
81#define XON 0021\r
82#define TAPE 0022\r
83#define XOFF 0023\r
84#define RUBOUT 0377\r
85\r
86extern uint16 M[];\r
87extern int32 PC;\r
88extern int32 stop_inst;\r
89extern int32 C, dp, ext, extoff_pending, sc;\r
90extern int32 dev_int, dev_enb;\r
91extern int32 sim_switches;\r
92extern UNIT cpu_unit;\r
93\r
94uint32 ptr_motion = 0; /* read motion */\r
95uint32 ptr_stopioe = 0; /* stop on error */\r
96uint32 ptp_stopioe = 0;\r
97uint32 ptp_power = 0; /* punch power, time */\r
98int32 ptp_ptime;\r
99uint32 ttr_stopioe = 0;\r
100uint32 tty_mode = 0; /* input (0), output (1) */\r
101uint32 tty_buf = 0; /* tty buffer */\r
102uint32 ttr_xoff_read = 0;\r
103uint32 ttp_tape_rcvd = 0;\r
104uint32 ttp_xoff_rcvd = 0;\r
105int32 clk_tps = 60; /* ticks per second */\r
106\r
107int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev);\r
108t_stat ptr_svc (UNIT *uptr);\r
109t_stat ptr_reset (DEVICE *dptr);\r
110t_stat ptr_boot (int32 unitno, DEVICE *dptr);\r
111int32 ptpio (int32 inst, int32 fnc, int32 dat, int32 dev);\r
112t_stat ptp_svc (UNIT *uptr);\r
113t_stat ptp_reset (DEVICE *dptr);\r
114int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev);\r
115t_stat tti_svc (UNIT *uptr);\r
116t_stat tto_svc (UNIT *uptr);\r
117t_stat tty_reset (DEVICE *dptr);\r
118t_stat ttio_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);\r
119t_stat ttrp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);\r
120t_stat ttrp_set_start_stop (UNIT *uptr, int32 val, char *cptr, void *desc);\r
121int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev);\r
122t_stat clk_svc (UNIT *uptr);\r
123t_stat clk_reset (DEVICE *dptr);\r
124t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);\r
125t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);\r
126t_stat pt_attach (UNIT *uptr, char *cptr);\r
127t_stat pt_detach (UNIT *uptr);\r
128t_stat tto_write (int32 c);\r
129t_stat ttp_write (int32 c);\r
130\r
131/* PTR data structures\r
132\r
133 ptr_dev PTR device descriptor\r
134 ptr_unit PTR unit descriptor\r
135 ptr_mod PTR modifiers\r
136 ptr_reg PTR register list\r
137*/\r
138\r
139DIB ptr_dib = { PTR, IOBUS, 1, &ptrio };\r
140\r
141UNIT ptr_unit = {\r
142 UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),\r
143 SERIAL_IN_WAIT\r
144 };\r
145\r
146REG ptr_reg[] = {\r
147 { ORDATA (BUF, ptr_unit.buf, 8) },\r
148 { FLDATA (READY, dev_int, INT_V_PTR) },\r
149 { FLDATA (ENABLE, dev_enb, INT_V_PTR) },\r
150 { FLDATA (MOTION, ptr_motion, 0) },\r
151 { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },\r
152 { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },\r
153 { ORDATA (RSTATE, ptr_unit.STA, 2), REG_HIDDEN },\r
154 { FLDATA (STOP_IOE, ptr_stopioe, 0) },\r
155 { NULL }\r
156 };\r
157\r
158MTAB pt_mod[] = {\r
159 { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC, "ASCII", NULL },\r
160 { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC+UNIT_UASC, "Unix ASCII", NULL },\r
161 { 0 }\r
162 };\r
163\r
164DEVICE ptr_dev = {\r
165 "PTR", &ptr_unit, ptr_reg, pt_mod,\r
166 1, 10, 31, 1, 8, 8,\r
167 NULL, NULL, &ptr_reset,\r
168 &ptr_boot, &pt_attach, &pt_detach,\r
169 &ptr_dib, 0\r
170 };\r
171\r
172/* PTP data structures\r
173\r
174 ptp_dev PTP device descriptor\r
175 ptp_unit PTP unit descriptor\r
176 ptp_mod PTP modifiers\r
177 ptp_reg PTP register list\r
178*/\r
179\r
180DIB ptp_dib = { PTP, IOBUS, 1, &ptpio };\r
181\r
182UNIT ptp_unit = {\r
183 UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT\r
184 };\r
185\r
186REG ptp_reg[] = {\r
187 { ORDATA (BUF, ptp_unit.buf, 8) },\r
188 { FLDATA (READY, dev_int, INT_V_PTP) },\r
189 { FLDATA (ENABLE, dev_enb, INT_V_PTP) },\r
190 { FLDATA (POWER, ptp_power, 0) },\r
191 { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },\r
192 { ORDATA (PSTATE, ptp_unit.STA, 2), REG_HIDDEN },\r
193 { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },\r
194 { DRDATA (PWRTIME, ptp_ptime, 24), PV_LEFT },\r
195 { FLDATA (STOP_IOE, ptp_stopioe, 0) },\r
196 { NULL }\r
197 };\r
198\r
199DEVICE ptp_dev = {\r
200 "PTP", &ptp_unit, ptp_reg, pt_mod,\r
201 1, 10, 31, 1, 8, 8,\r
202 NULL, NULL, &ptp_reset,\r
203 NULL, &pt_attach, NULL,\r
204 &ptp_dib, 0\r
205 };\r
206\r
207/* TTY data structures\r
208\r
209 tty_dev TTY device descriptor\r
210 tty_unit TTY unit descriptor\r
211 tty_reg TTY register list\r
212 tty_mod TTy modifiers list\r
213*/\r
214\r
215#define TTI 0\r
216#define TTO 1\r
217#define TTR 2\r
218#define TTP 3\r
219\r
220DIB tty_dib = { TTY, IOBUS, 1, &ttyio };\r
221\r
222UNIT tty_unit[] = {\r
223 { UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT },\r
224 { UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT },\r
225 { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) },\r
226 { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }\r
227 };\r
228\r
229REG tty_reg[] = {\r
230 { ORDATA (BUF, tty_buf, 8) },\r
231 { FLDATA (MODE, tty_mode, 0) },\r
232 { FLDATA (READY, dev_int, INT_V_TTY) },\r
233 { FLDATA (ENABLE, dev_enb, INT_V_TTY) },\r
234 { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT },\r
235 { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT },\r
236 { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT },\r
237 { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT },\r
238 { ORDATA (RXOFF, ttr_xoff_read, 2), REG_HIDDEN },\r
239 { ORDATA (RSTATE, tty_unit[TTR].STA, 2), REG_HIDDEN },\r
240 { DRDATA (RPOS, tty_unit[TTR].pos, T_ADDR_W), PV_LEFT },\r
241 { ORDATA (PTAPE, ttp_tape_rcvd, 2), REG_HIDDEN },\r
242 { ORDATA (PXOFF, ttp_xoff_rcvd, 2), REG_HIDDEN },\r
243 { ORDATA (PSTATE, tty_unit[TTP].STA, 2), REG_HIDDEN },\r
244 { DRDATA (PPOS, tty_unit[TTP].pos, T_ADDR_W), PV_LEFT },\r
245 { FLDATA (STOP_IOE, ttr_stopioe, 0) },\r
246 { NULL }\r
247 };\r
248\r
249MTAB tty_mod[] = {\r
250 { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &ttio_set_mode },\r
251 { TT_MODE, TT_MODE_7B, "7b", "7B", &ttio_set_mode },\r
252 { TT_MODE, TT_MODE_8B, "8b", "8B", &ttio_set_mode },\r
253 { TT_MODE, TT_MODE_7P, "7p", "7P", &ttio_set_mode },\r
254 { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE, NULL, "BINARY",\r
255 &ttrp_set_mode },\r
256 { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC, "ASCII", "ASCII",\r
257 &ttrp_set_mode },\r
258 { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, "Unix ASCII", "UASCII",\r
259 &ttrp_set_mode },\r
260 { MTAB_XTD|MTAB_VUN|MTAB_NMO, 1, NULL, "START", &ttrp_set_start_stop },\r
261 { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, NULL, "STOP", &ttrp_set_start_stop },\r
262 { 0 }\r
263 };\r
264\r
265DEVICE tty_dev = {\r
266 "TTY", tty_unit, tty_reg, tty_mod,\r
267 4, 10, 31, 1, 8, 8,\r
268 NULL, NULL, &tty_reset,\r
269 NULL, &pt_attach, &pt_detach,\r
270 &tty_dib, 0\r
271 };\r
272\r
273/* CLK data structures\r
274\r
275 clk_dev CLK device descriptor\r
276 clk_unit CLK unit descriptor\r
277 clk_mod CLK modifiers\r
278 clk_reg CLK register list\r
279*/\r
280\r
281DIB clk_dib = { CLK_KEYS, IOBUS, 1, &clkio };\r
282\r
283UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 };\r
284\r
285REG clk_reg[] = {\r
286 { FLDATA (READY, dev_int, INT_V_CLK) },\r
287 { FLDATA (ENABLE, dev_enb, INT_V_CLK) },\r
288 { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },\r
289 { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },\r
290 { NULL }\r
291 };\r
292\r
293MTAB clk_mod[] = {\r
294 { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",\r
295 &clk_set_freq, NULL, NULL },\r
296 { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",\r
297 &clk_set_freq, NULL, NULL },\r
298 { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,\r
299 NULL, &clk_show_freq, NULL },\r
300 { 0 }\r
301 };\r
302\r
303DEVICE clk_dev = {\r
304 "CLK", &clk_unit, clk_reg, clk_mod,\r
305 1, 0, 0, 0, 0, 0,\r
306 NULL, NULL, &clk_reset,\r
307 NULL, NULL, NULL,\r
308 &clk_dib, 0\r
309 };\r
310\r
311/* Paper tape reader: IO routine */\r
312\r
313int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev)\r
314{\r
315switch (inst) { /* case on opcode */\r
316\r
317 case ioOCP: /* OCP */\r
318 if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */\r
319 ptr_motion = fnc ^ 1;\r
320 if (fnc) sim_cancel (&ptr_unit); /* fnc 1? stop */\r
321 else sim_activate (&ptr_unit, ptr_unit.wait); /* fnc 0? start */\r
322 break;\r
323\r
324 case ioSKS: /* SKS */\r
325 if (fnc & 013) return IOBADFNC (dat); /* only fnc 0,4 */\r
326 if (((fnc == 000) && TST_INT (INT_PTR)) || /* fnc 0? skip rdy */\r
327 ((fnc == 004) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */\r
328 return IOSKIP (dat);\r
329 break;\r
330\r
331 case ioINA: /* INA */\r
332 if (fnc) return IOBADFNC (dat); /* only fnc 0 */\r
333 if (TST_INT (INT_PTR)) { /* ready? */\r
334 CLR_INT (INT_PTR); /* clear ready */\r
335 if (ptr_motion) /* if motion, restart */\r
336 sim_activate (&ptr_unit, ptr_unit.wait);\r
337 return IOSKIP (ptr_unit.buf | dat); /* ret buf, skip */\r
338 }\r
339 break;\r
340 } /* end case op */\r
341\r
342return dat;\r
343}\r
344\r
345/* Unit service */\r
346\r
347t_stat ptr_svc (UNIT *uptr)\r
348{\r
349int32 c;\r
350\r
351if ((uptr->flags & UNIT_ATT) == 0) /* attached? */\r
352 return IORETURN (ptr_stopioe, SCPE_UNATT);\r
353if (uptr->STA & LF_PEND) { /* lf pending? */\r
354 uptr->STA &= ~LF_PEND; /* clear flag */\r
355 c = 0212; /* insert LF */\r
356 }\r
357else {\r
358 if ((c = getc (uptr->fileref)) == EOF) { /* read byte */\r
359 if (feof (uptr->fileref)) {\r
360 if (ptr_stopioe) printf ("PTR end of file\n");\r
361 else return SCPE_OK;\r
362 }\r
363 else perror ("PTR I/O error");\r
364 clearerr (uptr->fileref);\r
365 return SCPE_IOERR;\r
366 }\r
367 if ((uptr->flags & UNIT_UASC) && (c == '\n')) { /* Unix newline? */\r
368 c = 0215; /* insert CR */\r
369 uptr->STA |= LF_PEND; /* lf pending */\r
370 }\r
371 else if ((uptr->flags & UNIT_ASC) && (c != 0)) /* ASCII? */\r
372 c = c | 0200;\r
373 uptr->pos = ftell (uptr->fileref); /* update pos */\r
374 }\r
375SET_INT (INT_PTR); /* set ready flag */\r
376uptr->buf = c & 0377; /* get byte */\r
377return SCPE_OK;\r
378}\r
379\r
380/* Paper tape attach routine - set or clear ASC/UASC flags if specified */\r
381\r
382t_stat pt_attach (UNIT *uptr, char *cptr)\r
383{\r
384t_stat r;\r
385\r
386if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC;\r
387if (r = attach_unit (uptr, cptr)) return r;\r
388if (sim_switches & SWMASK ('A')) /* -a? ASCII */\r
389 uptr->flags |= UNIT_ASC;\r
390else if (sim_switches & SWMASK ('U')) /* -u? Unix ASCII */\r
391 uptr->flags |= (UNIT_ASC|UNIT_UASC);\r
392else if (sim_switches & SWMASK ('B')) /* -b? binary */\r
393 uptr->flags &= ~(UNIT_ASC|UNIT_UASC);\r
394uptr->STA = 0;\r
395return r;\r
396}\r
397\r
398/* Detach routine - stop motion if not restore */\r
399\r
400t_stat pt_detach (UNIT *uptr)\r
401{\r
402if (!(sim_switches & SIM_SW_REST)) sim_cancel (uptr); /* stop motion */\r
403uptr->STA = 0;\r
404return detach_unit (uptr);\r
405}\r
406\r
407/* Reset routine */\r
408\r
409t_stat ptr_reset (DEVICE *dptr)\r
410{\r
411CLR_INT (INT_PTR); /* clear ready, enb */\r
412CLR_ENB (INT_PTR);\r
413ptr_unit.buf = 0; /* clear buffer */\r
414ptr_unit.STA = 0;\r
415ptr_motion = 0; /* unit stopped */\r
416sim_cancel (&ptr_unit); /* deactivate unit */\r
417return SCPE_OK;\r
418}\r
419\r
420/* Paper tape reader bootstrap routine */\r
421\r
422#define PBOOT_START 1\r
423#define PBOOT_SIZE (sizeof (pboot) / sizeof (int32))\r
424\r
425static const int32 pboot[] = {\r
426 0010057, /* STA 57 */\r
427 0030001, /* OCP 1 */\r
428 0131001, /* READ, INA 1001 */\r
429 0002003, /* JMP READ */\r
430 0101040, /* SNZ */\r
431 0002003, /* JMP READ */\r
432 0010000, /* STA 0 */\r
433 0131001, /* READ1, INA 1001 */\r
434 0002010, /* JMP READ1 */\r
435 0041470, /* LGL 8 */\r
436 0130001, /* READ2, INA 1 */\r
437 0002013, /* JMP READ2 */\r
438 0110000, /* STA* 0 */\r
439 0024000, /* IRS 0 */\r
440 0100040 /* SZE */\r
441 };\r
442\r
443t_stat ptr_boot (int32 unitno, DEVICE *dptr)\r
444{\r
445int32 i;\r
446\r
447for (i = 0; i < PBOOT_SIZE; i++) /* copy bootstrap */\r
448 M[PBOOT_START + i] = pboot[i];\r
449PC = PBOOT_START; \r
450return SCPE_OK;\r
451}\r
452\r
453/* Paper tape punch: IO routine */\r
454\r
455int32 ptpio (int32 inst, int32 fnc, int32 dat, int32 dev)\r
456{\r
457switch (inst) { /* case on opcode */\r
458\r
459 case ioOCP: /* OCP */\r
460 if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */\r
461 if (fnc) { /* fnc 1? pwr off */\r
462 CLR_INT (INT_PTP); /* not ready */\r
463 ptp_power = 0; /* turn off power */\r
464 sim_cancel (&ptp_unit); /* stop punch */\r
465 }\r
466 else if (ptp_power == 0) /* fnc 0? start */\r
467 sim_activate (&ptp_unit, ptp_ptime);\r
468 break;\r
469\r
470 case ioSKS: /* SKS */\r
471 if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */\r
472 return IOBADFNC (dat);\r
473 if (((fnc == 000) && TST_INT (INT_PTP)) || /* fnc 0? skip rdy */\r
474 ((fnc == 001) && /* fnc 1? skip ptp on */\r
475 (ptp_power || sim_is_active (&ptp_unit))) ||\r
476 ((fnc == 004) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */\r
477 return IOSKIP (dat);\r
478 break;\r
479\r
480 case ioOTA: /* OTA */\r
481 if (fnc) return IOBADFNC (dat); /* only fnc 0 */\r
482 if (TST_INT (INT_PTP)) { /* if ptp ready */\r
483 CLR_INT (INT_PTP); /* clear ready */\r
484 ptp_unit.buf = dat & 0377; /* store byte */\r
485 sim_activate (&ptp_unit, ptp_unit.wait);\r
486 return IOSKIP (dat); /* skip return */\r
487 }\r
488 break;\r
489 }\r
490\r
491return dat;\r
492}\r
493\r
494/* Unit service */\r
495\r
496t_stat ptp_svc (UNIT *uptr)\r
497{\r
498int32 c;\r
499\r
500SET_INT (INT_PTP); /* set flag */\r
501if (ptp_power == 0) { /* power on? */\r
502 ptp_power = 1; /* ptp is ready */\r
503 return SCPE_OK;\r
504 }\r
505if ((uptr->flags & UNIT_ATT) == 0) /* attached? */\r
506 return IORETURN (ptp_stopioe, SCPE_UNATT);\r
507if (uptr->flags & UNIT_ASC) { /* ASCII? */\r
508 c = uptr->buf & 0177; /* mask to 7b */\r
509 if ((uptr->flags & UNIT_UASC) && (c == 015)) /* cr? drop if Unix */\r
510 return SCPE_OK;\r
511 else if (c == 012) c = '\n'; /* lf? cvt to nl */\r
512 }\r
513else c = uptr->buf & 0377; /* no, binary */\r
514if (putc (c, uptr->fileref) == EOF) { /* output byte */\r
515 perror ("PTP I/O error");\r
516 clearerr (uptr->fileref);\r
517 return SCPE_IOERR;\r
518 }\r
519uptr->pos = ftell (uptr->fileref); /* update pos */\r
520return SCPE_OK;\r
521}\r
522\r
523/* Reset routine */\r
524\r
525t_stat ptp_reset (DEVICE *dptr)\r
526{\r
527CLR_INT (INT_PTP); /* clear ready, enb */\r
528CLR_ENB (INT_PTP);\r
529ptp_power = 0; /* power off */\r
530ptp_unit.buf = 0; /* clear buffer */\r
531ptp_unit.STA = 0;\r
532sim_cancel (&ptp_unit); /* deactivate unit */\r
533return SCPE_OK;\r
534}\r
535\r
536/* Terminal: IO routine */\r
537\r
538int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev)\r
539{\r
540switch (inst) { /* case on opcode */\r
541\r
542 case ioOCP: /* OCP */\r
543 if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */\r
544 if (fnc && (tty_mode == 0)) { /* input to output? */\r
545 if (!sim_is_active (&tty_unit[TTO])) /* set ready */\r
546 SET_INT (INT_TTY);\r
547 tty_mode = 1; /* mode is output */\r
548 }\r
549 else if ((fnc == 0) && tty_mode) { /* output to input? */\r
550 CLR_INT (INT_TTY); /* clear ready */\r
551 tty_mode = 0; /* mode is input */\r
552 }\r
553 break;\r
554\r
555 case ioSKS: /* SKS */\r
556 if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */\r
557 if (((fnc == 000) && TST_INT (INT_TTY)) || /* fnc 0? skip rdy */\r
558 ((fnc == 001) && /* fnc 1? skip !busy */\r
559 (!tty_mode || !sim_is_active (&tty_unit[TTO]))) ||\r
560 ((fnc == 004) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */\r
561 ((fnc == 005) && (tty_mode || /* fnc 5? skip !xoff */\r
562 ((tty_buf & 0177) != XOFF)))) /* input & XOFF char */\r
563 return IOSKIP (dat);\r
564 break;\r
565\r
566 case ioINA: /* INA */\r
567 if (fnc & 005) return IOBADFNC (dat); /* only 0,2 */\r
568 if (TST_INT (INT_TTY)) { /* ready? */\r
569 if (tty_mode == 0) CLR_INT (INT_TTY); /* inp? clear rdy */\r
570 return IOSKIP (dat |\r
571 (tty_buf & ((fnc & 002)? 077: 0377)));\r
572 }\r
573 break;\r
574\r
575 case ioOTA:\r
576 if (fnc & 015) return IOBADFNC (dat); /* only 0,2 */\r
577 if (TST_INT (INT_TTY)) { /* ready? */\r
578 tty_buf = dat & 0377; /* store char */\r
579 if (fnc & 002) { /* binary mode? */\r
580 tty_buf = tty_buf | 0100; /* set ch 7 */\r
581 if (tty_buf & 040) tty_buf = tty_buf & 0277;\r
582 }\r
583 if (tty_mode) {\r
584 sim_activate (&tty_unit[TTO], tty_unit[TTO].wait);\r
585 CLR_INT (INT_TTY);\r
586 }\r
587 return IOSKIP (dat);\r
588 }\r
589 break;\r
590 } /* end case op */\r
591\r
592return dat;\r
593}\r
594\r
595/* Input service - keyboard and reader */\r
596\r
597t_stat tti_svc (UNIT *uptr)\r
598{\r
599int32 out, c;\r
600UNIT *ruptr = &tty_unit[TTR];\r
601\r
602sim_activate (uptr, uptr->wait); /* continue poll */\r
603if ((c = sim_poll_kbd ()) >= SCPE_KFLAG) { /* character? */\r
604 out = c & 0177; /* mask echo to 7b */\r
605 if (c & SCPE_BREAK) c = 0; /* break? */\r
606 else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR);\r
607 uptr->pos = uptr->pos + 1;\r
608 }\r
609else if (c != SCPE_OK) return c; /* error? */\r
610else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */\r
611 (ruptr->STA & RUNNING)) { /* and running? */\r
612 if (ruptr->STA & LF_PEND) { /* lf pending? */\r
613 c = 0212; /* char is lf */\r
614 ruptr->STA &= ~LF_PEND; /* clear flag */\r
615 }\r
616 else { /* normal read */\r
617 if ((c = getc (ruptr->fileref)) == EOF) { /* read byte */\r
618 if (feof (ruptr->fileref)) { /* EOF? */\r
619 ruptr->STA &= ~RUNNING; /* stop reader */\r
620 if (ttr_stopioe) printf ("TTR end of file\n");\r
621 else return SCPE_OK;\r
622 }\r
623 else perror ("TTR I/O error");\r
624 clearerr (ruptr->fileref);\r
625 return SCPE_IOERR;\r
626 }\r
627 if ((ruptr->flags & UNIT_UASC) && (c == '\n')) {\r
628 c = 0215; /* Unix ASCII NL? */\r
629 ruptr->STA |= LF_PEND; /* LF pending */\r
630 }\r
631 else if ((ruptr->flags & UNIT_ASC) && (c != 0))\r
632 c = c | 0200; /* ASCII nz? cvt */\r
633 ruptr->pos = ftell (ruptr->fileref);\r
634 }\r
635 if (ttr_xoff_read != 0) { /* reader stopping? */\r
636 if (c == RUBOUT) ttr_xoff_read = 0; /* rubout? stop */\r
637 else ttr_xoff_read--; /* else decr state */\r
638 if (ttr_xoff_read == 0) /* delay done? */\r
639 ruptr->STA &= ~RUNNING; /* stop reader */\r
640 }\r
641 else if ((c & 0177) == XOFF) ttr_xoff_read = 2; /* XOFF read? */\r
642 out = c; /* echo char */\r
643 }\r
644else return SCPE_OK; /* no char */\r
645if (tty_mode == 0) { /* input mode? */\r
646 tty_buf = c & 0377; /* put char in buf */\r
647 SET_INT (INT_TTY); /* set flag */\r
648 }\r
649tto_write (out); /* echo to printer */\r
650return ttp_write (out); /* and punch */\r
651}\r
652\r
653/* Output service - printer and punch */\r
654\r
655t_stat tto_svc (UNIT *uptr)\r
656{\r
657uint32 c7b;\r
658UNIT *ruptr = &tty_unit[TTR];\r
659UNIT *puptr = &tty_unit[TTP];\r
660t_stat r;\r
661\r
662c7b = tty_buf & 0177;\r
663if (ttp_tape_rcvd != 0) { /* prev = tape? */\r
664 ttp_tape_rcvd--; /* decrement state */\r
665 if ((ttp_tape_rcvd == 0) && (puptr->flags & UNIT_ATT))\r
666 puptr->STA |= RUNNING; /* start after delay */\r
667 }\r
668else if (c7b == TAPE) ttp_tape_rcvd = 2; /* char = TAPE? */\r
669if (ttp_xoff_rcvd != 0) { /* prev = XOFF? */\r
670 ttp_xoff_rcvd--; /* decrement state */\r
671 if (ttp_xoff_rcvd == 0) puptr->STA &= ~RUNNING; /* stop after delay */\r
672 }\r
673else if (c7b == XOFF) ttp_xoff_rcvd = 2; /* char = XOFF? */\r
674if ((c7b == XON) && (ruptr->flags & UNIT_ATT)) { /* char = XON? */\r
675 ruptr->STA |= RUNNING; /* start reader */\r
676 ttr_xoff_read = 0; /* cancel stop */\r
677 }\r
678if ((r = tto_write (tty_buf)) != SCPE_OK) { /* print; error? */\r
679 sim_activate (uptr, uptr->wait); /* try again */\r
680 return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */\r
681 }\r
682if ((r = ttp_write (tty_buf)) != SCPE_OK) return r; /* punch; error? */\r
683SET_INT (INT_TTY); /* set done flag */\r
684return SCPE_OK;\r
685}\r
686\r
687/* Output to printer */\r
688\r
689t_stat tto_write (int32 c)\r
690{\r
691UNIT *tuptr = &tty_unit[TTO];\r
692\r
693c = sim_tt_outcvt (c, TT_GET_MODE (tuptr->flags) | TTUF_KSR);\r
694tuptr->pos = tuptr->pos + 1;\r
695if (c >= 0) return sim_putchar_s (c);\r
696else return SCPE_OK;\r
697}\r
698\r
699/* Output to punch */\r
700\r
701t_stat ttp_write (int32 c)\r
702{\r
703uint32 p, c7b;\r
704UNIT *puptr = &tty_unit[TTP];\r
705\r
706if ((puptr->flags & UNIT_ATT) && /* TTP attached */\r
707 (puptr->STA & RUNNING)) { /* and running? */\r
708 c7b = c & 0177;\r
709 if (!(puptr->flags & UNIT_UASC) || (c7b != 015)) {\r
710 if (puptr->flags & UNIT_ASC) { /* ASCII? */\r
711 if (c7b == 012) p = '\n'; /* cvt LF */\r
712 else p = c7b; /* else 7b */\r
713 }\r
714 else p = c; /* untouched */\r
715 if (putc (p, puptr->fileref) == EOF) { /* output byte */\r
716 perror ("TTP I/O error");\r
717 clearerr (puptr->fileref);\r
718 return SCPE_IOERR;\r
719 }\r
720 puptr->pos = ftell (puptr->fileref); /* update pos */\r
721 }\r
722 }\r
723return SCPE_OK;\r
724}\r
725\r
726/* Reset routine */\r
727\r
728t_stat tty_reset (DEVICE *dptr)\r
729{\r
730CLR_INT (INT_TTY); /* clear ready, enb */\r
731CLR_ENB (INT_TTY);\r
732tty_mode = 0; /* mode = input */\r
733tty_buf = 0;\r
734ttr_xoff_read = 0; /* clr TTR, TTP flags */\r
735ttp_tape_rcvd = 0;\r
736ttp_xoff_rcvd = 0;\r
737tty_unit[TTR].STA = 0;\r
738tty_unit[TTP].STA = 0;\r
739sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */\r
740sim_cancel (&tty_unit[TTO]); /* cancel output */\r
741return SCPE_OK;\r
742}\r
743\r
744/* Set keyboard/printer mode - make sure flags agree */\r
745\r
746t_stat ttio_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)\r
747{\r
748if (uptr->flags & UNIT_ATTABLE) return SCPE_NOFNC; /* not TTR, TTP */\r
749tty_unit[TTO].flags = (tty_unit[TTO].flags & ~TT_MODE) | val;\r
750if (val == TT_MODE_7P) val = TT_MODE_7B;\r
751tty_unit[TTI].flags = (tty_unit[TTI].flags & ~TT_MODE) | val;\r
752return SCPE_OK;\r
753}\r
754\r
755/* Set reader/punch mode */\r
756\r
757t_stat ttrp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)\r
758{\r
759if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; /* TTR, TTP only */\r
760if (!(val & UNIT_UASC)) uptr->STA &= ~LF_PEND;\r
761return SCPE_OK;\r
762}\r
763\r
764/* Set reader/punch start/stop */\r
765\r
766t_stat ttrp_set_start_stop (UNIT *uptr, int32 val, char *cptr, void *desc)\r
767{\r
768if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; /* TTR, TTP only */\r
769if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; /* must be attached */\r
770if (val) uptr->STA |= RUNNING; /* start? set running */\r
771else uptr->STA &= ~RUNNING; /* stop? clr running */\r
772if (uptr->flags & UNIT_ROABLE) ttr_xoff_read = 0; /* TTR? cancel stop */\r
773else ttp_tape_rcvd = ttp_xoff_rcvd = 0; /* TTP? cancel all */\r
774return SCPE_OK;\r
775}\r
776\r
777/* Clock/options: IO routine */\r
778\r
779int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev)\r
780{\r
781switch (inst) { /* case on opcode */\r
782\r
783 case ioOCP: /* OCP */\r
784 if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */\r
785 CLR_INT (INT_CLK); /* reset ready */\r
786 if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */\r
787 else { /* fnc = 0? */\r
788 if (!sim_is_active (&clk_unit))\r
789 sim_activate (&clk_unit, /* activate */\r
790 sim_rtc_init (clk_unit.wait)); /* init calibr */\r
791 }\r
792 break;\r
793\r
794 case ioSKS: /* SKS */\r
795 if (fnc == 000) { /* clock skip !int */\r
796 if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat);\r
797 }\r
798 else if ((fnc & 007) == 002) { /* mem parity? */\r
799 if (((fnc == 002) && !TST_INT (INT_MPE)) ||\r
800 ((fnc == 012) && TST_INT (INT_MPE)))\r
801 return IOSKIP (dat);\r
802 }\r
803 else return IOBADFNC (dat); /* invalid fnc */\r
804 break;\r
805\r
806 case ioOTA: /* OTA */\r
807 if (fnc == 000) dev_enb = dat; /* SMK */\r
808 else if (fnc == 010) { /* OTK */\r
809 C = (dat >> 15) & 1; /* set C */\r
810 if (cpu_unit.flags & UNIT_HSA) /* HSA included? */\r
811 dp = (dat >> 14) & 1; /* set dp */\r
812 if (cpu_unit.flags & UNIT_EXT) { /* ext opt? */\r
813 if (dat & 020000) { /* ext set? */\r
814 ext = 1; /* yes, set */\r
815 extoff_pending = 0;\r
816 }\r
817 else extoff_pending = 1; /* no, clr later */\r
818 }\r
819 sc = dat & 037; /* set sc */\r
820 }\r
821 else return IOBADFNC (dat);\r
822 break;\r
823 }\r
824\r
825return dat;\r
826}\r
827\r
828/* Unit service */\r
829\r
830t_stat clk_svc (UNIT *uptr)\r
831{\r
832\r
833M[M_CLK] = (M[M_CLK] + 1) & DMASK; /* increment mem ctr */\r
834if (M[M_CLK] == 0) SET_INT (INT_CLK); /* = 0? set flag */\r
835sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */\r
836return SCPE_OK;\r
837}\r
838\r
839/* Reset routine */\r
840\r
841t_stat clk_reset (DEVICE *dptr)\r
842{\r
843CLR_INT (INT_CLK); /* clear ready, enb */\r
844CLR_ENB (INT_CLK);\r
845sim_cancel (&clk_unit); /* deactivate unit */\r
846return SCPE_OK;\r
847}\r
848\r
849/* Set frequency */\r
850\r
851t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)\r
852{\r
853if (cptr) return SCPE_ARG;\r
854if ((val != 50) && (val != 60)) return SCPE_IERR;\r
855clk_tps = val;\r
856return SCPE_OK;\r
857}\r
858\r
859/* Show frequency */\r
860\r
861t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)\r
862{\r
863fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");\r
864return SCPE_OK;\r
865}\r