First Commit of my working state
[simh.git] / PDP11 / pdp11_stddev.c
1 /* pdp11_stddev.c: PDP-11 standard I/O devices simulator
2
3 Copyright (c) 1993-2008, Robert M Supnik
4
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:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
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.
21
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.
25
26 tti,tto DL11 terminal input/output
27 clk KW11L (and other) line frequency clock
28
29 20-May-08 RMS Standardized clock delay at 1mips
30 18-Jun-07 RMS Added UNIT_IDLE flag to console input, clock
31 29-Oct-06 RMS Synced keyboard and clock
32 Added clock coscheduling support
33 05-Jul-06 RMS Added UC only support for early DOS/RSTS
34 22-Nov-05 RMS Revised for new terminal processing routines
35 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
36 07-Jul-05 RMS Removed extraneous externs
37 11-Oct-04 RMS Added clock model dependencies
38 28-May-04 RMS Removed SET TTI CTRL-C
39 29-Dec-03 RMS Added console backpressure support
40 25-Apr-03 RMS Revised for extended file support
41 01-Mar-03 RMS Added SET/SHOW CLOCK FREQ, SET TTI CTRL-C
42 22-Nov-02 RMS Changed terminal default to 7B for UNIX
43 01-Nov-02 RMS Added 7B/8B support to terminal
44 29-Sep-02 RMS Added vector display support
45 Split out paper tape
46 Split DL11 dibs
47 30-May-02 RMS Widened POS to 32b
48 26-Jan-02 RMS Revised for multiple timers
49 09-Jan-02 RMS Fixed bugs in KW11L (found by John Dundas)
50 06-Jan-02 RMS Split I/O address routines, revised enable/disable support
51 29-Nov-01 RMS Added read only unit support
52 09-Nov-01 RMS Added RQDX3 support
53 07-Oct-01 RMS Upgraded clock to full KW11L for RSTS/E autoconfigure
54 07-Sep-01 RMS Moved function prototypes, revised interrupt mechanism
55 17-Jul-01 RMS Moved function prototype
56 04-Jul-01 RMS Added DZ11 support
57 05-Mar-01 RMS Added clock calibration support
58 30-Oct-00 RMS Standardized register order
59 25-Jun-98 RMS Fixed bugs in paper tape error handling
60 */
61
62 #include "pdp11_defs.h"
63
64 #define TTICSR_IMP (CSR_DONE + CSR_IE) /* terminal input */
65 #define TTICSR_RW (CSR_IE)
66 #define TTOCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */
67 #define TTOCSR_RW (CSR_IE)
68 #define CLKCSR_IMP (CSR_DONE + CSR_IE) /* real-time clock */
69 #define CLKCSR_RW (CSR_IE)
70 #define CLK_DELAY 16667
71
72 extern int32 int_req[IPL_HLVL];
73 extern uint32 cpu_type;
74
75 int32 tti_csr = 0; /* control/status */
76 int32 tto_csr = 0; /* control/status */
77 int32 clk_csr = 0; /* control/status */
78 int32 clk_tps = 60; /* ticks/second */
79 int32 clk_default = 60; /* default ticks/second */
80 int32 clk_fie = 0; /* force IE = 1 */
81 int32 clk_fnxm = 0; /* force NXM on reg */
82 int32 tmxr_poll = CLK_DELAY; /* term mux poll */
83 int32 tmr_poll = CLK_DELAY; /* timer poll */
84
85 t_stat tti_rd (int32 *data, int32 PA, int32 access);
86 t_stat tti_wr (int32 data, int32 PA, int32 access);
87 t_stat tti_svc (UNIT *uptr);
88 t_stat tti_reset (DEVICE *dptr);
89 t_stat tto_rd (int32 *data, int32 PA, int32 access);
90 t_stat tto_wr (int32 data, int32 PA, int32 access);
91 t_stat tto_svc (UNIT *uptr);
92 t_stat tto_reset (DEVICE *dptr);
93 t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
94 t_stat clk_rd (int32 *data, int32 PA, int32 access);
95 t_stat clk_wr (int32 data, int32 PA, int32 access);
96 t_stat clk_svc (UNIT *uptr);
97 int32 clk_inta (void);
98 t_stat clk_reset (DEVICE *dptr);
99 t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
100 t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
101
102 /* TTI data structures
103
104 tti_dev TTI device descriptor
105 tti_unit TTI unit descriptor
106 tti_reg TTI register list
107 */
108
109 DIB tti_dib = {
110 IOBA_TTI, IOLN_TTI, &tti_rd, &tti_wr,
111 1, IVCL (TTI), VEC_TTI, { NULL }
112 };
113
114 UNIT tti_unit = { UDATA (&tti_svc, UNIT_IDLE, 0), 0 };
115
116 REG tti_reg[] = {
117 { ORDATA (BUF, tti_unit.buf, 8) },
118 { ORDATA (CSR, tti_csr, 16) },
119 { FLDATA (INT, IREQ (TTI), INT_V_TTI) },
120 { FLDATA (ERR, tti_csr, CSR_V_ERR) },
121 { FLDATA (DONE, tti_csr, CSR_V_DONE) },
122 { FLDATA (IE, tti_csr, CSR_V_IE) },
123 { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
124 { DRDATA (TIME, tti_unit.wait, 24), PV_LEFT },
125 { NULL }
126 };
127
128 MTAB tti_mod[] = {
129 { TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_mode },
130 { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },
131 { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },
132 { TT_MODE, TT_MODE_7P, "7b", NULL, NULL },
133 { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
134 NULL, &show_addr, NULL },
135 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
136 NULL, &show_vec, NULL },
137 { 0 }
138 };
139
140 DEVICE tti_dev = {
141 "TTI", &tti_unit, tti_reg, tti_mod,
142 1, 10, 31, 1, 8, 8,
143 NULL, NULL, &tti_reset,
144 NULL, NULL, NULL,
145 &tti_dib, DEV_UBUS | DEV_QBUS
146 };
147
148 /* TTO data structures
149
150 tto_dev TTO device descriptor
151 tto_unit TTO unit descriptor
152 tto_reg TTO register list
153 */
154
155 DIB tto_dib = {
156 IOBA_TTO, IOLN_TTO, &tto_rd, &tto_wr,
157 1, IVCL (TTO), VEC_TTO, { NULL }
158 };
159
160 UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_7P, 0), SERIAL_OUT_WAIT };
161
162 REG tto_reg[] = {
163 { ORDATA (BUF, tto_unit.buf, 8) },
164 { ORDATA (CSR, tto_csr, 16) },
165 { FLDATA (INT, IREQ (TTO), INT_V_TTO) },
166 { FLDATA (ERR, tto_csr, CSR_V_ERR) },
167 { FLDATA (DONE, tto_csr, CSR_V_DONE) },
168 { FLDATA (IE, tto_csr, CSR_V_IE) },
169 { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
170 { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
171 { NULL }
172 };
173
174 MTAB tto_mod[] = {
175 { TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_mode },
176 { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },
177 { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },
178 { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode },
179 { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
180 NULL, &show_addr, NULL },
181 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
182 NULL, &show_vec, NULL },
183 { 0 }
184 };
185
186 DEVICE tto_dev = {
187 "TTO", &tto_unit, tto_reg, tto_mod,
188 1, 10, 31, 1, 8, 8,
189 NULL, NULL, &tto_reset,
190 NULL, NULL, NULL,
191 &tto_dib, DEV_UBUS | DEV_QBUS
192 };
193
194 /* CLK data structures
195
196 clk_dev CLK device descriptor
197 clk_unit CLK unit descriptor
198 clk_reg CLK register list
199 */
200
201 DIB clk_dib = {
202 IOBA_CLK, IOLN_CLK, &clk_rd, &clk_wr,
203 1, IVCL (CLK), VEC_CLK, { &clk_inta }
204 };
205
206 UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), CLK_DELAY };
207
208 REG clk_reg[] = {
209 { ORDATA (CSR, clk_csr, 16) },
210 { FLDATA (INT, IREQ (CLK), INT_V_CLK) },
211 { FLDATA (DONE, clk_csr, CSR_V_DONE) },
212 { FLDATA (IE, clk_csr, CSR_V_IE) },
213 { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
214 { DRDATA (TPS, clk_tps, 16), PV_LEFT + REG_HRO },
215 { DRDATA (DEFTPS, clk_default, 16), PV_LEFT + REG_HRO },
216 { FLDATA (FIE, clk_fie, 0), REG_HIDDEN },
217 { FLDATA (FNXM, clk_fnxm, 0), REG_HIDDEN },
218 { NULL }
219 };
220
221 MTAB clk_mod[] = {
222 { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
223 &clk_set_freq, NULL, NULL },
224 { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
225 &clk_set_freq, NULL, NULL },
226 { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
227 NULL, &clk_show_freq, NULL },
228 { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
229 NULL, &show_addr, NULL },
230 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
231 NULL, &show_vec, NULL },
232 { 0 }
233 };
234
235 DEVICE clk_dev = {
236 "CLK", &clk_unit, clk_reg, clk_mod,
237 1, 0, 0, 0, 0, 0,
238 NULL, NULL, &clk_reset,
239 NULL, NULL, NULL,
240 &clk_dib, DEV_UBUS | DEV_QBUS
241 };
242
243 /* Terminal input address routines */
244
245 t_stat tti_rd (int32 *data, int32 PA, int32 access)
246 {
247 switch ((PA >> 1) & 01) { /* decode PA<1> */
248
249 case 00: /* tti csr */
250 *data = tti_csr & TTICSR_IMP;
251 return SCPE_OK;
252
253 case 01: /* tti buf */
254 tti_csr = tti_csr & ~CSR_DONE;
255 CLR_INT (TTI);
256 *data = tti_unit.buf & 0377;
257 return SCPE_OK;
258 } /* end switch PA */
259
260 return SCPE_NXM;
261 }
262
263 t_stat tti_wr (int32 data, int32 PA, int32 access)
264 {
265 switch ((PA >> 1) & 01) { /* decode PA<1> */
266
267 case 00: /* tti csr */
268 if (PA & 1) return SCPE_OK;
269 if ((data & CSR_IE) == 0) CLR_INT (TTI);
270 else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
271 SET_INT (TTI);
272 tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW);
273 return SCPE_OK;
274
275 case 01: /* tti buf */
276 return SCPE_OK;
277 } /* end switch PA */
278
279 return SCPE_NXM;
280 }
281
282 /* Terminal input service */
283
284 t_stat tti_svc (UNIT *uptr)
285 {
286 int32 c;
287
288 sim_activate (uptr, KBD_WAIT (uptr->wait, tmr_poll)); /* continue poll */
289 if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
290 if (c & SCPE_BREAK) uptr->buf = 0; /* break? */
291 else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags));
292 uptr->pos = uptr->pos + 1;
293 tti_csr = tti_csr | CSR_DONE;
294 if (tti_csr & CSR_IE) SET_INT (TTI);
295 return SCPE_OK;
296 }
297
298 /* Terminal input reset */
299
300 t_stat tti_reset (DEVICE *dptr)
301 {
302 tti_unit.buf = 0;
303 tti_csr = 0;
304 CLR_INT (TTI);
305 sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmr_poll));
306 return SCPE_OK;
307 }
308
309 /* Terminal output address routines */
310
311 t_stat tto_rd (int32 *data, int32 PA, int32 access)
312 {
313 switch ((PA >> 1) & 01) { /* decode PA<1> */
314
315 case 00: /* tto csr */
316 *data = tto_csr & TTOCSR_IMP;
317 return SCPE_OK;
318
319 case 01: /* tto buf */
320 *data = tto_unit.buf;
321 return SCPE_OK;
322 } /* end switch PA */
323
324 return SCPE_NXM;
325 }
326
327 t_stat tto_wr (int32 data, int32 PA, int32 access)
328 {
329 switch ((PA >> 1) & 01) { /* decode PA<1> */
330
331 case 00: /* tto csr */
332 if (PA & 1) return SCPE_OK;
333 if ((data & CSR_IE) == 0) CLR_INT (TTO);
334 else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
335 SET_INT (TTO);
336 tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW);
337 return SCPE_OK;
338
339 case 01: /* tto buf */
340 if ((PA & 1) == 0) tto_unit.buf = data & 0377;
341 tto_csr = tto_csr & ~CSR_DONE;
342 CLR_INT (TTO);
343 sim_activate (&tto_unit, tto_unit.wait);
344 return SCPE_OK;
345 } /* end switch PA */
346
347 return SCPE_NXM;
348 }
349
350 /* Terminal output service */
351
352 t_stat tto_svc (UNIT *uptr)
353 {
354 int32 c;
355 t_stat r;
356
357 c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags));
358 if (c >= 0) {
359 if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
360 sim_activate (uptr, uptr->wait); /* try again */
361 return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */
362 }
363 }
364 tto_csr = tto_csr | CSR_DONE;
365 if (tto_csr & CSR_IE) SET_INT (TTO);
366 uptr->pos = uptr->pos + 1;
367 return SCPE_OK;
368 }
369
370 /* Terminal output reset */
371
372 t_stat tto_reset (DEVICE *dptr)
373 {
374 tto_unit.buf = 0;
375 tto_csr = CSR_DONE;
376 CLR_INT (TTO);
377 sim_cancel (&tto_unit); /* deactivate unit */
378 return SCPE_OK;
379 }
380
381 t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
382 {
383 tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val;
384 tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val;
385 return SCPE_OK;
386 }
387
388 /* The line time clock has a few twists and turns through the history of 11's
389
390 LSI-11 no CSR
391 LSI-11/23 (KDF11A) no CSR
392 PDP-11/23+ (KDF11B) no monitor bit
393 PDP-11/24 (KDF11U) monitor bit clears on IAK
394 */
395
396 /* Clock I/O address routines */
397
398 t_stat clk_rd (int32 *data, int32 PA, int32 access)
399 {
400 if (clk_fnxm) return SCPE_NXM; /* not there??? */
401 if (CPUT (HAS_LTCM)) *data = clk_csr & CLKCSR_IMP; /* monitor bit? */
402 else *data = clk_csr & (CLKCSR_IMP & ~CSR_DONE); /* no, just IE */
403 return SCPE_OK;
404 }
405
406 t_stat clk_wr (int32 data, int32 PA, int32 access)
407 {
408 if (clk_fnxm) return SCPE_NXM; /* not there??? */
409 if (PA & 1) return SCPE_OK;
410 clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
411 if (CPUT (HAS_LTCM) && ((data & CSR_DONE) == 0)) /* monitor bit? */
412 clk_csr = clk_csr & ~CSR_DONE; /* clr if zero */
413 if ((((clk_csr & CSR_IE) == 0) && !clk_fie) || /* unless IE+DONE */
414 ((clk_csr & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */
415 return SCPE_OK;
416 }
417
418 /* Clock service */
419
420 t_stat clk_svc (UNIT *uptr)
421 {
422 int32 t;
423
424 clk_csr = clk_csr | CSR_DONE; /* set done */
425 if ((clk_csr & CSR_IE) || clk_fie) SET_INT (CLK);
426 t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
427 sim_activate (&clk_unit, t); /* reactivate unit */
428 tmr_poll = t; /* set timer poll */
429 tmxr_poll = t; /* set mux poll */
430 return SCPE_OK;
431 }
432
433 /* Clock interrupt acknowledge */
434
435 int32 clk_inta (void)
436 {
437 if (CPUT (CPUT_24)) clk_csr = clk_csr & ~CSR_DONE;
438 return clk_dib.vec;
439 }
440
441 /* Clock coscheduling routine */
442
443 int32 clk_cosched (int32 wait)
444 {
445 int32 t;
446
447 t = sim_is_active (&clk_unit);
448 return (t? t - 1: wait);
449 }
450
451 /* Clock reset */
452
453 t_stat clk_reset (DEVICE *dptr)
454 {
455 if (CPUT (HAS_LTCR)) clk_fie = clk_fnxm = 0; /* reg there? */
456 else clk_fie = clk_fnxm = 1; /* no, BEVENT */
457 clk_tps = clk_default; /* set default tps */
458 clk_csr = CSR_DONE; /* set done */
459 CLR_INT (CLK);
460 sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init line clock */
461 sim_activate_abs (&clk_unit, clk_unit.wait); /* activate unit */
462 tmr_poll = clk_unit.wait; /* set timer poll */
463 tmxr_poll = clk_unit.wait; /* set mux poll */
464 return SCPE_OK;
465 }
466
467 /* Set frequency */
468
469 t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
470 {
471 if (cptr) return SCPE_ARG;
472 if ((val != 50) && (val != 60)) return SCPE_IERR;
473 clk_tps = clk_default = val;
474 return SCPE_OK;
475 }
476
477 /* Show frequency */
478
479 t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
480 {
481 fprintf (st, "%dHz", clk_tps);
482 return SCPE_OK;
483 }