xref: /netbsd-src/sys/arch/amiga/dev/kbd.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
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