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