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