vrkiu.c revision 1.19 1 /* $NetBSD: vrkiu.c,v 1.19 2000/03/31 13:01:17 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 #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, 15, 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*/ 29, 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, 58, 38, 24, 25, 9, 10, 11, /* Fn caps l o p 8 9 0 */
215 /*30*/ 26, 27, 75, 52, 53, 39, 12, 13, /* [ ] la , / ; \- = */
216 /*38*/ 54, 77, 72, 80, 39, 28, 43, 14, /* rsh ra ua da ; 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_MPRO700,
352 mobilepro_keytrans, KB_US },
353 { &platid_mask_MACH_NEC_MCR,
354 mcr_jp_keytrans, KB_JP },
355 { &platid_mask_MACH_IBM_WORKPAD_Z50,
356 z50_keytrans, KB_US },
357 { &platid_mask_MACH_SHARP_TRIPAD,
358 tripad_keytrans, KB_US },
359 { &platid_mask_MACH_NEC_MCCS,
360 mccs_keytrans, KB_JP },
361 { &platid_mask_MACH_FUJITSU_INTERTOP,
362 intertop_keytrans, KB_JP },
363 { NULL } /* end mark */
364 };
365
366 for (i = 0; table[i].mask; i++) {
367 if (platid_match(&platid, table[i].mask)) {
368 keytrans = table[i].keytrans;
369 #if !defined(PCKBD_LAYOUT)
370 vrkiu_keymapdata.layout = table[i].layout;
371 #endif
372 break;
373 }
374 }
375 }
376
377 /*
378 * initialize device
379 */
380 static int
381 vrkiu_init(chip, iot, ioh)
382 struct vrkiu_chip* chip;
383 bus_space_tag_t iot;
384 bus_space_handle_t ioh;
385 {
386 memset(chip, 0, sizeof(struct vrkiu_chip));
387 chip->kc_iot = iot;
388 chip->kc_ioh = ioh;
389 chip->kc_polling = 0;
390 chip->kc_head = chip->kc_tail = chip->kc_eventq;
391 chip->kc_nevents = 0;
392
393 /* set KIU */
394 vrkiu_write(chip, KIURST, 1); /* reset */
395 vrkiu_write(chip, KIUSCANLINE, 0); /* 96keys */
396 vrkiu_write(chip, KIUWKS, 0x18a4); /* XXX: scan timing! */
397 vrkiu_write(chip, KIUWKI, 450);
398 vrkiu_write(chip, KIUSCANREP, 0x8023);
399 /* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
400 vrkiu_initkeymap();
401 return 0;
402 }
403
404 /*
405 * put key event
406 */
407 static int
408 vrkiu_putevent(chip, type, data)
409 struct vrkiu_chip* chip;
410 u_int type;
411 int data;
412 {
413 if (chip->kc_nevents == NEVENTQ) {
414 return (0);
415 }
416 chip->kc_nevents++;
417 chip->kc_tail->kc_type = type;
418 chip->kc_tail->kc_data = data;
419 if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_tail) {
420 chip->kc_tail = chip->kc_eventq;
421 }
422 return (1);
423 }
424
425 /*
426 * gut key event
427 */
428 static int
429 vrkiu_getevent(chip, type, data)
430 struct vrkiu_chip* chip;
431 u_int *type;
432 int *data;
433 {
434 if (chip->kc_nevents == 0) {
435 return (0);
436 }
437 *type = chip->kc_head->kc_type;
438 *data = chip->kc_head->kc_data;
439 chip->kc_nevents--;
440 if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_head) {
441 chip->kc_head = chip->kc_eventq;
442 }
443 return (1);
444 }
445
446 /*
447 * probe
448 */
449 static int
450 vrkiumatch(parent, cf, aux)
451 struct device *parent;
452 struct cfdata *cf;
453 void *aux;
454 {
455 return 1;
456 }
457
458 /*
459 * attach
460 */
461 static void
462 vrkiuattach(parent, self, aux)
463 struct device *parent;
464 struct device *self;
465 void *aux;
466 {
467 struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
468 struct vrip_attach_args *va = aux;
469 struct wskbddev_attach_args wa;
470 int isconsole;
471
472 bus_space_tag_t iot = va->va_iot;
473 bus_space_handle_t ioh;
474
475 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
476 printf(": can't map bus space\n");
477 return;
478 }
479
480 isconsole = vrkiu_is_console(iot, ioh);
481 if (isconsole) {
482 sc->sc_chip = vrkiu_consdata;
483 } else {
484 sc->sc_chip = &sc->sc_chip_body;
485 vrkiu_init(sc->sc_chip, iot, ioh);
486 }
487 sc->sc_chip->kc_sc = sc;
488
489 if (!(sc->sc_handler =
490 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
491 vrkiu_intr, sc))) {
492 printf (": can't map interrupt line.\n");
493 return;
494 }
495 /* Level2 register setting */
496 vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
497
498 printf("\n");
499
500 wa.console = isconsole;
501 wa.keymap = &vrkiu_keymapdata;
502 wa.accessops = &vrkiu_accessops;
503 wa.accesscookie = sc;
504
505 sc->sc_wskbddev = config_found(self, &wa, wskbddevprint);
506 }
507
508 int
509 vrkiu_intr(arg)
510 void *arg;
511 {
512 struct vrkiu_softc *sc = arg;
513
514 /* When key scan finisshed, this entry is called. */
515 DPRINTF(("%s(%d): vrkiu_intr: %d\n",
516 __FILE__, __LINE__,
517 vrkiu_read(sc->sc_chip, KIUINT) & 7));
518
519 /*
520 * First, we must clear the interrupt register because
521 * detect_key() may takes long time if a bitmap screen
522 * scrolls up and it makes us to miss some key release
523 * event.
524 */
525 vrkiu_write(sc->sc_chip, KIUINT, 0x7); /* Clear all interrupt */
526 detect_key(sc->sc_chip);
527
528 return 0;
529 }
530
531 static int
532 detect_key(chip)
533 struct vrkiu_chip* chip;
534 {
535 int i, j, modified, mask;
536 int detected;
537 unsigned short scandata[KIU_NSCANLINE/2];
538
539 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
540 scandata[i] = vrkiu_read(chip, KIUDATP + i * 2);
541 }
542
543 DPRINTF(("%s(%d): detect_key():", __FILE__, __LINE__));
544
545 detected = 0;
546 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
547 modified = scandata[i] ^ chip->kc_scandata[i];
548 chip->kc_scandata[i] = scandata[i];
549 mask = 1;
550 for (j = 0; j < 16; j++, mask <<= 1) {
551 /*
552 * Simultaneous keypresses are resolved by registering
553 * the one with the lowest bit index first.
554 */
555 if (modified & mask) {
556 int key, type;
557 key = i * 16 + j;
558 if (keytrans[key] == UNK) {
559 printf("vrkiu: Unknown scan code 0x%02x\n", key);
560 continue;
561 } else if (keytrans[key] == IGN) {
562 continue;
563 }
564 type = (scandata[i] & mask) ?
565 WSCONS_EVENT_KEY_DOWN :
566 WSCONS_EVENT_KEY_UP;
567 DPRINTF(("(%d,%d)=%s%d ", i, j,
568 (scandata[i] & mask) ? "v" : "^",
569 keytrans[key]));
570 detected++;
571 if (chip->kc_polling) {
572 if (vrkiu_putevent(chip, type,
573 keytrans[key]) == 0)
574 printf("vrkiu: queue over flow");
575 } else {
576 wskbd_input(chip->kc_sc->sc_wskbddev,
577 type,
578 keytrans[key]);
579 }
580 }
581 }
582 }
583 DPRINTF(("\n"));
584
585 return (detected);
586 }
587
588 /* called from biconsdev.c */
589 int
590 vrkiu_getc()
591 {
592 /*
593 * XXX, currently
594 */
595 printf("%s(%d): vrkiu_getc() is not implemented\n",
596 __FILE__, __LINE__);
597 return 0;
598 }
599
600 int
601 vrkiu_enable(scx, on)
602 void *scx;
603 int on;
604 {
605 struct vrkiu_softc *sc = scx;
606
607 if (on) {
608 if (sc->sc_enabled)
609 return (EBUSY);
610 sc->sc_enabled = 1;
611 } else {
612 if (sc->sc_chip == vrkiu_consdata)
613 return (EBUSY);
614 sc->sc_enabled = 0;
615 }
616
617 return (0);
618 }
619
620 void
621 vrkiu_set_leds(scx, leds)
622 void *scx;
623 int leds;
624 {
625 /*struct pckbd_softc *sc = scx;
626 */
627
628 DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
629 __FILE__, __LINE__));
630 }
631
632 int
633 vrkiu_ioctl(scx, cmd, data, flag, p)
634 void *scx;
635 u_long cmd;
636 caddr_t data;
637 int flag;
638 struct proc *p;
639 {
640 /*struct vrkiu_softc *sc = scx;
641 */
642
643 switch (cmd) {
644 case WSKBDIO_GTYPE:
645 *(int *)data = WSKBD_TYPE_HPC_KBD;
646 return 0;
647 case WSKBDIO_SETLEDS:
648 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
649 return 0;
650 case WSKBDIO_GETLEDS:
651 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
652 *(int *)data = 0;
653 return (0);
654 }
655 return -1;
656 }
657
658 /*
659 * console support routines
660 */
661 int
662 vrkiu_cnattach(iot, iobase)
663 bus_space_tag_t iot;
664 int iobase;
665 {
666 static struct vrkiu_chip vrkiu_consdata_body;
667 bus_space_handle_t ioh;
668
669 if (vrkiu_consdata) {
670 panic("vrkiu is already attached as the console");
671 }
672 if (bus_space_map(iot, iobase, 1, 0, &ioh)) {
673 printf("%s(%d): can't map bus space\n", __FILE__, __LINE__);
674 return -1;
675 }
676
677 if (vrkiu_init(&vrkiu_consdata_body, iot, ioh) != 0) {
678 DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__, __LINE__));
679 return -1;
680 }
681 vrkiu_consdata = &vrkiu_consdata_body;
682
683 wskbd_cnattach(&vrkiu_consops, vrkiu_consdata, &vrkiu_keymapdata);
684
685 return (0);
686 }
687
688 void
689 vrkiu_cngetc(chipx, type, data)
690 void *chipx;
691 u_int *type;
692 int *data;
693 {
694 struct vrkiu_chip* chip = chipx;
695 int s;
696
697 if (!chip->kc_polling) {
698 printf("%s(%d): kiu is not polled\n", __FILE__, __LINE__);
699 /*
700 * Don't call panic() because it may call this routine
701 * recursively.
702 */
703 printf("halt\n");
704 while (1);
705 }
706
707 s = splimp();
708 while (vrkiu_getevent(chip, type, data) == 0) /* busy loop */
709 detect_key(chip);
710 splx(s);
711 }
712
713 void
714 vrkiu_cnpollc(chipx, on)
715 void *chipx;
716 int on;
717 {
718 struct vrkiu_chip* chip = chipx;
719 int s = splimp();
720
721 chip->kc_polling = on;
722
723 splx(s);
724
725 DPRINTF(("%s(%d): vrkiu polling %s\n",
726 __FILE__, __LINE__, on ? "ON" : "OFF"));
727 }
728