Home | History | Annotate | Line # | Download | only in dev
kbd.c revision 1.31
      1 /*	$NetBSD: kbd.c,v 1.31 1998/02/28 21:53: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 		/*draco_ioct->io_control &= ~DRCNTRL_KBDKBDACK;*/
    179 		printf("ioctrl: 0x%02x, iostat: 0x%02x\n",
    180 			draco_ioct->io_control, draco_ioct->io_status);
    181 
    182 		ciaa.icr = CIA_ICR_SP;  /* CIA SP interrupt disable */
    183 		ciaa.cra &= ~(1<<6);	/* serial line == input */
    184 		splx(s);
    185 		return;
    186 
    187 	LnoMFII:
    188 		kbd_softc.k_mf2 = 0;
    189 		*draco_intena |= DRIRQ_INT2;
    190 		ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;
    191 					/* SP interrupt enable */
    192 		ciaa.cra &= ~(1<<6);	/* serial line == input */
    193 		splx(s);
    194 		return;
    195 
    196 	} else {
    197 #endif
    198 	custom.intena = INTF_SETCLR | INTF_PORTS;
    199 	ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;  /* SP interrupt enable */
    200 	ciaa.cra &= ~(1<<6);		/* serial line == input */
    201 #ifdef DRACO
    202 	}
    203 #endif
    204 	kbd_softc.k_event_mode = 0;
    205 	kbd_softc.k_events.ev_io = 0;
    206 	splx(s);
    207 }
    208 
    209 /*
    210  * call this with kbd interupt blocked
    211  */
    212 
    213 int
    214 drkbdgetc()
    215 {
    216 	u_int8_t in;
    217 
    218 	while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    219 	in = draco_ioct->io_kbddata;
    220 	draco_ioct->io_kbdrst = 0;
    221 
    222 	return in;
    223 }
    224 
    225 #define WAIT0 if (drkbdwaitfor(0)) goto Ltimeout
    226 #define WAIT1 if (drkbdwaitfor(DRSTAT_KBDCLKIN)) goto Ltimeout
    227 
    228 int
    229 drkbdwaitfor(bit)
    230 	int bit;
    231 {
    232 	int i;
    233 
    234 
    235 
    236 	i = 60000;	/* about 50 ms max */
    237 
    238 	do {
    239 		if ((draco_ioct->io_status & DRSTAT_KBDCLKIN) == bit)
    240 			return 0;
    241 
    242 	} while (--i >= 0);
    243 
    244 	return 1;
    245 }
    246 
    247 /*
    248  * Output a raw byte to the keyboard (+ parity and stop bit).
    249  * return 0 on success, 1 on timeout.
    250  */
    251 int
    252 drkbdrputc(c)
    253 	u_int8_t c;
    254 {
    255 	u_int8_t parity;
    256 	int bitcnt;
    257 
    258 	DATLO; CLKHI; WAIT1;
    259 	parity = 0;
    260 
    261 	for (bitcnt=7; bitcnt >= 0; bitcnt--) {
    262 		WAIT0;
    263 		if (c & 1) {
    264 			DATHI;
    265 		} else {
    266 			++parity;
    267 			DATLO;
    268 		}
    269 		c >>= 1;
    270 		WAIT1;
    271 	}
    272 	WAIT0;
    273 	/* parity bit */
    274 	if (parity & 1) {
    275 		DATLO;
    276 	} else {
    277 		DATHI;
    278 	}
    279 	WAIT1;
    280 	/* stop bit */
    281 	WAIT0; DATHI; WAIT1;
    282 
    283 	WAIT0; /* XXX should check the ack bit here... */
    284 	WAIT1;
    285 	draco_ioct->io_kbdrst = 0;
    286 	return 0;
    287 
    288 Ltimeout:
    289 	DATHI;
    290 	draco_ioct->io_kbdrst = 0;
    291 	return 1;
    292 }
    293 
    294 /*
    295  * Output one cooked byte to the keyboard, with wait for ACK or RESEND,
    296  * and retry if necessary. 0 == success, 1 == timeout
    297  */
    298 int
    299 drkbdputc(c)
    300 	u_int8_t c;
    301 {
    302 	int rc;
    303 
    304 	do {
    305 		if (drkbdrputc(c))
    306 			return(-1);
    307 
    308 		rc = drkbdgetc();
    309 	} while (rc == 0xfe);
    310 	return (!(rc == 0xfa));
    311 }
    312 
    313 /*
    314  * same for twobyte sequence
    315  */
    316 
    317 int
    318 drkbdputc2(c1, c2)
    319 	u_int8_t c1, c2;
    320 {
    321 	int rc;
    322 
    323 	do {
    324 		do {
    325 			if (drkbdrputc(c1))
    326 				return(-1);
    327 
    328 			rc = drkbdgetc();
    329 		} while (rc == 0xfe);
    330 		if (rc != 0xfa)
    331 			return (-1);
    332 
    333 		if (drkbdrputc(c2))
    334 			return(-1);
    335 
    336 		rc = drkbdgetc();
    337 	} while (rc == 0xfe);
    338 	return (!(rc == 0xfa));
    339 }
    340 
    341 int
    342 kbdopen(dev, flags, mode, p)
    343 	dev_t dev;
    344 	int flags, mode;
    345 	struct proc *p;
    346 {
    347 
    348 	kbdenable();
    349 	if (kbd_softc.k_events.ev_io)
    350 		return EBUSY;
    351 
    352 	kbd_softc.k_events.ev_io = p;
    353 	ev_init(&kbd_softc.k_events);
    354 	return (0);
    355 }
    356 
    357 int
    358 kbdclose(dev, flags, mode, p)
    359 	dev_t dev;
    360 	int flags, mode;
    361 	struct proc *p;
    362 {
    363 
    364 	/* Turn off event mode, dump the queue */
    365 	kbd_softc.k_event_mode = 0;
    366 	ev_fini(&kbd_softc.k_events);
    367 	kbd_softc.k_events.ev_io = NULL;
    368 	return (0);
    369 }
    370 
    371 int
    372 kbdread(dev, uio, flags)
    373 	dev_t dev;
    374 	struct uio *uio;
    375 	int flags;
    376 {
    377 	return ev_read (&kbd_softc.k_events, uio, flags);
    378 }
    379 
    380 int
    381 kbdioctl(dev, cmd, data, flag, p)
    382 	dev_t dev;
    383 	u_long cmd;
    384 	register caddr_t data;
    385 	int flag;
    386 	struct proc *p;
    387 {
    388 	register struct kbd_softc *k = &kbd_softc;
    389 
    390 	switch (cmd) {
    391 		case KIOCTRANS:
    392 			if (*(int *)data == TR_UNTRANS_EVENT)
    393 				return 0;
    394 			break;
    395 
    396 		case KIOCGTRANS:
    397 			/* Get translation mode */
    398 			*(int *)data = TR_UNTRANS_EVENT;
    399 			return 0;
    400 
    401 		case KIOCSDIRECT:
    402 			k->k_event_mode = *(int *)data;
    403 			return 0;
    404 
    405 		case FIONBIO:	/* we will remove this someday (soon???) */
    406 			return 0;
    407 
    408 		case FIOASYNC:
    409 			k->k_events.ev_async = *(int *)data != 0;
    410 			return 0;
    411 
    412 		case TIOCSPGRP:
    413 			if (*(int *)data != k->k_events.ev_io->p_pgid)
    414 				return EPERM;
    415 			return 0;
    416 
    417 		default:
    418 			return ENOTTY;
    419 	}
    420 
    421 	/* We identified the ioctl, but we do not handle it. */
    422 	return EOPNOTSUPP;	/* misuse, but what the heck */
    423 }
    424 
    425 int
    426 kbdpoll(dev, events, p)
    427 	dev_t dev;
    428 	int events;
    429 	struct proc *p;
    430 {
    431 	return ev_poll (&kbd_softc.k_events, events, p);
    432 }
    433 
    434 
    435 void
    436 kbdintr(mask)
    437 	int mask;
    438 {
    439 	u_char c;
    440 #ifdef KBDRESET
    441 	static int reset_warn;
    442 #endif
    443 
    444 	/*
    445 	 * now only invoked from generic CIA interrupt handler if there *is*
    446 	 * a keyboard interrupt pending
    447 	 */
    448 
    449 	c = ~ciaa.sdr;	/* keyboard data is inverted */
    450 	/* ack */
    451 	ciaa.cra |= (1 << 6);	/* serial line output */
    452 #ifdef KBDRESET
    453 	if (reset_warn && c == 0xf0) {
    454 #ifdef DEBUG
    455 		printf ("kbdintr: !!!! Reset Warning !!!!\n");
    456 #endif
    457 		bootsync();
    458 		reset_warn = 0;
    459 		DELAY(30000000);
    460 	}
    461 #endif
    462 	/* wait 200 microseconds (for bloody Cherry keyboards..) */
    463 	DELAY(2000);			/* fudge delay a bit for some keyboards */
    464 	ciaa.cra &= ~(1 << 6);
    465 
    466 	/* process the character */
    467 	c = (c >> 1) | (c << 7);	/* rotate right once */
    468 
    469 #ifdef KBDRESET
    470 	if (c == 0x78) {
    471 #ifdef DEBUG
    472 		printf ("kbdintr: Reset Warning started\n");
    473 #endif
    474 		++reset_warn;
    475 		return;
    476 	}
    477 #endif
    478 	kbdstuffchar(c);
    479 }
    480 
    481 #ifdef DRACO
    482 /* maps MF-II keycodes to Amiga keycodes */
    483 
    484 const u_char drkbdtab[] = {
    485 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50,
    486 	0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51,
    487 
    488 	0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52,
    489 	0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53,
    490 
    491 	0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54,
    492 	0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55,
    493 
    494 	0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56,
    495 	0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57,
    496 	/* --- */
    497 	0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58,
    498 	0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59,
    499 
    500 	0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff,
    501 	0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff,
    502 
    503 	0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46,
    504 	0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62,
    505 
    506 	0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b,
    507 	0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff,
    508 	/* --- */
    509 	0xff, 0xff, 0xff, 0xff, 0x5d
    510 };
    511 #endif
    512 
    513 
    514 int
    515 kbdgetcn ()
    516 {
    517 	int s;
    518 	u_char ints, mask, c, in;
    519 
    520 #ifdef DRACO
    521 	/*
    522 	 * XXX todo: if CIA DraCo, get from cia if cia kbd
    523 	 * installed.
    524 	 */
    525 	if (is_draco() && kbd_softc.k_mf2) {
    526 		do {
    527 			c = 0;
    528 			s = spltty ();
    529 			while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    530 			in = draco_ioct->io_kbddata;
    531 			draco_ioct->io_kbdrst = 0;
    532 			if (in == 0xF0) { /* release prefix */
    533 				c = 0x80;
    534 				while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    535 				in = draco_ioct->io_kbddata;
    536 				draco_ioct->io_kbdrst = 0;
    537 			}
    538 			splx(s);
    539 #ifdef DRACORAWKEYDEBUG
    540 			printf("<%02x>", in);
    541 #endif
    542 			c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in];
    543 		} while (c == 0xff);
    544 		return (c);
    545 	}
    546 #endif
    547 	s = spltty();
    548 	for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP);
    549 	    ints |= mask) ;
    550 
    551 	in = ciaa.sdr;
    552 	c = ~in;
    553 
    554 	/* ack */
    555 	ciaa.cra |= (1 << 6);	/* serial line output */
    556 	ciaa.sdr = 0xff;	/* ack */
    557 	/* wait 200 microseconds */
    558 	DELAY(2000);	/* XXXX only works as long as DELAY doesn't
    559 			 * use a timer and waits.. */
    560 	ciaa.cra &= ~(1 << 6);
    561 	ciaa.sdr = in;
    562 
    563 	splx (s);
    564 	c = (c >> 1) | (c << 7);
    565 
    566 	/* take care that no CIA-interrupts are lost */
    567 	if (ints)
    568 		dispatch_cia_ints (0, ints);
    569 
    570 	return c;
    571 }
    572 
    573 void
    574 kbdstuffchar(c)
    575 	u_char c;
    576 {
    577 	struct firm_event *fe;
    578 	struct kbd_softc *k = &kbd_softc;
    579 	int put;
    580 
    581 	/*
    582 	 * If not in event mode, deliver straight to ite to process
    583 	 * key stroke
    584 	 */
    585 
    586 	if (! k->k_event_mode) {
    587 		ite_filter (c, ITEFILT_TTY);
    588 		return;
    589 	}
    590 
    591 	/*
    592 	 * Keyboard is generating events. Turn this keystroke into an
    593 	 * event and put it in the queue. If the queue is full, the
    594 	 * keystroke is lost (sorry!).
    595 	 */
    596 
    597 	put = k->k_events.ev_put;
    598 	fe = &k->k_events.ev_q[put];
    599 	put = (put + 1) % EV_QSIZE;
    600 	if (put == k->k_events.ev_get) {
    601 		log(LOG_WARNING, "keyboard event queue overflow\n");
    602 			/* ??? */
    603 		return;
    604 	}
    605 	fe->id = KEY_CODE(c);
    606 	fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
    607 	fe->time = time;
    608 	k->k_events.ev_put = put;
    609 	EV_WAKEUP(&k->k_events);
    610 }
    611 
    612 
    613 #ifdef DRACO
    614 void
    615 drkbdintr()
    616 {
    617 	u_char in;
    618 	struct kbd_softc *k = &kbd_softc;
    619 
    620 	in = draco_ioct->io_kbddata;
    621 	draco_ioct->io_kbdrst = 0;
    622 
    623 	if (in == 0xF0)
    624 		k->k_rlprfx = 0x80;
    625 	else {
    626 		kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff :
    627 		    drkbdtab[in] | k->k_rlprfx);
    628 		k->k_rlprfx = 0;
    629 	}
    630 }
    631 
    632 #endif
    633