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