vrkiu.c revision 1.1 1 /* $NetBSD: vrkiu.c,v 1.1 1999/09/16 12:23:33 takemura Exp $ */
2
3 /*-
4 * Copyright (c) 1999 SASAKI Takesi
5 * Copyright (c) 1999 PocketBSD Project. All rights reserved.
6 * All rights reserved.
7 *
8 * This code is a part of the PocketBSD.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the PocketBSD project
21 * and its contributors.
22 * 4. Neither the name of the project nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 */
39
40 #define VRKIUDEBUG
41
42 #include <sys/param.h>
43 #include <sys/tty.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46 #include <sys/conf.h>
47 #include <sys/kernel.h>
48 #include <sys/proc.h>
49
50 #include <machine/intr.h>
51 #include <machine/cpu.h>
52 #include <machine/bus.h>
53 #include <machine/platid.h>
54
55 #include <hpcmips/vr/vr.h>
56 #include <hpcmips/vr/vripvar.h>
57 #include <hpcmips/vr/vrkiuvar.h>
58 #include <hpcmips/vr/vrkiureg.h>
59 #include <hpcmips/vr/icureg.h>
60
61 #ifdef VRKIUDEBUG
62 int vrkiu_debug = 0;
63 #define DPRINTF(arg) if (vrkiu_debug) printf arg;
64 #else
65 #define DPRINTF(arg)
66 #endif
67
68 static int vrkiumatch __P((struct device *, struct cfdata *, void *));
69 static void vrkiuattach __P((struct device *, struct device *, void *));
70
71 static void vrkiu_write __P((struct vrkiu_softc *, int, unsigned short));
72 static unsigned short vrkiu_read __P((struct vrkiu_softc *, int));
73
74 int vrkiu_intr __P((void *));
75
76 static void detect_key __P((struct vrkiu_softc *));
77 static void process_key __P((struct vrkiu_softc *, int, int));
78
79 struct cfattach vrkiu_ca = {
80 sizeof(struct vrkiu_softc), vrkiumatch, vrkiuattach
81 };
82
83 static struct vrkiu_softc *the_vrkiu = NULL; /* XXX: kludge!! */
84
85 /* XXX: This tranlation table may depend on each machine.
86 Should I build it in? */
87 static char keytrans[] = {
88 -1, 28, 25, 52, 21, 48, 44, 57, /* - enter p . y b z space */
89 -1, 53, 24, 51, 20, 47, 30, -1, /* - / o , t v a - */
90 -1, -1, 23, 50, 19, 46, 17, -1, /* - - i m r c w - */
91 13, -1, 22, -1, 18, 45, 16, 2, /* = - u - e x q 1 */
92 -1, -1, 11, 38, 40, 34, 15, 59, /* - - 0 l ' g tab f1 */
93 -1, 39, 10, 49, 6, 33, 3, 37, /* - ; 9 n 5 f 2 k */
94 -1, 27, 9, 36, 5, 32, 7, -1, /* - ] 8 j 4 d 6 - */
95 12, 26, 8, 35, 4, 41, 31, -1, /* - [ 7 h 3 ` s - */
96 58, -1, -1, -1, 14, -1, 66, 61, /* caps - - - bs - f8 f3 */
97 -1, 56, -1, -1, 43, -1, 65, 62, /* - alt - - \ - f7 f4 */
98 -1, -1, 29, -1, 68, -1, 64, 60, /* - - ctrl - f10 - f6 f2 */
99 -1, -1, -1, 42, -1, 67, 63, 1, /* - - - shift - f9 f5 esc */
100 };
101 /* XXX: fill the field of funct. keys, ex. arrow, fnc, nfer... */
102
103 #define SCROLL 0x0001 /* stop output */
104 #define NUM 0x0002 /* numeric shift cursors vs. numeric */
105 #define CAPS 0x0004 /* caps shift -- swaps case of letter */
106 #define SHIFT 0x0008 /* keyboard shift */
107 #define CTL 0x0010 /* control shift -- allows ctl function */
108 #define ASCII 0x0020 /* ascii code for this key */
109 #define ALT 0x0080 /* alternate shift -- alternate chars */
110 #define FUNC 0x0100 /* function key */
111 #define KP 0x0200 /* Keypad keys */
112 #define NONE 0x0400 /* no function */
113
114 #define CODE_SIZE 4 /* Use a max of 4 for now... */
115
116 typedef struct {
117 u_short type;
118 char unshift[CODE_SIZE];
119 char shift[CODE_SIZE];
120 char ctl[CODE_SIZE];
121 } Scan_def;
122
123 #if !defined(PCCONS_REAL_BS)
124 #define PCCONS_REAL_BS 1
125 #endif
126 #if !defined(CAPS_IS_CONTROL)
127 #define CAPS_IS_CONTROL 1
128 #endif
129 #if !defined(CAPS_ADD_CONTROL)
130 #define CAPS_ADD_CONTROL 0
131 #endif
132
133 static Scan_def scan_codes[] = {
134 { NONE, "", "", "" }, /* 0 unused */
135 { ASCII,"\033", "\033", "\033" }, /* 1 ESCape */
136 { ASCII,"1", "!", "!" }, /* 2 1 */
137 { ASCII,"2", "@", "\000" }, /* 3 2 */
138 { ASCII,"3", "#", "#" }, /* 4 3 */
139 { ASCII,"4", "$", "$" }, /* 5 4 */
140 { ASCII,"5", "%", "%" }, /* 6 5 */
141 { ASCII,"6", "^", "\036" }, /* 7 6 */
142 { ASCII,"7", "&", "&" }, /* 8 7 */
143 { ASCII,"8", "*", "\010" }, /* 9 8 */
144 { ASCII,"9", "(", "(" }, /* 10 9 */
145 { ASCII,"0", ")", ")" }, /* 11 0 */
146 { ASCII,"-", "_", "\037" }, /* 12 - */
147 { ASCII,"=", "+", "+" }, /* 13 = */
148 #ifndef PCCONS_REAL_BS
149 { ASCII,"\177", "\177", "\010" }, /* 14 backspace */
150 #else
151 { ASCII,"\010", "\010", "\177" }, /* 14 backspace */
152 #endif
153 { ASCII,"\t", "\177\t", "\t" }, /* 15 tab */
154 { ASCII,"q", "Q", "\021" }, /* 16 q */
155 { ASCII,"w", "W", "\027" }, /* 17 w */
156 { ASCII,"e", "E", "\005" }, /* 18 e */
157 { ASCII,"r", "R", "\022" }, /* 19 r */
158 { ASCII,"t", "T", "\024" }, /* 20 t */
159 { ASCII,"y", "Y", "\031" }, /* 21 y */
160 { ASCII,"u", "U", "\025" }, /* 22 u */
161 { ASCII,"i", "I", "\011" }, /* 23 i */
162 { ASCII,"o", "O", "\017" }, /* 24 o */
163 { ASCII,"p", "P", "\020" }, /* 25 p */
164 { ASCII,"[", "{", "\033" }, /* 26 [ */
165 { ASCII,"]", "}", "\035" }, /* 27 ] */
166 { ASCII,"\r", "\r", "\n" }, /* 28 return */
167 #if CAPS_IS_CONTROL == 1 && CAPS_ADD_CONTROL == 0
168 { CAPS, "", "", "" }, /* 29 caps */
169 #else
170 { CTL, "", "", "" }, /* 29 control */
171 #endif
172 { ASCII,"a", "A", "\001" }, /* 30 a */
173 { ASCII,"s", "S", "\023" }, /* 31 s */
174 { ASCII,"d", "D", "\004" }, /* 32 d */
175 { ASCII,"f", "F", "\006" }, /* 33 f */
176 { ASCII,"g", "G", "\007" }, /* 34 g */
177 { ASCII,"h", "H", "\010" }, /* 35 h */
178 { ASCII,"j", "J", "\n" }, /* 36 j */
179 { ASCII,"k", "K", "\013" }, /* 37 k */
180 { ASCII,"l", "L", "\014" }, /* 38 l */
181 { ASCII,";", ":", ";" }, /* 39 ; */
182 { ASCII,"'", "\"", "'" }, /* 40 ' */
183 { ASCII,"`", "~", "`" }, /* 41 ` */
184 { SHIFT,"", "", "" }, /* 42 shift */
185 { ASCII,"\\", "|", "\034" }, /* 43 \ */
186 { ASCII,"z", "Z", "\032" }, /* 44 z */
187 { ASCII,"x", "X", "\030" }, /* 45 x */
188 { ASCII,"c", "C", "\003" }, /* 46 c */
189 { ASCII,"v", "V", "\026" }, /* 47 v */
190 { ASCII,"b", "B", "\002" }, /* 48 b */
191 { ASCII,"n", "N", "\016" }, /* 49 n */
192 { ASCII,"m", "M", "\r" }, /* 50 m */
193 { ASCII,",", "<", "<" }, /* 51 , */
194 { ASCII,".", ">", ">" }, /* 52 . */
195 { ASCII,"/", "?", "\037" }, /* 53 / */
196 { SHIFT,"", "", "" }, /* 54 shift */
197 { KP, "*", "*", "*" }, /* 55 kp * */
198 { ALT, "", "", "" }, /* 56 alt */
199 { ASCII," ", " ", "\000" }, /* 57 space */
200 #if CAPS_IS_CONTROL == 1 || CAPS_ADD_CONTROL == 1
201 { CTL, "", "", "" }, /* 58 control */
202 #else
203 { CAPS, "", "", "" }, /* 58 caps */
204 #endif
205 { FUNC, "\033[M", "\033[Y", "\033[k" }, /* 59 f1 */
206 { FUNC, "\033[N", "\033[Z", "\033[l" }, /* 60 f2 */
207 { FUNC, "\033[O", "\033[a", "\033[m" }, /* 61 f3 */
208 { FUNC, "\033[P", "\033[b", "\033[n" }, /* 62 f4 */
209 { FUNC, "\033[Q", "\033[c", "\033[o" }, /* 63 f5 */
210 { FUNC, "\033[R", "\033[d", "\033[p" }, /* 64 f6 */
211 { FUNC, "\033[S", "\033[e", "\033[q" }, /* 65 f7 */
212 { FUNC, "\033[T", "\033[f", "\033[r" }, /* 66 f8 */
213 { FUNC, "\033[U", "\033[g", "\033[s" }, /* 67 f9 */
214 { FUNC, "\033[V", "\033[h", "\033[t" }, /* 68 f10 */
215 { NUM, "", "", "" }, /* 69 num lock */
216 { SCROLL,"", "", "" }, /* 70 scroll lock */
217 { KP, "7", "\033[H", "7" }, /* 71 kp 7 */
218 { KP, "8", "\033[A", "8" }, /* 72 kp 8 */
219 { KP, "9", "\033[I", "9" }, /* 73 kp 9 */
220 { KP, "-", "-", "-" }, /* 74 kp - */
221 { KP, "4", "\033[D", "4" }, /* 75 kp 4 */
222 { KP, "5", "\033[E", "5" }, /* 76 kp 5 */
223 { KP, "6", "\033[C", "6" }, /* 77 kp 6 */
224 { KP, "+", "+", "+" }, /* 78 kp + */
225 { KP, "1", "\033[F", "1" }, /* 79 kp 1 */
226 { KP, "2", "\033[B", "2" }, /* 80 kp 2 */
227 { KP, "3", "\033[G", "3" }, /* 81 kp 3 */
228 { KP, "0", "\033[L", "0" }, /* 82 kp 0 */
229 { KP, ".", "\177", "." }, /* 83 kp . */
230 { NONE, "", "", "" }, /* 84 0 */
231 { NONE, "100", "", "" }, /* 85 0 */
232 { NONE, "101", "", "" }, /* 86 0 */
233 { FUNC, "\033[W", "\033[i", "\033[u" }, /* 87 f11 */
234 { FUNC, "\033[X", "\033[j", "\033[v" }, /* 88 f12 */
235 { NONE, "102", "", "" }, /* 89 0 */
236 { NONE, "103", "", "" }, /* 90 0 */
237 { NONE, "", "", "" }, /* 91 0 */
238 { ASCII,"\177", "\177", "\010" }, /* 92 del */
239 { NONE, "", "", "" }, /* 93 0 */
240 { NONE, "", "", "" }, /* 94 0 */
241 { NONE, "", "", "" }, /* 95 0 */
242 { NONE, "", "", "" }, /* 96 0 */
243 { NONE, "", "", "" }, /* 97 0 */
244 { NONE, "", "", "" }, /* 98 0 */
245 { NONE, "", "", "" }, /* 99 0 */
246 { NONE, "", "", "" }, /* 100 */
247 { NONE, "", "", "" }, /* 101 */
248 { NONE, "", "", "" }, /* 102 */
249 { NONE, "", "", "" }, /* 103 */
250 { NONE, "", "", "" }, /* 104 */
251 { NONE, "", "", "" }, /* 105 */
252 { NONE, "", "", "" }, /* 106 */
253 { NONE, "", "", "" }, /* 107 */
254 { NONE, "", "", "" }, /* 108 */
255 { NONE, "", "", "" }, /* 109 */
256 { NONE, "", "", "" }, /* 110 */
257 { NONE, "", "", "" }, /* 111 */
258 { NONE, "", "", "" }, /* 112 */
259 { NONE, "", "", "" }, /* 113 */
260 { NONE, "", "", "" }, /* 114 */
261 { NONE, "", "", "" }, /* 115 */
262 { NONE, "", "", "" }, /* 116 */
263 { NONE, "", "", "" }, /* 117 */
264 { NONE, "", "", "" }, /* 118 */
265 { NONE, "", "", "" }, /* 119 */
266 { NONE, "", "", "" }, /* 120 */
267 { NONE, "", "", "" }, /* 121 */
268 { NONE, "", "", "" }, /* 122 */
269 { NONE, "", "", "" }, /* 123 */
270 { NONE, "", "", "" }, /* 124 */
271 { NONE, "", "", "" }, /* 125 */
272 { NONE, "", "", "" }, /* 126 */
273 { NONE, "", "", "" }, /* 127 */
274 };
275
276 /* XXX: Make these queue obsolute, or move these into vrkiu_softc */
277 static int
278 vrkiumatch(parent, cf, aux)
279 struct device *parent;
280 struct cfdata *cf;
281 void *aux;
282 {
283 return 1; /* XXX */
284 }
285
286 static inline void
287 vrkiu_write(sc, port, val)
288 struct vrkiu_softc *sc;
289 int port;
290 unsigned short val;
291 {
292 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
293 }
294
295 static inline unsigned short
296 vrkiu_read(sc, port)
297 struct vrkiu_softc *sc;
298 int port;
299 {
300 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
301 }
302
303 static void
304 vrkiuattach(parent, self, aux)
305 struct device *parent;
306 struct device *self;
307 void *aux;
308 {
309 struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
310 struct vrip_attach_args *va = aux;
311
312 bus_space_tag_t iot = va->va_iot;
313 bus_space_handle_t ioh;
314
315 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
316 printf(": can't map bus space\n");
317 return;
318 }
319
320 sc->sc_iot = iot;
321 sc->sc_ioh = ioh;
322
323 /* set KIU */
324 vrkiu_write(sc, KIURST, 1); /* reset */
325 vrkiu_write(sc, KIUSCANLINE, 0); /* 96keys */
326 vrkiu_write(sc, KIUWKS, 0x18a4); /* XXX: scan timing! */
327 vrkiu_write(sc, KIUWKI, 450);
328 vrkiu_write(sc, KIUSCANREP, 0x8023);
329 /* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
330
331 the_vrkiu = sc;
332
333 if (!(sc->sc_handler =
334 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
335 vrkiu_intr, sc))) {
336 printf (": can't map interrupt line.\n");
337 return;
338 }
339 /* Level2 register setting */
340 vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
341
342 printf("\n");
343 }
344
345 int
346 vrkiu_intr(arg)
347 void *arg;
348 {
349 struct vrkiu_softc *sc = arg;
350 /* When key scan finisshed, this entry is called. */
351 detect_key(sc);
352 DPRINTF(("%d", vrkiu_read(sc, KIUINT) & 7));
353
354 vrkiu_write(sc, KIUINT, 0x7); /* Clear all interrupt */
355
356 return 0;
357 }
358
359 static void
360 detect_key(sc)
361 struct vrkiu_softc *sc;
362 {
363 int i, k;
364
365 DPRINTF(("[detect_key():begin read]"));
366
367 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
368 k = vrkiu_read(sc, KIUDATP + i * 2) ^ sc->keystat[i];
369 sc->keystat[i] = vrkiu_read(sc, KIUDATP + i * 2);
370 while (k) {
371 int n, m;
372 n = ffs(k) - 1;
373 if (n < 0) {
374 break;
375 }
376 k ^= 1 << n;
377 m = n + i * 16;
378 if (keytrans[m] < 0) {
379 printf("vrkiu: Unkown scan code 0x%02x\n", m);
380 continue;
381 }
382 /* XXX: scanbuf may overflow! */
383 process_key(sc, keytrans[m],
384 !((sc->keystat[i] & (1 << n))));
385 }
386 /* XXX: The order of keys can be a problem.
387 If CTRL and normal key are pushed simultaneously,
388 normal key can be entered in queue first.
389 Same problem would occur in key break. */
390 }
391 /* TODO: Enter scancode into the queue as long as the key pressed */
392
393 }
394
395 static void
396 process_key(sc, k, brk)
397 struct vrkiu_softc *sc;
398 int k, brk;
399 {
400 char *p;
401 extern struct tty biconsdev_tty[];
402
403 switch (scan_codes[k].type) {
404 case ALT:
405 sc->k_alt = brk ? 0 : 1;
406 break;
407 case SHIFT:
408 sc->k_sft = brk ? 0 : 1;
409 break;
410 case CTL:
411 sc->k_ctrl = brk ? 0 : 1;
412 break;
413 case ASCII:
414 if (!brk) {
415 if (sc->k_ctrl) {
416 p = scan_codes[k].ctl;
417 } else if (sc->k_sft) {
418 p = scan_codes[k].shift;
419 } else {
420 p = scan_codes[k].unshift;
421 }
422 sc->keybuf[sc->keybufhead++] =
423 sc->k_alt ? (*p | 0x80) : *p;
424 /* XXX: multi byte key! */
425 if (sc->keybufhead >= NKEYBUF) {
426 sc->keybufhead = 0;
427 }
428 (*linesw[0].l_rint)(sc->k_alt ? (*p | 0x80) : *p,
429 &biconsdev_tty [0]);
430 }
431 break;
432 default:
433 /* Ignored */
434 }
435 }
436
437 /* called from biconsdev.c */
438 int
439 vrkiu_getc()
440 {
441 int ret;
442
443 if (the_vrkiu == NULL) {
444 return 0; /* XXX */
445 }
446
447 while (the_vrkiu->keybuftail == the_vrkiu->keybufhead) {
448 detect_key(the_vrkiu);
449 }
450 ret = the_vrkiu->keybuf[the_vrkiu->keybuftail++];
451 if (the_vrkiu->keybuftail >= NKEYBUF) {
452 the_vrkiu->keybuftail = 0;
453 }
454 return ret;
455 }
456
457