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