vrkiu.c revision 1.12 1 /* $NetBSD: vrkiu.c,v 1.12 2000/01/22 09:12:35 takemura Exp $ */
2
3 /*-
4 * Copyright (c) 1999 SASAKI Takesi All rights reserved.
5 * Copyright (c) 1999 TAKEMRUA, Shin All rights reserved.
6 * Copyright (c) 1999 PocketBSD Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the PocketBSD project
19 * and its contributors.
20 * 4. Neither the name of the project nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 */
37
38 #define VRKIUDEBUG
39
40 #include <sys/param.h>
41 #include <sys/tty.h>
42 #include <sys/systm.h>
43 #include <sys/device.h>
44 #include <sys/conf.h>
45 #include <sys/kernel.h>
46 #include <sys/proc.h>
47
48 #include <machine/intr.h>
49 #include <machine/cpu.h>
50 #include <machine/bus.h>
51 #include <machine/platid.h>
52 #include <machine/platid_mask.h>
53
54 #include <hpcmips/vr/vr.h>
55 #include <hpcmips/vr/vripvar.h>
56 #include <hpcmips/vr/vrkiuvar.h>
57 #include <hpcmips/vr/vrkiureg.h>
58 #include <hpcmips/vr/icureg.h>
59
60 #include <dev/wscons/wsconsio.h>
61 #include <dev/wscons/wskbdvar.h>
62 #include <dev/wscons/wsksymdef.h>
63 #include <dev/wscons/wsksymvar.h>
64 #include <dev/pckbc/wskbdmap_mfii.h>
65
66 #include "opt_pckbd_layout.h"
67
68 #ifdef VRKIUDEBUG
69 int vrkiu_debug = 0;
70 #define DPRINTF(arg) if (vrkiu_debug) printf arg;
71 #else
72 #define DPRINTF(arg)
73 #endif
74
75 /*
76 * structure and data types
77 */
78 struct vrkiu_chip {
79 bus_space_tag_t kc_iot;
80 bus_space_handle_t kc_ioh;
81 unsigned short kc_scandata[KIU_NSCANLINE/2];
82 int kc_polling;
83 #define NEVENTQ 32
84 struct {
85 u_int kc_type;
86 int kc_data;
87 } kc_eventq[NEVENTQ], *kc_head, *kc_tail;
88 int kc_nevents;
89
90 struct vrkiu_softc* kc_sc; /* back link */
91 };
92
93 struct vrkiu_softc {
94 struct device sc_dev;
95 struct vrkiu_chip *sc_chip;
96 struct vrkiu_chip sc_chip_body;
97 int sc_enabled;
98 struct device *sc_wskbddev;
99
100 void *sc_handler;
101 };
102
103 /*
104 * function prototypes
105 */
106 static int vrkiumatch __P((struct device *, struct cfdata *, void *));
107 static void vrkiuattach __P((struct device *, struct device *, void *));
108
109 int vrkiu_intr __P((void *));
110
111 static int vrkiu_init(struct vrkiu_chip*, bus_space_tag_t, bus_space_handle_t);
112 static void vrkiu_write __P((struct vrkiu_chip *, int, unsigned short));
113 static unsigned short vrkiu_read __P((struct vrkiu_chip *, int));
114 static int vrkiu_is_console(bus_space_tag_t, bus_space_handle_t);
115 static int detect_key __P((struct vrkiu_chip *));
116 static int vrkiu_getevent __P((struct vrkiu_chip*, u_int*, int*));
117 static int vrkiu_putevent __P((struct vrkiu_chip*, u_int, int));
118
119 /* wskbd accessopts */
120 int vrkiu_enable __P((void *, int));
121 void vrkiu_set_leds __P((void *, int));
122 int vrkiu_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
123
124 /* consopts */
125 void vrkiu_cngetc __P((void*, u_int*, int*));
126 void vrkiu_cnpollc __P((void *, int));
127
128 /*
129 * global/static data
130 */
131 struct cfattach vrkiu_ca = {
132 sizeof(struct vrkiu_softc), vrkiumatch, vrkiuattach
133 };
134
135 const struct wskbd_accessops vrkiu_accessops = {
136 vrkiu_enable,
137 vrkiu_set_leds,
138 vrkiu_ioctl,
139 };
140
141 const struct wskbd_consops vrkiu_consops = {
142 vrkiu_cngetc,
143 vrkiu_cnpollc,
144 };
145
146 struct wskbd_mapdata vrkiu_keymapdata = {
147 pckbd_keydesctab,
148 #ifdef PCKBD_LAYOUT
149 PCKBD_LAYOUT,
150 #else
151 KB_US,
152 #endif
153 };
154
155 struct vrkiu_chip *vrkiu_consdata = NULL;
156
157 #define UNK -1 /* unknown */
158 #define IGN -2 /* ignore */
159
160 static char default_keytrans[] = {
161 /*00*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
162 /*08*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
163 /*10*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
164 /*18*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
165 /*20*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
166 /*28*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
167 /*30*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
168 /*38*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
169 /*40*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
170 /*48*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
171 /*50*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
172 /*58*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
173 };
174
175 /* NEC MobileGearII MCR series (Japan) */
176 static char mcr_jp_keytrans[] = {
177 /*00*/ 77, 28, 25, 52, 21, 48, 44, 57, /* right ent p . y b z space */
178 /*08*/ 80, 53, 24, 51, 20, 47, 30, 123, /* down / o , t v a nfer */
179 /*10*/ 75, 115, 23, 50, 19, 46, 17, 221, /* left \ i m r c w menu */
180 /*18*/ 13, IGN, 22, IGN, 18, 45, 16, 2, /* ^ - u - e x q 1 */
181 /*20*/ 81, 41, 11, 38, 40, 34, 15, 59, /* pgdn h/z 0 l : g tab f1 */
182 /*28*/ 121, 39, 10, 49, 6, 33, 3, 37, /* xfer ; 9 n 5 f 2 k */
183 /*30*/ 72, 27, 9, 36, 5, 32, 7, IGN, /* up [ 8 j 4 d 6 - */
184 /*38*/ 12, 26, 8, 35, 4, 43, 31, IGN, /* - @ 7 h 3 ] s - */
185 /*40*/ 58, IGN, IGN, IGN, 14, IGN, 66, 61, /* caps - - - bs - f8 f3 */
186 /*48*/ IGN, 56, IGN, IGN, 125, 112, 65, 62, /* - alt - - | k/h f7 f4 */
187 /*50*/ IGN, IGN, 29, IGN, 68, 73, 64, 60, /* - - ctrl - f10 pgup f6 f2 */
188 /*58*/ IGN, IGN, IGN, 42, 14, 67, 63, 1, /* - - - shift del f9 f5 esc */
189 };
190
191 /* IBM WorkPad z50 */
192 static char z50_keytrans[] = {
193 /*00*/ 59, 61, 63, 65, 67, IGN, IGN, 87, /* f1 f3 f5 f7 f9 - - f11 */
194 /*08*/ 60, 62, 64, 66, 68, IGN, IGN, 88, /* f2 f4 f6 f8 f10 - - f12 */
195 /*10*/ 40, 26, 12, 11, 25, 39, 72, 53, /* ' [ - 0 p ; up / */
196 /*18*/ IGN, IGN, IGN, 10, 24, 38, 52, IGN, /* - - - 9 o l . - */
197 /*20*/ 75, 27, 13, 9, 23, 37, 51, IGN, /* left ] = 8 i k , - */
198 /*28*/ 35, 21, 7, 8, 22, 36, 50, 49, /* h y 6 7 u j m n */
199 /*30*/ IGN, 14, 69, 14, IGN, 43, 28, 57, /* - bs num del - \ ent sp */
200 /*38*/ 34, 20, 6, 5, 19, 33, 47, 48, /* g t 5 4 r f v b */
201 /*40*/ IGN, IGN, IGN, 4, 18, 32, 46, 77, /* - - - 3 e d c right */
202 /*48*/ IGN, IGN, IGN, 3, 17, 31, 45, 80, /* - - - 2 w s x down */
203 /*50*/ 1, 29, 41, 2, 16, 30, 44, IGN, /* esc tab ~ 1 q a z - */
204 /*58*/ 221, 42, 29, 29, 56, 56, 54, IGN, /* menu Ls Lc Rc La Ra Rs - */
205 };
206
207 /* Sharp Tripad PV6000 */
208 static char tripad_keytrans[] = {
209 /*00*/ 42, 15, 41, 16, 1, 2, 104, 221, /* lsh tab ` q esc 1 WIN - */
210 /*08*/ 58, 44, 45, 30, 31, 17, 18, 3, /* ctrl z x a s w e 2 */
211 /*10*/ 56, 57, 46, 47, 32, 33, 19, 4, /* lalt sp c v d f r 3 */
212 /*18*/ 48, 49, 34, 35, 20, 21, 5, 6, /* b n g h t y 4 5 */
213 /*20*/ 50, 51, 36, 37, 22, 23, 7, 8, /* m , j k u i 6 7 */
214 /*28*/ 105, 29, 38, 24, 25, 9, 10, 11, /* Fn caps l o p 8 9 0 */
215 /*30*/ 26, 27, 102, 52, 53, 39, 12, 13, /* [ ] dar , / ; \- = */
216 /*38*/ 54, 103, 100, 102, 39, 28, 43, 14, /* rsh - - uar - ; ent \ del */
217 /*40*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
218 /*48*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
219 /*50*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
220 /*58*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
221 };
222
223 /* NEC Mobile Gear MCCS series */
224 static char mccs_keytrans[] = {
225 /*00*/ 58, 28, 102, 25, 52, 21, 48, 44, /* caps cr rar p . y b z */
226 /*08*/ 56, 27, 103, 24, 51, 20, 47, 30, /* alt [ dar o , t v a */
227 /*10*/ 41, 26, 101, 23, 50, 19, 46, 17, /* zen @ lar i m r c w */
228 /*18*/ 29, 39, 100, 22, 49, 18, 45, 16, /* lctrl ; uar u n e x q */
229 /*20*/ 42, 14, 115, 11, 38, 7, 34, 15, /* lshft bs \ 0 l 6 g tab */
230 /*28*/ 123, 125, 53, 10, 37, 6, 33, 3, /* nconv | / 9 k 5 f 2 */
231 /*30*/ 121, 13, 43, 9, 36, 5, 32, 2, /* conv = ] 8 j 4 d 1 */
232 /*38*/ 112, 12, 40, 8, 35, 4, 31, 1, /* hira - ' 7 h 3 s esc */
233 /*40*/ IGN, 57, IGN, IGN, IGN, IGN, IGN, IGN, /* - sp - - - - - - */
234 /*48*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
235 /*50*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
236 /*58*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
237 };
238
239 static char mobilepro_keytrans[] = {
240 /*00*/ 57, 27, 43, 53, 75, 80, 28, 38, /* space ] \ / - - enter l */
241 /*08*/ IGN, 26, 40, 39, 77, 72, 52, 24, /* - [ ' ; - - . o */
242 /*10*/ IGN, IGN, IGN, 221, 47, 46, 45, 44, /* - - - Windows v c x z */
243 /*18*/ IGN, 13, 12, 41, 33, 32, 31, 30, /* - = \- ` f d s a */
244 /*20*/ 9, 8, 7, 6, 19, 18, 17, 16, /* 8 7 6 5 r e w q */
245 /*28*/ 51, 50, 49, 48, IGN, IGN, 11, 10, /* , m n b - - 0 9 */
246 /*30*/ 37, 36, 35, 34, 5, 4, 3, 2, /* k j h g 4 3 2 1 */
247 /*38*/ 23, 22, 21, 20, IGN, 58, 14, 1, /* i u y t - caps del esc */
248 /*40*/ 184, IGN, IGN, IGN, 14, 25, 15, IGN, /* alt_R - - - BS p TAB Fn */
249 /*48*/ IGN, 56, IGN, IGN, 88, 87, 68, 67, /* - alt_L - - f12 f11 f10 f9*/
250 /*50*/ IGN, IGN, 29, IGN, 66, 65, 64, 63, /* - - ctrl - f8 f7 f6 f5 */
251 /*58*/ IGN, IGN, IGN, 42, 62, 61, 60, 59, /* - - - shift f4 f3 f2 f1 */
252 };
253
254 /* NEC MobilePro 750c by "Castor Fu" <castor (at) geocast.com> */
255 static char mobilepro750c_keytrans[] = {
256 /*00*/ 77, 43, 25, 52, 21, 48, 44, 57, /* right \ p . y b z space */
257 /*08*/ 80, 53, 24, 51, 20, 47, 30, IGN, /* down / o , t v a - */
258 /*10*/ 75, 28, 23, 50, 19, 46, 17, 221, /* left enter i m r c w Win */
259 /*18*/ 69, 27, 22, 49, 18, 45, 16, 58, /* num ] u n e x q caps */
260 /*20*/ 81, IGN, 11, 38, 7, 34, 15, 1, /* pgdn - 0 l : g tab esc */
261 /*28*/ IGN, 39, 10, 37, 6, 33, 3, 41, /* - ; 9 k 5 f 2 ` */
262 /*30*/ 72, 26, 9, 36, 5, 32, 2, 40, /* up [ 8 j 4 d 1 ' */
263 /*38*/ 12, 26, 8, 35, 4, 31, 83, IGN, /* - @ 7 h 3 s del - */
264 /*40*/ 42, IGN, IGN, IGN, 14, 88, 66, 62, /* shift - - - bs f12 f8 f4 */
265 /*48*/ IGN, 56, IGN, IGN, 125, 87, 65, 61, /* - alt - - | f11 f7 f3 */
266 /*50*/ IGN, IGN, 29, IGN, 68, 68, 64, 60, /* - - ctrl - f10 f10 f6 f2 */
267 /*58*/ IGN, IGN, IGN, 42, 13, 67, 63, 59, /* - - - shift del f9 f5 f1 */
268 };
269
270 /* FUJITSU INTERTOP CX300 */
271 static char intertop_keytrans[] = {
272 57, 60, 2, 15, 28, 58, 75, 41,
273 112, 59, 3, 16, IGN, 30, 56, 1,
274 210, 17, 4, 31, 83, 43, 80, 45,
275 44, 18, 5, 32, 68, 125, 77, 46,
276 115, 19, 39, 33, 67, 26, 13, 47,
277 53, 20, 6, 34, 66, 25, 12, 48,
278 52, 21, 7, 35, 65, 38, 11, 49,
279 IGN, 22, 8, 36, 63, 24, 14, 50,
280 IGN, 61, 9, 62, IGN, 23, 37, 51,
281 69, 40, 10, 27, 64, IGN, 72, IGN,
282 IGN, IGN, IGN, IGN, 42, IGN, IGN, 54,
283 29, 221, 123, 121, 184, IGN, IGN, IGN,
284 };
285 /*
286 space a2 1 tab enter caps left zenkaku
287 hiraga a1 2 q - a fnc esc
288 ins w 3 s del ] down x
289 z e 4 d a10 \ right c
290 backsla r ; f a9 @ ^ v
291 / t 5 g a8 p - b
292 . y 6 h a7 l 0 n
293 - u 7 j a5 o bs m
294 - a3 8 a4 - i k ,
295 num : 9 [ a6 - up -
296 - - - - shift_L - - shift_R
297 ctrl win muhenka henkan alt - - -
298 */
299
300 static char *keytrans = default_keytrans;
301
302 /*
303 * utilities
304 */
305 static inline void
306 vrkiu_write(chip, port, val)
307 struct vrkiu_chip *chip;
308 int port;
309 unsigned short val;
310 {
311 bus_space_write_2(chip->kc_iot, chip->kc_ioh, port, val);
312 }
313
314 static inline unsigned short
315 vrkiu_read(chip, port)
316 struct vrkiu_chip *chip;
317 int port;
318 {
319 return bus_space_read_2(chip->kc_iot, chip->kc_ioh, port);
320 }
321
322 static inline int
323 vrkiu_is_console(iot, ioh)
324 bus_space_tag_t iot;
325 bus_space_handle_t ioh;
326 {
327 if (vrkiu_consdata &&
328 vrkiu_consdata->kc_iot == iot &&
329 vrkiu_consdata->kc_ioh == ioh) {
330 return 1;
331 } else {
332 return 0;
333 }
334 }
335
336 static void
337 vrkiu_initkeymap(void)
338 {
339 int i;
340 static struct {
341 platid_mask_t *mask;
342 char *keytrans;
343 kbd_t layout;
344 } table[] = {
345 { &platid_mask_MACH_NEC_MCR_520A,
346 mobilepro_keytrans, KB_US },
347 { &platid_mask_MACH_NEC_MCR_500A,
348 mobilepro750c_keytrans, KB_US },
349 { &platid_mask_MACH_NEC_MCR_700A,
350 mobilepro_keytrans, KB_US },
351 { &platid_mask_MACH_NEC_MCR,
352 mcr_jp_keytrans, KB_JP },
353 { &platid_mask_MACH_IBM_WORKPAD_Z50,
354 z50_keytrans, KB_US },
355 { &platid_mask_MACH_SHARP_TRIPAD,
356 tripad_keytrans, KB_JP },
357 { &platid_mask_MACH_NEC_MCCS,
358 mccs_keytrans, KB_JP },
359 { &platid_mask_MACH_FUJITSU_INTERTOP,
360 intertop_keytrans, KB_JP },
361 { NULL } /* end mark */
362 };
363
364 for (i = 0; table[i].mask; i++) {
365 if (platid_match(&platid, table[i].mask)) {
366 keytrans = table[i].keytrans;
367 #if !defined(PCKBD_LAYOUT)
368 vrkiu_keymapdata.layout = table[i].layout;
369 #endif
370 }
371 }
372
373 #if 0
374 if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_520A)) {
375 keytrans = mobilepro_keytrans;
376 #if !defined(PCKBD_LAYOUT)
377 vrkiu_keymapdata.layout = KB_US;
378 #endif
379 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_500A)) {
380 keytrans = mobilepro750c_keytrans;
381 #if !defined(PCKBD_LAYOUT)
382 vrkiu_keymapdata.layout = KB_US;
383 #endif
384 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_700A)) {
385 keytrans = mobilepro_keytrans;
386 #if !defined(PCKBD_LAYOUT)
387 vrkiu_keymapdata.layout = KB_US;
388 #endif
389 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR)) {
390 keytrans = mcr_jp_keytrans;
391 #if !defined(PCKBD_LAYOUT)
392 vrkiu_keymapdata.layout = KB_JP;
393 #endif
394 } else if (platid_match(&platid, &platid_mask_MACH_IBM_WORKPAD_Z50)) {
395 keytrans = z50_keytrans;
396 #if !defined(PCKBD_LAYOUT)
397 vrkiu_keymapdata.layout = KB_US;
398 #endif
399 } else if (platid_match(&platid, &platid_mask_MACH_SHARP_TRIPAD)) {
400 keytrans = tripad_keytrans;
401 #if !defined(PCKBD_LAYOUT)
402 vrkiu_keymapdata.layout = KB_JP;
403 #endif
404 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCCS)) {
405 keytrans = mccs_keytrans;
406 #if !defined(PCKBD_LAYOUT)
407 vrkiu_keymapdata.layout = KB_JP;
408 #endif
409 } else if (platid_match(&platid, &platid_mask_MACH_FUJITSU_INTERTOP)) {
410 keytrans = intertop_keytrans;
411 #if !defined(PCKBD_LAYOUT)
412 vrkiu_keymapdata.layout = KB_JP;
413 #endif
414 }
415 #endif
416 }
417
418 /*
419 * initialize device
420 */
421 static int
422 vrkiu_init(chip, iot, ioh)
423 struct vrkiu_chip* chip;
424 bus_space_tag_t iot;
425 bus_space_handle_t ioh;
426 {
427 memset(chip, 0, sizeof(struct vrkiu_chip));
428 chip->kc_iot = iot;
429 chip->kc_ioh = ioh;
430 chip->kc_polling = 0;
431 chip->kc_head = chip->kc_tail = chip->kc_eventq;
432 chip->kc_nevents = 0;
433
434 /* set KIU */
435 vrkiu_write(chip, KIURST, 1); /* reset */
436 vrkiu_write(chip, KIUSCANLINE, 0); /* 96keys */
437 vrkiu_write(chip, KIUWKS, 0x18a4); /* XXX: scan timing! */
438 vrkiu_write(chip, KIUWKI, 450);
439 vrkiu_write(chip, KIUSCANREP, 0x8023);
440 /* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
441 vrkiu_initkeymap();
442 return 0;
443 }
444
445 /*
446 * put key event
447 */
448 static int
449 vrkiu_putevent(chip, type, data)
450 struct vrkiu_chip* chip;
451 u_int type;
452 int data;
453 {
454 if (chip->kc_nevents == NEVENTQ) {
455 return (0);
456 }
457 chip->kc_nevents++;
458 chip->kc_tail->kc_type = type;
459 chip->kc_tail->kc_data = data;
460 if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_tail) {
461 chip->kc_tail = chip->kc_eventq;
462 }
463 return (1);
464 }
465
466 /*
467 * gut key event
468 */
469 static int
470 vrkiu_getevent(chip, type, data)
471 struct vrkiu_chip* chip;
472 u_int *type;
473 int *data;
474 {
475 if (chip->kc_nevents == 0) {
476 return (0);
477 }
478 *type = chip->kc_head->kc_type;
479 *data = chip->kc_head->kc_data;
480 chip->kc_nevents--;
481 if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_head) {
482 chip->kc_head = chip->kc_eventq;
483 }
484 return (1);
485 }
486
487 /*
488 * probe
489 */
490 static int
491 vrkiumatch(parent, cf, aux)
492 struct device *parent;
493 struct cfdata *cf;
494 void *aux;
495 {
496 return 1;
497 }
498
499 /*
500 * attach
501 */
502 static void
503 vrkiuattach(parent, self, aux)
504 struct device *parent;
505 struct device *self;
506 void *aux;
507 {
508 struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
509 struct vrip_attach_args *va = aux;
510 struct wskbddev_attach_args wa;
511 int isconsole;
512
513 bus_space_tag_t iot = va->va_iot;
514 bus_space_handle_t ioh;
515
516 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
517 printf(": can't map bus space\n");
518 return;
519 }
520
521 isconsole = vrkiu_is_console(iot, ioh);
522 if (isconsole) {
523 sc->sc_chip = vrkiu_consdata;
524 } else {
525 sc->sc_chip = &sc->sc_chip_body;
526 vrkiu_init(sc->sc_chip, iot, ioh);
527 }
528 sc->sc_chip->kc_sc = sc;
529
530 if (!(sc->sc_handler =
531 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
532 vrkiu_intr, sc))) {
533 printf (": can't map interrupt line.\n");
534 return;
535 }
536 /* Level2 register setting */
537 vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
538
539 printf("\n");
540
541 wa.console = isconsole;
542 wa.keymap = &vrkiu_keymapdata;
543 wa.accessops = &vrkiu_accessops;
544 wa.accesscookie = sc;
545
546 sc->sc_wskbddev = config_found(self, &wa, wskbddevprint);
547 }
548
549 int
550 vrkiu_intr(arg)
551 void *arg;
552 {
553 struct vrkiu_softc *sc = arg;
554
555 /* When key scan finisshed, this entry is called. */
556 DPRINTF(("%s(%d): vrkiu_intr: %d\n",
557 __FILE__, __LINE__,
558 vrkiu_read(sc->sc_chip, KIUINT) & 7));
559
560 /*
561 * First, we must clear the interrupt register because
562 * detect_key() may takes long time if a bitmap screen
563 * scrolls up and it makes us to miss some key release
564 * event.
565 */
566 vrkiu_write(sc->sc_chip, KIUINT, 0x7); /* Clear all interrupt */
567 detect_key(sc->sc_chip);
568
569 return 0;
570 }
571
572 static int
573 detect_key(chip)
574 struct vrkiu_chip* chip;
575 {
576 int i, j, modified, mask;
577 int detected;
578 unsigned short scandata[KIU_NSCANLINE/2];
579
580 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
581 scandata[i] = vrkiu_read(chip, KIUDATP + i * 2);
582 }
583
584 DPRINTF(("%s(%d): detect_key():", __FILE__, __LINE__));
585
586 detected = 0;
587 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
588 modified = scandata[i] ^ chip->kc_scandata[i];
589 mask = 1;
590 for (j = 0; j < 16; j++, mask <<= 1) {
591 /* XXX: The order of keys can be a problem.
592 If CTRL and normal key are pushed simultaneously,
593 normal key can be entered in queue first.
594 Same problem would occur in key break. */
595 if (modified & mask) {
596 int key, type;
597 key = i * 16 + j;
598 if (keytrans[key] == UNK) {
599 printf("vrkiu: Unknown scan code 0x%02x\n", key);
600 continue;
601 } else if (keytrans[key] == IGN) {
602 continue;
603 }
604 type = (scandata[i] & mask) ?
605 WSCONS_EVENT_KEY_DOWN :
606 WSCONS_EVENT_KEY_UP;
607 DPRINTF(("(%d,%d)=%s%d ", i, j,
608 (scandata[i] & mask) ? "v" : "^",
609 keytrans[key]));
610 detected++;
611 if (chip->kc_polling) {
612 if (vrkiu_putevent(chip, type,
613 keytrans[key]) == 0)
614 printf("vrkiu: queue over flow");
615 } else {
616 wskbd_input(chip->kc_sc->sc_wskbddev,
617 type,
618 keytrans[key]);
619 }
620 }
621 }
622 chip->kc_scandata[i] = scandata[i];
623 }
624 DPRINTF(("\n"));
625
626 return (detected);
627 }
628
629 /* called from biconsdev.c */
630 int
631 vrkiu_getc()
632 {
633 /*
634 * XXX, currently
635 */
636 printf("%s(%d): vrkiu_getc() is not implemented\n",
637 __FILE__, __LINE__);
638 return 0;
639 }
640
641 int
642 vrkiu_enable(scx, on)
643 void *scx;
644 int on;
645 {
646 struct vrkiu_softc *sc = scx;
647
648 if (on) {
649 if (sc->sc_enabled)
650 return (EBUSY);
651 sc->sc_enabled = 1;
652 } else {
653 if (sc->sc_chip == vrkiu_consdata)
654 return (EBUSY);
655 sc->sc_enabled = 0;
656 }
657
658 return (0);
659 }
660
661 void
662 vrkiu_set_leds(scx, leds)
663 void *scx;
664 int leds;
665 {
666 /*struct pckbd_softc *sc = scx;
667 */
668
669 DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
670 __FILE__, __LINE__));
671 }
672
673 int
674 vrkiu_ioctl(scx, cmd, data, flag, p)
675 void *scx;
676 u_long cmd;
677 caddr_t data;
678 int flag;
679 struct proc *p;
680 {
681 /*struct vrkiu_softc *sc = scx;
682 */
683
684 switch (cmd) {
685 case WSKBDIO_GTYPE:
686 /*
687 * XXX, fix me !
688 */
689 *(int *)data = WSKBD_TYPE_PC_XT;
690 return 0;
691 case WSKBDIO_SETLEDS:
692 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
693 return 0;
694 case WSKBDIO_GETLEDS:
695 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
696 *(int *)data = 0;
697 return (0);
698 }
699 return -1;
700 }
701
702 /*
703 * console support routines
704 */
705 int
706 vrkiu_cnattach(iot, iobase)
707 bus_space_tag_t iot;
708 int iobase;
709 {
710 static struct vrkiu_chip vrkiu_consdata_body;
711 bus_space_handle_t ioh;
712
713 if (vrkiu_consdata) {
714 panic("vrkiu is already attached as the console");
715 }
716 if (bus_space_map(iot, iobase, 1, 0, &ioh)) {
717 printf("%s(%d): can't map bus space\n", __FILE__, __LINE__);
718 return -1;
719 }
720
721 if (vrkiu_init(&vrkiu_consdata_body, iot, ioh) != 0) {
722 DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__, __LINE__));
723 return -1;
724 }
725 vrkiu_consdata = &vrkiu_consdata_body;
726
727 wskbd_cnattach(&vrkiu_consops, vrkiu_consdata, &vrkiu_keymapdata);
728
729 return (0);
730 }
731
732 void
733 vrkiu_cngetc(chipx, type, data)
734 void *chipx;
735 u_int *type;
736 int *data;
737 {
738 struct vrkiu_chip* chip = chipx;
739 int s;
740
741 if (!chip->kc_polling) {
742 printf("%s(%d): kiu is not polled\n", __FILE__, __LINE__);
743 /*
744 * Don't call panic() because it may call this routine
745 * recursively.
746 */
747 printf("halt\n");
748 while (1);
749 }
750
751 s = splimp();
752 while (vrkiu_getevent(chip, type, data) == 0) /* busy loop */
753 detect_key(chip);
754 splx(s);
755 }
756
757 void
758 vrkiu_cnpollc(chipx, on)
759 void *chipx;
760 int on;
761 {
762 struct vrkiu_chip* chip = chipx;
763 int s = splimp();
764
765 chip->kc_polling = on;
766
767 splx(s);
768
769 DPRINTF(("%s(%d): vrkiu polling %s\n",
770 __FILE__, __LINE__, on ? "ON" : "OFF"));
771 }
772