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