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