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