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