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