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