Home | History | Annotate | Line # | Download | only in vr
vrkiu.c revision 1.2
      1 /*	$NetBSD: vrkiu.c,v 1.2 1999/10/24 08:37:30 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 
     53 #include <hpcmips/vr/vr.h>
     54 #include <hpcmips/vr/vripvar.h>
     55 #include <hpcmips/vr/vrkiuvar.h>
     56 #include <hpcmips/vr/vrkiureg.h>
     57 #include <hpcmips/vr/icureg.h>
     58 
     59 #include <dev/wscons/wsconsio.h>
     60 #include <dev/wscons/wskbdvar.h>
     61 #include <dev/wscons/wsksymdef.h>
     62 #include <dev/wscons/wsksymvar.h>
     63 #include <dev/pckbc/wskbdmap_mfii.h>
     64 
     65 #ifdef VRKIUDEBUG
     66 int vrkiu_debug = 0;
     67 #define DPRINTF(arg) if (vrkiu_debug) printf arg;
     68 #else
     69 #define	DPRINTF(arg)
     70 #endif
     71 
     72 /*
     73  * structure and data types
     74  */
     75 struct vrkiu_chip {
     76 	bus_space_tag_t kc_iot;
     77 	bus_space_handle_t kc_ioh;
     78 	unsigned short kc_scandata[KIU_NSCANLINE/2];
     79 	int kc_polling;
     80 	u_int kc_type;
     81 	int kc_data;
     82 
     83 	int kc_sft:1, kc_alt:1, kc_ctrl:1;
     84 
     85 	struct vrkiu_softc* kc_sc;	/* back link */
     86 };
     87 
     88 struct vrkiu_softc {
     89 	struct device sc_dev;
     90 	struct vrkiu_chip *sc_chip;
     91 	struct vrkiu_chip sc_chip_body;
     92 	int sc_enabled;
     93 	struct device *sc_wskbddev;
     94 
     95 	void *sc_handler;
     96 #define NKEYBUF 32
     97 	unsigned char keybuf[NKEYBUF];
     98 	int keybufhead, keybuftail;
     99 };
    100 
    101 /*
    102  * function prototypes
    103  */
    104 static int vrkiumatch __P((struct device *, struct cfdata *, void *));
    105 static void vrkiuattach __P((struct device *, struct device *, void *));
    106 
    107 int vrkiu_intr __P((void *));
    108 
    109 static int vrkiu_init(struct vrkiu_chip*, bus_space_tag_t, bus_space_handle_t);
    110 static void vrkiu_write __P((struct vrkiu_chip *, int, unsigned short));
    111 static unsigned short vrkiu_read __P((struct vrkiu_chip *, int));
    112 static int vrkiu_is_console(bus_space_tag_t, bus_space_handle_t);
    113 static void detect_key __P((struct vrkiu_chip *));
    114 
    115 static struct vrkiu_softc *the_vrkiu = NULL; /* XXX: kludge!! */
    116 
    117 /* wskbd accessopts */
    118 int vrkiu_enable __P((void *, int));
    119 void vrkiu_set_leds __P((void *, int));
    120 int vrkiu_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
    121 
    122 /* consopts */
    123 void vrkiu_cngetc __P((void*, u_int*, int*));
    124 void vrkiu_cnpollc __P((void *, int));
    125 
    126 /*
    127  * global/static data
    128  */
    129 struct cfattach vrkiu_ca = {
    130 	sizeof(struct vrkiu_softc), vrkiumatch, vrkiuattach
    131 };
    132 
    133 const struct wskbd_accessops vrkiu_accessops = {
    134 	vrkiu_enable,
    135 	vrkiu_set_leds,
    136 	vrkiu_ioctl,
    137 };
    138 
    139 const struct wskbd_consops vrkiu_consops = {
    140 	vrkiu_cngetc,
    141 	vrkiu_cnpollc,
    142 };
    143 
    144 const struct wskbd_mapdata vrkiu_keymapdata = {
    145 	pckbd_keydesctab,
    146 	KB_US,
    147 };
    148 
    149 struct vrkiu_chip *vrkiu_consdata = NULL;
    150 
    151 /* XXX: This tranlation table may depend on each machine.
    152         Should I build it in? */
    153 static char keytrans[] = {
    154 	-1,  28,  25,  52,  21,  48,  44,  57,  /* - enter p . y b z space */
    155 	-1,  53,  24,  51,  20,  47,  30,  -1,  /* - / o , t v a - */
    156 	-1,  -1,  23,  50,  19,  46,  17,  -1,  /* - - i m r c w - */
    157 	13,  -1,  22,  -1,  18,  45,  16,   2,  /* = - u - e x q 1 */
    158 	-1,  -1,  11,  38,  40,  34,  15,  59,  /* - - 0 l ' g tab f1 */
    159 	-1,  39,  10,  49,   6,  33,   3,  37,  /* - ; 9 n 5 f 2 k */
    160 	-1,  27,   9,  36,   5,  32,   7,  -1,  /* - ] 8 j 4 d 6 - */
    161 	12,  26,   8,  35,   4,  41,  31,  -1,  /* - [ 7 h 3 ` s - */
    162 	58,  -1,  -1,  -1,  14,  -1,  66,  61,  /* caps - - - bs - f8 f3 */
    163 	-1,  56,  -1,  -1,  43,  -1,  65,  62,  /* - alt - - \ - f7 f4 */
    164 	-1,  -1,  29,  -1,  68,  -1,  64,  60,  /* - - ctrl - f10 - f6 f2 */
    165 	-1,  -1,  -1,  42,  -1,  67,  63,   1,  /* - - - shift - f9 f5 esc */
    166 };
    167 /* XXX: fill the field of funct. keys, ex. arrow, fnc, nfer... */
    168 
    169 #define	SCROLL		0x0001	/* stop output */
    170 #define	NUM		0x0002	/* numeric shift  cursors vs. numeric */
    171 #define	CAPS		0x0004	/* caps shift -- swaps case of letter */
    172 #define	SHIFT		0x0008	/* keyboard shift */
    173 #define	CTL		0x0010	/* control shift  -- allows ctl function */
    174 #define	ASCII		0x0020	/* ascii code for this key */
    175 #define	ALT		0x0080	/* alternate shift -- alternate chars */
    176 #define	FUNC		0x0100	/* function key */
    177 #define	KP		0x0200	/* Keypad keys */
    178 #define	NONE		0x0400	/* no function */
    179 
    180 /*
    181  * utilities
    182  */
    183 static inline void
    184 vrkiu_write(chip, port, val)
    185 	struct vrkiu_chip *chip;
    186 	int port;
    187 	unsigned short val;
    188 {
    189 	bus_space_write_2(chip->kc_iot, chip->kc_ioh, port, val);
    190 }
    191 
    192 static inline unsigned short
    193 vrkiu_read(chip, port)
    194 	struct vrkiu_chip *chip;
    195 	int port;
    196 {
    197 	return bus_space_read_2(chip->kc_iot, chip->kc_ioh, port);
    198 }
    199 
    200 static inline int
    201 vrkiu_is_console(iot, ioh)
    202 	bus_space_tag_t iot;
    203 	bus_space_handle_t ioh;
    204 {
    205 	if (vrkiu_consdata &&
    206 	    vrkiu_consdata->kc_iot == iot &&
    207 	    vrkiu_consdata->kc_ioh == ioh) {
    208 		return 1;
    209 	} else {
    210 		return 0;
    211 	}
    212 }
    213 
    214 /*
    215  * initialize device
    216  */
    217 static int
    218 vrkiu_init(chip, iot, ioh)
    219 	struct vrkiu_chip* chip;
    220 	bus_space_tag_t iot;
    221 	bus_space_handle_t ioh;
    222 {
    223 	memset(chip, 0, sizeof(struct vrkiu_chip));
    224 	chip->kc_iot = iot;
    225 	chip->kc_ioh = ioh;
    226 	chip->kc_polling = 0;
    227 
    228 	/* set KIU */
    229 	vrkiu_write(chip, KIURST, 1);   /* reset */
    230 	vrkiu_write(chip, KIUSCANLINE, 0); /* 96keys */
    231 	vrkiu_write(chip, KIUWKS, 0x18a4); /* XXX: scan timing! */
    232 	vrkiu_write(chip, KIUWKI, 450);
    233 	vrkiu_write(chip, KIUSCANREP, 0x8023);
    234 				/* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
    235 	return 0;
    236 }
    237 
    238 /*
    239  * probe
    240  */
    241 static int
    242 vrkiumatch(parent, cf, aux)
    243 	struct device *parent;
    244 	struct cfdata *cf;
    245 	void *aux;
    246 {
    247 	return 1;
    248 }
    249 
    250 /*
    251  * attach
    252  */
    253 static void
    254 vrkiuattach(parent, self, aux)
    255 	struct device *parent;
    256 	struct device *self;
    257 	void *aux;
    258 {
    259 	struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
    260 	struct vrip_attach_args *va = aux;
    261 	struct wskbddev_attach_args wa;
    262 	int isconsole;
    263 
    264 	bus_space_tag_t iot = va->va_iot;
    265 	bus_space_handle_t ioh;
    266 
    267 	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
    268 		printf(": can't map bus space\n");
    269 		return;
    270 	}
    271 
    272 	isconsole = vrkiu_is_console(iot, ioh);
    273 	if (isconsole) {
    274 		sc->sc_chip = vrkiu_consdata;
    275 	} else {
    276 		sc->sc_chip = &sc->sc_chip_body;
    277 		vrkiu_init(sc->sc_chip, iot, ioh);
    278 	}
    279 	sc->sc_chip->kc_sc = sc;
    280 
    281 	if (!(sc->sc_handler =
    282 	      vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
    283 				  vrkiu_intr, sc))) {
    284 		printf (": can't map interrupt line.\n");
    285 		return;
    286 	}
    287 	/* Level2 register setting */
    288 	vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
    289 
    290 	printf("\n");
    291 
    292 	wa.console = isconsole;
    293 	wa.keymap = &vrkiu_keymapdata;
    294 	wa.accessops = &vrkiu_accessops;
    295 	wa.accesscookie = sc;
    296 
    297 	sc->sc_wskbddev = config_found(self, &wa, wskbddevprint);
    298 }
    299 
    300 int
    301 vrkiu_intr(arg)
    302 	void *arg;
    303 {
    304         struct vrkiu_softc *sc = arg;
    305 
    306 	/* When key scan finisshed, this entry is called. */
    307 	DPRINTF(("%s(%d): vrkiu_intr: %d\n",
    308 		 __FILE__, __LINE__,
    309 		 vrkiu_read(sc->sc_chip, KIUINT) & 7));
    310 
    311 	detect_key(sc->sc_chip);
    312 
    313 	vrkiu_write(sc->sc_chip, KIUINT, 0x7); /* Clear all interrupt */
    314 
    315 	return 0;
    316 }
    317 
    318 static void
    319 detect_key(chip)
    320 	struct vrkiu_chip* chip;
    321 {
    322 	int i, j, modified, mask;
    323 	unsigned short scandata[KIU_NSCANLINE/2];
    324 
    325 	for (i = 0; i < KIU_NSCANLINE / 2; i++) {
    326 		scandata[i] = vrkiu_read(chip, KIUDATP + i * 2);
    327 	}
    328 
    329 	DPRINTF(("%s(%d): detect_key():", __FILE__, __LINE__));
    330 
    331 	if (chip->kc_polling) {
    332 		chip->kc_type = WSCONS_EVENT_ALL_KEYS_UP;
    333 	}
    334 
    335 	for (i = 0; i < KIU_NSCANLINE / 2; i++) {
    336 		modified = scandata[i] ^ chip->kc_scandata[i];
    337 		mask = 1;
    338 		for (j = 0; j < 16; j++) {
    339 			/* XXX: The order of keys can be a problem.
    340 			   If CTRL and normal key are pushed simultaneously,
    341 			   normal key can be entered in queue first.
    342 			   Same problem would occur in key break. */
    343 			if (modified & mask) {
    344 				int key, type;
    345 				key = i * 16 + j;
    346 				if (keytrans[key] < 0) {
    347 	                                printf("vrkiu: Unkown scan code 0x%02x\n", key);
    348 	                                continue;
    349 				}
    350 				type = (scandata[i] & mask) ?
    351 					WSCONS_EVENT_KEY_DOWN :
    352 					WSCONS_EVENT_KEY_UP;
    353 				DPRINTF(("(%d,%d)=%s%d ", i, j,
    354 					 (scandata[i] & mask) ? "v" : "^",
    355 					 keytrans[key]));
    356 				if (chip->kc_polling) {
    357 					chip->kc_type = type;
    358 					chip->kc_data = keytrans[key];
    359 				} else {
    360 					wskbd_input(chip->kc_sc->sc_wskbddev,
    361 						    type,
    362 						    keytrans[key]);
    363 				}
    364 			}
    365 			mask <<= 1;
    366 		}
    367 		chip->kc_scandata[i] = scandata[i];
    368 	}
    369 	DPRINTF(("\n"));
    370 }
    371 
    372 /* called from biconsdev.c */
    373 int
    374 vrkiu_getc()
    375 {
    376 	int ret;
    377 
    378 	if (the_vrkiu == NULL) {
    379 		return 0;	/* XXX */
    380 	}
    381 
    382 	while (the_vrkiu->keybuftail == the_vrkiu->keybufhead) {
    383 		detect_key(vrkiu_consdata);
    384 	}
    385 	ret = the_vrkiu->keybuf[the_vrkiu->keybuftail++];
    386 	if (the_vrkiu->keybuftail >= NKEYBUF) {
    387 		the_vrkiu->keybuftail = 0;
    388 	}
    389 	return ret;
    390 }
    391 
    392 int
    393 vrkiu_enable(scx, on)
    394 	void *scx;
    395 	int on;
    396 {
    397 	struct vrkiu_softc *sc = scx;
    398 
    399 	if (on) {
    400 		if (sc->sc_enabled)
    401 			return (EBUSY);
    402 		sc->sc_enabled = 1;
    403 	} else {
    404 		if (sc->sc_chip == vrkiu_consdata)
    405 			return (EBUSY);
    406 		sc->sc_enabled = 0;
    407 	}
    408 
    409 	return (0);
    410 }
    411 
    412 void
    413 vrkiu_set_leds(scx, leds)
    414 	void *scx;
    415 	int leds;
    416 {
    417 	/*struct pckbd_softc *sc = scx;
    418 	 */
    419 
    420 	DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
    421 		 __FILE__, __LINE__));
    422 }
    423 
    424 int
    425 vrkiu_ioctl(scx, cmd, data, flag, p)
    426 	void *scx;
    427 	u_long cmd;
    428 	caddr_t data;
    429 	int flag;
    430 	struct proc *p;
    431 {
    432 	/*struct vrkiu_softc *sc = scx;
    433 	 */
    434 
    435 	switch (cmd) {
    436 	case WSKBDIO_GTYPE:
    437 		/*
    438 		 * XXX, fix me !
    439 		 */
    440 		*(int *)data = WSKBD_TYPE_PC_XT;
    441 		return 0;
    442 	case WSKBDIO_SETLEDS:
    443 		DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
    444 		return 0;
    445 	case WSKBDIO_GETLEDS:
    446 		DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
    447 		*(int *)data = 0;
    448 		return (0);
    449 	}
    450 	return -1;
    451 }
    452 
    453 /*
    454  * console support routines
    455  */
    456 int
    457 vrkiu_cnattach(iot, iobase)
    458 	bus_space_tag_t iot;
    459 	int iobase;
    460 {
    461 	static struct vrkiu_chip vrkiu_consdata_body;
    462 	bus_space_handle_t ioh;
    463 
    464 	if (vrkiu_consdata) {
    465 		panic("vrkiu is already attached as the console");
    466 	}
    467 	if (bus_space_map(iot, iobase, 1, 0, &ioh)) {
    468 		printf("%s(%d): can't map bus space\n", __FILE__, __LINE__);
    469 		return -1;
    470 	}
    471 
    472 	if (vrkiu_init(&vrkiu_consdata_body, iot, ioh) != 0) {
    473 		DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__, __LINE__));
    474 		return -1;
    475 	}
    476 	vrkiu_consdata = &vrkiu_consdata_body;
    477 
    478 	wskbd_cnattach(&vrkiu_consops, vrkiu_consdata, &vrkiu_keymapdata);
    479 
    480 	return (0);
    481 }
    482 
    483 void
    484 vrkiu_cngetc(chipx, type, data)
    485 	void *chipx;
    486 	u_int *type;
    487 	int *data;
    488 {
    489 	struct vrkiu_chip* chip = chipx;
    490 	int s;
    491 
    492 	if (!chip->kc_polling) {
    493 		printf("%s(%d): kiu is not polled\n", __FILE__, __LINE__);
    494 		while (1);
    495 	}
    496 
    497 	s = splimp();
    498 	if (chip->kc_type == WSCONS_EVENT_ALL_KEYS_UP) {
    499 		detect_key(chip);
    500 	}
    501 	*type = chip->kc_type;
    502 	*data = chip->kc_data;
    503 	chip->kc_type = WSCONS_EVENT_ALL_KEYS_UP;
    504 	splx(s);
    505 }
    506 
    507 void
    508 vrkiu_cnpollc(chipx, on)
    509 	void *chipx;
    510         int on;
    511 {
    512 	struct vrkiu_chip* chip = chipx;
    513 	int s = splimp();
    514 
    515 	chip->kc_polling = on;
    516 
    517 	splx(s);
    518 
    519 	DPRINTF(("%s(%d): vrkiu polling %s\n",
    520 		 __FILE__, __LINE__, on ? "ON" : "OFF"));
    521 }
    522