1 /* sds_stddev.c: SDS 940 standard devices
3 Copyright (c) 2001-2005, 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.
31 29-Dec-03 RMS Added console backpressure support
32 25-Apr-03 RMS Revised for extended file support
37 #define TT_CR 052 /* typewriter */
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 */
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
);
67 extern const char ascii_to_sds
[128];
68 extern const char sds_to_ascii
[64];
69 extern const char odd_par
[64];
71 /* PTR data structures
73 ptr_dev PTR device descriptor
75 ptr_reg PTR register list
78 DIB ptr_dib
= { CHAN_W
, DEV_PTR
, XFR_PTR
, std_tplt
, &ptr
};
81 UDATA (&ptr_svc
, UNIT_SEQ
+UNIT_ATTABLE
+UNIT_ROABLE
, 0),
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) },
96 { MTAB_XTD
|MTAB_VDV
, 0, "CHANNEL", "CHANNEL",
97 &set_chan
, &show_chan
, NULL
},
102 "PTR", &ptr_unit
, ptr_reg
, ptr_mod
,
104 NULL
, NULL
, &ptr_reset
,
105 &ptr_boot
, NULL
, NULL
,
106 &ptr_dib
, DEV_DISABLE
109 /* PTP data structures
111 ptp_dev PTP device descriptor
113 ptp_reg PTP register list
116 DIB ptp_dib
= { CHAN_W
, DEV_PTP
, XFR_PTP
, std_tplt
, &ptp
};
119 UDATA (&ptp_svc
, UNIT_SEQ
+UNIT_ATTABLE
, 0), SERIAL_OUT_WAIT
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) },
133 { MTAB_XTD
|MTAB_VDV
, 0, "CHANNEL", "CHANNEL",
134 &set_chan
, &show_chan
, NULL
},
139 "PTP", &ptp_unit
, ptp_reg
, ptp_mod
,
141 NULL
, NULL
, &ptp_reset
,
143 &ptp_dib
, DEV_DISABLE
146 /* TTI data structures
148 tti_dev TTI device descriptor
150 tti_reg TTI register list
153 DIB tti_dib
= { CHAN_W
, DEV_TTI
, XFR_TTI
, std_tplt
, &tti
};
155 UNIT tti_unit
= { UDATA (&tti_svc
, 0, 0), KBD_POLL_WAIT
};
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
},
166 { MTAB_XTD
|MTAB_VDV
, 0, "CHANNEL", "CHANNEL",
167 &set_chan
, &show_chan
, &tti_dib
},
172 "TTI", &tti_unit
, tti_reg
, tti_mod
,
174 NULL
, NULL
, &tti_reset
,
179 /* TTO data structures
181 tto_dev TTO device descriptor
183 tto_reg TTO register list
186 DIB tto_dib
= { CHAN_W
, DEV_TTO
, XFR_TTO
, std_tplt
, &tto
};
188 UNIT tto_unit
= { UDATA (&tto_svc
, 0, 0), SERIAL_OUT_WAIT
};
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
},
199 { MTAB_XTD
|MTAB_VDV
, 0, "CHANNEL", "CHANNEL",
200 &set_chan
, &show_chan
, &tto_dib
},
205 "TTO", &tto_unit
, tto_reg
, tto_mod
,
207 NULL
, NULL
, &tto_reset
,
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
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.
227 t_stat
ptr (uint32 fnc
, uint32 inst
, uint32
*dat
)
231 switch (fnc
) { /* case function */
233 case IO_CONN
: /* connect */
234 new_ch
= I_GETEOCH (inst
); /* get new chan */
235 if (new_ch
!= ptr_dib
.chan
) return SCPE_IERR
; /* inv conn? err */
236 ptr_sor
= 1; /* start of rec */
237 xfr_req
= xfr_req
& ~XFR_PTR
; /* clr xfr flag */
238 sim_activate (&ptr_unit
, ptr_unit
.wait
); /* activate */
241 case IO_DISC
: /* disconnect */
242 ptr_sor
= 0; /* clear state */
243 xfr_req
= xfr_req
& ~XFR_PTR
; /* clr xfr flag */
244 sim_cancel (&ptr_unit
); /* deactivate unit */
247 case IO_READ
: /* read */
248 xfr_req
= xfr_req
& ~XFR_PTR
; /* clr xfr flag */
249 *dat
= ptr_unit
.buf
& 077; /* get buf data */
250 if (ptr_unit
.buf
!= odd_par
[*dat
]) /* good parity? */
251 chan_set_flag (ptr_dib
.chan
, CHF_ERR
); /* no, error */
254 case IO_WREOR
: /* write eor */
257 case IO_EOM1
: /* EOM mode 1*/
258 case IO_WRITE
: /* write */
267 t_stat
ptr_svc (UNIT
*uptr
)
271 if ((ptr_unit
.flags
& UNIT_ATT
) == 0) { /* attached? */
272 ptr_set_err (); /* no, err, disc */
273 CRETIOE (ptr_stopioe
, SCPE_UNATT
);
275 if ((temp
= getc (ptr_unit
.fileref
)) == EOF
) { /* end of file? */
276 ptr_set_err (); /* yes, err, disc */
277 if (feof (ptr_unit
.fileref
)) { /* end of file? */
278 if (ptr_stopioe
) printf ("PTR end of file\n");
281 else perror ("PTR I/O error"); /* I/O error */
282 clearerr (ptr_unit
.fileref
);
285 ptr_unit
.pos
= ptr_unit
.pos
+ 1; /* inc position */
286 if (temp
) { /* leader/gap? */
287 ptr_unit
.buf
= temp
& 0177; /* no, save char */
288 xfr_req
= xfr_req
| XFR_PTR
; /* set xfr flag */
289 ptr_sor
= 0; /* in record */
291 else if (!ptr_sor
) /* end record? */
292 chan_set_flag (ptr_dib
.chan
, CHF_EOR
); /* ignore leader */
293 sim_activate (&ptr_unit
, ptr_unit
.wait
); /* get next char */
299 void ptr_set_err (void)
301 chan_set_flag (ptr_dib
.chan
, CHF_EOR
| CHF_ERR
); /* eor, error */
302 chan_disc (ptr_dib
.chan
); /* disconnect */
303 xfr_req
= xfr_req
& ~XFR_PTR
; /* clear xfr */
304 sim_cancel (&ptr_unit
); /* stop */
310 t_stat
ptr_reset (DEVICE
*dptr
)
312 chan_disc (ptr_dib
.chan
); /* disconnect */
313 ptr_sor
= 0; /* clear state */
315 xfr_req
= xfr_req
& ~XFR_PTR
; /* clr xfr flag */
316 sim_cancel (&ptr_unit
); /* deactivate unit */
320 /* Boot routine - simulate FILL console command */
322 t_stat
ptr_boot (int32 unitno
, DEVICE
*dptr
)
324 extern uint32 P
, M
[];
326 M
[0] = 077777771; /* -7B */
327 M
[1] = 007100000; /* LDX 0 */
328 M
[2] = 000203604; /* EOM 3604B */
329 M
[3] = 003200002; /* WIM 2 */
330 M
[4] = 000100002; /* BRU 2 */
331 P
= 1; /* start at 1 */
337 conn - inst = EOM0, dat = NULL
338 eom1 - inst = EOM1, dat = NULL
339 sks - inst = SKS, dat = ptr to result
340 disc - inst = device number, dat = NULL
341 wreor - inst = device number, dat = NULL
342 read - inst = device number, dat = ptr to data
343 write - inst = device number, dat = ptr to result
345 The paper tape punch is an asynchronous streaming output device. That is,
346 it can never cause a channel rate error; if no data is available, it waits.
349 t_stat
ptp (uint32 fnc
, uint32 inst
, uint32
*dat
)
353 switch (fnc
) { /* case function */
356 new_ch
= I_GETEOCH (inst
); /* get new chan */
357 if (new_ch
!= ptp_dib
.chan
) return SCPE_IERR
; /* inv conn? err */
358 ptp_ldr
= (inst
& CHC_NLDR
)? 0: 1; /* leader? */
359 xfr_req
= xfr_req
& ~XFR_PTP
; /* clr xfr flag */
360 sim_activate (&ptp_unit
, ptp_unit
.wait
); /* activate */
363 case IO_DISC
: /* disconnect */
364 ptp_ldr
= 0; /* clear state */
365 xfr_req
= xfr_req
& ~XFR_PTP
; /* clr xfr flag */
366 sim_cancel (&ptp_unit
); /* deactivate unit */
369 case IO_WRITE
: /* write */
370 xfr_req
= xfr_req
& ~XFR_PTP
; /* clr xfr flag */
371 sim_activate (&ptp_unit
, ptp_unit
.wait
); /* activate */
372 ptp_unit
.buf
= odd_par
[(*dat
) & 077]; /* save data */
373 return ptp_out (ptp_unit
.buf
); /* punch w/ par */
375 case IO_WREOR
: /* write eor */
378 case IO_EOM1
: /* EOM mode 1*/
379 case IO_READ
: /* read */
388 t_stat
ptp_svc (UNIT
*uptr
)
393 if (ptp_ldr
) { /* need leader? */
394 for (i
= 0; i
< 12; i
++) { /* punch leader */
395 if (r
= ptp_out (0)) break;
398 ptp_ldr
= 0; /* clear flag */
399 chan_set_ordy (ptp_dib
.chan
); /* ptp ready */
405 t_stat
ptp_out (int32 dat
)
407 if ((ptp_unit
.flags
& UNIT_ATT
) == 0) { /* attached? */
408 ptp_set_err (); /* no, disc, err */
409 CRETIOE (ptp_stopioe
, SCPE_UNATT
);
411 if (putc (dat
, ptp_unit
.fileref
) == EOF
) { /* I/O error? */
412 ptp_set_err (); /* yes, disc, err */
413 perror ("PTP I/O error"); /* print msg */
414 clearerr (ptp_unit
.fileref
);
417 ptp_unit
.pos
= ptp_unit
.pos
+ 1; /* inc position */
423 void ptp_set_err (void)
425 chan_set_flag (ptp_dib
.chan
, CHF_ERR
); /* error */
426 chan_disc (ptp_dib
.chan
); /* disconnect */
427 xfr_req
= xfr_req
& ~XFR_PTP
; /* clear xfr */
428 sim_cancel (&ptp_unit
); /* stop */
434 t_stat
ptp_reset (DEVICE
*dptr
)
436 chan_disc (ptp_dib
.chan
); /* disconnect */
437 ptp_ldr
= 0; /* clear state */
439 xfr_req
= xfr_req
& ~XFR_PTP
; /* clr xfr flag */
440 sim_cancel (&ptp_unit
); /* deactivate unit */
446 conn - inst = EOM0, dat = NULL
447 eom1 - inst = EOM1, dat = NULL
448 sks - inst = SKS, dat = ptr to result
449 disc - inst = device number, dat = NULL
450 wreor - inst = device number, dat = NULL
451 read - inst = device number, dat = ptr to data
452 write - inst = device number, dat = ptr to result
454 The typewriter input is an asynchronous input device. That is, it can
455 never cause a channel rate error; if no data is available, it waits.
458 t_stat
tti (uint32 fnc
, uint32 inst
, uint32
*dat
)
462 switch (fnc
) { /* case function */
464 case IO_CONN
: /* connect */
465 new_ch
= I_GETEOCH (inst
); /* get new chan */
466 if (new_ch
!= tti_dib
.chan
) return SCPE_IERR
; /* inv conn? err */
467 xfr_req
= xfr_req
& ~XFR_TTI
; /* clr xfr flag */
470 case IO_DISC
: /* disconnect */
471 xfr_req
= xfr_req
& ~XFR_TTI
; /* clr xfr flag */
474 case IO_READ
: /* read */
475 xfr_req
= xfr_req
& ~XFR_TTI
; /* clr xfr flag */
476 *dat
= tti_unit
.buf
; /* get buf data */
479 case IO_WREOR
: /* write eor */
482 case IO_EOM1
: /* EOM mode 1*/
483 case IO_WRITE
: /* write */
492 t_stat
tti_svc (UNIT
*uptr
)
496 sim_activate (&tti_unit
, tti_unit
.wait
); /* continue poll */
497 if ((temp
= sim_poll_kbd ()) < SCPE_KFLAG
) return temp
; /* no char or error? */
498 if (temp
& SCPE_BREAK
) return SCPE_OK
; /* ignore break */
500 tti_unit
.pos
= tti_unit
.pos
+ 1;
501 if (ascii_to_sds
[temp
] >= 0) {
502 tti_unit
.buf
= ascii_to_sds
[temp
]; /* internal rep */
503 sim_putchar (temp
); /* echo */
504 if (temp
== '\r') sim_putchar ('\n'); /* lf after cr */
505 xfr_req
= xfr_req
| XFR_TTI
; /* set xfr flag */
507 else sim_putchar (007); /* ding! */
511 t_stat
tti_reset (DEVICE
*dptr
)
513 chan_disc (tti_dib
.chan
); /* disconnect */
514 tti_unit
.buf
= 0; /* clear state */
515 xfr_req
= xfr_req
& ~XFR_TTI
; /* clr xfr flag */
516 sim_activate (&tti_unit
, tti_unit
.wait
); /* start poll */
522 conn - inst = EOM0, dat = NULL
523 eom1 - inst = EOM1, dat = NULL
524 sks - inst = SKS, dat = ptr to result
525 disc - inst = device number, dat = NULL
526 wreor - inst = device number, dat = NULL
527 read - inst = device number, dat = ptr to data
528 write - inst = device number, dat = ptr to result
530 The typewriter output is an asynchronous streaming output device. That is,
531 it can never cause a channel rate error; if no data is available, it waits.
534 t_stat
tto (uint32 fnc
, uint32 inst
, uint32
*dat
)
538 switch (fnc
) { /* case function */
541 new_ch
= I_GETEOCH (inst
); /* get new chan */
542 if (new_ch
!= tto_dib
.chan
) return SCPE_IERR
; /* inv conn? err */
543 xfr_req
= xfr_req
& ~XFR_TTO
; /* clr xfr flag */
544 sim_activate (&tto_unit
, tto_unit
.wait
); /* activate */
547 case IO_DISC
: /* disconnect */
548 xfr_req
= xfr_req
& ~XFR_TTO
; /* clr xfr flag */
549 sim_cancel (&tto_unit
); /* deactivate unit */
552 case IO_WRITE
: /* write */
553 xfr_req
= xfr_req
& ~XFR_TTO
; /* clr xfr flag */
554 tto_unit
.buf
= (*dat
) & 077; /* save data */
555 sim_activate (&tto_unit
, tto_unit
.wait
); /* activate */
558 case IO_WREOR
: /* write eor */
561 case IO_EOM1
: /* EOM mode 1*/
562 case IO_READ
: /* read */
571 t_stat
tto_svc (UNIT
*uptr
)
576 if (uptr
->buf
== TT_CR
) asc
= '\r'; /* control chars? */
577 else if (uptr
->buf
== TT_BS
) asc
= '\b';
578 else if (uptr
->buf
== TT_TB
) asc
= '\t';
579 else asc
= sds_to_ascii
[uptr
->buf
]; /* translate */
580 if ((r
= sim_putchar_s (asc
)) != SCPE_OK
) { /* output; error? */
581 sim_activate (uptr
, uptr
->wait
); /* retry */
582 return ((r
== SCPE_STALL
)? SCPE_OK
: r
); /* !stall? report */
584 uptr
->pos
= uptr
->pos
+ 1; /* inc position */
585 chan_set_ordy (tto_dib
.chan
); /* tto rdy */
586 if (asc
== '\r') { /* CR? */
587 sim_putchar ('\n'); /* add lf */
588 uptr
->pos
= uptr
->pos
+ 1; /* inc position */
595 t_stat
tto_reset (DEVICE
*dptr
)
597 chan_disc (tto_dib
.chan
); /* disconnect */
598 tto_unit
.buf
= 0; /* clear state */
599 xfr_req
= xfr_req
& ~XFR_TTO
; /* clr xfr flag */
600 sim_cancel (&tto_unit
); /* deactivate unit */