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