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