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