vrkiu.c revision 1.11 1 /* $NetBSD: vrkiu.c,v 1.11 2000/01/17 12:22:37 shin 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 u_int kc_type;
84 int kc_data;
85
86 int kc_sft:1, kc_alt:1, kc_ctrl:1;
87
88 struct vrkiu_softc* kc_sc; /* back link */
89 };
90
91 struct vrkiu_softc {
92 struct device sc_dev;
93 struct vrkiu_chip *sc_chip;
94 struct vrkiu_chip sc_chip_body;
95 int sc_enabled;
96 struct device *sc_wskbddev;
97
98 void *sc_handler;
99 #define NKEYBUF 32
100 unsigned char keybuf[NKEYBUF];
101 int keybufhead, keybuftail;
102 };
103
104 /*
105 * function prototypes
106 */
107 static int vrkiumatch __P((struct device *, struct cfdata *, void *));
108 static void vrkiuattach __P((struct device *, struct device *, void *));
109
110 int vrkiu_intr __P((void *));
111
112 static int vrkiu_init(struct vrkiu_chip*, bus_space_tag_t, bus_space_handle_t);
113 static void vrkiu_write __P((struct vrkiu_chip *, int, unsigned short));
114 static unsigned short vrkiu_read __P((struct vrkiu_chip *, int));
115 static int vrkiu_is_console(bus_space_tag_t, bus_space_handle_t);
116 static void detect_key __P((struct vrkiu_chip *));
117
118 static struct vrkiu_softc *the_vrkiu = NULL; /* XXX: kludge!! */
119
120 /* wskbd accessopts */
121 int vrkiu_enable __P((void *, int));
122 void vrkiu_set_leds __P((void *, int));
123 int vrkiu_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
124
125 /* consopts */
126 void vrkiu_cngetc __P((void*, u_int*, int*));
127 void vrkiu_cnpollc __P((void *, int));
128
129 /*
130 * global/static data
131 */
132 struct cfattach vrkiu_ca = {
133 sizeof(struct vrkiu_softc), vrkiumatch, vrkiuattach
134 };
135
136 const struct wskbd_accessops vrkiu_accessops = {
137 vrkiu_enable,
138 vrkiu_set_leds,
139 vrkiu_ioctl,
140 };
141
142 const struct wskbd_consops vrkiu_consops = {
143 vrkiu_cngetc,
144 vrkiu_cnpollc,
145 };
146
147 struct wskbd_mapdata vrkiu_keymapdata = {
148 pckbd_keydesctab,
149 #ifdef PCKBD_LAYOUT
150 PCKBD_LAYOUT,
151 #else
152 KB_US,
153 #endif
154 };
155
156 struct vrkiu_chip *vrkiu_consdata = NULL;
157
158 #define UNK -1 /* unknown */
159 #define IGN -2 /* ignore */
160
161 static char default_keytrans[] = {
162 /*00*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
163 /*08*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
164 /*10*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
165 /*18*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
166 /*20*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
167 /*28*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
168 /*30*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
169 /*38*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
170 /*40*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
171 /*48*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
172 /*50*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
173 /*58*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
174 };
175
176 /* NEC MobileGearII MCR series (Japan) */
177 static char mcr_jp_keytrans[] = {
178 /*00*/ 77, 28, 25, 52, 21, 48, 44, 57, /* right ent p . y b z space */
179 /*08*/ 80, 53, 24, 51, 20, 47, 30, 123, /* down / o , t v a nfer */
180 /*10*/ 75, 115, 23, 50, 19, 46, 17, 221, /* left \ i m r c w menu */
181 /*18*/ 13, IGN, 22, IGN, 18, 45, 16, 2, /* ^ - u - e x q 1 */
182 /*20*/ 81, 41, 11, 38, 40, 34, 15, 59, /* pgdn h/z 0 l : g tab f1 */
183 /*28*/ 121, 39, 10, 49, 6, 33, 3, 37, /* xfer ; 9 n 5 f 2 k */
184 /*30*/ 72, 27, 9, 36, 5, 32, 7, IGN, /* up [ 8 j 4 d 6 - */
185 /*38*/ 12, 26, 8, 35, 4, 43, 31, IGN, /* - @ 7 h 3 ] s - */
186 /*40*/ 58, IGN, IGN, IGN, 14, IGN, 66, 61, /* caps - - - bs - f8 f3 */
187 /*48*/ IGN, 56, IGN, IGN, 125, 112, 65, 62, /* - alt - - | k/h f7 f4 */
188 /*50*/ IGN, IGN, 29, IGN, 68, 73, 64, 60, /* - - ctrl - f10 pgup f6 f2 */
189 /*58*/ IGN, IGN, IGN, 42, 14, 67, 63, 1, /* - - - shift del f9 f5 esc */
190 };
191
192 /* IBM WorkPad z50 */
193 static char z50_keytrans[] = {
194 /*00*/ 59, 61, 63, 65, 67, IGN, IGN, 87, /* f1 f3 f5 f7 f9 - - f11 */
195 /*08*/ 60, 62, 64, 66, 68, IGN, IGN, 88, /* f2 f4 f6 f8 f10 - - f12 */
196 /*10*/ 40, 26, 12, 11, 25, 39, 72, 53, /* ' [ - 0 p ; up / */
197 /*18*/ IGN, IGN, IGN, 10, 24, 38, 52, IGN, /* - - - 9 o l . - */
198 /*20*/ 75, 27, 13, 9, 23, 37, 51, IGN, /* left ] = 8 i k , - */
199 /*28*/ 35, 21, 7, 8, 22, 36, 50, 49, /* h y 6 7 u j m n */
200 /*30*/ IGN, 14, 69, 14, IGN, 43, 28, 57, /* - bs num del - \ ent sp */
201 /*38*/ 34, 20, 6, 5, 19, 33, 47, 48, /* g t 5 4 r f v b */
202 /*40*/ IGN, IGN, IGN, 4, 18, 32, 46, 77, /* - - - 3 e d c right */
203 /*48*/ IGN, IGN, IGN, 3, 17, 31, 45, 80, /* - - - 2 w s x down */
204 /*50*/ 1, 29, 41, 2, 16, 30, 44, IGN, /* esc tab ~ 1 q a z - */
205 /*58*/ 221, 42, 29, 29, 56, 56, 54, IGN, /* menu Ls Lc Rc La Ra Rs - */
206 };
207
208 /* Sharp Tripad PV6000 */
209 static char tripad_keytrans[] = {
210 /*00*/ 42, 15, 41, 16, 1, 2, 104, 221, /* lsh tab ` q esc 1 WIN - */
211 /*08*/ 58, 44, 45, 30, 31, 17, 18, 3, /* ctrl z x a s w e 2 */
212 /*10*/ 56, 57, 46, 47, 32, 33, 19, 4, /* lalt sp c v d f r 3 */
213 /*18*/ 48, 49, 34, 35, 20, 21, 5, 6, /* b n g h t y 4 5 */
214 /*20*/ 50, 51, 36, 37, 22, 23, 7, 8, /* m , j k u i 6 7 */
215 /*28*/ 105, 29, 38, 24, 25, 9, 10, 11, /* Fn caps l o p 8 9 0 */
216 /*30*/ 26, 27, 102, 52, 53, 39, 12, 13, /* [ ] dar , / ; \- = */
217 /*38*/ 54, 103, 100, 102, 39, 28, 43, 14, /* rsh - - uar - ; ent \ del */
218 /*40*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
219 /*48*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
220 /*50*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
221 /*58*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
222 };
223
224 /* NEC Mobile Gear MCCS series */
225 static char mccs_keytrans[] = {
226 /*00*/ 58, 28, 102, 25, 52, 21, 48, 44, /* caps cr rar p . y b z */
227 /*08*/ 56, 27, 103, 24, 51, 20, 47, 30, /* alt [ dar o , t v a */
228 /*10*/ 41, 26, 101, 23, 50, 19, 46, 17, /* zen @ lar i m r c w */
229 /*18*/ 29, 39, 100, 22, 49, 18, 45, 16, /* lctrl ; uar u n e x q */
230 /*20*/ 42, 14, 115, 11, 38, 7, 34, 15, /* lshft bs \ 0 l 6 g tab */
231 /*28*/ 123, 125, 53, 10, 37, 6, 33, 3, /* nconv | / 9 k 5 f 2 */
232 /*30*/ 121, 13, 43, 9, 36, 5, 32, 2, /* conv = ] 8 j 4 d 1 */
233 /*38*/ 112, 12, 40, 8, 35, 4, 31, 1, /* hira - ' 7 h 3 s esc */
234 /*40*/ IGN, 57, IGN, IGN, IGN, IGN, IGN, IGN, /* - sp - - - - - - */
235 /*48*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
236 /*50*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
237 /*58*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
238 };
239
240 static char mobilepro_keytrans[] = {
241 /*00*/ 57, 27, 43, 53, 75, 80, 28, 38, /* space ] \ / - - enter l */
242 /*08*/ IGN, 26, 40, 39, 77, 72, 52, 24, /* - [ ' ; - - . o */
243 /*10*/ IGN, IGN, IGN, 221, 47, 46, 45, 44, /* - - - Windows v c x z */
244 /*18*/ IGN, 13, 12, 41, 33, 32, 31, 30, /* - = \- ` f d s a */
245 /*20*/ 9, 8, 7, 6, 19, 18, 17, 16, /* 8 7 6 5 r e w q */
246 /*28*/ 51, 50, 49, 48, IGN, IGN, 11, 10, /* , m n b - - 0 9 */
247 /*30*/ 37, 36, 35, 34, 5, 4, 3, 2, /* k j h g 4 3 2 1 */
248 /*38*/ 23, 22, 21, 20, IGN, 58, 14, 1, /* i u y t - caps del esc */
249 /*40*/ 184, IGN, IGN, IGN, 14, 25, 15, IGN, /* alt_R - - - BS p TAB Fn */
250 /*48*/ IGN, 56, IGN, IGN, 88, 87, 68, 67, /* - alt_L - - f12 f11 f10 f9*/
251 /*50*/ IGN, IGN, 29, IGN, 66, 65, 64, 63, /* - - ctrl - f8 f7 f6 f5 */
252 /*58*/ IGN, IGN, IGN, 42, 62, 61, 60, 59, /* - - - shift f4 f3 f2 f1 */
253 };
254
255 /* NEC MobilePro 750c by "Castor Fu" <castor (at) geocast.com> */
256 static char mobilepro750c_keytrans[] = {
257 /*00*/ 77, 43, 25, 52, 21, 48, 44, 57, /* right \ p . y b z space */
258 /*08*/ 80, 53, 24, 51, 20, 47, 30, IGN, /* down / o , t v a - */
259 /*10*/ 75, 28, 23, 50, 19, 46, 17, 221, /* left enter i m r c w Win */
260 /*18*/ 69, 27, 22, 49, 18, 45, 16, 58, /* num ] u n e x q caps */
261 /*20*/ 81, IGN, 11, 38, 7, 34, 15, 1, /* pgdn - 0 l : g tab esc */
262 /*28*/ IGN, 39, 10, 37, 6, 33, 3, 41, /* - ; 9 k 5 f 2 ` */
263 /*30*/ 72, 26, 9, 36, 5, 32, 2, 40, /* up [ 8 j 4 d 1 ' */
264 /*38*/ 12, 26, 8, 35, 4, 31, 83, IGN, /* - @ 7 h 3 s del - */
265 /*40*/ 42, IGN, IGN, IGN, 14, 88, 66, 62, /* shift - - - bs f12 f8 f4 */
266 /*48*/ IGN, 56, IGN, IGN, 125, 87, 65, 61, /* - alt - - | f11 f7 f3 */
267 /*50*/ IGN, IGN, 29, IGN, 68, 68, 64, 60, /* - - ctrl - f10 f10 f6 f2 */
268 /*58*/ IGN, IGN, IGN, 42, 13, 67, 63, 59, /* - - - shift del f9 f5 f1 */
269 };
270
271 /* FUJITSU INTERTOP CX300 */
272 static char intertop_keytrans[] = {
273 57, 60, 2, 15, 28, 58, 75, 41,
274 112, 59, 3, 16, IGN, 30, 56, 1,
275 210, 17, 4, 31, 83, 43, 80, 45,
276 44, 18, 5, 32, 68, 125, 77, 46,
277 115, 19, 39, 33, 67, 26, 13, 47,
278 53, 20, 6, 34, 66, 25, 12, 48,
279 52, 21, 7, 35, 65, 38, 11, 49,
280 IGN, 22, 8, 36, 63, 24, 14, 50,
281 IGN, 61, 9, 62, IGN, 23, 37, 51,
282 69, 40, 10, 27, 64, IGN, 72, IGN,
283 IGN, IGN, IGN, IGN, 42, IGN, IGN, 54,
284 29, 221, 123, 121, 184, IGN, IGN, IGN,
285 };
286 /*
287 space a2 1 tab enter caps left zenkaku
288 hiraga a1 2 q - a fnc esc
289 ins w 3 s del ] down x
290 z e 4 d a10 \ right c
291 backsla r ; f a9 @ ^ v
292 / t 5 g a8 p - b
293 . y 6 h a7 l 0 n
294 - u 7 j a5 o bs m
295 - a3 8 a4 - i k ,
296 num : 9 [ a6 - up -
297 - - - - shift_L - - shift_R
298 ctrl win muhenka henkan alt - - -
299 */
300
301 static char *keytrans = default_keytrans;
302
303 /*
304 * utilities
305 */
306 static inline void
307 vrkiu_write(chip, port, val)
308 struct vrkiu_chip *chip;
309 int port;
310 unsigned short val;
311 {
312 bus_space_write_2(chip->kc_iot, chip->kc_ioh, port, val);
313 }
314
315 static inline unsigned short
316 vrkiu_read(chip, port)
317 struct vrkiu_chip *chip;
318 int port;
319 {
320 return bus_space_read_2(chip->kc_iot, chip->kc_ioh, port);
321 }
322
323 static inline int
324 vrkiu_is_console(iot, ioh)
325 bus_space_tag_t iot;
326 bus_space_handle_t ioh;
327 {
328 if (vrkiu_consdata &&
329 vrkiu_consdata->kc_iot == iot &&
330 vrkiu_consdata->kc_ioh == ioh) {
331 return 1;
332 } else {
333 return 0;
334 }
335 }
336
337 static void
338 vrkiu_initkeymap(void)
339 {
340 if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_520A)) {
341 keytrans = mobilepro_keytrans;
342 #if !defined(PCKBD_LAYOUT)
343 vrkiu_keymapdata.layout = KB_US;
344 #endif
345 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_500A)) {
346 keytrans = mobilepro750c_keytrans;
347 #if !defined(PCKBD_LAYOUT)
348 vrkiu_keymapdata.layout = KB_US;
349 #endif
350 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_700A)) {
351 keytrans = mobilepro_keytrans;
352 #if !defined(PCKBD_LAYOUT)
353 vrkiu_keymapdata.layout = KB_US;
354 #endif
355 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR)) {
356 keytrans = mcr_jp_keytrans;
357 #if !defined(PCKBD_LAYOUT)
358 vrkiu_keymapdata.layout = KB_JP;
359 #endif
360 } else if (platid_match(&platid, &platid_mask_MACH_IBM_WORKPAD_Z50)) {
361 keytrans = z50_keytrans;
362 #if !defined(PCKBD_LAYOUT)
363 vrkiu_keymapdata.layout = KB_US;
364 #endif
365 } else if (platid_match(&platid, &platid_mask_MACH_SHARP_TRIPAD)) {
366 keytrans = tripad_keytrans;
367 #if !defined(PCKBD_LAYOUT)
368 vrkiu_keymapdata.layout = KB_JP;
369 #endif
370 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCCS)) {
371 keytrans = mccs_keytrans;
372 #if !defined(PCKBD_LAYOUT)
373 vrkiu_keymapdata.layout = KB_JP;
374 #endif
375 } else if (platid_match(&platid, &platid_mask_MACH_FUJITSU_INTERTOP)) {
376 keytrans = intertop_keytrans;
377 #if !defined(PCKBD_LAYOUT)
378 vrkiu_keymapdata.layout = KB_JP;
379 #endif
380 }
381 }
382
383 /*
384 * initialize device
385 */
386 static int
387 vrkiu_init(chip, iot, ioh)
388 struct vrkiu_chip* chip;
389 bus_space_tag_t iot;
390 bus_space_handle_t ioh;
391 {
392 memset(chip, 0, sizeof(struct vrkiu_chip));
393 chip->kc_iot = iot;
394 chip->kc_ioh = ioh;
395 chip->kc_polling = 0;
396
397 /* set KIU */
398 vrkiu_write(chip, KIURST, 1); /* reset */
399 vrkiu_write(chip, KIUSCANLINE, 0); /* 96keys */
400 vrkiu_write(chip, KIUWKS, 0x18a4); /* XXX: scan timing! */
401 vrkiu_write(chip, KIUWKI, 450);
402 vrkiu_write(chip, KIUSCANREP, 0x8023);
403 /* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
404 vrkiu_initkeymap();
405 return 0;
406 }
407
408 /*
409 * probe
410 */
411 static int
412 vrkiumatch(parent, cf, aux)
413 struct device *parent;
414 struct cfdata *cf;
415 void *aux;
416 {
417 return 1;
418 }
419
420 /*
421 * attach
422 */
423 static void
424 vrkiuattach(parent, self, aux)
425 struct device *parent;
426 struct device *self;
427 void *aux;
428 {
429 struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
430 struct vrip_attach_args *va = aux;
431 struct wskbddev_attach_args wa;
432 int isconsole;
433
434 bus_space_tag_t iot = va->va_iot;
435 bus_space_handle_t ioh;
436
437 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
438 printf(": can't map bus space\n");
439 return;
440 }
441
442 isconsole = vrkiu_is_console(iot, ioh);
443 if (isconsole) {
444 sc->sc_chip = vrkiu_consdata;
445 } else {
446 sc->sc_chip = &sc->sc_chip_body;
447 vrkiu_init(sc->sc_chip, iot, ioh);
448 }
449 sc->sc_chip->kc_sc = sc;
450
451 if (!(sc->sc_handler =
452 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
453 vrkiu_intr, sc))) {
454 printf (": can't map interrupt line.\n");
455 return;
456 }
457 /* Level2 register setting */
458 vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
459
460 printf("\n");
461
462 wa.console = isconsole;
463 wa.keymap = &vrkiu_keymapdata;
464 wa.accessops = &vrkiu_accessops;
465 wa.accesscookie = sc;
466
467 sc->sc_wskbddev = config_found(self, &wa, wskbddevprint);
468 }
469
470 int
471 vrkiu_intr(arg)
472 void *arg;
473 {
474 struct vrkiu_softc *sc = arg;
475
476 /* When key scan finisshed, this entry is called. */
477 DPRINTF(("%s(%d): vrkiu_intr: %d\n",
478 __FILE__, __LINE__,
479 vrkiu_read(sc->sc_chip, KIUINT) & 7));
480
481 /*
482 * First, we must clear the interrupt register because
483 * detect_key() may takes long time if a bitmap screen
484 * scrolls up and it makes us to miss some key release
485 * event.
486 */
487 vrkiu_write(sc->sc_chip, KIUINT, 0x7); /* Clear all interrupt */
488 detect_key(sc->sc_chip);
489
490 return 0;
491 }
492
493 static void
494 detect_key(chip)
495 struct vrkiu_chip* chip;
496 {
497 int i, j, modified, mask;
498 unsigned short scandata[KIU_NSCANLINE/2];
499
500 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
501 scandata[i] = vrkiu_read(chip, KIUDATP + i * 2);
502 }
503
504 DPRINTF(("%s(%d): detect_key():", __FILE__, __LINE__));
505
506 if (chip->kc_polling) {
507 chip->kc_type = WSCONS_EVENT_ALL_KEYS_UP;
508 }
509
510 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
511 modified = scandata[i] ^ chip->kc_scandata[i];
512 mask = 1;
513 for (j = 0; j < 16; j++, mask <<= 1) {
514 /* XXX: The order of keys can be a problem.
515 If CTRL and normal key are pushed simultaneously,
516 normal key can be entered in queue first.
517 Same problem would occur in key break. */
518 if (modified & mask) {
519 int key, type;
520 key = i * 16 + j;
521 if (keytrans[key] == UNK) {
522 printf("vrkiu: Unknown scan code 0x%02x\n", key);
523 continue;
524 } else if (keytrans[key] == IGN) {
525 continue;
526 }
527 type = (scandata[i] & mask) ?
528 WSCONS_EVENT_KEY_DOWN :
529 WSCONS_EVENT_KEY_UP;
530 DPRINTF(("(%d,%d)=%s%d ", i, j,
531 (scandata[i] & mask) ? "v" : "^",
532 keytrans[key]));
533 if (chip->kc_polling) {
534 chip->kc_type = type;
535 chip->kc_data = keytrans[key];
536 } else {
537 wskbd_input(chip->kc_sc->sc_wskbddev,
538 type,
539 keytrans[key]);
540 }
541 }
542 }
543 chip->kc_scandata[i] = scandata[i];
544 }
545 DPRINTF(("\n"));
546 }
547
548 /* called from biconsdev.c */
549 int
550 vrkiu_getc()
551 {
552 int ret;
553
554 if (the_vrkiu == NULL) {
555 return 0; /* XXX */
556 }
557
558 while (the_vrkiu->keybuftail == the_vrkiu->keybufhead) {
559 detect_key(vrkiu_consdata);
560 }
561 ret = the_vrkiu->keybuf[the_vrkiu->keybuftail++];
562 if (the_vrkiu->keybuftail >= NKEYBUF) {
563 the_vrkiu->keybuftail = 0;
564 }
565 return ret;
566 }
567
568 int
569 vrkiu_enable(scx, on)
570 void *scx;
571 int on;
572 {
573 struct vrkiu_softc *sc = scx;
574
575 if (on) {
576 if (sc->sc_enabled)
577 return (EBUSY);
578 sc->sc_enabled = 1;
579 } else {
580 if (sc->sc_chip == vrkiu_consdata)
581 return (EBUSY);
582 sc->sc_enabled = 0;
583 }
584
585 return (0);
586 }
587
588 void
589 vrkiu_set_leds(scx, leds)
590 void *scx;
591 int leds;
592 {
593 /*struct pckbd_softc *sc = scx;
594 */
595
596 DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
597 __FILE__, __LINE__));
598 }
599
600 int
601 vrkiu_ioctl(scx, cmd, data, flag, p)
602 void *scx;
603 u_long cmd;
604 caddr_t data;
605 int flag;
606 struct proc *p;
607 {
608 /*struct vrkiu_softc *sc = scx;
609 */
610
611 switch (cmd) {
612 case WSKBDIO_GTYPE:
613 /*
614 * XXX, fix me !
615 */
616 *(int *)data = WSKBD_TYPE_PC_XT;
617 return 0;
618 case WSKBDIO_SETLEDS:
619 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
620 return 0;
621 case WSKBDIO_GETLEDS:
622 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
623 *(int *)data = 0;
624 return (0);
625 }
626 return -1;
627 }
628
629 /*
630 * console support routines
631 */
632 int
633 vrkiu_cnattach(iot, iobase)
634 bus_space_tag_t iot;
635 int iobase;
636 {
637 static struct vrkiu_chip vrkiu_consdata_body;
638 bus_space_handle_t ioh;
639
640 if (vrkiu_consdata) {
641 panic("vrkiu is already attached as the console");
642 }
643 if (bus_space_map(iot, iobase, 1, 0, &ioh)) {
644 printf("%s(%d): can't map bus space\n", __FILE__, __LINE__);
645 return -1;
646 }
647
648 if (vrkiu_init(&vrkiu_consdata_body, iot, ioh) != 0) {
649 DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__, __LINE__));
650 return -1;
651 }
652 vrkiu_consdata = &vrkiu_consdata_body;
653
654 wskbd_cnattach(&vrkiu_consops, vrkiu_consdata, &vrkiu_keymapdata);
655
656 return (0);
657 }
658
659 void
660 vrkiu_cngetc(chipx, type, data)
661 void *chipx;
662 u_int *type;
663 int *data;
664 {
665 struct vrkiu_chip* chip = chipx;
666 int s;
667
668 if (!chip->kc_polling) {
669 printf("%s(%d): kiu is not polled\n", __FILE__, __LINE__);
670 while (1);
671 }
672
673 s = splimp();
674 if (chip->kc_type == WSCONS_EVENT_ALL_KEYS_UP) {
675 detect_key(chip);
676 }
677 *type = chip->kc_type;
678 *data = chip->kc_data;
679 chip->kc_type = WSCONS_EVENT_ALL_KEYS_UP;
680 splx(s);
681 }
682
683 void
684 vrkiu_cnpollc(chipx, on)
685 void *chipx;
686 int on;
687 {
688 struct vrkiu_chip* chip = chipx;
689 int s = splimp();
690
691 chip->kc_polling = on;
692
693 splx(s);
694
695 DPRINTF(("%s(%d): vrkiu polling %s\n",
696 __FILE__, __LINE__, on ? "ON" : "OFF"));
697 }
698