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