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