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