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