Home | History | Annotate | Line # | Download | only in dev
kbd.c revision 1.57
      1 /*	$NetBSD: kbd.c,v 1.57 2014/07/25 08:10:31 dholland 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. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  *
     31  *	kbd.c
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.57 2014/07/25 08:10:31 dholland Exp $");
     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 <sys/conf.h>
     48 #include <dev/cons.h>
     49 #include <machine/cpu.h>
     50 #include <amiga/amiga/device.h>
     51 #include <amiga/amiga/custom.h>
     52 #ifdef DRACO
     53 #include <m68k/asm_single.h>
     54 #include <amiga/amiga/drcustom.h>
     55 #endif
     56 #include <amiga/amiga/cia.h>
     57 #include <amiga/dev/itevar.h>
     58 #include <amiga/dev/kbdreg.h>
     59 #include <amiga/dev/kbdmap.h>
     60 #include <amiga/dev/kbdvar.h>
     61 #include <amiga/dev/event_var.h>
     62 #include <amiga/dev/vuid_event.h>
     63 
     64 #include "kbd.h"
     65 #include "ite.h"
     66 
     67 /* WSKBD */
     68 
     69 /*
     70  * If NWSKBD>0 we try to attach an wskbd device to us. What follows
     71  * is definitions of callback functions and structures that are passed
     72  * to wscons when initializing.
     73  */
     74 
     75 /*
     76  * Now with wscons this driver exhibits some weird behaviour.
     77  * It may act both as a driver of its own and the md part of the
     78  * wskbd driver. Therefore it can be accessed through /dev/kbd
     79  * and /dev/wskbd0 both.
     80  *
     81  * The data from they keyboard may end up in at least four different
     82  * places:
     83  * - If this driver has been opened (/dev/kbd) and the
     84  *   direct mode (TIOCDIRECT) has been set, data goes to
     85  *   the process who opened the device. Data will transmit itself
     86  *   as described by the firm_event structure.
     87  * - If wskbd support is compiled in and a wskbd driver has been
     88  *   attached then the data is sent to it. Wskbd in turn may
     89  *   - Send the data in the wscons_event form to a process that
     90  *     has opened /dev/wskbd0
     91  *   - Feed the data to a virtual terminal.
     92  * - If an ite is present the data may be fed to it.
     93  */
     94 
     95 #include "wskbd.h"
     96 
     97 #if NWSKBD>0
     98 #include <dev/wscons/wsconsio.h>
     99 #include <dev/wscons/wskbdvar.h>
    100 #include <dev/wscons/wsksymdef.h>
    101 #include <dev/wscons/wsksymvar.h>
    102 #include <amiga/dev/wskbdmap_amiga.h>
    103 
    104 /* accessops */
    105 int     kbd_enable(void *, int);
    106 void    kbd_set_leds(void *, int);
    107 int     kbd_ioctl(void *, u_long, void *, int, struct lwp *);
    108 
    109 /* console ops */
    110 void    kbd_getc(void *, u_int *, int *);
    111 void    kbd_pollc(void *, int);
    112 void    kbd_bell(void *, u_int, u_int, u_int);
    113 
    114 static struct wskbd_accessops kbd_accessops = {
    115 	kbd_enable,
    116 	kbd_set_leds,
    117 	kbd_ioctl
    118 };
    119 
    120 static struct wskbd_consops kbd_consops = {
    121 	kbd_getc,
    122 	kbd_pollc,
    123 	kbd_bell
    124 };
    125 
    126 /*
    127  * Pointer to keymaps. They are defined in wskbdmap_amiga.c.
    128  */
    129 static struct wskbd_mapdata kbd_mapdata = {
    130 	amigakbd_keydesctab,
    131 	KB_US
    132 };
    133 
    134 #endif /* WSKBD */
    135 
    136 struct kbd_softc {
    137 	int k_event_mode;	/* if true, collect events, else pass to ite */
    138 	struct evvar k_events;	/* event queue state */
    139 #ifdef DRACO
    140 	u_char k_rlprfx;	/* MF-II rel. prefix has been seen */
    141 	u_char k_mf2;
    142 #endif
    143 
    144 	int k_console;		/* true if used as console keyboard */
    145 #if NWSKBD>0
    146 	device_t k_wskbddev; /* pointer to wskbd for sending strokes */
    147 	int k_pollingmode;         /* polling mode on? whatever it isss... */
    148 #endif
    149 };
    150 struct kbd_softc kbd_softc;
    151 
    152 int kbdmatch(device_t, cfdata_t, void *);
    153 void kbdattach(device_t, device_t, void *);
    154 void kbdintr(int);
    155 void kbdstuffchar(u_char);
    156 
    157 int drkbdgetc(void);
    158 int drkbdrputc(u_int8_t);
    159 int drkbdputc(u_int8_t);
    160 int drkbdputc2(u_int8_t, u_int8_t);
    161 int drkbdwaitfor(int);
    162 
    163 CFATTACH_DECL_NEW(kbd, 0,
    164     kbdmatch, kbdattach, NULL, NULL);
    165 
    166 dev_type_open(kbdopen);
    167 dev_type_close(kbdclose);
    168 dev_type_read(kbdread);
    169 dev_type_ioctl(kbdioctl);
    170 dev_type_poll(kbdpoll);
    171 dev_type_kqfilter(kbdkqfilter);
    172 
    173 const struct cdevsw kbd_cdevsw = {
    174 	.d_open = kbdopen,
    175 	.d_close = kbdclose,
    176 	.d_read = kbdread,
    177 	.d_write = nowrite,
    178 	.d_ioctl = kbdioctl,
    179 	.d_stop = nostop,
    180 	.d_tty = notty,
    181 	.d_poll = kbdpoll,
    182 	.d_mmap = nommap,
    183 	.d_kqfilter = kbdkqfilter,
    184 	.d_discard = nodiscard,
    185 	.d_flag = 0
    186 };
    187 
    188 /*ARGSUSED*/
    189 int
    190 kbdmatch(device_t parent, cfdata_t cf, void *aux)
    191 {
    192 
    193 	if (matchname((char *)aux, "kbd"))
    194 		return(1);
    195 	return(0);
    196 }
    197 
    198 /*ARGSUSED*/
    199 void
    200 kbdattach(device_t parent, device_t self, void *aux)
    201 {
    202 #ifdef DRACO
    203 	kbdenable();
    204 	if (kbd_softc.k_mf2)
    205 		printf(": QuickLogic type MF-II\n");
    206 	else
    207 		printf(": CIA A type Amiga\n");
    208 #else
    209 	printf(": CIA A type Amiga\n");
    210 #endif
    211 
    212 #if NWSKBD>0
    213 	if (self != NULL) {
    214 		/*
    215 		 * Try to attach the wskbd.
    216 		 */
    217 		struct wskbddev_attach_args waa;
    218 		waa.console = kbd_softc.k_console;
    219 		waa.keymap = &kbd_mapdata;
    220 		waa.accessops = &kbd_accessops;
    221 		waa.accesscookie = NULL;
    222 		kbd_softc.k_wskbddev = config_found(self, &waa, wskbddevprint);
    223 
    224 		kbd_softc.k_pollingmode = 0;
    225 	}
    226 	kbdenable();
    227 #endif /* WSKBD */
    228 }
    229 
    230 /*
    231  * This is called when somebody wants to use kbd as the console keyboard.
    232  */
    233 void
    234 kbd_cnattach(void)
    235 {
    236 #if NWSKBD>0
    237 	wskbd_cnattach(&kbd_consops, NULL, &kbd_mapdata);
    238 	kbd_softc.k_console = 1;
    239 #endif
    240 }
    241 
    242 /* definitions for amiga keyboard encoding. */
    243 #define KEY_CODE(c)  ((c) & 0x7f)
    244 #define KEY_UP(c)    ((c) & 0x80)
    245 
    246 #define DATLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT)
    247 #define DATHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT)
    248 
    249 #define CLKLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT)
    250 #define CLKHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT)
    251 
    252 void
    253 kbdenable(void)
    254 {
    255 	static int kbd_inited = 0;
    256 
    257 	int s;
    258 
    259 #ifdef DRACO
    260 	int id;
    261 #endif
    262 	/*
    263 	 * collides with external ints from SCSI, watch out for this when
    264 	 * enabling/disabling interrupts there !!
    265 	 */
    266 	s = splhigh();	/* don't lower; might be called from early ddb */
    267 	if (kbd_inited) {
    268 		splx(s);
    269 		return;
    270 	}
    271 	kbd_inited = 1;
    272 #ifdef DRACO
    273 	if (is_draco()) {
    274 
    275 		CLKLO;
    276 		delay(5000);
    277 		draco_ioct->io_kbdrst = 0;
    278 
    279 		if (drkbdputc(0xf2))
    280 			goto LnoMFII;
    281 
    282 		id = drkbdgetc() << 8;
    283 		id |= drkbdgetc();
    284 
    285 		if (id != 0xab83)
    286 			goto LnoMFII;
    287 
    288 		if (drkbdputc2(0xf0, 3))	/* mode 3 */
    289 			goto LnoMFII;
    290 
    291 		if (drkbdputc(0xf8))		/* make/break, no typematic */
    292 			goto LnoMFII;
    293 
    294 		if (drkbdputc(0xf4))		/* enable */
    295 			goto LnoMFII;
    296 		kbd_softc.k_mf2 = 1;
    297 		single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDINTENA);
    298 
    299 		ciaa.icr = CIA_ICR_SP;  /* CIA SP interrupt disable */
    300 		ciaa.cra &= ~(1<<6);	/* serial line == input */
    301 		splx(s);
    302 		return;
    303 
    304 	LnoMFII:
    305 		kbd_softc.k_mf2 = 0;
    306 		single_inst_bset_b(*draco_intena, DRIRQ_INT2);
    307 		ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;
    308 					/* SP interrupt enable */
    309 		ciaa.cra &= ~(1<<6);	/* serial line == input */
    310 		splx(s);
    311 		return;
    312 
    313 	} else {
    314 #endif
    315 	custom.intena = INTF_SETCLR | INTF_PORTS;
    316 	ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;  /* SP interrupt enable */
    317 	ciaa.cra &= ~(1<<6);		/* serial line == input */
    318 #ifdef DRACO
    319 	}
    320 #endif
    321 	kbd_softc.k_event_mode = 0;
    322 	kbd_softc.k_events.ev_io = 0;
    323 	splx(s);
    324 }
    325 
    326 #ifdef DRACO
    327 /*
    328  * call this with kbd interrupt blocked
    329  */
    330 
    331 int
    332 drkbdgetc(void)
    333 {
    334 	u_int8_t in;
    335 
    336 	while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    337 	in = draco_ioct->io_kbddata;
    338 	draco_ioct->io_kbdrst = 0;
    339 
    340 	return in;
    341 }
    342 
    343 #define WAIT0 if (drkbdwaitfor(0)) goto Ltimeout
    344 #define WAIT1 if (drkbdwaitfor(DRSTAT_KBDCLKIN)) goto Ltimeout
    345 
    346 int
    347 drkbdwaitfor(int bit)
    348 {
    349 	int i;
    350 
    351 
    352 
    353 	i = 60000;	/* about 50 ms max */
    354 
    355 	do {
    356 		if ((draco_ioct->io_status & DRSTAT_KBDCLKIN) == bit)
    357 			return 0;
    358 
    359 	} while (--i >= 0);
    360 
    361 	return 1;
    362 }
    363 
    364 /*
    365  * Output a raw byte to the keyboard (+ parity and stop bit).
    366  * return 0 on success, 1 on timeout.
    367  */
    368 int
    369 drkbdrputc(u_int8_t c)
    370 {
    371 	u_int8_t parity;
    372 	int bitcnt;
    373 
    374 	DATLO; CLKHI; WAIT1;
    375 	parity = 0;
    376 
    377 	for (bitcnt=7; bitcnt >= 0; bitcnt--) {
    378 		WAIT0;
    379 		if (c & 1) {
    380 			DATHI;
    381 		} else {
    382 			++parity;
    383 			DATLO;
    384 		}
    385 		c >>= 1;
    386 		WAIT1;
    387 	}
    388 	WAIT0;
    389 	/* parity bit */
    390 	if (parity & 1) {
    391 		DATLO;
    392 	} else {
    393 		DATHI;
    394 	}
    395 	WAIT1;
    396 	/* stop bit */
    397 	WAIT0; DATHI; WAIT1;
    398 
    399 	WAIT0; /* XXX should check the ack bit here... */
    400 	WAIT1;
    401 	draco_ioct->io_kbdrst = 0;
    402 	return 0;
    403 
    404 Ltimeout:
    405 	DATHI;
    406 	draco_ioct->io_kbdrst = 0;
    407 	return 1;
    408 }
    409 
    410 /*
    411  * Output one cooked byte to the keyboard, with wait for ACK or RESEND,
    412  * and retry if necessary. 0 == success, 1 == timeout
    413  */
    414 int
    415 drkbdputc(u_int8_t c)
    416 {
    417 	int rc;
    418 
    419 	do {
    420 		if (drkbdrputc(c))
    421 			return(-1);
    422 
    423 		rc = drkbdgetc();
    424 	} while (rc == 0xfe);
    425 	return (!(rc == 0xfa));
    426 }
    427 
    428 /*
    429  * same for twobyte sequence
    430  */
    431 
    432 int
    433 drkbdputc2(u_int8_t c1, u_int8_t c2)
    434 {
    435 	int rc;
    436 
    437 	do {
    438 		do {
    439 			if (drkbdrputc(c1))
    440 				return(-1);
    441 
    442 			rc = drkbdgetc();
    443 		} while (rc == 0xfe);
    444 		if (rc != 0xfa)
    445 			return (-1);
    446 
    447 		if (drkbdrputc(c2))
    448 			return(-1);
    449 
    450 		rc = drkbdgetc();
    451 	} while (rc == 0xfe);
    452 	return (!(rc == 0xfa));
    453 }
    454 #endif
    455 
    456 int
    457 kbdopen(dev_t dev, int flags, int mode, struct lwp *l)
    458 {
    459 
    460 	kbdenable();
    461 	if (kbd_softc.k_events.ev_io)
    462 		return EBUSY;
    463 
    464 	kbd_softc.k_events.ev_io = l->l_proc;
    465 	ev_init(&kbd_softc.k_events);
    466 	return (0);
    467 }
    468 
    469 int
    470 kbdclose(dev_t dev, int flags, int mode, struct lwp *l)
    471 {
    472 
    473 	/* Turn off event mode, dump the queue */
    474 	kbd_softc.k_event_mode = 0;
    475 	ev_fini(&kbd_softc.k_events);
    476 	kbd_softc.k_events.ev_io = NULL;
    477 	return (0);
    478 }
    479 
    480 int
    481 kbdread(dev_t dev, struct uio *uio, int flags)
    482 {
    483 	return ev_read (&kbd_softc.k_events, uio, flags);
    484 }
    485 
    486 int
    487 kbdioctl(dev_t dev, u_long cmd, register void *data, int flag,
    488          struct lwp *l)
    489 {
    490 	register struct kbd_softc *k = &kbd_softc;
    491 
    492 	switch (cmd) {
    493 		case KIOCTRANS:
    494 			if (*(int *)data == TR_UNTRANS_EVENT)
    495 				return 0;
    496 			break;
    497 
    498 		case KIOCGTRANS:
    499 			/* Get translation mode */
    500 			*(int *)data = TR_UNTRANS_EVENT;
    501 			return 0;
    502 
    503 		case KIOCSDIRECT:
    504 			k->k_event_mode = *(int *)data;
    505 			return 0;
    506 
    507 		case FIONBIO:	/* we will remove this someday (soon???) */
    508 			return 0;
    509 
    510 		case FIOASYNC:
    511 			k->k_events.ev_async = *(int *)data != 0;
    512 			return 0;
    513 
    514 		case FIOSETOWN:
    515 			if (-*(int *)data != k->k_events.ev_io->p_pgid
    516 			    && *(int *)data != k->k_events.ev_io->p_pid)
    517 				return EPERM;
    518 			return 0;
    519 
    520 		case TIOCSPGRP:
    521 			if (*(int *)data != k->k_events.ev_io->p_pgid)
    522 				return EPERM;
    523 			return 0;
    524 
    525 		default:
    526 			return ENOTTY;
    527 	}
    528 
    529 	/* We identified the ioctl, but we do not handle it. */
    530 	return EOPNOTSUPP;	/* misuse, but what the heck */
    531 }
    532 
    533 int
    534 kbdpoll(dev_t dev, int events, struct lwp *l)
    535 {
    536 	return ev_poll (&kbd_softc.k_events, events, l);
    537 }
    538 
    539 int
    540 kbdkqfilter(dev_t dev, struct knote *kn)
    541 {
    542 
    543 	return (ev_kqfilter(&kbd_softc.k_events, kn));
    544 }
    545 
    546 void
    547 kbdintr(int mask)
    548 {
    549 	u_char c;
    550 #ifdef KBDRESET
    551 	static int reset_warn;
    552 #endif
    553 
    554 	/*
    555 	 * now only invoked from generic CIA interrupt handler if there *is*
    556 	 * a keyboard interrupt pending
    557 	 */
    558 
    559 	c = ~ciaa.sdr;	/* keyboard data is inverted */
    560 	/* ack */
    561 	ciaa.cra |= (1 << 6);	/* serial line output */
    562 #ifdef KBDRESET
    563 	if (reset_warn && c == 0xf0) {
    564 #ifdef DEBUG
    565 		printf ("kbdintr: !!!! Reset Warning !!!!\n");
    566 #endif
    567 		bootsync();
    568 		reset_warn = 0;
    569 		DELAY(30000000);
    570 	}
    571 #endif
    572 	/* wait 200 microseconds (for bloody Cherry keyboards..) */
    573 	DELAY(200);			/* fudge delay a bit for some keyboards */
    574 	ciaa.cra &= ~(1 << 6);
    575 
    576 	/* process the character */
    577 	c = (c >> 1) | (c << 7);	/* rotate right once */
    578 
    579 #ifdef KBDRESET
    580 	if (c == 0x78) {
    581 #ifdef DEBUG
    582 		printf ("kbdintr: Reset Warning started\n");
    583 #endif
    584 		++reset_warn;
    585 		return;
    586 	}
    587 #endif
    588 	kbdstuffchar(c);
    589 }
    590 
    591 #ifdef DRACO
    592 /* maps MF-II keycodes to Amiga keycodes */
    593 
    594 const u_char drkbdtab[] = {
    595 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50,
    596 	0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51,
    597 
    598 	0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52,
    599 	0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53,
    600 
    601 	0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54,
    602 	0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55,
    603 
    604 	0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56,
    605 	0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57,
    606 	/* --- */
    607 	0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58,
    608 	0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59,
    609 
    610 	0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff,
    611 	0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff,
    612 
    613 	0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46,
    614 	0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62,
    615 
    616 	0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b,
    617 	0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff,
    618 	/* --- */
    619 	0xff, 0xff, 0xff, 0xff, 0x5d
    620 };
    621 #endif
    622 
    623 
    624 int
    625 kbdgetcn(void)
    626 {
    627 	int s;
    628 	u_char ints, mask, c, in;
    629 
    630 #ifdef DRACO
    631 	if (is_draco() && kbd_softc.k_mf2) {
    632 		do {
    633 			c = 0;
    634 			s = spltty ();
    635 			while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    636 			in = draco_ioct->io_kbddata;
    637 			draco_ioct->io_kbdrst = 0;
    638 			if (in == 0xF0) { /* release prefix */
    639 				c = 0x80;
    640 				while ((draco_ioct->io_status &
    641 				    DRSTAT_KBDRECV) == 0);
    642 				in = draco_ioct->io_kbddata;
    643 				draco_ioct->io_kbdrst = 0;
    644 			}
    645 			splx(s);
    646 #ifdef DRACORAWKEYDEBUG
    647 			printf("<%02x>", in);
    648 #endif
    649 			c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in];
    650 		} while (c == 0xff);
    651 		return (c);
    652 	}
    653 #endif
    654 	s = spltty();
    655 	for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP);
    656 	    ints |= mask) ;
    657 
    658 	in = ciaa.sdr;
    659 	c = ~in;
    660 
    661 	/* ack */
    662 	ciaa.cra |= (1 << 6);	/* serial line output */
    663 	ciaa.sdr = 0xff;	/* ack */
    664 	/* wait 200 microseconds */
    665 	DELAY(200);	/* XXXX only works as long as DELAY doesn't
    666 			 * use a timer and waits.. */
    667 	ciaa.cra &= ~(1 << 6);
    668 	ciaa.sdr = in;
    669 
    670 	splx (s);
    671 	c = (c >> 1) | (c << 7);
    672 
    673 	/* take care that no CIA-interrupts are lost */
    674 	if (ints)
    675 		dispatch_cia_ints (0, ints);
    676 
    677 	return c;
    678 }
    679 
    680 void
    681 kbdstuffchar(u_char c)
    682 {
    683 	struct firm_event *fe;
    684 	struct kbd_softc *k = &kbd_softc;
    685 	int put;
    686 
    687 #if NWSKBD>0
    688 	/*
    689 	 * If we have attached a wskbd and not in polling mode and
    690 	 * nobody has opened us directly, then send the keystroke
    691 	 * to the wskbd.
    692 	 */
    693 
    694 	if (kbd_softc.k_pollingmode == 0
    695 	    && kbd_softc.k_wskbddev != NULL
    696 	    && k->k_event_mode == 0) {
    697 		wskbd_input(kbd_softc.k_wskbddev,
    698 			    KEY_UP(c) ?
    699 			    WSCONS_EVENT_KEY_UP :
    700 			    WSCONS_EVENT_KEY_DOWN,
    701 			    KEY_CODE(c));
    702 		return;
    703 	}
    704 
    705 #endif /* NWSKBD */
    706 
    707 	/*
    708 	 * If not in event mode, deliver straight to ite to process
    709 	 * key stroke
    710 	 */
    711 
    712 	if (! k->k_event_mode) {
    713 #if NITE>0
    714 		ite_filter (c, ITEFILT_TTY);
    715 #endif
    716 		return;
    717 	}
    718 
    719 	/*
    720 	 * Keyboard is generating events. Turn this keystroke into an
    721 	 * event and put it in the queue. If the queue is full, the
    722 	 * keystroke is lost (sorry!).
    723 	 */
    724 
    725 	put = k->k_events.ev_put;
    726 	fe = &k->k_events.ev_q[put];
    727 	put = (put + 1) % EV_QSIZE;
    728 	if (put == k->k_events.ev_get) {
    729 		log(LOG_WARNING, "keyboard event queue overflow\n");
    730 			/* ??? */
    731 		return;
    732 	}
    733 	fe->id = KEY_CODE(c);
    734 	fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
    735 	firm_gettime(fe);
    736 	k->k_events.ev_put = put;
    737 	EV_WAKEUP(&k->k_events);
    738 }
    739 
    740 
    741 #ifdef DRACO
    742 void
    743 drkbdintr(void)
    744 {
    745 	u_char in;
    746 	struct kbd_softc *k = &kbd_softc;
    747 
    748 	in = draco_ioct->io_kbddata;
    749 	draco_ioct->io_kbdrst = 0;
    750 
    751 	if (in == 0xF0)
    752 		k->k_rlprfx = 0x80;
    753 	else {
    754 		kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff :
    755 		    drkbdtab[in] | k->k_rlprfx);
    756 		k->k_rlprfx = 0;
    757 	}
    758 }
    759 
    760 #endif
    761 
    762 
    763 #if NWSKBD>0
    764 /*
    765  * These are the callback functions that are passed to wscons.
    766  * They really don't do anything worth noting, just call the
    767  * other functions above.
    768  */
    769 
    770 int
    771 kbd_enable(void *c, int on)
    772 {
    773 	/* Wonder what this is supposed to do... */
    774 	return (0);
    775 }
    776 
    777 void
    778 kbd_set_leds(void *c, int leds)
    779 {
    780 }
    781 
    782 int
    783 kbd_ioctl(void *c, u_long cmd, void *data, int flag, struct lwp *l)
    784 {
    785 	switch (cmd)
    786 	{
    787 	case WSKBDIO_COMPLEXBELL:
    788 		return 0;
    789 	case WSKBDIO_SETLEDS:
    790 		return 0;
    791 	case WSKBDIO_GETLEDS:
    792 		*(int*)data = 0;
    793 		return 0;
    794 	case WSKBDIO_GTYPE:
    795 		*(u_int*)data = WSKBD_TYPE_AMIGA;
    796 		return 0;
    797 	}
    798 
    799 	/*
    800 	 * We are supposed to return EPASSTHROUGH to wscons if we didn't
    801 	 * understand.
    802 	 */
    803 	return (EPASSTHROUGH);
    804 }
    805 
    806 void
    807 kbd_getc(void *c, u_int *type, int *data)
    808 {
    809 	int key;
    810 
    811 	key = kbdgetcn();
    812 
    813 	*data = KEY_CODE(key);
    814 	*type = KEY_UP(key) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
    815 }
    816 
    817 void
    818 kbd_pollc(void *c, int on)
    819 {
    820 	kbd_softc.k_pollingmode = on;
    821 }
    822 
    823 void
    824 kbd_bell(void *c, u_int x, u_int y, u_int z)
    825 {
    826 }
    827 #endif /* WSKBD */
    828