Home | History | Annotate | Line # | Download | only in vr
vrkiu.c revision 1.12
      1 /*	$NetBSD: vrkiu.c,v 1.12 2000/01/22 09:12:35 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 #if 0
    374 	if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_520A)) {
    375 		keytrans = mobilepro_keytrans;
    376 #if !defined(PCKBD_LAYOUT)
    377 		vrkiu_keymapdata.layout = KB_US;
    378 #endif
    379 	} else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_500A)) {
    380 		keytrans = mobilepro750c_keytrans;
    381 #if !defined(PCKBD_LAYOUT)
    382 		vrkiu_keymapdata.layout = KB_US;
    383 #endif
    384 	} else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_700A)) {
    385 		keytrans = mobilepro_keytrans;
    386 #if !defined(PCKBD_LAYOUT)
    387 		vrkiu_keymapdata.layout = KB_US;
    388 #endif
    389 	} else if (platid_match(&platid, &platid_mask_MACH_NEC_MCR)) {
    390 		keytrans = mcr_jp_keytrans;
    391 #if !defined(PCKBD_LAYOUT)
    392 		vrkiu_keymapdata.layout = KB_JP;
    393 #endif
    394 	} else if (platid_match(&platid, &platid_mask_MACH_IBM_WORKPAD_Z50)) {
    395 		keytrans = z50_keytrans;
    396 #if !defined(PCKBD_LAYOUT)
    397 		vrkiu_keymapdata.layout = KB_US;
    398 #endif
    399 	} else if (platid_match(&platid, &platid_mask_MACH_SHARP_TRIPAD)) {
    400 		keytrans = tripad_keytrans;
    401 #if !defined(PCKBD_LAYOUT)
    402 		vrkiu_keymapdata.layout = KB_JP;
    403 #endif
    404 	} else if (platid_match(&platid, &platid_mask_MACH_NEC_MCCS)) {
    405 		keytrans = mccs_keytrans;
    406 #if !defined(PCKBD_LAYOUT)
    407 		vrkiu_keymapdata.layout = KB_JP;
    408 #endif
    409 	} else if (platid_match(&platid, &platid_mask_MACH_FUJITSU_INTERTOP)) {
    410 		keytrans = intertop_keytrans;
    411 #if !defined(PCKBD_LAYOUT)
    412 		vrkiu_keymapdata.layout = KB_JP;
    413 #endif
    414 	}
    415 #endif
    416 }
    417 
    418 /*
    419  * initialize device
    420  */
    421 static int
    422 vrkiu_init(chip, iot, ioh)
    423 	struct vrkiu_chip* chip;
    424 	bus_space_tag_t iot;
    425 	bus_space_handle_t ioh;
    426 {
    427 	memset(chip, 0, sizeof(struct vrkiu_chip));
    428 	chip->kc_iot = iot;
    429 	chip->kc_ioh = ioh;
    430 	chip->kc_polling = 0;
    431 	chip->kc_head = chip->kc_tail = chip->kc_eventq;
    432 	chip->kc_nevents = 0;
    433 
    434 	/* set KIU */
    435 	vrkiu_write(chip, KIURST, 1);   /* reset */
    436 	vrkiu_write(chip, KIUSCANLINE, 0); /* 96keys */
    437 	vrkiu_write(chip, KIUWKS, 0x18a4); /* XXX: scan timing! */
    438 	vrkiu_write(chip, KIUWKI, 450);
    439 	vrkiu_write(chip, KIUSCANREP, 0x8023);
    440 				/* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
    441 	vrkiu_initkeymap();
    442 	return 0;
    443 }
    444 
    445 /*
    446  * put key event
    447  */
    448 static int
    449 vrkiu_putevent(chip, type, data)
    450 	struct vrkiu_chip* chip;
    451 	u_int type;
    452 	int data;
    453 {
    454 	if (chip->kc_nevents == NEVENTQ) {
    455 	  return (0);
    456 	}
    457 	chip->kc_nevents++;
    458 	chip->kc_tail->kc_type = type;
    459 	chip->kc_tail->kc_data = data;
    460 	if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_tail) {
    461 		chip->kc_tail = chip->kc_eventq;
    462 	}
    463 	return (1);
    464 }
    465 
    466 /*
    467  * gut key event
    468  */
    469 static int
    470 vrkiu_getevent(chip, type, data)
    471 	struct vrkiu_chip* chip;
    472 	u_int *type;
    473 	int *data;
    474 {
    475 	if (chip->kc_nevents == 0) {
    476 	  return (0);
    477 	}
    478 	*type = chip->kc_head->kc_type;
    479 	*data = chip->kc_head->kc_data;
    480 	chip->kc_nevents--;
    481 	if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_head) {
    482 		chip->kc_head = chip->kc_eventq;
    483 	}
    484 	return (1);
    485 }
    486 
    487 /*
    488  * probe
    489  */
    490 static int
    491 vrkiumatch(parent, cf, aux)
    492 	struct device *parent;
    493 	struct cfdata *cf;
    494 	void *aux;
    495 {
    496 	return 1;
    497 }
    498 
    499 /*
    500  * attach
    501  */
    502 static void
    503 vrkiuattach(parent, self, aux)
    504 	struct device *parent;
    505 	struct device *self;
    506 	void *aux;
    507 {
    508 	struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
    509 	struct vrip_attach_args *va = aux;
    510 	struct wskbddev_attach_args wa;
    511 	int isconsole;
    512 
    513 	bus_space_tag_t iot = va->va_iot;
    514 	bus_space_handle_t ioh;
    515 
    516 	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
    517 		printf(": can't map bus space\n");
    518 		return;
    519 	}
    520 
    521 	isconsole = vrkiu_is_console(iot, ioh);
    522 	if (isconsole) {
    523 		sc->sc_chip = vrkiu_consdata;
    524 	} else {
    525 		sc->sc_chip = &sc->sc_chip_body;
    526 		vrkiu_init(sc->sc_chip, iot, ioh);
    527 	}
    528 	sc->sc_chip->kc_sc = sc;
    529 
    530 	if (!(sc->sc_handler =
    531 	      vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
    532 				  vrkiu_intr, sc))) {
    533 		printf (": can't map interrupt line.\n");
    534 		return;
    535 	}
    536 	/* Level2 register setting */
    537 	vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
    538 
    539 	printf("\n");
    540 
    541 	wa.console = isconsole;
    542 	wa.keymap = &vrkiu_keymapdata;
    543 	wa.accessops = &vrkiu_accessops;
    544 	wa.accesscookie = sc;
    545 
    546 	sc->sc_wskbddev = config_found(self, &wa, wskbddevprint);
    547 }
    548 
    549 int
    550 vrkiu_intr(arg)
    551 	void *arg;
    552 {
    553         struct vrkiu_softc *sc = arg;
    554 
    555 	/* When key scan finisshed, this entry is called. */
    556 	DPRINTF(("%s(%d): vrkiu_intr: %d\n",
    557 		 __FILE__, __LINE__,
    558 		 vrkiu_read(sc->sc_chip, KIUINT) & 7));
    559 
    560 	/*
    561 	 * First, we must clear the interrupt register because
    562 	 * detect_key() may takes long time if a bitmap screen
    563 	 * scrolls up and it makes us to miss some key release
    564 	 * event.
    565 	 */
    566 	vrkiu_write(sc->sc_chip, KIUINT, 0x7); /* Clear all interrupt */
    567 	detect_key(sc->sc_chip);
    568 
    569 	return 0;
    570 }
    571 
    572 static int
    573 detect_key(chip)
    574 	struct vrkiu_chip* chip;
    575 {
    576 	int i, j, modified, mask;
    577 	int detected;
    578 	unsigned short scandata[KIU_NSCANLINE/2];
    579 
    580 	for (i = 0; i < KIU_NSCANLINE / 2; i++) {
    581 		scandata[i] = vrkiu_read(chip, KIUDATP + i * 2);
    582 	}
    583 
    584 	DPRINTF(("%s(%d): detect_key():", __FILE__, __LINE__));
    585 
    586 	detected = 0;
    587 	for (i = 0; i < KIU_NSCANLINE / 2; i++) {
    588 		modified = scandata[i] ^ chip->kc_scandata[i];
    589 		mask = 1;
    590 		for (j = 0; j < 16; j++, mask <<= 1) {
    591 			/* XXX: The order of keys can be a problem.
    592 			   If CTRL and normal key are pushed simultaneously,
    593 			   normal key can be entered in queue first.
    594 			   Same problem would occur in key break. */
    595 			if (modified & mask) {
    596 				int key, type;
    597 				key = i * 16 + j;
    598 				if (keytrans[key] == UNK) {
    599 	                                printf("vrkiu: Unknown scan code 0x%02x\n", key);
    600 	                                continue;
    601 				} else if (keytrans[key] == IGN) {
    602 					continue;
    603 				}
    604 				type = (scandata[i] & mask) ?
    605 					WSCONS_EVENT_KEY_DOWN :
    606 					WSCONS_EVENT_KEY_UP;
    607 				DPRINTF(("(%d,%d)=%s%d ", i, j,
    608 					 (scandata[i] & mask) ? "v" : "^",
    609 					 keytrans[key]));
    610 				detected++;
    611 				if (chip->kc_polling) {
    612 					if (vrkiu_putevent(chip, type,
    613 							   keytrans[key]) == 0)
    614 						printf("vrkiu: queue over flow");
    615 				} else {
    616 					wskbd_input(chip->kc_sc->sc_wskbddev,
    617 						    type,
    618 						    keytrans[key]);
    619 				}
    620 			}
    621 		}
    622 		chip->kc_scandata[i] = scandata[i];
    623 	}
    624 	DPRINTF(("\n"));
    625 
    626 	return (detected);
    627 }
    628 
    629 /* called from biconsdev.c */
    630 int
    631 vrkiu_getc()
    632 {
    633 	/*
    634 	 * XXX, currently
    635 	 */
    636 	printf("%s(%d): vrkiu_getc() is not implemented\n",
    637 	       __FILE__, __LINE__);
    638 	return 0;
    639 }
    640 
    641 int
    642 vrkiu_enable(scx, on)
    643 	void *scx;
    644 	int on;
    645 {
    646 	struct vrkiu_softc *sc = scx;
    647 
    648 	if (on) {
    649 		if (sc->sc_enabled)
    650 			return (EBUSY);
    651 		sc->sc_enabled = 1;
    652 	} else {
    653 		if (sc->sc_chip == vrkiu_consdata)
    654 			return (EBUSY);
    655 		sc->sc_enabled = 0;
    656 	}
    657 
    658 	return (0);
    659 }
    660 
    661 void
    662 vrkiu_set_leds(scx, leds)
    663 	void *scx;
    664 	int leds;
    665 {
    666 	/*struct pckbd_softc *sc = scx;
    667 	 */
    668 
    669 	DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
    670 		 __FILE__, __LINE__));
    671 }
    672 
    673 int
    674 vrkiu_ioctl(scx, cmd, data, flag, p)
    675 	void *scx;
    676 	u_long cmd;
    677 	caddr_t data;
    678 	int flag;
    679 	struct proc *p;
    680 {
    681 	/*struct vrkiu_softc *sc = scx;
    682 	 */
    683 
    684 	switch (cmd) {
    685 	case WSKBDIO_GTYPE:
    686 		/*
    687 		 * XXX, fix me !
    688 		 */
    689 		*(int *)data = WSKBD_TYPE_PC_XT;
    690 		return 0;
    691 	case WSKBDIO_SETLEDS:
    692 		DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
    693 		return 0;
    694 	case WSKBDIO_GETLEDS:
    695 		DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
    696 		*(int *)data = 0;
    697 		return (0);
    698 	}
    699 	return -1;
    700 }
    701 
    702 /*
    703  * console support routines
    704  */
    705 int
    706 vrkiu_cnattach(iot, iobase)
    707 	bus_space_tag_t iot;
    708 	int iobase;
    709 {
    710 	static struct vrkiu_chip vrkiu_consdata_body;
    711 	bus_space_handle_t ioh;
    712 
    713 	if (vrkiu_consdata) {
    714 		panic("vrkiu is already attached as the console");
    715 	}
    716 	if (bus_space_map(iot, iobase, 1, 0, &ioh)) {
    717 		printf("%s(%d): can't map bus space\n", __FILE__, __LINE__);
    718 		return -1;
    719 	}
    720 
    721 	if (vrkiu_init(&vrkiu_consdata_body, iot, ioh) != 0) {
    722 		DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__, __LINE__));
    723 		return -1;
    724 	}
    725 	vrkiu_consdata = &vrkiu_consdata_body;
    726 
    727 	wskbd_cnattach(&vrkiu_consops, vrkiu_consdata, &vrkiu_keymapdata);
    728 
    729 	return (0);
    730 }
    731 
    732 void
    733 vrkiu_cngetc(chipx, type, data)
    734 	void *chipx;
    735 	u_int *type;
    736 	int *data;
    737 {
    738 	struct vrkiu_chip* chip = chipx;
    739 	int s;
    740 
    741 	if (!chip->kc_polling) {
    742 		printf("%s(%d): kiu is not polled\n", __FILE__, __LINE__);
    743 		/*
    744 		 * Don't call panic() because it may call this routine
    745 		 * recursively.
    746 		 */
    747 		printf("halt\n");
    748 		while (1);
    749 	}
    750 
    751 	s = splimp();
    752 	while (vrkiu_getevent(chip, type, data) == 0) /* busy loop */
    753 		detect_key(chip);
    754 	splx(s);
    755 }
    756 
    757 void
    758 vrkiu_cnpollc(chipx, on)
    759 	void *chipx;
    760         int on;
    761 {
    762 	struct vrkiu_chip* chip = chipx;
    763 	int s = splimp();
    764 
    765 	chip->kc_polling = on;
    766 
    767 	splx(s);
    768 
    769 	DPRINTF(("%s(%d): vrkiu polling %s\n",
    770 		 __FILE__, __LINE__, on ? "ON" : "OFF"));
    771 }
    772