Home | History | Annotate | Line # | Download | only in dev
kbd.c revision 1.32
      1 /*	$NetBSD: kbd.c,v 1.32 1998/03/08 19:59:15 is Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  *	kbd.c
     36  */
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/device.h>
     40 #include <sys/ioctl.h>
     41 #include <sys/tty.h>
     42 #include <sys/proc.h>
     43 #include <sys/file.h>
     44 #include <sys/kernel.h>
     45 #include <sys/syslog.h>
     46 #include <sys/signalvar.h>
     47 #include <dev/cons.h>
     48 #include <m68k/asm_single.h>
     49 #include <machine/cpu.h>
     50 #include <amiga/amiga/device.h>
     51 #include <amiga/amiga/custom.h>
     52 #ifdef DRACO
     53 #include <amiga/amiga/drcustom.h>
     54 #endif
     55 #include <amiga/amiga/cia.h>
     56 #include <amiga/dev/itevar.h>
     57 #include <amiga/dev/kbdreg.h>
     58 #include <amiga/dev/kbdmap.h>
     59 #include <amiga/dev/event_var.h>
     60 #include <amiga/dev/vuid_event.h>
     61 #include "kbd.h"
     62 
     63 #include <sys/conf.h>
     64 #include <machine/conf.h>
     65 
     66 struct kbd_softc {
     67 	int k_event_mode;	/* if true, collect events, else pass to ite */
     68 	struct evvar k_events;	/* event queue state */
     69 #ifdef DRACO
     70 	u_char k_rlprfx;	/* MF-II rel. prefix has been seen */
     71 	u_char k_mf2;
     72 #endif
     73 };
     74 struct kbd_softc kbd_softc;
     75 
     76 int kbdmatch __P((struct device *, struct cfdata *, void *));
     77 void kbdattach __P((struct device *, struct device *, void *));
     78 void kbdintr __P((int));
     79 void kbdstuffchar __P((u_char));
     80 
     81 int drkbdgetc __P((void));
     82 int drkbdrputc __P((int));
     83 int drkbdputc __P((int));
     84 int drkbdputc2 __P((int, int));
     85 int drkbdwaitfor __P((int));
     86 
     87 struct cfattach kbd_ca = {
     88 	sizeof(struct device), kbdmatch, kbdattach
     89 };
     90 
     91 /*ARGSUSED*/
     92 int
     93 kbdmatch(pdp, cfp, auxp)
     94 	struct device *pdp;
     95 	struct cfdata *cfp;
     96 	void *auxp;
     97 {
     98 
     99 	if (matchname((char *)auxp, "kbd"))
    100 		return(1);
    101 	return(0);
    102 }
    103 
    104 /*ARGSUSED*/
    105 void
    106 kbdattach(pdp, dp, auxp)
    107 	struct device *pdp, *dp;
    108 	void *auxp;
    109 {
    110 #ifdef DRACO
    111 	kbdenable();
    112 	if (kbd_softc.k_mf2)
    113 		printf(": QuickLogic type MF-II\n");
    114 	else
    115 		printf(": CIA A type Amiga\n");
    116 #else
    117 	printf(": CIA A type Amiga\n");
    118 #endif
    119 
    120 }
    121 
    122 /* definitions for amiga keyboard encoding. */
    123 #define KEY_CODE(c)  ((c) & 0x7f)
    124 #define KEY_UP(c)    ((c) & 0x80)
    125 
    126 #define DATLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT)
    127 #define DATHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT)
    128 
    129 #define CLKLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT)
    130 #define CLKHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT)
    131 
    132 void
    133 kbdenable()
    134 {
    135 	static int kbd_inited = 0;
    136 
    137 	int s;
    138 
    139 #ifdef DRACO
    140 	int id;
    141 #endif
    142 	/*
    143 	 * collides with external ints from SCSI, watch out for this when
    144 	 * enabling/disabling interrupts there !!
    145 	 */
    146 	s = splhigh();	/* don't lower; might be called from early ddb */
    147 	if (kbd_inited) {
    148 		splx(s);
    149 		return;
    150 	}
    151 	kbd_inited = 1;
    152 #ifdef DRACO
    153 	if (is_draco()) {
    154 
    155 		CLKLO;
    156 		delay(5000);
    157 		draco_ioct->io_kbdrst = 0;
    158 
    159 		if (drkbdputc(0xf2))
    160 			goto LnoMFII;
    161 
    162 		id = drkbdgetc() << 8;
    163 		id |= drkbdgetc();
    164 
    165 		if (id != 0xab83)
    166 			goto LnoMFII;
    167 
    168 		if (drkbdputc2(0xf0, 3))	/* mode 3 */
    169 			goto LnoMFII;
    170 
    171 		if (drkbdputc(0xf8))		/* make/break, no typematic */
    172 			goto LnoMFII;
    173 
    174 		if (drkbdputc(0xf4))		/* enable */
    175 			goto LnoMFII;
    176 		kbd_softc.k_mf2 = 1;
    177 		draco_ioct->io_control &= ~DRCNTRL_KBDINTENA;
    178 
    179 		ciaa.icr = CIA_ICR_SP;  /* CIA SP interrupt disable */
    180 		ciaa.cra &= ~(1<<6);	/* serial line == input */
    181 		splx(s);
    182 		return;
    183 
    184 	LnoMFII:
    185 		kbd_softc.k_mf2 = 0;
    186 		*draco_intena |= DRIRQ_INT2;
    187 		ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;
    188 					/* SP interrupt enable */
    189 		ciaa.cra &= ~(1<<6);	/* serial line == input */
    190 		splx(s);
    191 		return;
    192 
    193 	} else {
    194 #endif
    195 	custom.intena = INTF_SETCLR | INTF_PORTS;
    196 	ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;  /* SP interrupt enable */
    197 	ciaa.cra &= ~(1<<6);		/* serial line == input */
    198 #ifdef DRACO
    199 	}
    200 #endif
    201 	kbd_softc.k_event_mode = 0;
    202 	kbd_softc.k_events.ev_io = 0;
    203 	splx(s);
    204 }
    205 
    206 #ifdef DRACO
    207 /*
    208  * call this with kbd interupt blocked
    209  */
    210 
    211 int
    212 drkbdgetc()
    213 {
    214 	u_int8_t in;
    215 
    216 	while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    217 	in = draco_ioct->io_kbddata;
    218 	draco_ioct->io_kbdrst = 0;
    219 
    220 	return in;
    221 }
    222 
    223 #define WAIT0 if (drkbdwaitfor(0)) goto Ltimeout
    224 #define WAIT1 if (drkbdwaitfor(DRSTAT_KBDCLKIN)) goto Ltimeout
    225 
    226 int
    227 drkbdwaitfor(bit)
    228 	int bit;
    229 {
    230 	int i;
    231 
    232 
    233 
    234 	i = 60000;	/* about 50 ms max */
    235 
    236 	do {
    237 		if ((draco_ioct->io_status & DRSTAT_KBDCLKIN) == bit)
    238 			return 0;
    239 
    240 	} while (--i >= 0);
    241 
    242 	return 1;
    243 }
    244 
    245 /*
    246  * Output a raw byte to the keyboard (+ parity and stop bit).
    247  * return 0 on success, 1 on timeout.
    248  */
    249 int
    250 drkbdrputc(c)
    251 	u_int8_t c;
    252 {
    253 	u_int8_t parity;
    254 	int bitcnt;
    255 
    256 	DATLO; CLKHI; WAIT1;
    257 	parity = 0;
    258 
    259 	for (bitcnt=7; bitcnt >= 0; bitcnt--) {
    260 		WAIT0;
    261 		if (c & 1) {
    262 			DATHI;
    263 		} else {
    264 			++parity;
    265 			DATLO;
    266 		}
    267 		c >>= 1;
    268 		WAIT1;
    269 	}
    270 	WAIT0;
    271 	/* parity bit */
    272 	if (parity & 1) {
    273 		DATLO;
    274 	} else {
    275 		DATHI;
    276 	}
    277 	WAIT1;
    278 	/* stop bit */
    279 	WAIT0; DATHI; WAIT1;
    280 
    281 	WAIT0; /* XXX should check the ack bit here... */
    282 	WAIT1;
    283 	draco_ioct->io_kbdrst = 0;
    284 	return 0;
    285 
    286 Ltimeout:
    287 	DATHI;
    288 	draco_ioct->io_kbdrst = 0;
    289 	return 1;
    290 }
    291 
    292 /*
    293  * Output one cooked byte to the keyboard, with wait for ACK or RESEND,
    294  * and retry if necessary. 0 == success, 1 == timeout
    295  */
    296 int
    297 drkbdputc(c)
    298 	u_int8_t c;
    299 {
    300 	int rc;
    301 
    302 	do {
    303 		if (drkbdrputc(c))
    304 			return(-1);
    305 
    306 		rc = drkbdgetc();
    307 	} while (rc == 0xfe);
    308 	return (!(rc == 0xfa));
    309 }
    310 
    311 /*
    312  * same for twobyte sequence
    313  */
    314 
    315 int
    316 drkbdputc2(c1, c2)
    317 	u_int8_t c1, c2;
    318 {
    319 	int rc;
    320 
    321 	do {
    322 		do {
    323 			if (drkbdrputc(c1))
    324 				return(-1);
    325 
    326 			rc = drkbdgetc();
    327 		} while (rc == 0xfe);
    328 		if (rc != 0xfa)
    329 			return (-1);
    330 
    331 		if (drkbdrputc(c2))
    332 			return(-1);
    333 
    334 		rc = drkbdgetc();
    335 	} while (rc == 0xfe);
    336 	return (!(rc == 0xfa));
    337 }
    338 #endif
    339 
    340 int
    341 kbdopen(dev, flags, mode, p)
    342 	dev_t dev;
    343 	int flags, mode;
    344 	struct proc *p;
    345 {
    346 
    347 	kbdenable();
    348 	if (kbd_softc.k_events.ev_io)
    349 		return EBUSY;
    350 
    351 	kbd_softc.k_events.ev_io = p;
    352 	ev_init(&kbd_softc.k_events);
    353 	return (0);
    354 }
    355 
    356 int
    357 kbdclose(dev, flags, mode, p)
    358 	dev_t dev;
    359 	int flags, mode;
    360 	struct proc *p;
    361 {
    362 
    363 	/* Turn off event mode, dump the queue */
    364 	kbd_softc.k_event_mode = 0;
    365 	ev_fini(&kbd_softc.k_events);
    366 	kbd_softc.k_events.ev_io = NULL;
    367 	return (0);
    368 }
    369 
    370 int
    371 kbdread(dev, uio, flags)
    372 	dev_t dev;
    373 	struct uio *uio;
    374 	int flags;
    375 {
    376 	return ev_read (&kbd_softc.k_events, uio, flags);
    377 }
    378 
    379 int
    380 kbdioctl(dev, cmd, data, flag, p)
    381 	dev_t dev;
    382 	u_long cmd;
    383 	register caddr_t data;
    384 	int flag;
    385 	struct proc *p;
    386 {
    387 	register struct kbd_softc *k = &kbd_softc;
    388 
    389 	switch (cmd) {
    390 		case KIOCTRANS:
    391 			if (*(int *)data == TR_UNTRANS_EVENT)
    392 				return 0;
    393 			break;
    394 
    395 		case KIOCGTRANS:
    396 			/* Get translation mode */
    397 			*(int *)data = TR_UNTRANS_EVENT;
    398 			return 0;
    399 
    400 		case KIOCSDIRECT:
    401 			k->k_event_mode = *(int *)data;
    402 			return 0;
    403 
    404 		case FIONBIO:	/* we will remove this someday (soon???) */
    405 			return 0;
    406 
    407 		case FIOASYNC:
    408 			k->k_events.ev_async = *(int *)data != 0;
    409 			return 0;
    410 
    411 		case TIOCSPGRP:
    412 			if (*(int *)data != k->k_events.ev_io->p_pgid)
    413 				return EPERM;
    414 			return 0;
    415 
    416 		default:
    417 			return ENOTTY;
    418 	}
    419 
    420 	/* We identified the ioctl, but we do not handle it. */
    421 	return EOPNOTSUPP;	/* misuse, but what the heck */
    422 }
    423 
    424 int
    425 kbdpoll(dev, events, p)
    426 	dev_t dev;
    427 	int events;
    428 	struct proc *p;
    429 {
    430 	return ev_poll (&kbd_softc.k_events, events, p);
    431 }
    432 
    433 
    434 void
    435 kbdintr(mask)
    436 	int mask;
    437 {
    438 	u_char c;
    439 #ifdef KBDRESET
    440 	static int reset_warn;
    441 #endif
    442 
    443 	/*
    444 	 * now only invoked from generic CIA interrupt handler if there *is*
    445 	 * a keyboard interrupt pending
    446 	 */
    447 
    448 	c = ~ciaa.sdr;	/* keyboard data is inverted */
    449 	/* ack */
    450 	ciaa.cra |= (1 << 6);	/* serial line output */
    451 #ifdef KBDRESET
    452 	if (reset_warn && c == 0xf0) {
    453 #ifdef DEBUG
    454 		printf ("kbdintr: !!!! Reset Warning !!!!\n");
    455 #endif
    456 		bootsync();
    457 		reset_warn = 0;
    458 		DELAY(30000000);
    459 	}
    460 #endif
    461 	/* wait 200 microseconds (for bloody Cherry keyboards..) */
    462 	DELAY(2000);			/* fudge delay a bit for some keyboards */
    463 	ciaa.cra &= ~(1 << 6);
    464 
    465 	/* process the character */
    466 	c = (c >> 1) | (c << 7);	/* rotate right once */
    467 
    468 #ifdef KBDRESET
    469 	if (c == 0x78) {
    470 #ifdef DEBUG
    471 		printf ("kbdintr: Reset Warning started\n");
    472 #endif
    473 		++reset_warn;
    474 		return;
    475 	}
    476 #endif
    477 	kbdstuffchar(c);
    478 }
    479 
    480 #ifdef DRACO
    481 /* maps MF-II keycodes to Amiga keycodes */
    482 
    483 const u_char drkbdtab[] = {
    484 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50,
    485 	0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51,
    486 
    487 	0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52,
    488 	0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53,
    489 
    490 	0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54,
    491 	0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55,
    492 
    493 	0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56,
    494 	0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57,
    495 	/* --- */
    496 	0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58,
    497 	0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59,
    498 
    499 	0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff,
    500 	0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff,
    501 
    502 	0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46,
    503 	0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62,
    504 
    505 	0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b,
    506 	0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff,
    507 	/* --- */
    508 	0xff, 0xff, 0xff, 0xff, 0x5d
    509 };
    510 #endif
    511 
    512 
    513 int
    514 kbdgetcn ()
    515 {
    516 	int s;
    517 	u_char ints, mask, c, in;
    518 
    519 #ifdef DRACO
    520 	if (is_draco() && kbd_softc.k_mf2) {
    521 		do {
    522 			c = 0;
    523 			s = spltty ();
    524 			while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    525 			in = draco_ioct->io_kbddata;
    526 			draco_ioct->io_kbdrst = 0;
    527 			if (in == 0xF0) { /* release prefix */
    528 				c = 0x80;
    529 				while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    530 				in = draco_ioct->io_kbddata;
    531 				draco_ioct->io_kbdrst = 0;
    532 			}
    533 			splx(s);
    534 #ifdef DRACORAWKEYDEBUG
    535 			printf("<%02x>", in);
    536 #endif
    537 			c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in];
    538 		} while (c == 0xff);
    539 		return (c);
    540 	}
    541 #endif
    542 	s = spltty();
    543 	for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP);
    544 	    ints |= mask) ;
    545 
    546 	in = ciaa.sdr;
    547 	c = ~in;
    548 
    549 	/* ack */
    550 	ciaa.cra |= (1 << 6);	/* serial line output */
    551 	ciaa.sdr = 0xff;	/* ack */
    552 	/* wait 200 microseconds */
    553 	DELAY(2000);	/* XXXX only works as long as DELAY doesn't
    554 			 * use a timer and waits.. */
    555 	ciaa.cra &= ~(1 << 6);
    556 	ciaa.sdr = in;
    557 
    558 	splx (s);
    559 	c = (c >> 1) | (c << 7);
    560 
    561 	/* take care that no CIA-interrupts are lost */
    562 	if (ints)
    563 		dispatch_cia_ints (0, ints);
    564 
    565 	return c;
    566 }
    567 
    568 void
    569 kbdstuffchar(c)
    570 	u_char c;
    571 {
    572 	struct firm_event *fe;
    573 	struct kbd_softc *k = &kbd_softc;
    574 	int put;
    575 
    576 	/*
    577 	 * If not in event mode, deliver straight to ite to process
    578 	 * key stroke
    579 	 */
    580 
    581 	if (! k->k_event_mode) {
    582 		ite_filter (c, ITEFILT_TTY);
    583 		return;
    584 	}
    585 
    586 	/*
    587 	 * Keyboard is generating events. Turn this keystroke into an
    588 	 * event and put it in the queue. If the queue is full, the
    589 	 * keystroke is lost (sorry!).
    590 	 */
    591 
    592 	put = k->k_events.ev_put;
    593 	fe = &k->k_events.ev_q[put];
    594 	put = (put + 1) % EV_QSIZE;
    595 	if (put == k->k_events.ev_get) {
    596 		log(LOG_WARNING, "keyboard event queue overflow\n");
    597 			/* ??? */
    598 		return;
    599 	}
    600 	fe->id = KEY_CODE(c);
    601 	fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
    602 	fe->time = time;
    603 	k->k_events.ev_put = put;
    604 	EV_WAKEUP(&k->k_events);
    605 }
    606 
    607 
    608 #ifdef DRACO
    609 void
    610 drkbdintr()
    611 {
    612 	u_char in;
    613 	struct kbd_softc *k = &kbd_softc;
    614 
    615 	in = draco_ioct->io_kbddata;
    616 	draco_ioct->io_kbdrst = 0;
    617 
    618 	if (in == 0xF0)
    619 		k->k_rlprfx = 0x80;
    620 	else {
    621 		kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff :
    622 		    drkbdtab[in] | k->k_rlprfx);
    623 		k->k_rlprfx = 0;
    624 	}
    625 }
    626 
    627 #endif
    628