1
/* vax_stddev.c: VAX standard I/O devices simulator
3
Copyright (c) 1998-2004, 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
23
be 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.
28
clk 100Hz and TODR clock
30
29-Dec-03 RMS Added console backpressure support
31
25-Apr-03 RMS Revised for extended file support
32
02-Mar-02 RMS Added SET TTI CTRL-C
33
22-Dec-02 RMS Added console halt capability
34
01-Nov-02 RMS Added 7B/8B capability to terminal
35
12-Sep-02 RMS Removed paper tape, added variable vector support
36
30-May-02 RMS Widened POS to 32b
37
30-Apr-02 RMS Automatically set TODR to VMS-correct value during boot
43
#define TTICSR_IMP (CSR_DONE + CSR_IE) /* terminal input */
44
#define TTICSR_RW (CSR_IE)
45
#define TTIBUF_ERR 0x8000 /* error */
46
#define TTIBUF_OVR 0x4000 /* overrun */
47
#define TTIBUF_FRM 0x2000 /* framing error */
48
#define TTIBUF_RBR 0x0400 /* receive break */
49
#define TTOCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */
50
#define TTOCSR_RW (CSR_IE)
51
#define CLKCSR_IMP (CSR_IE) /* real-time clock */
52
#define CLKCSR_RW (CSR_IE)
53
#define CLK_DELAY 5000 /* 100 Hz */
54
#define TMXR_MULT 2 /* 50 Hz */
56
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B mode */
57
#define UNIT_8B (1 << UNIT_V_8B)
59
extern int32 int_req[IPL_HLVL];
62
int32 tti_csr = 0; /* control/status */
63
int32 tto_csr = 0; /* control/status */
64
int32 clk_csr = 0; /* control/status */
65
int32 clk_tps = 100; /* ticks/second */
66
int32 todr_reg = 0; /* TODR register */
67
int32 todr_blow = 1; /* TODR battery low */
68
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
69
int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
71
t_stat tti_svc (UNIT *uptr);
72
t_stat tto_svc (UNIT *uptr);
73
t_stat clk_svc (UNIT *uptr);
74
t_stat tti_reset (DEVICE *dptr);
75
t_stat tto_reset (DEVICE *dptr);
76
t_stat clk_reset (DEVICE *dptr);
77
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc);
79
extern int32 sysd_hlt_enb (void);
81
/* TTI data structures
83
tti_dev TTI device descriptor
84
tti_unit TTI unit descriptor
85
tti_reg TTI register list
88
DIB tti_dib = { 0, 0, NULL, NULL, 1, IVCL (TTI), SCB_TTI, { NULL } };
90
UNIT tti_unit = { UDATA (&tti_svc, UNIT_8B, 0), KBD_POLL_WAIT };
93
{ HRDATA (BUF, tti_unit.buf, 16) },
94
{ HRDATA (CSR, tti_csr, 16) },
95
{ FLDATA (INT, int_req[IPL_TTI], INT_V_TTI) },
96
{ FLDATA (DONE, tti_csr, CSR_V_DONE) },
97
{ FLDATA (IE, tti_csr, CSR_V_IE) },
98
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
99
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
103
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
104
{ UNIT_8B, 0 , "7b", "7B", NULL },
105
{ MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C",
106
&tti_set_ctrlc, NULL, NULL },
107
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
108
NULL, &show_vec, NULL },
112
"TTI", &tti_unit, tti_reg, tti_mod,
114
NULL, NULL, &tti_reset,
118
/* TTO data structures
120
tto_dev TTO device descriptor
121
tto_unit TTO unit descriptor
122
tto_reg TTO register list
125
DIB tto_dib = { 0, 0, NULL, NULL, 1, IVCL (TTO), SCB_TTO, { NULL } };
127
UNIT tto_unit = { UDATA (&tto_svc, UNIT_8B, 0), SERIAL_OUT_WAIT };
130
{ HRDATA (BUF, tto_unit.buf, 8) },
131
{ HRDATA (CSR, tto_csr, 16) },
132
{ FLDATA (INT, int_req[IPL_TTO], INT_V_TTO) },
133
{ FLDATA (DONE, tto_csr, CSR_V_DONE) },
134
{ FLDATA (IE, tto_csr, CSR_V_IE) },
135
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
136
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
140
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
141
{ UNIT_8B, 0 , "7b", "7B", NULL },
142
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec },
146
"TTO", &tto_unit, tto_reg, tto_mod,
148
NULL, NULL, &tto_reset,
152
/* CLK data structures
154
clk_dev CLK device descriptor
155
clk_unit CLK unit descriptor
156
clk_reg CLK register list
159
DIB clk_dib = { 0, 0, NULL, NULL, 1, IVCL (CLK), SCB_INTTIM, { NULL } };
161
UNIT clk_unit = { UDATA (&clk_svc, 0, 0), CLK_DELAY };
164
{ HRDATA (CSR, clk_csr, 16) },
165
{ FLDATA (INT, int_req[IPL_CLK], INT_V_CLK) },
166
{ FLDATA (IE, clk_csr, CSR_V_IE) },
167
{ DRDATA (TODR, todr_reg, 32), PV_LEFT },
168
{ FLDATA (BLOW, todr_blow, 0) },
169
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
170
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
174
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec },
178
"CLK", &clk_unit, clk_reg, clk_mod,
180
NULL, NULL, &clk_reset,
184
/* Clock and terminal MxPR routines
186
iccs_rd/wr interval timer
187
todr_rd/wr time of year clock
188
rxcs_rd/wr input control/status
190
txcs_rd/wr output control/status
191
txdb_wr output buffer
196
return (clk_csr & CLKCSR_IMP);
206
return (tti_csr & TTICSR_IMP);
211
int32 t = tti_unit.buf; /* char + error */
213
tti_csr = tti_csr & ~CSR_DONE; /* clr done */
214
tti_unit.buf = tti_unit.buf & 0377; /* clr errors */
221
return (tto_csr & TTOCSR_IMP);
224
void iccs_wr (int32 data)
226
if ((data & CSR_IE) == 0) CLR_INT (CLK);
227
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
231
void todr_wr (int32 data)
234
if (data) todr_blow = 0;
238
void rxcs_wr (int32 data)
240
if ((data & CSR_IE) == 0) CLR_INT (TTI);
241
else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
243
tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW);
247
void txcs_wr (int32 data)
249
if ((data & CSR_IE) == 0) CLR_INT (TTO);
250
else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
252
tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW);
256
void txdb_wr (int32 data)
258
tto_unit.buf = data & 0377;
259
tto_csr = tto_csr & ~CSR_DONE;
261
sim_activate (&tto_unit, tto_unit.wait);
265
/* Terminal input routines
267
tti_svc process event (character ready)
268
tti_reset process reset
271
t_stat tti_svc (UNIT *uptr)
275
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
276
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
277
if (c & SCPE_BREAK) { /* break? */
278
if (sysd_hlt_enb ()) hlt_pin = 1; /* if enabled, halt */
279
tti_unit.buf = TTIBUF_ERR | TTIBUF_FRM | TTIBUF_RBR; }
280
else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177);
281
tti_unit.pos = tti_unit.pos + 1;
282
tti_csr = tti_csr | CSR_DONE;
283
if (tti_csr & CSR_IE) SET_INT (TTI);
287
t_stat tti_reset (DEVICE *dptr)
292
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
298
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc)
300
if (cptr) return SCPE_ARG;
302
uptr->pos = uptr->pos + 1;
303
tti_csr = tti_csr | CSR_DONE;
304
if (tti_csr & CSR_IE) SET_INT (TTI);
308
/* Terminal output routines
310
tto_svc process event (character typed)
311
tto_reset process reset
314
t_stat tto_svc (UNIT *uptr)
319
c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
320
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
321
sim_activate (uptr, uptr->wait); /* retry */
322
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
323
tto_csr = tto_csr | CSR_DONE;
324
if (tto_csr & CSR_IE) SET_INT (TTO);
325
tto_unit.pos = tto_unit.pos + 1;
329
t_stat tto_reset (DEVICE *dptr)
334
sim_cancel (&tto_unit); /* deactivate unit */
340
clk_svc process event (clock tick)
341
clk_reset process reset
342
todr_powerup powerup for TODR (get date from system)
345
t_stat clk_svc (UNIT *uptr)
349
if (clk_csr & CSR_IE) SET_INT (CLK);
350
t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
351
sim_activate (&clk_unit, t); /* reactivate unit */
352
tmr_poll = t; /* set tmr poll */
353
tmxr_poll = t * TMXR_MULT; /* set mux poll */
354
if (!todr_blow) todr_reg = todr_reg + 1; /* incr TODR */
358
t_stat clk_reset (DEVICE *dptr)
364
t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init timer */
365
sim_activate (&clk_unit, t); /* activate unit */
366
tmr_poll = t; /* set tmr poll */
367
tmxr_poll = t * TMXR_MULT; /* set mux poll */
371
t_stat todr_powerup (void)
377
curr = time (NULL); /* get curr time */
378
if (curr == (time_t) -1) return SCPE_NOFNC; /* error? */
379
ctm = localtime (&curr); /* decompose */
380
if (ctm == NULL) return SCPE_NOFNC; /* error? */
381
base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */
382
ctm->tm_hour) * 60) +
385
todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */