kbd.c revision 1.44 1 /* $NetBSD: kbd.c,v 1.44 2003/01/06 13:04:59 wiz 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.44 2003/01/06 13:04:59 wiz 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 dev_type_kqfilter(kbdkqfilter);
174
175 const struct cdevsw kbd_cdevsw = {
176 kbdopen, kbdclose, kbdread, nowrite, kbdioctl,
177 nostop, notty, kbdpoll, nommap, kbdkqfilter,
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 interrupt 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 int
518 kbdkqfilter(dev, kn)
519 dev_t dev;
520 struct knote *kn;
521 {
522
523 return (ev_kqfilter(&kbd_softc.k_events, kn));
524 }
525
526 void
527 kbdintr(int mask)
528 {
529 u_char c;
530 #ifdef KBDRESET
531 static int reset_warn;
532 #endif
533
534 /*
535 * now only invoked from generic CIA interrupt handler if there *is*
536 * a keyboard interrupt pending
537 */
538
539 c = ~ciaa.sdr; /* keyboard data is inverted */
540 /* ack */
541 ciaa.cra |= (1 << 6); /* serial line output */
542 #ifdef KBDRESET
543 if (reset_warn && c == 0xf0) {
544 #ifdef DEBUG
545 printf ("kbdintr: !!!! Reset Warning !!!!\n");
546 #endif
547 bootsync();
548 reset_warn = 0;
549 DELAY(30000000);
550 }
551 #endif
552 /* wait 200 microseconds (for bloody Cherry keyboards..) */
553 DELAY(2000); /* fudge delay a bit for some keyboards */
554 ciaa.cra &= ~(1 << 6);
555
556 /* process the character */
557 c = (c >> 1) | (c << 7); /* rotate right once */
558
559 #ifdef KBDRESET
560 if (c == 0x78) {
561 #ifdef DEBUG
562 printf ("kbdintr: Reset Warning started\n");
563 #endif
564 ++reset_warn;
565 return;
566 }
567 #endif
568 kbdstuffchar(c);
569 }
570
571 #ifdef DRACO
572 /* maps MF-II keycodes to Amiga keycodes */
573
574 const u_char drkbdtab[] = {
575 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50,
576 0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51,
577
578 0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52,
579 0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53,
580
581 0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54,
582 0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55,
583
584 0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56,
585 0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57,
586 /* --- */
587 0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58,
588 0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59,
589
590 0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff,
591 0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff,
592
593 0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46,
594 0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62,
595
596 0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b,
597 0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff,
598 /* --- */
599 0xff, 0xff, 0xff, 0xff, 0x5d
600 };
601 #endif
602
603
604 int
605 kbdgetcn(void)
606 {
607 int s;
608 u_char ints, mask, c, in;
609
610 #ifdef DRACO
611 if (is_draco() && kbd_softc.k_mf2) {
612 do {
613 c = 0;
614 s = spltty ();
615 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
616 in = draco_ioct->io_kbddata;
617 draco_ioct->io_kbdrst = 0;
618 if (in == 0xF0) { /* release prefix */
619 c = 0x80;
620 while ((draco_ioct->io_status &
621 DRSTAT_KBDRECV) == 0);
622 in = draco_ioct->io_kbddata;
623 draco_ioct->io_kbdrst = 0;
624 }
625 splx(s);
626 #ifdef DRACORAWKEYDEBUG
627 printf("<%02x>", in);
628 #endif
629 c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in];
630 } while (c == 0xff);
631 return (c);
632 }
633 #endif
634 s = spltty();
635 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP);
636 ints |= mask) ;
637
638 in = ciaa.sdr;
639 c = ~in;
640
641 /* ack */
642 ciaa.cra |= (1 << 6); /* serial line output */
643 ciaa.sdr = 0xff; /* ack */
644 /* wait 200 microseconds */
645 DELAY(2000); /* XXXX only works as long as DELAY doesn't
646 * use a timer and waits.. */
647 ciaa.cra &= ~(1 << 6);
648 ciaa.sdr = in;
649
650 splx (s);
651 c = (c >> 1) | (c << 7);
652
653 /* take care that no CIA-interrupts are lost */
654 if (ints)
655 dispatch_cia_ints (0, ints);
656
657 return c;
658 }
659
660 void
661 kbdstuffchar(u_char c)
662 {
663 struct firm_event *fe;
664 struct kbd_softc *k = &kbd_softc;
665 int put;
666
667 #if NWSKBD>0
668 /*
669 * If we have attached a wskbd and not in polling mode and
670 * nobody has opened us directly, then send the keystroke
671 * to the wskbd.
672 */
673
674 if (kbd_softc.k_pollingmode == 0
675 && kbd_softc.k_wskbddev != NULL
676 && k->k_event_mode == 0) {
677 wskbd_input(kbd_softc.k_wskbddev,
678 KEY_UP(c) ?
679 WSCONS_EVENT_KEY_UP :
680 WSCONS_EVENT_KEY_DOWN,
681 KEY_CODE(c));
682 return;
683 }
684
685 #endif /* NWSKBD */
686
687 /*
688 * If not in event mode, deliver straight to ite to process
689 * key stroke
690 */
691
692 if (! k->k_event_mode) {
693 #if NITE>0
694 ite_filter (c, ITEFILT_TTY);
695 #endif
696 return;
697 }
698
699 /*
700 * Keyboard is generating events. Turn this keystroke into an
701 * event and put it in the queue. If the queue is full, the
702 * keystroke is lost (sorry!).
703 */
704
705 put = k->k_events.ev_put;
706 fe = &k->k_events.ev_q[put];
707 put = (put + 1) % EV_QSIZE;
708 if (put == k->k_events.ev_get) {
709 log(LOG_WARNING, "keyboard event queue overflow\n");
710 /* ??? */
711 return;
712 }
713 fe->id = KEY_CODE(c);
714 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
715 fe->time = time;
716 k->k_events.ev_put = put;
717 EV_WAKEUP(&k->k_events);
718 }
719
720
721 #ifdef DRACO
722 void
723 drkbdintr(void)
724 {
725 u_char in;
726 struct kbd_softc *k = &kbd_softc;
727
728 in = draco_ioct->io_kbddata;
729 draco_ioct->io_kbdrst = 0;
730
731 if (in == 0xF0)
732 k->k_rlprfx = 0x80;
733 else {
734 kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff :
735 drkbdtab[in] | k->k_rlprfx);
736 k->k_rlprfx = 0;
737 }
738 }
739
740 #endif
741
742
743 #if NWSKBD>0
744 /*
745 * These are the callback functions that are passed to wscons.
746 * They really don't do anything worth noting, just call the
747 * other functions above.
748 */
749
750 int
751 kbd_enable(void *c, int on)
752 {
753 /* Wonder what this is supposed to do... */
754 return (0);
755 }
756
757 void
758 kbd_set_leds(void *c, int leds)
759 {
760 }
761
762 int
763 kbd_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc *p)
764 {
765 switch (cmd)
766 {
767 case WSKBDIO_COMPLEXBELL:
768 return 0;
769 case WSKBDIO_SETLEDS:
770 return 0;
771 case WSKBDIO_GETLEDS:
772 *(int*)data = 0;
773 return 0;
774 case WSKBDIO_GTYPE:
775 *(u_int*)data = WSKBD_TYPE_AMIGA;
776 return 0;
777 }
778
779 /*
780 * We are supposed to return EPASSTHROUGH to wscons if we didn't
781 * understand.
782 */
783 return (EPASSTHROUGH);
784 }
785
786 void
787 kbd_getc(void *c, u_int *type, int *data)
788 {
789 int key;
790
791 key = kbdgetcn();
792
793 *data = KEY_CODE(key);
794 *type = KEY_UP(key) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
795 }
796
797 void
798 kbd_pollc(void *c, int on)
799 {
800 kbd_softc.k_pollingmode = on;
801 }
802
803 void
804 kbd_bell(void *c, u_int x, u_int y, u_int z)
805 {
806 }
807 #endif /* WSKBD */
808