Home | History | Annotate | Line # | Download | only in dev
kbd.c revision 1.59.2.1
      1 /*	$NetBSD: kbd.c,v 1.59.2.1 2021/06/17 04:46:17 thorpej 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.59.2.1 2021/06/17 04:46:17 thorpej 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? Otherwise send events. */
    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 		    CFARG_IATTR, "wskbddev",
    224 		    CFARG_EOL);
    225 
    226 		kbd_softc.k_pollingmode = 0;
    227 	}
    228 	kbdenable();
    229 #endif /* WSKBD */
    230 }
    231 
    232 /*
    233  * This is called when somebody wants to use kbd as the console keyboard.
    234  */
    235 void
    236 kbd_cnattach(void)
    237 {
    238 #if NWSKBD>0
    239 	wskbd_cnattach(&kbd_consops, NULL, &kbd_mapdata);
    240 	kbd_softc.k_console = 1;
    241 #endif
    242 }
    243 
    244 /* definitions for amiga keyboard encoding. */
    245 #define KEY_CODE(c)  ((c) & 0x7f)
    246 #define KEY_UP(c)    ((c) & 0x80)
    247 
    248 #define DATLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT)
    249 #define DATHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT)
    250 
    251 #define CLKLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT)
    252 #define CLKHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT)
    253 
    254 void
    255 kbdenable(void)
    256 {
    257 	static int kbd_inited = 0;
    258 
    259 	int s;
    260 
    261 #ifdef DRACO
    262 	int id;
    263 #endif
    264 	/*
    265 	 * collides with external ints from SCSI, watch out for this when
    266 	 * enabling/disabling interrupts there !!
    267 	 */
    268 	s = splhigh();	/* don't lower; might be called from early ddb */
    269 	if (kbd_inited) {
    270 		splx(s);
    271 		return;
    272 	}
    273 	kbd_inited = 1;
    274 #ifdef DRACO
    275 	if (is_draco()) {
    276 
    277 		CLKLO;
    278 		delay(5000);
    279 		draco_ioct->io_kbdrst = 0;
    280 
    281 		if (drkbdputc(0xf2))
    282 			goto LnoMFII;
    283 
    284 		id = drkbdgetc() << 8;
    285 		id |= drkbdgetc();
    286 
    287 		if (id != 0xab83)
    288 			goto LnoMFII;
    289 
    290 		if (drkbdputc2(0xf0, 3))	/* mode 3 */
    291 			goto LnoMFII;
    292 
    293 		if (drkbdputc(0xf8))		/* make/break, no typematic */
    294 			goto LnoMFII;
    295 
    296 		if (drkbdputc(0xf4))		/* enable */
    297 			goto LnoMFII;
    298 		kbd_softc.k_mf2 = 1;
    299 		single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDINTENA);
    300 
    301 		ciaa.icr = CIA_ICR_SP;  /* CIA SP interrupt disable */
    302 		ciaa.cra &= ~(1<<6);	/* serial line == input */
    303 		splx(s);
    304 		return;
    305 
    306 	LnoMFII:
    307 		kbd_softc.k_mf2 = 0;
    308 		single_inst_bset_b(*draco_intena, DRIRQ_INT2);
    309 		ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;
    310 					/* SP interrupt enable */
    311 		ciaa.cra &= ~(1<<6);	/* serial line == input */
    312 		splx(s);
    313 		return;
    314 
    315 	} else {
    316 #endif
    317 	custom.intena = INTF_SETCLR | INTF_PORTS;
    318 	ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;  /* SP interrupt enable */
    319 	ciaa.cra &= ~(1<<6);		/* serial line == input */
    320 #ifdef DRACO
    321 	}
    322 #endif
    323 	kbd_softc.k_event_mode = 0;
    324 	kbd_softc.k_events.ev_io = 0;
    325 	splx(s);
    326 }
    327 
    328 #ifdef DRACO
    329 /*
    330  * call this with kbd interrupt blocked
    331  */
    332 
    333 int
    334 drkbdgetc(void)
    335 {
    336 	u_int8_t in;
    337 
    338 	while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    339 	in = draco_ioct->io_kbddata;
    340 	draco_ioct->io_kbdrst = 0;
    341 
    342 	return in;
    343 }
    344 
    345 #define WAIT0 if (drkbdwaitfor(0)) goto Ltimeout
    346 #define WAIT1 if (drkbdwaitfor(DRSTAT_KBDCLKIN)) goto Ltimeout
    347 
    348 int
    349 drkbdwaitfor(int bit)
    350 {
    351 	int i;
    352 
    353 
    354 
    355 	i = 60000;	/* about 50 ms max */
    356 
    357 	do {
    358 		if ((draco_ioct->io_status & DRSTAT_KBDCLKIN) == bit)
    359 			return 0;
    360 
    361 	} while (--i >= 0);
    362 
    363 	return 1;
    364 }
    365 
    366 /*
    367  * Output a raw byte to the keyboard (+ parity and stop bit).
    368  * return 0 on success, 1 on timeout.
    369  */
    370 int
    371 drkbdrputc(u_int8_t c)
    372 {
    373 	u_int8_t parity;
    374 	int bitcnt;
    375 
    376 	DATLO; CLKHI; WAIT1;
    377 	parity = 0;
    378 
    379 	for (bitcnt=7; bitcnt >= 0; bitcnt--) {
    380 		WAIT0;
    381 		if (c & 1) {
    382 			DATHI;
    383 		} else {
    384 			++parity;
    385 			DATLO;
    386 		}
    387 		c >>= 1;
    388 		WAIT1;
    389 	}
    390 	WAIT0;
    391 	/* parity bit */
    392 	if (parity & 1) {
    393 		DATLO;
    394 	} else {
    395 		DATHI;
    396 	}
    397 	WAIT1;
    398 	/* stop bit */
    399 	WAIT0; DATHI; WAIT1;
    400 
    401 	WAIT0; /* XXX should check the ack bit here... */
    402 	WAIT1;
    403 	draco_ioct->io_kbdrst = 0;
    404 	return 0;
    405 
    406 Ltimeout:
    407 	DATHI;
    408 	draco_ioct->io_kbdrst = 0;
    409 	return 1;
    410 }
    411 
    412 /*
    413  * Output one cooked byte to the keyboard, with wait for ACK or RESEND,
    414  * and retry if necessary. 0 == success, 1 == timeout
    415  */
    416 int
    417 drkbdputc(u_int8_t c)
    418 {
    419 	int rc;
    420 
    421 	do {
    422 		if (drkbdrputc(c))
    423 			return(-1);
    424 
    425 		rc = drkbdgetc();
    426 	} while (rc == 0xfe);
    427 	return (!(rc == 0xfa));
    428 }
    429 
    430 /*
    431  * same for twobyte sequence
    432  */
    433 
    434 int
    435 drkbdputc2(u_int8_t c1, u_int8_t c2)
    436 {
    437 	int rc;
    438 
    439 	do {
    440 		do {
    441 			if (drkbdrputc(c1))
    442 				return(-1);
    443 
    444 			rc = drkbdgetc();
    445 		} while (rc == 0xfe);
    446 		if (rc != 0xfa)
    447 			return (-1);
    448 
    449 		if (drkbdrputc(c2))
    450 			return(-1);
    451 
    452 		rc = drkbdgetc();
    453 	} while (rc == 0xfe);
    454 	return (!(rc == 0xfa));
    455 }
    456 #endif
    457 
    458 int
    459 kbdopen(dev_t dev, int flags, int mode, struct lwp *l)
    460 {
    461 
    462 	kbdenable();
    463 	if (kbd_softc.k_events.ev_io)
    464 		return EBUSY;
    465 
    466 	kbd_softc.k_events.ev_io = l->l_proc;
    467 	ev_init(&kbd_softc.k_events);
    468 	return (0);
    469 }
    470 
    471 int
    472 kbdclose(dev_t dev, int flags, int mode, struct lwp *l)
    473 {
    474 
    475 	/* Turn off event mode, dump the queue */
    476 	kbd_softc.k_event_mode = 0;
    477 	ev_fini(&kbd_softc.k_events);
    478 	kbd_softc.k_events.ev_io = NULL;
    479 	return (0);
    480 }
    481 
    482 int
    483 kbdread(dev_t dev, struct uio *uio, int flags)
    484 {
    485 	return ev_read (&kbd_softc.k_events, uio, flags);
    486 }
    487 
    488 int
    489 kbdioctl(dev_t dev, u_long cmd, register void *data, int flag,
    490          struct lwp *l)
    491 {
    492 	register struct kbd_softc *k = &kbd_softc;
    493 
    494 	switch (cmd) {
    495 		case KIOCTRANS:
    496 			if (*(int *)data == TR_UNTRANS_EVENT)
    497 				return 0;
    498 			break;
    499 
    500 		case KIOCGTRANS:
    501 			/* Get translation mode */
    502 			*(int *)data = TR_UNTRANS_EVENT;
    503 			return 0;
    504 
    505 		case KIOCSDIRECT:
    506 			k->k_event_mode = *(int *)data;
    507 			return 0;
    508 
    509 		case FIONBIO:	/* we will remove this someday (soon???) */
    510 			return 0;
    511 
    512 		case FIOASYNC:
    513 			k->k_events.ev_async = *(int *)data != 0;
    514 			return 0;
    515 
    516 		case FIOSETOWN:
    517 			if (-*(int *)data != k->k_events.ev_io->p_pgid
    518 			    && *(int *)data != k->k_events.ev_io->p_pid)
    519 				return EPERM;
    520 			return 0;
    521 
    522 		case TIOCSPGRP:
    523 			if (*(int *)data != k->k_events.ev_io->p_pgid)
    524 				return EPERM;
    525 			return 0;
    526 
    527 		default:
    528 			return ENOTTY;
    529 	}
    530 
    531 	/* We identified the ioctl, but we do not handle it. */
    532 	return EOPNOTSUPP;	/* misuse, but what the heck */
    533 }
    534 
    535 int
    536 kbdpoll(dev_t dev, int events, struct lwp *l)
    537 {
    538 	return ev_poll (&kbd_softc.k_events, events, l);
    539 }
    540 
    541 int
    542 kbdkqfilter(dev_t dev, struct knote *kn)
    543 {
    544 
    545 	return (ev_kqfilter(&kbd_softc.k_events, kn));
    546 }
    547 
    548 void
    549 kbdintr(int mask)
    550 {
    551 	u_char c;
    552 #ifdef KBDRESET
    553 	static int reset_warn;
    554 #endif
    555 
    556 	/*
    557 	 * now only invoked from generic CIA interrupt handler if there *is*
    558 	 * a keyboard interrupt pending
    559 	 */
    560 
    561 	c = ~ciaa.sdr;	/* keyboard data is inverted */
    562 	/* ack */
    563 	ciaa.cra |= (1 << 6);	/* serial line output */
    564 #ifdef KBDRESET
    565 	if (reset_warn && c == 0xf0) {
    566 #ifdef DEBUG
    567 		printf ("kbdintr: !!!! Reset Warning !!!!\n");
    568 #endif
    569 		bootsync();
    570 		reset_warn = 0;
    571 		DELAY(30000000);
    572 	}
    573 #endif
    574 	/* wait 200 microseconds (for bloody Cherry keyboards..) */
    575 	DELAY(200);			/* fudge delay a bit for some keyboards */
    576 	ciaa.cra &= ~(1 << 6);
    577 
    578 	/* process the character */
    579 	c = (c >> 1) | (c << 7);	/* rotate right once */
    580 
    581 #ifdef KBDRESET
    582 	if (c == 0x78) {
    583 #ifdef DEBUG
    584 		printf ("kbdintr: Reset Warning started\n");
    585 #endif
    586 		++reset_warn;
    587 		return;
    588 	}
    589 #endif
    590 	kbdstuffchar(c);
    591 }
    592 
    593 #ifdef DRACO
    594 /* maps MF-II keycodes to Amiga keycodes */
    595 
    596 const u_char drkbdtab[] = {
    597 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50,
    598 	0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51,
    599 
    600 	0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52,
    601 	0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53,
    602 
    603 	0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54,
    604 	0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55,
    605 
    606 	0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56,
    607 	0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57,
    608 	/* --- */
    609 	0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58,
    610 	0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59,
    611 
    612 	0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff,
    613 	0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff,
    614 
    615 	0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46,
    616 	0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62,
    617 
    618 	0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b,
    619 	0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff,
    620 	/* --- */
    621 	0xff, 0xff, 0xff, 0xff, 0x5d
    622 };
    623 #endif
    624 
    625 
    626 int
    627 kbdgetcn(void)
    628 {
    629 	int s;
    630 	u_char ints, mask, c, in;
    631 
    632 #ifdef DRACO
    633 	if (is_draco() && kbd_softc.k_mf2) {
    634 		do {
    635 			c = 0;
    636 			s = spltty ();
    637 			while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
    638 			in = draco_ioct->io_kbddata;
    639 			draco_ioct->io_kbdrst = 0;
    640 			if (in == 0xF0) { /* release prefix */
    641 				c = 0x80;
    642 				while ((draco_ioct->io_status &
    643 				    DRSTAT_KBDRECV) == 0);
    644 				in = draco_ioct->io_kbddata;
    645 				draco_ioct->io_kbdrst = 0;
    646 			}
    647 			splx(s);
    648 #ifdef DRACORAWKEYDEBUG
    649 			printf("<%02x>", in);
    650 #endif
    651 			c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in];
    652 		} while (c == 0xff);
    653 		return (c);
    654 	}
    655 #endif
    656 	s = spltty();
    657 	for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP);
    658 	    ints |= mask) ;
    659 
    660 	in = ciaa.sdr;
    661 	c = ~in;
    662 
    663 	/* ack */
    664 	ciaa.cra |= (1 << 6);	/* serial line output */
    665 	ciaa.sdr = 0xff;	/* ack */
    666 	/* wait 200 microseconds */
    667 	DELAY(200);	/* XXXX only works as long as DELAY doesn't
    668 			 * use a timer and waits.. */
    669 	ciaa.cra &= ~(1 << 6);
    670 	ciaa.sdr = in;
    671 
    672 	splx (s);
    673 	c = (c >> 1) | (c << 7);
    674 
    675 	/* take care that no CIA-interrupts are lost */
    676 	if (ints)
    677 		dispatch_cia_ints (0, ints);
    678 
    679 	return c;
    680 }
    681 
    682 void
    683 kbdstuffchar(u_char c)
    684 {
    685 	struct firm_event *fe;
    686 	struct kbd_softc *k = &kbd_softc;
    687 	int put;
    688 
    689 #if NWSKBD>0
    690 	/*
    691 	 * If we have attached a wskbd and not in polling mode and
    692 	 * nobody has opened us directly, then send the keystroke
    693 	 * to the wskbd.
    694 	 */
    695 
    696 	if (kbd_softc.k_pollingmode == 0
    697 	    && kbd_softc.k_wskbddev != NULL
    698 	    && k->k_event_mode == 0) {
    699 		wskbd_input(kbd_softc.k_wskbddev,
    700 			    KEY_UP(c) ?
    701 			    WSCONS_EVENT_KEY_UP :
    702 			    WSCONS_EVENT_KEY_DOWN,
    703 			    KEY_CODE(c));
    704 		return;
    705 	}
    706 
    707 #endif /* NWSKBD */
    708 
    709 	/*
    710 	 * If not in event mode, deliver straight to ite to process
    711 	 * key stroke
    712 	 */
    713 
    714 	if (! k->k_event_mode) {
    715 #if NITE>0
    716 		ite_filter (c, ITEFILT_TTY);
    717 #endif
    718 		return;
    719 	}
    720 
    721 	/*
    722 	 * Keyboard is generating events. Turn this keystroke into an
    723 	 * event and put it in the queue. If the queue is full, the
    724 	 * keystroke is lost (sorry!).
    725 	 */
    726 
    727 	put = k->k_events.ev_put;
    728 	fe = &k->k_events.ev_q[put];
    729 	put = (put + 1) % EV_QSIZE;
    730 	if (put == k->k_events.ev_get) {
    731 		log(LOG_WARNING, "keyboard event queue overflow\n");
    732 			/* ??? */
    733 		return;
    734 	}
    735 	fe->id = KEY_CODE(c);
    736 	fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
    737 	firm_gettime(fe);
    738 	k->k_events.ev_put = put;
    739 	EV_WAKEUP(&k->k_events);
    740 }
    741 
    742 
    743 #ifdef DRACO
    744 void
    745 drkbdintr(void)
    746 {
    747 	u_char in;
    748 	struct kbd_softc *k = &kbd_softc;
    749 
    750 	in = draco_ioct->io_kbddata;
    751 	draco_ioct->io_kbdrst = 0;
    752 
    753 	if (in == 0xF0)
    754 		k->k_rlprfx = 0x80;
    755 	else {
    756 		kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff :
    757 		    drkbdtab[in] | k->k_rlprfx);
    758 		k->k_rlprfx = 0;
    759 	}
    760 }
    761 
    762 #endif
    763 
    764 
    765 #if NWSKBD>0
    766 /*
    767  * These are the callback functions that are passed to wscons.
    768  * They really don't do anything worth noting, just call the
    769  * other functions above.
    770  */
    771 
    772 int
    773 kbd_enable(void *c, int on)
    774 {
    775 	/* Wonder what this is supposed to do... */
    776 	return (0);
    777 }
    778 
    779 void
    780 kbd_set_leds(void *c, int leds)
    781 {
    782 }
    783 
    784 int
    785 kbd_ioctl(void *c, u_long cmd, void *data, int flag, struct lwp *l)
    786 {
    787 	switch (cmd)
    788 	{
    789 	case WSKBDIO_COMPLEXBELL:
    790 		return 0;
    791 	case WSKBDIO_SETLEDS:
    792 		return 0;
    793 	case WSKBDIO_GETLEDS:
    794 		*(int*)data = 0;
    795 		return 0;
    796 	case WSKBDIO_GTYPE:
    797 		*(u_int*)data = WSKBD_TYPE_AMIGA;
    798 		return 0;
    799 	}
    800 
    801 	/*
    802 	 * We are supposed to return EPASSTHROUGH to wscons if we didn't
    803 	 * understand.
    804 	 */
    805 	return (EPASSTHROUGH);
    806 }
    807 
    808 void
    809 kbd_getc(void *c, u_int *type, int *data)
    810 {
    811 	int key;
    812 
    813 	key = kbdgetcn();
    814 
    815 	*data = KEY_CODE(key);
    816 	*type = KEY_UP(key) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
    817 }
    818 
    819 void
    820 kbd_pollc(void *c, int on)
    821 {
    822 	kbd_softc.k_pollingmode = on;
    823 }
    824 
    825 void
    826 kbd_bell(void *c, u_int x, u_int y, u_int z)
    827 {
    828 }
    829 #endif /* WSKBD */
    830