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