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