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