Home | History | Annotate | Line # | Download | only in vr
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