kbd.c revision 1.35.8.1 1 /* $NetBSD: kbd.c,v 1.35.8.1 2002/02/28 04:06:51 nathanw 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.35.8.1 2002/02/28 04:06:51 nathanw 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