vrkiu.c revision 1.9 1 /* $NetBSD: vrkiu.c,v 1.9 1999/12/09 03:14:06 jun 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, UNK, /* 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, UNK, 11, 38, 7, 34, 15, 1, /* pgdn - 0 l : g tab esc */
262 /*28*/ UNK, 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, UNK, /* - @ 7 h 3 s del - */
265 /*40*/ 42, UNK, UNK, UNK, 14, 88, 66, 62, /* shift - - - bs f12 f8 f4 */
266 /*48*/ UNK, 184, UNK, UNK, 125, 87, 65, 61, /* - alt - - | f11 f7 f3 */
267 /*50*/ UNK, UNK, 29, UNK, 68, 68, 64, 60, /* - - ctrl - f10 f10 f6 f2 */
268 /*58*/ UNK, UNK, UNK, 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 /*
338 * initialize device
339 */
340 static int
341 vrkiu_init(chip, iot, ioh)
342 struct vrkiu_chip* chip;
343 bus_space_tag_t iot;
344 bus_space_handle_t ioh;
345 {
346 memset(chip, 0, sizeof(struct vrkiu_chip));
347 chip->kc_iot = iot;
348 chip->kc_ioh = ioh;
349 chip->kc_polling = 0;
350
351 /* set KIU */
352 vrkiu_write(chip, KIURST, 1); /* reset */
353 vrkiu_write(chip, KIUSCANLINE, 0); /* 96keys */
354 vrkiu_write(chip, KIUWKS, 0x18a4); /* XXX: scan timing! */
355 vrkiu_write(chip, KIUWKI, 450);
356 vrkiu_write(chip, KIUSCANREP, 0x8023);
357 /* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
358 return 0;
359 }
360
361 /*
362 * probe
363 */
364 static int
365 vrkiumatch(parent, cf, aux)
366 struct device *parent;
367 struct cfdata *cf;
368 void *aux;
369 {
370 return 1;
371 }
372
373 /*
374 * attach
375 */
376 static void
377 vrkiuattach(parent, self, aux)
378 struct device *parent;
379 struct device *self;
380 void *aux;
381 {
382 struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
383 struct vrip_attach_args *va = aux;
384 struct wskbddev_attach_args wa;
385 int isconsole;
386
387 bus_space_tag_t iot = va->va_iot;
388 bus_space_handle_t ioh;
389
390 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
391 printf(": can't map bus space\n");
392 return;
393 }
394
395 isconsole = vrkiu_is_console(iot, ioh);
396 if (isconsole) {
397 sc->sc_chip = vrkiu_consdata;
398 } else {
399 sc->sc_chip = &sc->sc_chip_body;
400 vrkiu_init(sc->sc_chip, iot, ioh);
401 }
402 sc->sc_chip->kc_sc = sc;
403
404 if (!(sc->sc_handler =
405 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
406 vrkiu_intr, sc))) {
407 printf (": can't map interrupt line.\n");
408 return;
409 }
410 /* Level2 register setting */
411 vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
412
413 printf("\n");
414
415 if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_520A)) {
416 keytrans = mobilepro_keytrans;
417 #if !defined(PCKBD_LAYOUT)
418 vrkiu_keymapdata.layout = KB_US;
419 #endif
420 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_500A)) {
421 keytrans = mobilepro750c_keytrans;
422 #if !defined(PCKBD_LAYOUT)
423 vrkiu_keymapdata.layout = KB_US;
424 #endif
425 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_700A)) {
426 keytrans = mobilepro_keytrans;
427 #if !defined(PCKBD_LAYOUT)
428 vrkiu_keymapdata.layout = KB_US;
429 #endif
430 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR)) {
431 keytrans = mcr_jp_keytrans;
432 #if !defined(PCKBD_LAYOUT)
433 vrkiu_keymapdata.layout = KB_JP;
434 #endif
435 } else if (platid_match(&platid, &platid_mask_MACH_IBM_WORKPAD_Z50)) {
436 keytrans = z50_keytrans;
437 #if !defined(PCKBD_LAYOUT)
438 vrkiu_keymapdata.layout = KB_US;
439 #endif
440 } else if (platid_match(&platid, &platid_mask_MACH_SHARP_TRIPAD)) {
441 keytrans = tripad_keytrans;
442 #if !defined(PCKBD_LAYOUT)
443 vrkiu_keymapdata.layout = KB_JP;
444 #endif
445 } else if (platid_match(&platid, &platid_mask_MACH_NEC_MCCS)) {
446 keytrans = mccs_keytrans;
447 #if !defined(PCKBD_LAYOUT)
448 vrkiu_keymapdata.layout = KB_JP;
449 #endif
450 } else if (platid_match(&platid, &platid_mask_MACH_FUJITSU_INTERTOP)) {
451 keytrans = intertop_keytrans;
452 #if !defined(PCKBD_LAYOUT)
453 vrkiu_keymapdata.layout = KB_JP;
454 #endif
455 }
456 wa.console = isconsole;
457 wa.keymap = &vrkiu_keymapdata;
458 wa.accessops = &vrkiu_accessops;
459 wa.accesscookie = sc;
460
461 sc->sc_wskbddev = config_found(self, &wa, wskbddevprint);
462 }
463
464 int
465 vrkiu_intr(arg)
466 void *arg;
467 {
468 struct vrkiu_softc *sc = arg;
469
470 /* When key scan finisshed, this entry is called. */
471 DPRINTF(("%s(%d): vrkiu_intr: %d\n",
472 __FILE__, __LINE__,
473 vrkiu_read(sc->sc_chip, KIUINT) & 7));
474
475 /*
476 * First, we must clear the interrupt register because
477 * detect_key() may takes long time if a bitmap screen
478 * scrolls up and it makes us to miss some key release
479 * event.
480 */
481 vrkiu_write(sc->sc_chip, KIUINT, 0x7); /* Clear all interrupt */
482 detect_key(sc->sc_chip);
483
484 return 0;
485 }
486
487 static void
488 detect_key(chip)
489 struct vrkiu_chip* chip;
490 {
491 int i, j, modified, mask;
492 unsigned short scandata[KIU_NSCANLINE/2];
493
494 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
495 scandata[i] = vrkiu_read(chip, KIUDATP + i * 2);
496 }
497
498 DPRINTF(("%s(%d): detect_key():", __FILE__, __LINE__));
499
500 if (chip->kc_polling) {
501 chip->kc_type = WSCONS_EVENT_ALL_KEYS_UP;
502 }
503
504 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
505 modified = scandata[i] ^ chip->kc_scandata[i];
506 mask = 1;
507 for (j = 0; j < 16; j++, mask <<= 1) {
508 /* XXX: The order of keys can be a problem.
509 If CTRL and normal key are pushed simultaneously,
510 normal key can be entered in queue first.
511 Same problem would occur in key break. */
512 if (modified & mask) {
513 int key, type;
514 key = i * 16 + j;
515 if (keytrans[key] == UNK) {
516 printf("vrkiu: Unknown scan code 0x%02x\n", key);
517 continue;
518 } else if (keytrans[key] == IGN) {
519 continue;
520 }
521 type = (scandata[i] & mask) ?
522 WSCONS_EVENT_KEY_DOWN :
523 WSCONS_EVENT_KEY_UP;
524 DPRINTF(("(%d,%d)=%s%d ", i, j,
525 (scandata[i] & mask) ? "v" : "^",
526 keytrans[key]));
527 if (chip->kc_polling) {
528 chip->kc_type = type;
529 chip->kc_data = keytrans[key];
530 } else {
531 wskbd_input(chip->kc_sc->sc_wskbddev,
532 type,
533 keytrans[key]);
534 }
535 }
536 }
537 chip->kc_scandata[i] = scandata[i];
538 }
539 DPRINTF(("\n"));
540 }
541
542 /* called from biconsdev.c */
543 int
544 vrkiu_getc()
545 {
546 int ret;
547
548 if (the_vrkiu == NULL) {
549 return 0; /* XXX */
550 }
551
552 while (the_vrkiu->keybuftail == the_vrkiu->keybufhead) {
553 detect_key(vrkiu_consdata);
554 }
555 ret = the_vrkiu->keybuf[the_vrkiu->keybuftail++];
556 if (the_vrkiu->keybuftail >= NKEYBUF) {
557 the_vrkiu->keybuftail = 0;
558 }
559 return ret;
560 }
561
562 int
563 vrkiu_enable(scx, on)
564 void *scx;
565 int on;
566 {
567 struct vrkiu_softc *sc = scx;
568
569 if (on) {
570 if (sc->sc_enabled)
571 return (EBUSY);
572 sc->sc_enabled = 1;
573 } else {
574 if (sc->sc_chip == vrkiu_consdata)
575 return (EBUSY);
576 sc->sc_enabled = 0;
577 }
578
579 return (0);
580 }
581
582 void
583 vrkiu_set_leds(scx, leds)
584 void *scx;
585 int leds;
586 {
587 /*struct pckbd_softc *sc = scx;
588 */
589
590 DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
591 __FILE__, __LINE__));
592 }
593
594 int
595 vrkiu_ioctl(scx, cmd, data, flag, p)
596 void *scx;
597 u_long cmd;
598 caddr_t data;
599 int flag;
600 struct proc *p;
601 {
602 /*struct vrkiu_softc *sc = scx;
603 */
604
605 switch (cmd) {
606 case WSKBDIO_GTYPE:
607 /*
608 * XXX, fix me !
609 */
610 *(int *)data = WSKBD_TYPE_PC_XT;
611 return 0;
612 case WSKBDIO_SETLEDS:
613 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
614 return 0;
615 case WSKBDIO_GETLEDS:
616 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
617 *(int *)data = 0;
618 return (0);
619 }
620 return -1;
621 }
622
623 /*
624 * console support routines
625 */
626 int
627 vrkiu_cnattach(iot, iobase)
628 bus_space_tag_t iot;
629 int iobase;
630 {
631 static struct vrkiu_chip vrkiu_consdata_body;
632 bus_space_handle_t ioh;
633
634 if (vrkiu_consdata) {
635 panic("vrkiu is already attached as the console");
636 }
637 if (bus_space_map(iot, iobase, 1, 0, &ioh)) {
638 printf("%s(%d): can't map bus space\n", __FILE__, __LINE__);
639 return -1;
640 }
641
642 if (vrkiu_init(&vrkiu_consdata_body, iot, ioh) != 0) {
643 DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__, __LINE__));
644 return -1;
645 }
646 vrkiu_consdata = &vrkiu_consdata_body;
647
648 wskbd_cnattach(&vrkiu_consops, vrkiu_consdata, &vrkiu_keymapdata);
649
650 return (0);
651 }
652
653 void
654 vrkiu_cngetc(chipx, type, data)
655 void *chipx;
656 u_int *type;
657 int *data;
658 {
659 struct vrkiu_chip* chip = chipx;
660 int s;
661
662 if (!chip->kc_polling) {
663 printf("%s(%d): kiu is not polled\n", __FILE__, __LINE__);
664 while (1);
665 }
666
667 s = splimp();
668 if (chip->kc_type == WSCONS_EVENT_ALL_KEYS_UP) {
669 detect_key(chip);
670 }
671 *type = chip->kc_type;
672 *data = chip->kc_data;
673 chip->kc_type = WSCONS_EVENT_ALL_KEYS_UP;
674 splx(s);
675 }
676
677 void
678 vrkiu_cnpollc(chipx, on)
679 void *chipx;
680 int on;
681 {
682 struct vrkiu_chip* chip = chipx;
683 int s = splimp();
684
685 chip->kc_polling = on;
686
687 splx(s);
688
689 DPRINTF(("%s(%d): vrkiu polling %s\n",
690 __FILE__, __LINE__, on ? "ON" : "OFF"));
691 }
692