First Commit of my working state
[simh.git] / SDS / sds_stddev.c
CommitLineData
196ba1fc
PH
1/* sds_stddev.c: SDS 940 standard devices\r
2\r
3 Copyright (c) 2001-2005, 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 ptr paper tape reader\r
27 ptp paper tape punch\r
28 tti keyboard\r
29 tto teleprinter\r
30\r
31 29-Dec-03 RMS Added console backpressure support\r
32 25-Apr-03 RMS Revised for extended file support\r
33*/\r
34\r
35#include "sds_defs.h"\r
36\r
37#define TT_CR 052 /* typewriter */\r
38#define TT_TB 072\r
39#define TT_BS 032\r
40\r
41extern uint32 xfr_req;\r
42extern int32 stop_invins, stop_invdev, stop_inviop;\r
43int32 ptr_sor = 0; /* start of rec */\r
44int32 ptr_stopioe = 1; /* stop on err */\r
45int32 ptp_ldr = 0; /* no leader */\r
46int32 ptp_stopioe = 1;\r
47DSPT std_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */\r
48\r
49DEVICE ptr_dev, ptp_dev;\r
50t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat);\r
51t_stat ptr_svc (UNIT *uptr);\r
52t_stat ptr_reset (DEVICE *dptr);\r
53t_stat ptr_boot (int32 unitno, DEVICE *dptr);\r
54void ptr_set_err (void);\r
55t_stat ptp (uint32 fnc, uint32 inst, uint32 *dat);\r
56t_stat ptp_svc (UNIT *uptr);\r
57t_stat ptp_reset (DEVICE *dptr);\r
58t_stat ptp_out (int32 dat);\r
59void ptp_set_err (void);\r
60t_stat tti (uint32 fnc, uint32 inst, uint32 *dat);\r
61t_stat tti_svc (UNIT *uptr);\r
62t_stat tti_reset (DEVICE *dptr);\r
63t_stat tto (uint32 fnc, uint32 inst, uint32 *dat);\r
64t_stat tto_svc (UNIT *uptr);\r
65t_stat tto_reset (DEVICE *dptr);\r
66\r
67extern const char ascii_to_sds[128];\r
68extern const char sds_to_ascii[64];\r
69extern const char odd_par[64];\r
70\r
71/* PTR data structures\r
72\r
73 ptr_dev PTR device descriptor\r
74 ptr_unit PTR unit\r
75 ptr_reg PTR register list\r
76*/\r
77\r
78DIB ptr_dib = { CHAN_W, DEV_PTR, XFR_PTR, std_tplt, &ptr };\r
79\r
80UNIT ptr_unit = {\r
81 UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),\r
82 SERIAL_IN_WAIT\r
83 };\r
84\r
85REG ptr_reg[] = {\r
86 { ORDATA (BUF, ptr_unit.buf, 7) },\r
87 { FLDATA (XFR, xfr_req, XFR_V_PTR) },\r
88 { FLDATA (SOR, ptr_sor, 0) },\r
89 { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },\r
90 { DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT },\r
91 { FLDATA (STOP_IOE, ptr_stopioe, 0) },\r
92 { NULL }\r
93 };\r
94\r
95MTAB ptr_mod[] = {\r
96 { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",\r
97 &set_chan, &show_chan, NULL },\r
98 { 0 }\r
99 };\r
100\r
101DEVICE ptr_dev = {\r
102 "PTR", &ptr_unit, ptr_reg, ptr_mod,\r
103 1, 10, 31, 1, 8, 8,\r
104 NULL, NULL, &ptr_reset,\r
105 &ptr_boot, NULL, NULL,\r
106 &ptr_dib, DEV_DISABLE\r
107 };\r
108\r
109/* PTP data structures\r
110\r
111 ptp_dev PTP device descriptor\r
112 ptp_unit PTP unit\r
113 ptp_reg PTP register list\r
114*/\r
115\r
116DIB ptp_dib = { CHAN_W, DEV_PTP, XFR_PTP, std_tplt, &ptp };\r
117\r
118UNIT ptp_unit = {\r
119 UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT\r
120 };\r
121\r
122REG ptp_reg[] = {\r
123 { ORDATA (BUF, ptp_unit.buf, 7) },\r
124 { FLDATA (XFR, xfr_req, XFR_V_PTP) },\r
125 { FLDATA (LDR, ptp_ldr, 0) },\r
126 { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },\r
127 { DRDATA (TIME, ptp_unit.wait, 24), REG_NZ + PV_LEFT },\r
128 { FLDATA (STOP_IOE, ptp_stopioe, 0) },\r
129 { NULL }\r
130 };\r
131\r
132MTAB ptp_mod[] = {\r
133 { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",\r
134 &set_chan, &show_chan, NULL },\r
135 { 0 }\r
136 };\r
137\r
138DEVICE ptp_dev = {\r
139 "PTP", &ptp_unit, ptp_reg, ptp_mod,\r
140 1, 10, 31, 1, 8, 8,\r
141 NULL, NULL, &ptp_reset,\r
142 NULL, NULL, NULL,\r
143 &ptp_dib, DEV_DISABLE\r
144 };\r
145\r
146/* TTI data structures\r
147\r
148 tti_dev TTI device descriptor\r
149 tti_unit TTI unit\r
150 tti_reg TTI register list\r
151*/\r
152\r
153DIB tti_dib = { CHAN_W, DEV_TTI, XFR_TTI, std_tplt, &tti };\r
154\r
155UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };\r
156\r
157REG tti_reg[] = {\r
158 { ORDATA (BUF, tti_unit.buf, 6) },\r
159 { FLDATA (XFR, xfr_req, XFR_V_TTI) },\r
160 { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },\r
161 { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },\r
162 { NULL }\r
163 };\r
164\r
165MTAB tti_mod[] = {\r
166 { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",\r
167 &set_chan, &show_chan, &tti_dib },\r
168 { 0 }\r
169 };\r
170\r
171DEVICE tti_dev = {\r
172 "TTI", &tti_unit, tti_reg, tti_mod,\r
173 1, 10, 31, 1, 8, 8,\r
174 NULL, NULL, &tti_reset,\r
175 NULL, NULL, NULL,\r
176 &tti_dib, 0\r
177 };\r
178\r
179/* TTO data structures\r
180\r
181 tto_dev TTO device descriptor\r
182 tto_unit TTO unit\r
183 tto_reg TTO register list\r
184*/\r
185\r
186DIB tto_dib = { CHAN_W, DEV_TTO, XFR_TTO, std_tplt, &tto };\r
187\r
188UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };\r
189\r
190REG tto_reg[] = {\r
191 { ORDATA (BUF, tto_unit.buf, 6) },\r
192 { FLDATA (XFR, xfr_req, XFR_V_TTO) },\r
193 { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },\r
194 { DRDATA (TIME, tto_unit.wait, 24), REG_NZ + PV_LEFT },\r
195 { NULL }\r
196 };\r
197\r
198MTAB tto_mod[] = {\r
199 { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",\r
200 &set_chan, &show_chan, &tto_dib },\r
201 { 0 }\r
202 };\r
203\r
204DEVICE tto_dev = {\r
205 "TTO", &tto_unit, tto_reg, tto_mod,\r
206 1, 10, 31, 1, 8, 8,\r
207 NULL, NULL, &tto_reset,\r
208 NULL, NULL, NULL,\r
209 &tto_dib, 0\r
210 };\r
211\r
212/* Paper tape reader\r
213\r
214 conn - inst = EOM0, dat = NULL\r
215 eom1 - inst = EOM1, dat = NULL\r
216 sks - inst = SKS, dat = ptr to result\r
217 disc - inst = device number, dat = NULL\r
218 wreor - inst = device number, dat = NULL\r
219 read - inst = device number, dat = ptr to data\r
220 write - inst = device number, dat = ptr to result\r
221\r
222 The paper tape reader is a streaming input device. Once started, it\r
223 continues to read until disconnected. Leader before the current record\r
224 is ignored; leader after the current record sets channel EndOfRecord.\r
225*/\r
226\r
227t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat)\r
228{\r
229int32 new_ch;\r
230\r
231switch (fnc) { /* case function */\r
232\r
233 case IO_CONN: /* connect */\r
234 new_ch = I_GETEOCH (inst); /* get new chan */\r
235 if (new_ch != ptr_dib.chan) return SCPE_IERR; /* inv conn? err */\r
236 ptr_sor = 1; /* start of rec */\r
237 xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */\r
238 sim_activate (&ptr_unit, ptr_unit.wait); /* activate */\r
239 break;\r
240\r
241 case IO_DISC: /* disconnect */\r
242 ptr_sor = 0; /* clear state */\r
243 xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */\r
244 sim_cancel (&ptr_unit); /* deactivate unit */\r
245 break;\r
246\r
247 case IO_READ: /* read */\r
248 xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */\r
249 *dat = ptr_unit.buf & 077; /* get buf data */\r
250 if (ptr_unit.buf != odd_par[*dat]) /* good parity? */\r
251 chan_set_flag (ptr_dib.chan, CHF_ERR); /* no, error */\r
252 break;\r
253\r
254 case IO_WREOR: /* write eor */\r
255 break;\r
256\r
257 case IO_EOM1: /* EOM mode 1*/\r
258 case IO_WRITE: /* write */\r
259 CRETINS; /* error */\r
260 }\r
261\r
262return SCPE_OK;\r
263}\r
264\r
265/* Unit service */\r
266\r
267t_stat ptr_svc (UNIT *uptr)\r
268{\r
269int32 temp;\r
270\r
271if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */\r
272 ptr_set_err (); /* no, err, disc */\r
273 CRETIOE (ptr_stopioe, SCPE_UNATT);\r
274 }\r
275if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */\r
276 ptr_set_err (); /* yes, err, disc */\r
277 if (feof (ptr_unit.fileref)) { /* end of file? */\r
278 if (ptr_stopioe) printf ("PTR end of file\n");\r
279 else return SCPE_OK;\r
280 }\r
281 else perror ("PTR I/O error"); /* I/O error */\r
282 clearerr (ptr_unit.fileref);\r
283 return SCPE_IOERR;\r
284 }\r
285ptr_unit.pos = ptr_unit.pos + 1; /* inc position */\r
286if (temp) { /* leader/gap? */\r
287 ptr_unit.buf = temp & 0177; /* no, save char */\r
288 xfr_req = xfr_req | XFR_PTR; /* set xfr flag */\r
289 ptr_sor = 0; /* in record */\r
290 }\r
291else if (!ptr_sor) /* end record? */\r
292 chan_set_flag (ptr_dib.chan, CHF_EOR); /* ignore leader */\r
293sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */\r
294return SCPE_OK;\r
295}\r
296\r
297/* Fatal error */\r
298\r
299void ptr_set_err (void)\r
300{\r
301chan_set_flag (ptr_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */\r
302chan_disc (ptr_dib.chan); /* disconnect */\r
303xfr_req = xfr_req & ~XFR_PTR; /* clear xfr */\r
304sim_cancel (&ptr_unit); /* stop */\r
305return;\r
306}\r
307\r
308/* Reset routine */\r
309\r
310t_stat ptr_reset (DEVICE *dptr)\r
311{\r
312chan_disc (ptr_dib.chan); /* disconnect */\r
313ptr_sor = 0; /* clear state */\r
314ptr_unit.buf = 0;\r
315xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */\r
316sim_cancel (&ptr_unit); /* deactivate unit */\r
317return SCPE_OK;\r
318}\r
319\r
320/* Boot routine - simulate FILL console command */\r
321\r
322t_stat ptr_boot (int32 unitno, DEVICE *dptr)\r
323{\r
324extern uint32 P, M[];\r
325\r
326M[0] = 077777771; /* -7B */\r
327M[1] = 007100000; /* LDX 0 */\r
328M[2] = 000203604; /* EOM 3604B */\r
329M[3] = 003200002; /* WIM 2 */\r
330M[4] = 000100002; /* BRU 2 */\r
331P = 1; /* start at 1 */\r
332return SCPE_OK;\r
333}\r
334\r
335/* Paper tape punch\r
336\r
337 conn - inst = EOM0, dat = NULL\r
338 eom1 - inst = EOM1, dat = NULL\r
339 sks - inst = SKS, dat = ptr to result\r
340 disc - inst = device number, dat = NULL\r
341 wreor - inst = device number, dat = NULL\r
342 read - inst = device number, dat = ptr to data\r
343 write - inst = device number, dat = ptr to result\r
344\r
345 The paper tape punch is an asynchronous streaming output device. That is,\r
346 it can never cause a channel rate error; if no data is available, it waits.\r
347*/\r
348\r
349t_stat ptp (uint32 fnc, uint32 inst, uint32 *dat)\r
350{\r
351int32 new_ch;\r
352\r
353switch (fnc) { /* case function */\r
354\r
355 case IO_CONN:\r
356 new_ch = I_GETEOCH (inst); /* get new chan */\r
357 if (new_ch != ptp_dib.chan) return SCPE_IERR; /* inv conn? err */\r
358 ptp_ldr = (inst & CHC_NLDR)? 0: 1; /* leader? */\r
359 xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */\r
360 sim_activate (&ptp_unit, ptp_unit.wait); /* activate */\r
361 break;\r
362\r
363 case IO_DISC: /* disconnect */\r
364 ptp_ldr = 0; /* clear state */\r
365 xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */\r
366 sim_cancel (&ptp_unit); /* deactivate unit */\r
367 break;\r
368\r
369 case IO_WRITE: /* write */\r
370 xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */\r
371 sim_activate (&ptp_unit, ptp_unit.wait); /* activate */\r
372 ptp_unit.buf = odd_par[(*dat) & 077]; /* save data */\r
373 return ptp_out (ptp_unit.buf); /* punch w/ par */\r
374\r
375 case IO_WREOR: /* write eor */\r
376 break;\r
377\r
378 case IO_EOM1: /* EOM mode 1*/\r
379 case IO_READ: /* read */\r
380 CRETINS; /* error */\r
381 }\r
382\r
383return SCPE_OK;\r
384}\r
385\r
386/* Unit service */\r
387\r
388t_stat ptp_svc (UNIT *uptr)\r
389{\r
390int32 i;\r
391t_stat r = SCPE_OK;\r
392\r
393if (ptp_ldr) { /* need leader? */\r
394 for (i = 0; i < 12; i++) { /* punch leader */\r
395 if (r = ptp_out (0)) break;\r
396 }\r
397 }\r
398ptp_ldr = 0; /* clear flag */\r
399chan_set_ordy (ptp_dib.chan); /* ptp ready */\r
400return r;\r
401}\r
402\r
403/* Punch I/O */\r
404\r
405t_stat ptp_out (int32 dat)\r
406{\r
407if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */\r
408 ptp_set_err (); /* no, disc, err */\r
409 CRETIOE (ptp_stopioe, SCPE_UNATT);\r
410 }\r
411if (putc (dat, ptp_unit.fileref) == EOF) { /* I/O error? */\r
412 ptp_set_err (); /* yes, disc, err */\r
413 perror ("PTP I/O error"); /* print msg */\r
414 clearerr (ptp_unit.fileref);\r
415 return SCPE_IOERR;\r
416 }\r
417ptp_unit.pos = ptp_unit.pos + 1; /* inc position */\r
418return SCPE_OK;\r
419}\r
420\r
421/* Fatal error */\r
422\r
423void ptp_set_err (void)\r
424{\r
425chan_set_flag (ptp_dib.chan, CHF_ERR); /* error */\r
426chan_disc (ptp_dib.chan); /* disconnect */\r
427xfr_req = xfr_req & ~XFR_PTP; /* clear xfr */\r
428sim_cancel (&ptp_unit); /* stop */\r
429return;\r
430}\r
431\r
432/* Reset routine */\r
433\r
434t_stat ptp_reset (DEVICE *dptr)\r
435{\r
436chan_disc (ptp_dib.chan); /* disconnect */\r
437ptp_ldr = 0; /* clear state */\r
438ptp_unit.buf = 0;\r
439xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */\r
440sim_cancel (&ptp_unit); /* deactivate unit */\r
441return SCPE_OK;\r
442}\r
443\r
444/* Typewriter input\r
445\r
446 conn - inst = EOM0, dat = NULL\r
447 eom1 - inst = EOM1, dat = NULL\r
448 sks - inst = SKS, dat = ptr to result\r
449 disc - inst = device number, dat = NULL\r
450 wreor - inst = device number, dat = NULL\r
451 read - inst = device number, dat = ptr to data\r
452 write - inst = device number, dat = ptr to result\r
453\r
454 The typewriter input is an asynchronous input device. That is, it can\r
455 never cause a channel rate error; if no data is available, it waits.\r
456*/\r
457\r
458t_stat tti (uint32 fnc, uint32 inst, uint32 *dat)\r
459{\r
460int32 new_ch;\r
461\r
462switch (fnc) { /* case function */\r
463\r
464 case IO_CONN: /* connect */\r
465 new_ch = I_GETEOCH (inst); /* get new chan */\r
466 if (new_ch != tti_dib.chan) return SCPE_IERR; /* inv conn? err */\r
467 xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */\r
468 break;\r
469\r
470 case IO_DISC: /* disconnect */\r
471 xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */\r
472 break;\r
473\r
474 case IO_READ: /* read */\r
475 xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */\r
476 *dat = tti_unit.buf; /* get buf data */\r
477 break;\r
478\r
479 case IO_WREOR: /* write eor */\r
480 break;\r
481\r
482 case IO_EOM1: /* EOM mode 1*/\r
483 case IO_WRITE: /* write */\r
484 CRETINS; /* error */\r
485 }\r
486\r
487return SCPE_OK;\r
488}\r
489\r
490/* Unit service */\r
491\r
492t_stat tti_svc (UNIT *uptr)\r
493{\r
494int32 temp;\r
495\r
496sim_activate (&tti_unit, tti_unit.wait); /* continue poll */\r
497if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */\r
498if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */\r
499temp = temp & 0177;\r
500tti_unit.pos = tti_unit.pos + 1;\r
501if (ascii_to_sds[temp] >= 0) {\r
502 tti_unit.buf = ascii_to_sds[temp]; /* internal rep */\r
503 sim_putchar (temp); /* echo */\r
504 if (temp == '\r') sim_putchar ('\n'); /* lf after cr */\r
505 xfr_req = xfr_req | XFR_TTI; /* set xfr flag */\r
506 }\r
507else sim_putchar (007); /* ding! */\r
508return SCPE_OK;\r
509}\r
510\r
511t_stat tti_reset (DEVICE *dptr)\r
512{\r
513chan_disc (tti_dib.chan); /* disconnect */\r
514tti_unit.buf = 0; /* clear state */\r
515xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */\r
516sim_activate (&tti_unit, tti_unit.wait); /* start poll */\r
517return SCPE_OK;\r
518}\r
519\r
520/* Typewriter output\r
521\r
522 conn - inst = EOM0, dat = NULL\r
523 eom1 - inst = EOM1, dat = NULL\r
524 sks - inst = SKS, dat = ptr to result\r
525 disc - inst = device number, dat = NULL\r
526 wreor - inst = device number, dat = NULL\r
527 read - inst = device number, dat = ptr to data\r
528 write - inst = device number, dat = ptr to result\r
529\r
530 The typewriter output is an asynchronous streaming output device. That is,\r
531 it can never cause a channel rate error; if no data is available, it waits.\r
532*/\r
533\r
534t_stat tto (uint32 fnc, uint32 inst, uint32 *dat)\r
535{\r
536int32 new_ch;\r
537\r
538switch (fnc) { /* case function */\r
539\r
540 case IO_CONN:\r
541 new_ch = I_GETEOCH (inst); /* get new chan */\r
542 if (new_ch != tto_dib.chan) return SCPE_IERR; /* inv conn? err */\r
543 xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */\r
544 sim_activate (&tto_unit, tto_unit.wait); /* activate */\r
545 break;\r
546\r
547 case IO_DISC: /* disconnect */\r
548 xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */\r
549 sim_cancel (&tto_unit); /* deactivate unit */\r
550 break;\r
551\r
552 case IO_WRITE: /* write */\r
553 xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */\r
554 tto_unit.buf = (*dat) & 077; /* save data */\r
555 sim_activate (&tto_unit, tto_unit.wait); /* activate */\r
556 break;\r
557\r
558 case IO_WREOR: /* write eor */\r
559 break;\r
560 \r
561 case IO_EOM1: /* EOM mode 1*/\r
562 case IO_READ: /* read */\r
563 CRETINS; /* error */\r
564 }\r
565\r
566return SCPE_OK;\r
567}\r
568\r
569/* Unit service */\r
570\r
571t_stat tto_svc (UNIT *uptr)\r
572{\r
573int32 asc;\r
574t_stat r;\r
575\r
576if (uptr->buf == TT_CR) asc = '\r'; /* control chars? */\r
577else if (uptr->buf == TT_BS) asc = '\b';\r
578else if (uptr->buf == TT_TB) asc = '\t';\r
579else asc = sds_to_ascii[uptr->buf]; /* translate */\r
580if ((r = sim_putchar_s (asc)) != SCPE_OK) { /* output; error? */\r
581 sim_activate (uptr, uptr->wait); /* retry */\r
582 return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */\r
583 }\r
584uptr->pos = uptr->pos + 1; /* inc position */\r
585chan_set_ordy (tto_dib.chan); /* tto rdy */\r
586if (asc == '\r') { /* CR? */\r
587 sim_putchar ('\n'); /* add lf */\r
588 uptr->pos = uptr->pos + 1; /* inc position */\r
589 }\r
590return SCPE_OK;\r
591}\r
592\r
593/* Reset routine */\r
594\r
595t_stat tto_reset (DEVICE *dptr)\r
596{\r
597chan_disc (tto_dib.chan); /* disconnect */\r
598tto_unit.buf = 0; /* clear state */\r
599xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */\r
600sim_cancel (&tto_unit); /* deactivate unit */\r
601return SCPE_OK;\r
602}\r