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