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