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