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