First Commit of my working state
[simh.git] / Interdata / id_ttp.c
1 /* id_ttp.c: Interdata PASLA console interface
2
3 Copyright (c) 2000-2007, 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 ttp console (on PAS)
27
28 18-Jun-07 RMS Added UNIT_IDLE flag to console input
29 18-Oct-06 RMS Sync keyboard to LFC clock
30 22-Nov-05 RMS Revised for new terminal processing routines
31 29-Dec-03 RMS Added support for console backpressure
32 25-Apr-03 RMS Revised for extended file support
33 */
34
35 #include "id_defs.h"
36 #include <ctype.h>
37
38 #define TTI 0
39 #define TTO 1
40
41 /* Status byte */
42
43 #define STA_OVR 0x80 /* overrun RO */
44 #define STA_PF 0x40 /* parity err RO */
45 #define STA_FR 0x20 /* framing err RO */
46 #define STA_RCV (STA_OVR|STA_PF|STA_FR)
47 #define SET_EX (STA_OVR|STA_PF|STA_FR)
48 #define STA_XMT (STA_BSY)
49
50 /* Command bytes 1,0 */
51
52 #define CMD_ECHO (0x10 << 8) /* echoplex */
53 #define CMD_WRT (0x02 << 8) /* write/read */
54 #define CMD_TYP 0x01 /* command type */
55
56 extern uint32 int_req[INTSZ], int_enb[INTSZ];
57 extern int32 pas_par (int32 cmd, int32 c);
58 extern int32 lfc_poll;
59
60 uint32 ttp_sta = 0; /* status */
61 uint32 ttp_cmd = 0; /* command */
62 uint32 ttp_kchp = 0; /* rcvr chr pend */
63 uint32 ttp_karm = 0; /* rcvr int armed */
64 uint32 ttp_tarm = 0; /* xmt int armed */
65 uint8 ttp_tplte[] = { 0, 1, TPL_END };
66
67 uint32 ttp (uint32 dev, uint32 op, uint32 dat);
68 t_stat ttpi_svc (UNIT *uptr);
69 t_stat ttpo_svc (UNIT *uptr);
70 t_stat ttp_reset (DEVICE *dptr);
71 t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
72 t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc);
73 t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc);
74
75 /* TTP data structures */
76
77 DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL };
78
79 UNIT ttp_unit[] = {
80 { UDATA (&ttpi_svc, UNIT_IDLE, 0), 0 },
81 { UDATA (&ttpo_svc, 0, 0), SERIAL_OUT_WAIT }
82 };
83
84 REG ttp_reg[] = {
85 { HRDATA (CMD, ttp_cmd, 16) },
86 { HRDATA (KBUF, ttp_unit[TTI].buf, 8) },
87 { DRDATA (KPOS, ttp_unit[TTI].pos, T_ADDR_W), PV_LEFT },
88 { DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT + REG_HRO },
89 { FLDATA (KIREQ, int_req[l_TTP], i_TTP) },
90 { FLDATA (KIENB, int_enb[l_TTP], i_TTP) },
91 { FLDATA (KARM, ttp_karm, 0) },
92 { FLDATA (CHP, ttp_kchp, 0) },
93 { HRDATA (TBUF, ttp_unit[TTO].buf, 8) },
94 { DRDATA (TPOS, ttp_unit[TTO].pos, T_ADDR_W), PV_LEFT },
95 { DRDATA (TTIME, ttp_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
96 { FLDATA (TIREQ, int_req[l_TTP], i_TTP + 1) },
97 { FLDATA (TIENB, int_enb[l_TTP], i_TTP + 1) },
98 { FLDATA (TARM, ttp_tarm, 0) },
99 { HRDATA (DEVNO, ttp_dib.dno, 8), REG_HRO },
100 { NULL }
101 };
102
103 MTAB ttp_mod[] = {
104 { TT_MODE, TT_MODE_UC, "UC", "UC", &ttp_set_mode },
105 { TT_MODE, TT_MODE_7B, "7b", "7B", &ttp_set_mode },
106 { TT_MODE, TT_MODE_8B, "8b", "8B", &ttp_set_mode },
107 { TT_MODE, TT_MODE_7P, "7p", "7P", &ttp_set_mode },
108 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED",
109 &ttp_set_enbdis, NULL, NULL },
110 { MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED",
111 &ttp_set_enbdis, NULL, NULL },
112 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK",
113 &ttp_set_break, NULL, NULL },
114 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
115 &set_dev, &show_dev, NULL },
116 { 0 }
117 };
118
119 DEVICE ttp_dev = {
120 "TTP", ttp_unit, ttp_reg, ttp_mod,
121 2, 10, 31, 1, 16, 8,
122 NULL, NULL, &ttp_reset,
123 NULL, NULL, NULL,
124 &ttp_dib, DEV_DIS
125 };
126
127 /* Terminal: I/O routine */
128
129 uint32 ttp (uint32 dev, uint32 op, uint32 dat)
130 {
131 int32 xmt = dev & 1;
132 int32 t, old_cmd;
133
134 switch (op) { /* case IO op */
135
136 case IO_ADR: /* select */
137 return BY; /* byte only */
138
139 case IO_RD: /* read */
140 ttp_kchp = 0; /* clr chr pend */
141 ttp_sta = ttp_sta & ~STA_OVR; /* clr overrun */
142 return ttp_unit[TTI].buf; /* return buf */
143
144 case IO_WD: /* write */
145 ttp_unit[TTO].buf = dat & 0xFF; /* store char */
146 ttp_sta = ttp_sta | STA_BSY; /* set busy */
147 sim_activate (&ttp_unit[TTO], ttp_unit[TTO].wait);
148 break;
149
150 case IO_SS: /* status */
151 if (xmt) t = ttp_sta & STA_XMT; /* xmt? just busy */
152 else { /* rcv */
153 t = ttp_sta & STA_RCV; /* get static */
154 if (!ttp_kchp) t = t | STA_BSY; /* no char? busy */
155 if (t & SET_EX) t = t | STA_EX; /* test for ex */
156 }
157 return t;
158
159 case IO_OC: /* command */
160 old_cmd = ttp_cmd; /* old cmd */
161 if (dat & CMD_TYP) { /* type 1? */
162 ttp_cmd = (ttp_cmd & 0xFF) | (dat << 8);
163 if (ttp_cmd & CMD_WRT) /* write? */
164 ttp_tarm = int_chg (v_TTP + 1, dat, ttp_tarm);
165 else ttp_karm = int_chg (v_TTP, dat, ttp_karm);
166 }
167 else ttp_cmd = (ttp_cmd & ~0xFF) | dat;
168 break;
169 }
170
171 return 0;
172 }
173
174 /* Unit service */
175
176 t_stat ttpi_svc (UNIT *uptr)
177 {
178 int32 c, out;
179
180 sim_activate (uptr, KBD_WAIT (uptr->wait, lfc_poll)); /* continue poll */
181 ttp_sta = ttp_sta & ~STA_FR; /* clear break */
182 if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
183 ttp_sta = ttp_sta & ~STA_PF; /* clear parity err */
184 if (ttp_kchp) ttp_sta = ttp_sta | STA_OVR; /* overrun? */
185 if (ttp_karm) SET_INT (v_TTP);
186 if (c & SCPE_BREAK) { /* break? */
187 ttp_sta = ttp_sta | STA_FR; /* framing error */
188 uptr->buf = 0; /* no character */
189 }
190 else {
191 out = c & 0x7F; /* echo is 7b */
192 c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags));
193 if (TT_GET_MODE (uptr->flags) != TT_MODE_8B) /* not 8b mode? */
194 c = pas_par (ttp_cmd, c); /* apply parity */
195 uptr->buf = c; /* save char */
196 uptr->pos = uptr->pos + 1; /* incr count */
197 ttp_kchp = 1; /* char pending */
198 if (ttp_cmd & CMD_ECHO) {
199 out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags));
200 if (c >= 0) sim_putchar (out);
201 ttp_unit[TTO].pos = ttp_unit[TTO].pos + 1;
202 }
203 }
204 return SCPE_OK;
205 }
206
207 t_stat ttpo_svc (UNIT *uptr)
208 {
209 int32 c;
210 t_stat r;
211
212 if (TT_GET_MODE (uptr->flags) == TT_MODE_8B) /* 8b? */
213 c = pas_par (ttp_cmd, uptr->buf); /* apply parity */
214 else c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags));
215 if (c >= 0) {
216 if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
217 sim_activate (uptr, uptr->wait); /* try again */
218 return ((r == SCPE_STALL)? SCPE_OK: r);
219 }
220 }
221 ttp_sta = ttp_sta & ~STA_BSY; /* not busy */
222 if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */
223 uptr->pos = uptr->pos + 1; /* incr count */
224 return SCPE_OK;
225 }
226
227 /* Reset routine */
228
229 t_stat ttp_reset (DEVICE *dptr)
230 {
231 if (dptr->flags & DEV_DIS) sim_cancel (&ttp_unit[TTI]);
232 else sim_activate_abs (&ttp_unit[TTI], KBD_WAIT (ttp_unit[TTI].wait, lfc_poll));
233 sim_cancel (&ttp_unit[TTO]);
234 CLR_INT (v_TTP); /* clear int */
235 CLR_ENB (v_TTP);
236 CLR_INT (v_TTP + 1); /* disable int */
237 CLR_ENB (v_TTP + 1);
238 ttp_karm = ttp_tarm = 0; /* disarm int */
239 ttp_cmd = 0;
240 ttp_sta = 0;
241 ttp_kchp = 0;
242 return SCPE_OK;
243 }
244
245 /* Make mode flags uniform */
246
247 t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
248 {
249 ttp_unit[TTO].flags = (ttp_unit[TTO].flags & ~TT_MODE) | val;
250 if (val == TT_MODE_7P) val = TT_MODE_7B;
251 ttp_unit[TTI].flags = (ttp_unit[TTI].flags & ~TT_MODE) | val;
252 return SCPE_OK;
253 }
254
255 /* Set input break */
256
257 t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc)
258 {
259 if (ttp_dev.flags & DEV_DIS) return SCPE_NOFNC;
260 ttp_sta = ttp_sta | STA_FR;
261 if (ttp_karm) SET_INT (v_TTP); /* if armed, intr */
262 sim_cancel (&ttp_unit[TTI]); /* restart TT poll */
263 sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait);
264 return SCPE_OK;
265 }
266
267 /* Set enabled/disabled */
268
269 t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc)
270 {
271 extern DEVICE tt_dev;
272 extern t_stat tt_reset (DEVICE *dptr);
273
274 ttp_dev.flags = (ttp_dev.flags & ~DEV_DIS) | val;
275 tt_dev.flags = (tt_dev.flags & ~DEV_DIS) | (val ^ DEV_DIS);
276 ttp_reset (&ttp_dev);
277 tt_reset (&tt_dev);
278 return SCPE_OK;
279 }