First Commit of my working state
[simh.git] / VAX / vax_stddev.c
CommitLineData
196ba1fc
PH
1/* vax_stddev.c: VAX 3900 standard I/O devices\r
2\r
3 Copyright (c) 1998-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 tti terminal input\r
27 tto terminal output\r
28 clk 100Hz and TODR clock\r
29\r
30 18-Jun-07 RMS Added UNIT_IDLE flag to console input, clock\r
31 17-Oct-06 RMS Synced keyboard poll to real-time clock for idling\r
32 22-Nov-05 RMS Revised for new terminal processing routines\r
33 09-Sep-04 RMS Integrated powerup into RESET (with -p)\r
34 28-May-04 RMS Removed SET TTI CTRL-C\r
35 29-Dec-03 RMS Added console backpressure support\r
36 25-Apr-03 RMS Revised for extended file support\r
37 02-Mar-02 RMS Added SET TTI CTRL-C\r
38 22-Dec-02 RMS Added console halt capability\r
39 01-Nov-02 RMS Added 7B/8B capability to terminal\r
40 12-Sep-02 RMS Removed paper tape, added variable vector support\r
41 30-May-02 RMS Widened POS to 32b\r
42 30-Apr-02 RMS Automatically set TODR to VMS-correct value during boot\r
43*/\r
44\r
45#include "vax_defs.h"\r
46#include <time.h>\r
47\r
48#define TTICSR_IMP (CSR_DONE + CSR_IE) /* terminal input */\r
49#define TTICSR_RW (CSR_IE)\r
50#define TTIBUF_ERR 0x8000 /* error */\r
51#define TTIBUF_OVR 0x4000 /* overrun */\r
52#define TTIBUF_FRM 0x2000 /* framing error */\r
53#define TTIBUF_RBR 0x0400 /* receive break */\r
54#define TTOCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */\r
55#define TTOCSR_RW (CSR_IE)\r
56#define CLKCSR_IMP (CSR_IE) /* real-time clock */\r
57#define CLKCSR_RW (CSR_IE)\r
58#define CLK_DELAY 5000 /* 100 Hz */\r
59#define TMXR_MULT 1 /* 100 Hz */\r
60\r
61extern int32 int_req[IPL_HLVL];\r
62extern int32 hlt_pin;\r
63extern int32 sim_switches;\r
64\r
65int32 tti_csr = 0; /* control/status */\r
66int32 tto_csr = 0; /* control/status */\r
67int32 clk_csr = 0; /* control/status */\r
68int32 clk_tps = 100; /* ticks/second */\r
69int32 todr_reg = 0; /* TODR register */\r
70int32 todr_blow = 1; /* TODR battery low */\r
71int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */\r
72int32 tmr_poll = CLK_DELAY; /* pgm timer poll */\r
73\r
74t_stat tti_svc (UNIT *uptr);\r
75t_stat tto_svc (UNIT *uptr);\r
76t_stat clk_svc (UNIT *uptr);\r
77t_stat tti_reset (DEVICE *dptr);\r
78t_stat tto_reset (DEVICE *dptr);\r
79t_stat clk_reset (DEVICE *dptr);\r
80\r
81extern int32 sysd_hlt_enb (void);\r
82\r
83/* TTI data structures\r
84\r
85 tti_dev TTI device descriptor\r
86 tti_unit TTI unit descriptor\r
87 tti_reg TTI register list\r
88*/\r
89\r
90DIB tti_dib = { 0, 0, NULL, NULL, 1, IVCL (TTI), SCB_TTI, { NULL } };\r
91\r
92UNIT tti_unit = { UDATA (&tti_svc, UNIT_IDLE|TT_MODE_8B, 0), 0 };\r
93\r
94REG tti_reg[] = {\r
95 { HRDATA (BUF, tti_unit.buf, 16) },\r
96 { HRDATA (CSR, tti_csr, 16) },\r
97 { FLDATA (INT, int_req[IPL_TTI], INT_V_TTI) },\r
98 { FLDATA (DONE, tti_csr, CSR_V_DONE) },\r
99 { FLDATA (IE, tti_csr, CSR_V_IE) },\r
100 { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },\r
101 { DRDATA (TIME, tti_unit.wait, 24), PV_LEFT },\r
102 { NULL }\r
103 };\r
104\r
105MTAB tti_mod[] = {\r
106 { TT_MODE, TT_MODE_7B, "7b", "7B", NULL },\r
107 { TT_MODE, TT_MODE_8B, "8b", "8B", NULL },\r
108 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,\r
109 NULL, &show_vec, NULL },\r
110 { 0 }\r
111 };\r
112\r
113DEVICE tti_dev = {\r
114 "TTI", &tti_unit, tti_reg, tti_mod,\r
115 1, 10, 31, 1, 16, 8,\r
116 NULL, NULL, &tti_reset,\r
117 NULL, NULL, NULL,\r
118 &tti_dib, 0\r
119 };\r
120\r
121/* TTO data structures\r
122\r
123 tto_dev TTO device descriptor\r
124 tto_unit TTO unit descriptor\r
125 tto_reg TTO register list\r
126*/\r
127\r
128DIB tto_dib = { 0, 0, NULL, NULL, 1, IVCL (TTO), SCB_TTO, { NULL } };\r
129\r
130UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_8B, 0), SERIAL_OUT_WAIT };\r
131\r
132REG tto_reg[] = {\r
133 { HRDATA (BUF, tto_unit.buf, 8) },\r
134 { HRDATA (CSR, tto_csr, 16) },\r
135 { FLDATA (INT, int_req[IPL_TTO], INT_V_TTO) },\r
136 { FLDATA (DONE, tto_csr, CSR_V_DONE) },\r
137 { FLDATA (IE, tto_csr, CSR_V_IE) },\r
138 { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },\r
139 { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },\r
140 { NULL }\r
141 };\r
142\r
143MTAB tto_mod[] = {\r
144 { TT_MODE, TT_MODE_7B, "7b", "7B", NULL },\r
145 { TT_MODE, TT_MODE_8B, "8b", "8B", NULL },\r
146 { TT_MODE, TT_MODE_7P, "7p", "7P", NULL },\r
147 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec },\r
148 { 0 }\r
149 };\r
150\r
151DEVICE tto_dev = {\r
152 "TTO", &tto_unit, tto_reg, tto_mod,\r
153 1, 10, 31, 1, 16, 8,\r
154 NULL, NULL, &tto_reset,\r
155 NULL, NULL, NULL,\r
156 &tto_dib, 0\r
157 };\r
158\r
159/* CLK data structures\r
160\r
161 clk_dev CLK device descriptor\r
162 clk_unit CLK unit descriptor\r
163 clk_reg CLK register list\r
164*/\r
165\r
166DIB clk_dib = { 0, 0, NULL, NULL, 1, IVCL (CLK), SCB_INTTIM, { NULL } };\r
167\r
168UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), CLK_DELAY };\r
169\r
170REG clk_reg[] = {\r
171 { HRDATA (CSR, clk_csr, 16) },\r
172 { FLDATA (INT, int_req[IPL_CLK], INT_V_CLK) },\r
173 { FLDATA (IE, clk_csr, CSR_V_IE) },\r
174 { DRDATA (TODR, todr_reg, 32), PV_LEFT },\r
175 { FLDATA (BLOW, todr_blow, 0) },\r
176 { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },\r
177 { DRDATA (POLL, tmr_poll, 24), REG_NZ + PV_LEFT + REG_HRO },\r
178 { DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },\r
179 { NULL }\r
180 };\r
181\r
182MTAB clk_mod[] = {\r
183 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec },\r
184 { 0 }\r
185 };\r
186\r
187DEVICE clk_dev = {\r
188 "CLK", &clk_unit, clk_reg, clk_mod,\r
189 1, 0, 0, 0, 0, 0,\r
190 NULL, NULL, &clk_reset,\r
191 NULL, NULL, NULL,\r
192 &clk_dib, 0\r
193 };\r
194\r
195/* Clock and terminal MxPR routines\r
196\r
197 iccs_rd/wr interval timer\r
198 todr_rd/wr time of year clock\r
199 rxcs_rd/wr input control/status\r
200 rxdb_rd input buffer\r
201 txcs_rd/wr output control/status\r
202 txdb_wr output buffer\r
203*/\r
204\r
205int32 iccs_rd (void)\r
206{\r
207return (clk_csr & CLKCSR_IMP);\r
208}\r
209\r
210int32 todr_rd (void)\r
211{\r
212return todr_reg;\r
213}\r
214\r
215int32 rxcs_rd (void)\r
216{\r
217return (tti_csr & TTICSR_IMP);\r
218}\r
219\r
220int32 rxdb_rd (void)\r
221{\r
222int32 t = tti_unit.buf; /* char + error */\r
223\r
224tti_csr = tti_csr & ~CSR_DONE; /* clr done */\r
225tti_unit.buf = tti_unit.buf & 0377; /* clr errors */\r
226CLR_INT (TTI);\r
227return t;\r
228}\r
229\r
230int32 txcs_rd (void)\r
231{\r
232return (tto_csr & TTOCSR_IMP);\r
233}\r
234\r
235void iccs_wr (int32 data)\r
236{\r
237if ((data & CSR_IE) == 0) CLR_INT (CLK);\r
238clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);\r
239return;\r
240}\r
241\r
242void todr_wr (int32 data)\r
243{\r
244todr_reg = data;\r
245if (data) todr_blow = 0;\r
246return;\r
247}\r
248\r
249void rxcs_wr (int32 data)\r
250{\r
251if ((data & CSR_IE) == 0) CLR_INT (TTI);\r
252else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)\r
253 SET_INT (TTI);\r
254tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW);\r
255return;\r
256}\r
257\r
258void txcs_wr (int32 data)\r
259{\r
260if ((data & CSR_IE) == 0) CLR_INT (TTO);\r
261else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)\r
262 SET_INT (TTO);\r
263tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW);\r
264return;\r
265}\r
266\r
267void txdb_wr (int32 data)\r
268{\r
269tto_unit.buf = data & 0377;\r
270tto_csr = tto_csr & ~CSR_DONE;\r
271CLR_INT (TTO);\r
272sim_activate (&tto_unit, tto_unit.wait);\r
273return;\r
274}\r
275\r
276/* Terminal input routines\r
277\r
278 tti_svc process event (character ready)\r
279 tti_reset process reset\r
280*/\r
281\r
282t_stat tti_svc (UNIT *uptr)\r
283{\r
284int32 c;\r
285\r
286sim_activate (uptr, KBD_WAIT (uptr->wait, tmr_poll)); /* continue poll */\r
287if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */\r
288if (c & SCPE_BREAK) { /* break? */\r
289 if (sysd_hlt_enb ()) hlt_pin = 1; /* if enabled, halt */\r
290 tti_unit.buf = TTIBUF_ERR | TTIBUF_FRM | TTIBUF_RBR;\r
291 }\r
292else tti_unit.buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags));\r
293uptr->pos = uptr->pos + 1;\r
294tti_csr = tti_csr | CSR_DONE;\r
295if (tti_csr & CSR_IE) SET_INT (TTI);\r
296return SCPE_OK;\r
297}\r
298\r
299t_stat tti_reset (DEVICE *dptr)\r
300{\r
301tti_unit.buf = 0;\r
302tti_csr = 0;\r
303CLR_INT (TTI);\r
304sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmr_poll));\r
305return SCPE_OK;\r
306}\r
307\r
308/* Terminal output routines\r
309\r
310 tto_svc process event (character typed)\r
311 tto_reset process reset\r
312*/\r
313\r
314t_stat tto_svc (UNIT *uptr)\r
315{\r
316int32 c;\r
317t_stat r;\r
318\r
319c = sim_tt_outcvt (tto_unit.buf, TT_GET_MODE (uptr->flags));\r
320if (c >= 0) {\r
321 if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */\r
322 sim_activate (uptr, uptr->wait); /* retry */\r
323 return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */\r
324 }\r
325 }\r
326tto_csr = tto_csr | CSR_DONE;\r
327if (tto_csr & CSR_IE) SET_INT (TTO);\r
328uptr->pos = uptr->pos + 1;\r
329return SCPE_OK;\r
330}\r
331\r
332t_stat tto_reset (DEVICE *dptr)\r
333{\r
334tto_unit.buf = 0;\r
335tto_csr = CSR_DONE;\r
336CLR_INT (TTO);\r
337sim_cancel (&tto_unit); /* deactivate unit */\r
338return SCPE_OK;\r
339}\r
340\r
341/* Clock routines\r
342\r
343 clk_svc process event (clock tick)\r
344 clk_reset process reset\r
345 todr_powerup powerup for TODR (get date from system)\r
346*/\r
347\r
348t_stat clk_svc (UNIT *uptr)\r
349{\r
350int32 t;\r
351\r
352if (clk_csr & CSR_IE) SET_INT (CLK);\r
353t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */\r
354sim_activate (&clk_unit, t); /* reactivate unit */\r
355tmr_poll = t; /* set tmr poll */\r
356tmxr_poll = t * TMXR_MULT; /* set mux poll */\r
357if (!todr_blow) todr_reg = todr_reg + 1; /* incr TODR */\r
358return SCPE_OK;\r
359}\r
360\r
361/* Clock coscheduling routine */\r
362\r
363int32 clk_cosched (int32 wait)\r
364{\r
365int32 t;\r
366\r
367t = sim_is_active (&clk_unit);\r
368return (t? t - 1: wait);\r
369}\r
370\r
371/* Powerup routine */\r
372\r
373t_stat todr_powerup (void)\r
374{\r
375uint32 base;\r
376time_t curr;\r
377struct tm *ctm;\r
378\r
379curr = time (NULL); /* get curr time */\r
380if (curr == (time_t) -1) return SCPE_NOFNC; /* error? */\r
381ctm = localtime (&curr); /* decompose */\r
382if (ctm == NULL) return SCPE_NOFNC; /* error? */\r
383base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */\r
384 ctm->tm_hour) * 60) +\r
385 ctm->tm_min) * 60) +\r
386 ctm->tm_sec;\r
387todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */\r
388todr_blow = 0;\r
389return SCPE_OK;\r
390}\r
391\r
392/* Reset routine */\r
393\r
394t_stat clk_reset (DEVICE *dptr)\r
395{\r
396int32 t;\r
397\r
398if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? */\r
399clk_csr = 0;\r
400CLR_INT (CLK);\r
401t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init timer */\r
402sim_activate_abs (&clk_unit, t); /* activate unit */\r
403tmr_poll = t; /* set tmr poll */\r
404tmxr_poll = t * TMXR_MULT; /* set mux poll */\r
405return SCPE_OK;\r
406}\r
407\r