1 /* pdp11_stddev.c: PDP-11 standard I/O devices simulator
3 Copyright (c) 1993-2008, 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 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.
26 tti,tto DL11 terminal input/output
27 clk KW11L (and other) line frequency clock
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
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
62 #include "pdp11_defs.h"
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
72 extern int32 int_req
[IPL_HLVL
];
73 extern uint32 cpu_type
;
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 */
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
);
102 /* TTI data structures
104 tti_dev TTI device descriptor
105 tti_unit TTI unit descriptor
106 tti_reg TTI register list
110 IOBA_TTI
, IOLN_TTI
, &tti_rd
, &tti_wr
,
111 1, IVCL (TTI
), VEC_TTI
, { NULL
}
114 UNIT tti_unit
= { UDATA (&tti_svc
, UNIT_IDLE
, 0), 0 };
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
},
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
},
141 "TTI", &tti_unit
, tti_reg
, tti_mod
,
143 NULL
, NULL
, &tti_reset
,
145 &tti_dib
, DEV_UBUS
| DEV_QBUS
148 /* TTO data structures
150 tto_dev TTO device descriptor
151 tto_unit TTO unit descriptor
152 tto_reg TTO register list
156 IOBA_TTO
, IOLN_TTO
, &tto_rd
, &tto_wr
,
157 1, IVCL (TTO
), VEC_TTO
, { NULL
}
160 UNIT tto_unit
= { UDATA (&tto_svc
, TT_MODE_7P
, 0), SERIAL_OUT_WAIT
};
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
},
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
},
187 "TTO", &tto_unit
, tto_reg
, tto_mod
,
189 NULL
, NULL
, &tto_reset
,
191 &tto_dib
, DEV_UBUS
| DEV_QBUS
194 /* CLK data structures
196 clk_dev CLK device descriptor
197 clk_unit CLK unit descriptor
198 clk_reg CLK register list
202 IOBA_CLK
, IOLN_CLK
, &clk_rd
, &clk_wr
,
203 1, IVCL (CLK
), VEC_CLK
, { &clk_inta
}
206 UNIT clk_unit
= { UDATA (&clk_svc
, UNIT_IDLE
, 0), CLK_DELAY
};
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
},
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
},
236 "CLK", &clk_unit
, clk_reg
, clk_mod
,
238 NULL
, NULL
, &clk_reset
,
240 &clk_dib
, DEV_UBUS
| DEV_QBUS
243 /* Terminal input address routines */
245 t_stat
tti_rd (int32
*data
, int32 PA
, int32 access
)
247 switch ((PA
>> 1) & 01) { /* decode PA<1> */
249 case 00: /* tti csr */
250 *data
= tti_csr
& TTICSR_IMP
;
253 case 01: /* tti buf */
254 tti_csr
= tti_csr
& ~CSR_DONE
;
256 *data
= tti_unit
.buf
& 0377;
258 } /* end switch PA */
263 t_stat
tti_wr (int32 data
, int32 PA
, int32 access
)
265 switch ((PA
>> 1) & 01) { /* decode PA<1> */
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
)
272 tti_csr
= (tti_csr
& ~TTICSR_RW
) | (data
& TTICSR_RW
);
275 case 01: /* tti buf */
277 } /* end switch PA */
282 /* Terminal input service */
284 t_stat
tti_svc (UNIT
*uptr
)
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
);
298 /* Terminal input reset */
300 t_stat
tti_reset (DEVICE
*dptr
)
305 sim_activate_abs (&tti_unit
, KBD_WAIT (tti_unit
.wait
, tmr_poll
));
309 /* Terminal output address routines */
311 t_stat
tto_rd (int32
*data
, int32 PA
, int32 access
)
313 switch ((PA
>> 1) & 01) { /* decode PA<1> */
315 case 00: /* tto csr */
316 *data
= tto_csr
& TTOCSR_IMP
;
319 case 01: /* tto buf */
320 *data
= tto_unit
.buf
;
322 } /* end switch PA */
327 t_stat
tto_wr (int32 data
, int32 PA
, int32 access
)
329 switch ((PA
>> 1) & 01) { /* decode PA<1> */
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
)
336 tto_csr
= (tto_csr
& ~TTOCSR_RW
) | (data
& TTOCSR_RW
);
339 case 01: /* tto buf */
340 if ((PA
& 1) == 0) tto_unit
.buf
= data
& 0377;
341 tto_csr
= tto_csr
& ~CSR_DONE
;
343 sim_activate (&tto_unit
, tto_unit
.wait
);
345 } /* end switch PA */
350 /* Terminal output service */
352 t_stat
tto_svc (UNIT
*uptr
)
357 c
= sim_tt_outcvt (uptr
->buf
, TT_GET_MODE (uptr
->flags
));
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 */
364 tto_csr
= tto_csr
| CSR_DONE
;
365 if (tto_csr
& CSR_IE
) SET_INT (TTO
);
366 uptr
->pos
= uptr
->pos
+ 1;
370 /* Terminal output reset */
372 t_stat
tto_reset (DEVICE
*dptr
)
377 sim_cancel (&tto_unit
); /* deactivate unit */
381 t_stat
tty_set_mode (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
383 tti_unit
.flags
= (tti_unit
.flags
& ~TT_MODE
) | val
;
384 tto_unit
.flags
= (tto_unit
.flags
& ~TT_MODE
) | val
;
388 /* The line time clock has a few twists and turns through the history of 11's
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
396 /* Clock I/O address routines */
398 t_stat
clk_rd (int32
*data
, int32 PA
, int32 access
)
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 */
406 t_stat
clk_wr (int32 data
, int32 PA
, int32 access
)
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 */
420 t_stat
clk_svc (UNIT
*uptr
)
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 */
433 /* Clock interrupt acknowledge */
435 int32
clk_inta (void)
437 if (CPUT (CPUT_24
)) clk_csr
= clk_csr
& ~CSR_DONE
;
441 /* Clock coscheduling routine */
443 int32
clk_cosched (int32 wait
)
447 t
= sim_is_active (&clk_unit
);
448 return (t
? t
- 1: wait
);
453 t_stat
clk_reset (DEVICE
*dptr
)
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 */
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 */
469 t_stat
clk_set_freq (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
471 if (cptr
) return SCPE_ARG
;
472 if ((val
!= 50) && (val
!= 60)) return SCPE_IERR
;
473 clk_tps
= clk_default
= val
;
479 t_stat
clk_show_freq (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
481 fprintf (st
, "%dHz", clk_tps
);