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