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