0ba620909eab6dd9aa35f4faf58b9c17e6d345d5
1 /* s3_pkb.c: System/3 5471 console terminal simulator
3 Copyright (c) 2001-2005, Charles E. Owen
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 Charles E. Owen 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 Charles E. Owen.
26 pkb 5471 printer/keyboard
28 25-Apr-03 RMS Revised for extended file support
29 08-Oct-02 RMS Added impossible function catcher
35 extern int32 int_req
, dev_busy
, dev_done
, dev_disable
;
36 t_stat
pkb_svc (UNIT
*uptr
);
37 t_stat
pkb_reset (DEVICE
*dptr
);
38 extern t_stat
sim_poll_kbd (void);
39 extern t_stat
sim_putchar (int32 out
);
40 extern int32 IAR
[], level
;
41 extern int32 debug_reg
;
43 /* 5471 data structures
45 pkb_dev TTI device descriptor
46 pkb_unit TTI unit descriptor
47 pkb_reg TTI register list
48 pkb_mod TTI/TTO modifiers list
51 /* Flag bits : (kept in pkb_unit.u3) */
53 #define PRT_INTREQ 0x800 /* Printer interrupt pending */
54 #define KBD_INTREQ 0x400 /* Request key interrupt pending */
55 #define KBD_INTEND 0x200 /* End or cancel key interrupt pending */
56 #define KBD_INTKEY 0x100 /* Return or other key interrupt pending */
57 #define KBD_REQLIGHT 0x20 /* Request Pending Indicator (light on/off) */
58 #define KBD_PROLIGHT 0x10 /* Proceed indicator (light on/off) */
59 #define KBD_REQINT 0x04 /* Req key interrupts enabled */
60 #define KBD_KEYINT 0x02 /* Other key interrupts enabled */
61 #define PRT_PRTINT 0x01 /* Printer interrupts enabled */
63 /* Keys mapped to 5471 functions */
65 int32 key_req
= 0x01; /* Request key: ^A */
66 int32 key_rtn
= 0x12; /* Return key: ^R */
67 int32 key_can
= 0x1B; /* Cancel key: ESC */
68 int32 key_end
= 0x0d; /* End key - CR */
70 UNIT pkb_unit
= { UDATA (&pkb_svc
, 0, 0), KBD_POLL_WAIT
};
73 { HRDATA (FLAG
, pkb_unit
.u3
, 16) },
74 { HRDATA (IBUF
, pkb_unit
.buf
, 8) },
75 { HRDATA (OBUF
, pkb_unit
.u4
, 8) },
76 { HRDATA (REQKEY
, key_req
, 8) },
77 { HRDATA (RTNKEY
, key_rtn
, 8) },
78 { HRDATA (CANKEY
, key_can
, 8) },
79 { HRDATA (ENDKEY
, key_end
, 8) },
80 { DRDATA (POS
, pkb_unit
.pos
, T_ADDR_W
), PV_LEFT
},
81 { DRDATA (TIME
, pkb_unit
.wait
, 24), REG_NZ
+ PV_LEFT
},
90 "PKB", &pkb_unit
, pkb_reg
, pkb_mod
,
92 NULL
, NULL
, &pkb_reset
,
97 /*-------------------------------------------------------------------*/
98 /* EBCDIC to ASCII translate table */
99 /*-------------------------------------------------------------------*/
100 unsigned char ebcdic_to_ascii
[] = {
101 "\x00\x01\x02\x03\xA6\x09\xA7\x7F\xA9\xB0\xB1\x0B\x0C\x0D\x0E\x0F"
102 "\x10\x11\x12\x13\xB2\xB4\x08\xB7\x18\x19\x1A\xB8\xBA\x1D\xBB\x1F"
103 "\xBD\xC0\x1C\xC1\xC2\x0A\x17\x1B\xC3\xC4\xC5\xC6\xC7\x05\x06\x07"
104 "\xC8\xC9\x16\xCB\xCC\x1E\xCD\x04\xCE\xD0\xD1\xD2\x14\x15\xD3\xFC"
105 "\x20\xD4\x83\x84\x85\xA0\xD5\x86\x87\xA4\xD6\x2E\x3C\x28\x2B\xD7"
106 "\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xD8\x21\x24\x2A\x29\x3B\x5E"
107 "\x2D\x2F\xD9\x8E\xDB\xDC\xDD\x8F\x80\xA5\x7C\x2C\x25\x5F\x3E\x3F"
108 "\xDE\x90\xDF\xE0\xE2\xE3\xE4\xE5\xE6\x60\x3A\x23\x40\x27\x3D\x22"
109 "\xE7\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xE8\xE9\xEA\xEC"
110 "\xF0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xF1\xF2\x91\xF3\x92\xF4"
111 "\xF5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xA8\xF6\x5B\xF7\xF8"
112 "\x9B\x9C\x9D\x9E\x9F\xB5\xB6\xAC\xAB\xB9\xAA\xB3\xBC\x5D\xBE\xBF"
113 "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xCA\x93\x94\x95\xA2\xCF"
114 "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xDA\x96\x81\x97\xA3\x98"
115 "\x5C\xE1\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\xEB\x99\xED\xEE\xEF"
116 "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xFE\xFB\x9A\xF9\xFA\xFF"
119 /*-------------------------------------------------------------------*/
120 /* ASCII to EBCDIC translate table */
121 /*-------------------------------------------------------------------*/
122 unsigned char ascii_to_ebcdic
[] = {
123 "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F"
124 "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x1A\x27\x22\x1D\x35\x1F"
125 "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61"
126 "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F"
127 "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6"
128 "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D"
129 "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96"
130 "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x6A\xD0\xA1\x07"
131 "\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67"
132 "\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\xB0\xB1\xB2\xB3\xB4"
133 "\x45\x55\xCE\xDE\x49\x69\x04\x06\xAB\x08\xBA\xB8\xB7\xAA\x8A\x8B"
134 "\x09\x0A\x14\xBB\x15\xB5\xB6\x17\x1B\xB9\x1C\x1E\xBC\x20\xBE\xBF"
135 "\x21\x23\x24\x28\x29\x2A\x2B\x2C\x30\x31\xCA\x33\x34\x36\x38\xCF"
136 "\x39\x3A\x3B\x3E\x41\x46\x4A\x4F\x59\x62\xDA\x64\x65\x66\x70\x72"
137 "\x73\xE1\x74\x75\x76\x77\x78\x80\x8C\x8D\x8E\xEB\x8F\xED\xEE\xEF"
138 "\x90\x9A\x9B\x9D\x9F\xA0\xAC\xAE\xAF\xFD\xFE\xFB\x3F\xEA\xFA\xFF"
141 /* -------------------------------------------------------------------- */
143 /* Console Input: master routine */
145 int32
pkb (int32 op
, int32 m
, int32 n
, int32 data
)
147 int32 iodata
= 0, ec
, ac
;
149 case 0: /* SIO 5471 */
152 /*printf("%04X SIO %d,%d,%02X\n\r", IAR[level]-4, m, n, data);*/
153 if (m
== 0) { /* Keyboard */
154 pkb_unit
.u3
&= 0xFC1;
157 pkb_unit
.u3
&= ~KBD_INTREQ
;
158 pkb_unit
.u3
&= ~KBD_INTKEY
;
159 pkb_unit
.u3
&= ~KBD_INTEND
;
160 return RESET_INTERRUPT
;
162 } else { /* Printer */
163 if (data
& 0x80) { /* start print bit */
164 if (debug_reg
& 0x80)
166 ec
= pkb_unit
.u4
& 0xff;
167 ac
= ebcdic_to_ascii
[ec
];
169 pkb_unit
.u3
|= PRT_INTREQ
;
171 if (data
& 0x40) { /* Carr. Return */
174 pkb_unit
.u3
|= PRT_INTREQ
;
176 pkb_unit
.u3
&= 0xFFe;
177 if (data
& 0x04) /* Print interrupt flag */
178 pkb_unit
.u3
|= PRT_PRTINT
;
179 if (data
& 0x01) { /* Reset Interrupt */
182 pkb_unit
.u3
&= ~PRT_INTREQ
;
183 return RESET_INTERRUPT
;
188 case 1: /* LIO 5471 */
193 pkb_unit
.u4
= (data
>> 8) & 0xff;
196 case 2: /* TIO 5471 */
198 case 3: /* SNS 5471 */
199 if (n
!= 1 && n
!= 3)
200 return (STOP_INVDEV
<< 16);
201 if (m
== 0) { /* Keyboard data */
202 if (n
== 1) { /* Sense bytes 0 & 1 */
203 iodata
= (pkb_unit
.buf
<< 8) & 0xff00;
204 if (pkb_unit
.u3
& KBD_INTREQ
)
206 if (pkb_unit
.u3
& KBD_INTEND
)
208 if (pkb_unit
.u3
& KBD_INTKEY
)
210 if (pkb_unit
.buf
== 0x12) /* Return key */
212 if (pkb_unit
.buf
== 0x03) /* Cancel key */
214 if (pkb_unit
.buf
== 0x0d) /* End key */
216 iodata
|= ((SCPE_OK
<< 16) & 0xffff0000);
217 } else { /* Sense bytes 2 & 3 */
218 iodata
= 0; /* Manual says CE use only */
220 } else { /* Printer Data */
221 if (n
== 1) { /* Sense bytes 0 & 1 */
223 if (pkb_unit
.u3
& PRT_INTREQ
)
226 iodata
= 0; /* CE use only */
229 iodata
|= ((SCPE_OK
<< 16) & 0xffff0000);
231 case 4: /* APL 5471 */
236 printf (">>PKB non-existent function %d\n", op
);
242 t_stat
pkb_svc (UNIT
*uptr
)
246 sim_activate (&pkb_unit
, pkb_unit
.wait
); /* continue poll */
248 if (pkb_unit
.u3
& PRT_INTREQ
) { /* Printer Interrupt */
253 /* Keyboard : handle input */
255 if ((temp
= sim_poll_kbd ()) < SCPE_KFLAG
) return temp
; /* no char or error? */
257 ac
= temp
& 0x7f; /* placed type ASCII char in ac */
258 if (pkb_unit
.u3
& KBD_REQINT
) {
259 if (ac
== key_req
) { /* Request Key */
260 pkb_unit
.u3
|= KBD_INTREQ
;
267 ec
= ascii_to_ebcdic
[ac
]; /* Translate */
268 pkb_unit
.buf
= ec
; /* put in buf */
269 pkb_unit
.pos
= pkb_unit
.pos
+ 1;
270 if (ac
== key_end
) { /* End key */
271 if (pkb_unit
.u3
& KBD_KEYINT
) {
272 pkb_unit
.u3
|= KBD_INTEND
;
278 if (ac
== key_can
) { /* Cancel key */
279 if (pkb_unit
.u3
& KBD_KEYINT
) {
280 pkb_unit
.u3
|= KBD_INTEND
;
286 if (ac
== key_rtn
) { /* Return key */
287 if (pkb_unit
.u3
& KBD_KEYINT
) {
288 pkb_unit
.u3
|= KBD_INTKEY
;
294 if (pkb_unit
.u3
& KBD_KEYINT
) { /* Key interupts enabled ? */
295 int_req
|= 2; /* Device 1 Interrupt! */
296 pkb_unit
.u3
|= KBD_INTKEY
; /* Set pending flag */
303 t_stat
pkb_reset (DEVICE
*dptr
)
306 int_req
= int_req
& ~0x02; /* reset interrupt */
307 sim_activate (&pkb_unit
, pkb_unit
.wait
); /* activate unit */
311 t_stat
pkb_setmod (UNIT
*uptr
, int32 value
)