First Commit of my working state
[simh.git] / GRI / gri_stddev.c
1 /* gri_stddev.c: GRI-909 standard devices
2
3 Copyright (c) 2001-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 S42-001 terminal input
27 tto S42-002 terminal output
28 hsr S42-004 high speed reader
29 hsp S42-006 high speed punch
30 rtc real time clock
31
32 31-May-08 RMS Fixed declarations (found by Peter Schorn)
33 30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode
34 22-Nov-05 RMS Revised for new terminal processing routines
35 29-Dec-03 RMS Added support for console backpressure
36 25-Apr-03 RMS Revised for extended file support
37 22-Dec-02 RMS Added break support
38 01-Nov-02 RMS Added 7b/8B support to terminal
39 */
40
41 #include "gri_defs.h"
42 #include <ctype.h>
43
44 uint32 hsr_stopioe = 1, hsp_stopioe = 1;
45
46 extern uint16 M[];
47 extern uint32 dev_done, ISR;
48
49 t_stat tti_svc (UNIT *uhsr);
50 t_stat tto_svc (UNIT *uhsr);
51 t_stat tti_reset (DEVICE *dhsr);
52 t_stat tto_reset (DEVICE *dhsr);
53 t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
54 t_stat hsr_svc (UNIT *uhsr);
55 t_stat hsp_svc (UNIT *uhsr);
56 t_stat hsr_reset (DEVICE *dhsr);
57 t_stat hsp_reset (DEVICE *dhsr);
58 t_stat rtc_svc (UNIT *uhsr);
59 t_stat rtc_reset (DEVICE *dhsr);
60 int32 rtc_tps = 1000;
61
62 /* TTI data structures
63
64 tti_dev TTI device descriptor
65 tti_unit TTI unit descriptor
66 tti_reg TTI register list
67 tti_mod TTI modifiers list
68 */
69
70 UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT };
71
72 REG tti_reg[] = {
73 { ORDATA (BUF, tti_unit.buf, 8) },
74 { FLDATA (IRDY, dev_done, INT_V_TTI) },
75 { FLDATA (IENB, ISR, INT_V_TTI) },
76 { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
77 { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
78 { NULL }
79 };
80
81 MTAB tti_mod[] = {
82 { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode },
83 { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },
84 { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },
85 { TT_MODE, TT_MODE_7P, "7b", NULL, NULL },
86 { 0 }
87 };
88
89 DEVICE tti_dev = {
90 "TTI", &tti_unit, tti_reg, tti_mod,
91 1, 10, 31, 1, 8, 8,
92 NULL, NULL, &tti_reset,
93 NULL, NULL, NULL
94 };
95
96 /* TTO data structures
97
98 tto_dev TTO device descriptor
99 tto_unit TTO unit descriptor
100 tto_reg TTO register list
101 */
102
103 UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT };
104
105 REG tto_reg[] = {
106 { ORDATA (BUF, tto_unit.buf, 8) },
107 { FLDATA (ORDY, dev_done, INT_V_TTO) },
108 { FLDATA (IENB, ISR, INT_V_TTO) },
109 { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
110 { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
111 { NULL }
112 };
113
114 MTAB tto_mod[] = {
115 { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode },
116 { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },
117 { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },
118 { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode },
119 { 0 }
120 };
121
122 DEVICE tto_dev = {
123 "TTO", &tto_unit, tto_reg, tto_mod,
124 1, 10, 31, 1, 8, 8,
125 NULL, NULL, &tto_reset,
126 NULL, NULL, NULL
127 };
128
129 /* HSR data structures
130
131 hsr_dev HSR device descriptor
132 hsr_unit HSR unit descriptor
133 hsr_reg HSR register list
134 hsr_mod HSR modifiers list
135 */
136
137 UNIT hsr_unit = {
138 UDATA (&hsr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), SERIAL_IN_WAIT
139 };
140
141 REG hsr_reg[] = {
142 { ORDATA (BUF, hsr_unit.buf, 8) },
143 { FLDATA (IRDY, dev_done, INT_V_HSR) },
144 { FLDATA (IENB, ISR, INT_V_HSR) },
145 { DRDATA (POS, hsr_unit.pos, T_ADDR_W), PV_LEFT },
146 { DRDATA (TIME, hsr_unit.wait, 24), REG_NZ + PV_LEFT },
147 { FLDATA (STOP_IOE, hsr_stopioe, 0) },
148 { NULL }
149 };
150
151 DEVICE hsr_dev = {
152 "HSR", &hsr_unit, hsr_reg, NULL,
153 1, 10, 31, 1, 8, 8,
154 NULL, NULL, &hsr_reset,
155 NULL, NULL, NULL
156 };
157
158 /* HSP data structures
159
160 hsp_dev HSP device descriptor
161 hsp_unit HSP unit descriptor
162 hsp_reg HSP register list
163 */
164
165 UNIT hsp_unit = {
166 UDATA (&hsp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
167 };
168
169 REG hsp_reg[] = {
170 { ORDATA (BUF, hsp_unit.buf, 8) },
171 { FLDATA (ORDY, dev_done, INT_V_HSP) },
172 { FLDATA (IENB, ISR, INT_V_HSP) },
173 { DRDATA (POS, hsp_unit.pos, T_ADDR_W), PV_LEFT },
174 { DRDATA (TIME, hsp_unit.wait, 24), PV_LEFT },
175 { FLDATA (STOP_IOE, hsp_stopioe, 0) },
176 { NULL }
177 };
178
179 DEVICE hsp_dev = {
180 "HSP", &hsp_unit, hsp_reg, NULL,
181 1, 10, 31, 1, 8, 8,
182 NULL, NULL, &hsp_reset,
183 NULL, NULL, NULL
184 };
185
186 /* RTC data structures
187
188 rtc_dev RTC device descriptor
189 rtc_unit RTC unit descriptor
190 rtc_reg RTC register list
191 */
192
193 UNIT rtc_unit = { UDATA (&rtc_svc, 0, 0), 16000 };
194
195 REG rtc_reg[] = {
196 { FLDATA (RDY, dev_done, INT_V_RTC) },
197 { FLDATA (IENB, ISR, INT_V_RTC) },
198 { DRDATA (TIME, rtc_unit.wait, 24), REG_NZ + PV_LEFT },
199 { DRDATA (TPS, rtc_tps, 8), REG_NZ + PV_LEFT + REG_HIDDEN },
200 { NULL }
201 };
202
203 DEVICE rtc_dev = {
204 "RTC", &rtc_unit, rtc_reg, NULL,
205 1, 0, 0, 0, 0, 0,
206 NULL, NULL, &rtc_reset,
207 NULL, NULL, NULL
208 };
209
210 /* Console terminal function processors */
211
212 uint32 tty_rd (int32 src, int32 ea)
213 {
214 return tti_unit.buf; /* return data */
215 }
216
217 t_stat tty_wr (uint32 dst, uint32 val)
218 {
219 tto_unit.buf = val & 0377; /* save char */
220 dev_done = dev_done & ~INT_TTO; /* clear ready */
221 sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
222 return SCPE_OK;
223 }
224
225 t_stat tty_fo (uint32 op)
226 {
227 if (op & TTY_IRDY) dev_done = dev_done & ~INT_TTI;
228 if (op & TTY_ORDY) dev_done = dev_done & ~INT_TTO;
229 return SCPE_OK;
230 }
231
232 uint32 tty_sf (uint32 op)
233 {
234 if (((op & TTY_IRDY) && (dev_done & INT_TTI)) ||
235 ((op & TTY_ORDY) && (dev_done & INT_TTO))) return 1;
236 return 0;
237 }
238
239 /* Service routines */
240
241 t_stat tti_svc (UNIT *uptr)
242 {
243 int32 c;
244
245 sim_activate (uptr, uptr->wait); /* continue poll */
246 if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
247 if (c & SCPE_BREAK) uptr->buf = 0; /* break? */
248 else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR);
249 dev_done = dev_done | INT_TTI; /* set ready */
250 uptr->pos = uptr->pos + 1;
251 return SCPE_OK;
252 }
253
254 t_stat tto_svc (UNIT *uptr)
255 {
256 int32 c;
257 t_stat r;
258
259 c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags) | TTUF_KSR);
260 if (c >= 0) {
261 if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
262 sim_activate (uptr, uptr->wait); /* try again */
263 return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */
264 }
265 }
266 dev_done = dev_done | INT_TTO; /* set ready */
267 uptr->pos = uptr->pos + 1;
268 return SCPE_OK;
269 }
270
271 /* Reset routines */
272
273 t_stat tti_reset (DEVICE *dptr)
274 {
275 tti_unit.buf = 0; /* clear buffer */
276 dev_done = dev_done & ~INT_TTI; /* clear ready */
277 sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
278 return SCPE_OK;
279 }
280
281 t_stat tto_reset (DEVICE *dptr)
282 {
283 tto_unit.buf = 0; /* clear buffer */
284 dev_done = dev_done | INT_TTO; /* set ready */
285 sim_cancel (&tto_unit); /* deactivate unit */
286 return SCPE_OK;
287 }
288
289 t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
290 {
291 tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val;
292 tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val;
293 return SCPE_OK;
294 }
295
296 /* High speed paper tape function processors */
297
298 uint32 hsrp_rd (int32 src, int32 ea)
299 {
300 return hsr_unit.buf; /* return data */
301 }
302
303 t_stat hsrp_wr (uint32 dst, uint32 val)
304 {
305 hsp_unit.buf = val & 0377; /* save char */
306 dev_done = dev_done & ~INT_HSP; /* clear ready */
307 sim_activate (&hsp_unit, hsp_unit.wait); /* activate unit */
308 return SCPE_OK;
309 }
310
311 t_stat hsrp_fo (uint32 op)
312 {
313 if (op & PT_IRDY) dev_done = dev_done & ~INT_HSR;
314 if (op & PT_ORDY) dev_done = dev_done & ~INT_HSP;
315 if (op & PT_STRT) sim_activate (&hsr_unit, hsr_unit.wait);
316 return SCPE_OK;
317 }
318
319 uint32 hsrp_sf (uint32 op)
320 {
321 if (((op & PT_IRDY) && (dev_done & INT_HSR)) ||
322 ((op & PT_ORDY) && (dev_done & INT_HSP))) return 1;
323 return 0;
324 }
325
326 t_stat hsr_svc (UNIT *uptr)
327 {
328 int32 temp;
329
330 if ((hsr_unit.flags & UNIT_ATT) == 0) /* attached? */
331 return IORETURN (hsr_stopioe, SCPE_UNATT);
332 if ((temp = getc (hsr_unit.fileref)) == EOF) { /* read char */
333 if (feof (hsr_unit.fileref)) { /* err or eof? */
334 if (hsr_stopioe) printf ("HSR end of file\n");
335 else return SCPE_OK;
336 }
337 else perror ("HSR I/O error");
338 clearerr (hsr_unit.fileref);
339 return SCPE_IOERR;
340 }
341 dev_done = dev_done | INT_HSR; /* set ready */
342 hsr_unit.buf = temp & 0377; /* save char */
343 hsr_unit.pos = hsr_unit.pos + 1;
344 return SCPE_OK;
345 }
346
347 t_stat hsp_svc (UNIT *uptr)
348 {
349 dev_done = dev_done | INT_HSP; /* set ready */
350 if ((hsp_unit.flags & UNIT_ATT) == 0) /* attached? */
351 return IORETURN (hsp_stopioe, SCPE_UNATT);
352 if (putc (hsp_unit.buf, hsp_unit.fileref) == EOF) { /* write char */
353 perror ("HSP I/O error"); /* error? */
354 clearerr (hsp_unit.fileref);
355 return SCPE_IOERR;
356 }
357 hsp_unit.pos = hsp_unit.pos + 1;
358 return SCPE_OK;
359 }
360
361 /* Reset routines */
362
363 t_stat hsr_reset (DEVICE *dptr)
364 {
365 hsr_unit.buf = 0; /* clear buffer */
366 dev_done = dev_done & ~INT_HSR; /* clear ready */
367 sim_cancel (&hsr_unit); /* deactivate unit */
368 return SCPE_OK;
369 }
370
371 t_stat hsp_reset (DEVICE *dptr)
372 {
373 hsp_unit.buf = 0; /* clear buffer */
374 dev_done = dev_done | INT_HSP; /* set ready */
375 sim_cancel (&hsp_unit); /* deactivate unit */
376 return SCPE_OK;
377 }
378
379 /* Clock function processors */
380
381 t_stat rtc_fo (int32 op)
382 {
383 if (op & RTC_OFF) sim_cancel (&rtc_unit); /* clock off? */
384 if ((op & RTC_ON) && !sim_is_active (&rtc_unit)) /* clock on? */
385 sim_activate (&rtc_unit, sim_rtc_init (rtc_unit.wait));
386 if (op & RTC_OV) dev_done = dev_done & ~INT_RTC; /* clr ovflo? */
387 return SCPE_OK;
388 }
389
390 uint32 rtc_sf (int32 op)
391 {
392 if ((op & RTC_OV) && (dev_done & INT_RTC)) return 1;
393 return 0;
394 }
395
396 t_stat rtc_svc (UNIT *uptr)
397 {
398 M[RTC_CTR] = (M[RTC_CTR] + 1) & DMASK; /* incr counter */
399 if (M[RTC_CTR] == 0) dev_done = dev_done | INT_RTC; /* ovflo? set ready */
400 sim_activate (&rtc_unit, sim_rtc_calb (rtc_tps)); /* reactivate */
401 return SCPE_OK;
402 }
403
404 t_stat rtc_reset (DEVICE *dptr)
405 {
406 dev_done = dev_done & ~INT_RTC; /* clear ready */
407 sim_cancel (&rtc_unit); /* stop clock */
408 return SCPE_OK;
409 }