vrkiu.c revision 1.13 1 /* $NetBSD: vrkiu.c,v 1.13 2000/01/28 15:02:11 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 #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, 29, 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*/ 58, 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, 29, 38, 24, 25, 9, 10, 11, /* Fn caps l o p 8 9 0 */
215 /*30*/ 26, 27, 102, 52, 53, 39, 12, 13, /* [ ] dar , / ; \- = */
216 /*38*/ 54, 103, 100, 102, 39, 28, 43, 14, /* rsh - - uar - ; 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_JP },
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 }
371 }
372 }
373
374 /*
375 * initialize device
376 */
377 static int
378 vrkiu_init(chip, iot, ioh)
379 struct vrkiu_chip* chip;
380 bus_space_tag_t iot;
381 bus_space_handle_t ioh;
382 {
383 memset(chip, 0, sizeof(struct vrkiu_chip));
384 chip->kc_iot = iot;
385 chip->kc_ioh = ioh;
386 chip->kc_polling = 0;
387 chip->kc_head = chip->kc_tail = chip->kc_eventq;
388 chip->kc_nevents = 0;
389
390 /* set KIU */
391 vrkiu_write(chip, KIURST, 1); /* reset */
392 vrkiu_write(chip, KIUSCANLINE, 0); /* 96keys */
393 vrkiu_write(chip, KIUWKS, 0x18a4); /* XXX: scan timing! */
394 vrkiu_write(chip, KIUWKI, 450);
395 vrkiu_write(chip, KIUSCANREP, 0x8023);
396 /* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
397 vrkiu_initkeymap();
398 return 0;
399 }
400
401 /*
402 * put key event
403 */
404 static int
405 vrkiu_putevent(chip, type, data)
406 struct vrkiu_chip* chip;
407 u_int type;
408 int data;
409 {
410 if (chip->kc_nevents == NEVENTQ) {
411 return (0);
412 }
413 chip->kc_nevents++;
414 chip->kc_tail->kc_type = type;
415 chip->kc_tail->kc_data = data;
416 if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_tail) {
417 chip->kc_tail = chip->kc_eventq;
418 }
419 return (1);
420 }
421
422 /*
423 * gut key event
424 */
425 static int
426 vrkiu_getevent(chip, type, data)
427 struct vrkiu_chip* chip;
428 u_int *type;
429 int *data;
430 {
431 if (chip->kc_nevents == 0) {
432 return (0);
433 }
434 *type = chip->kc_head->kc_type;
435 *data = chip->kc_head->kc_data;
436 chip->kc_nevents--;
437 if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_head) {
438 chip->kc_head = chip->kc_eventq;
439 }
440 return (1);
441 }
442
443 /*
444 * probe
445 */
446 static int
447 vrkiumatch(parent, cf, aux)
448 struct device *parent;
449 struct cfdata *cf;
450 void *aux;
451 {
452 return 1;
453 }
454
455 /*
456 * attach
457 */
458 static void
459 vrkiuattach(parent, self, aux)
460 struct device *parent;
461 struct device *self;
462 void *aux;
463 {
464 struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
465 struct vrip_attach_args *va = aux;
466 struct wskbddev_attach_args wa;
467 int isconsole;
468
469 bus_space_tag_t iot = va->va_iot;
470 bus_space_handle_t ioh;
471
472 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
473 printf(": can't map bus space\n");
474 return;
475 }
476
477 isconsole = vrkiu_is_console(iot, ioh);
478 if (isconsole) {
479 sc->sc_chip = vrkiu_consdata;
480 } else {
481 sc->sc_chip = &sc->sc_chip_body;
482 vrkiu_init(sc->sc_chip, iot, ioh);
483 }
484 sc->sc_chip->kc_sc = sc;
485
486 if (!(sc->sc_handler =
487 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
488 vrkiu_intr, sc))) {
489 printf (": can't map interrupt line.\n");
490 return;
491 }
492 /* Level2 register setting */
493 vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
494
495 printf("\n");
496
497 wa.console = isconsole;
498 wa.keymap = &vrkiu_keymapdata;
499 wa.accessops = &vrkiu_accessops;
500 wa.accesscookie = sc;
501
502 sc->sc_wskbddev = config_found(self, &wa, wskbddevprint);
503 }
504
505 int
506 vrkiu_intr(arg)
507 void *arg;
508 {
509 struct vrkiu_softc *sc = arg;
510
511 /* When key scan finisshed, this entry is called. */
512 DPRINTF(("%s(%d): vrkiu_intr: %d\n",
513 __FILE__, __LINE__,
514 vrkiu_read(sc->sc_chip, KIUINT) & 7));
515
516 /*
517 * First, we must clear the interrupt register because
518 * detect_key() may takes long time if a bitmap screen
519 * scrolls up and it makes us to miss some key release
520 * event.
521 */
522 vrkiu_write(sc->sc_chip, KIUINT, 0x7); /* Clear all interrupt */
523 detect_key(sc->sc_chip);
524
525 return 0;
526 }
527
528 static int
529 detect_key(chip)
530 struct vrkiu_chip* chip;
531 {
532 int i, j, modified, mask;
533 int detected;
534 unsigned short scandata[KIU_NSCANLINE/2];
535
536 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
537 scandata[i] = vrkiu_read(chip, KIUDATP + i * 2);
538 }
539
540 DPRINTF(("%s(%d): detect_key():", __FILE__, __LINE__));
541
542 detected = 0;
543 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
544 modified = scandata[i] ^ chip->kc_scandata[i];
545 mask = 1;
546 for (j = 0; j < 16; j++, mask <<= 1) {
547 /* XXX: The order of keys can be a problem.
548 If CTRL and normal key are pushed simultaneously,
549 normal key can be entered in queue first.
550 Same problem would occur in key break. */
551 if (modified & mask) {
552 int key, type;
553 key = i * 16 + j;
554 if (keytrans[key] == UNK) {
555 printf("vrkiu: Unknown scan code 0x%02x\n", key);
556 continue;
557 } else if (keytrans[key] == IGN) {
558 continue;
559 }
560 type = (scandata[i] & mask) ?
561 WSCONS_EVENT_KEY_DOWN :
562 WSCONS_EVENT_KEY_UP;
563 DPRINTF(("(%d,%d)=%s%d ", i, j,
564 (scandata[i] & mask) ? "v" : "^",
565 keytrans[key]));
566 detected++;
567 if (chip->kc_polling) {
568 if (vrkiu_putevent(chip, type,
569 keytrans[key]) == 0)
570 printf("vrkiu: queue over flow");
571 } else {
572 wskbd_input(chip->kc_sc->sc_wskbddev,
573 type,
574 keytrans[key]);
575 }
576 }
577 }
578 chip->kc_scandata[i] = scandata[i];
579 }
580 DPRINTF(("\n"));
581
582 return (detected);
583 }
584
585 /* called from biconsdev.c */
586 int
587 vrkiu_getc()
588 {
589 /*
590 * XXX, currently
591 */
592 printf("%s(%d): vrkiu_getc() is not implemented\n",
593 __FILE__, __LINE__);
594 return 0;
595 }
596
597 int
598 vrkiu_enable(scx, on)
599 void *scx;
600 int on;
601 {
602 struct vrkiu_softc *sc = scx;
603
604 if (on) {
605 if (sc->sc_enabled)
606 return (EBUSY);
607 sc->sc_enabled = 1;
608 } else {
609 if (sc->sc_chip == vrkiu_consdata)
610 return (EBUSY);
611 sc->sc_enabled = 0;
612 }
613
614 return (0);
615 }
616
617 void
618 vrkiu_set_leds(scx, leds)
619 void *scx;
620 int leds;
621 {
622 /*struct pckbd_softc *sc = scx;
623 */
624
625 DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
626 __FILE__, __LINE__));
627 }
628
629 int
630 vrkiu_ioctl(scx, cmd, data, flag, p)
631 void *scx;
632 u_long cmd;
633 caddr_t data;
634 int flag;
635 struct proc *p;
636 {
637 /*struct vrkiu_softc *sc = scx;
638 */
639
640 switch (cmd) {
641 case WSKBDIO_GTYPE:
642 /*
643 * XXX, fix me !
644 */
645 *(int *)data = WSKBD_TYPE_PC_XT;
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