kbd.c revision 1.28.2.3 1 /* $NetBSD: kbd.c,v 1.28.2.3 2002/06/23 17:48:53 jdolecek Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by the University of
27 * California, Berkeley and its contributors.
28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * SUCH DAMAGE.
43 *
44 * @(#)kbd.c 8.2 (Berkeley) 10/30/93
45 */
46
47 /*
48 * Keyboard driver (/dev/kbd -- note that we do not have minor numbers
49 * [yet?]). Translates incoming bytes to ASCII or to `firm_events' and
50 * passes them up to the appropriate reader.
51 */
52
53 #include <sys/cdefs.h>
54 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.28.2.3 2002/06/23 17:48:53 jdolecek Exp $");
55
56 #include "opt_ddb.h"
57
58 /*
59 * This is the "slave" driver that will be attached to
60 * the "zsc" driver for a Sun keyboard.
61 */
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/conf.h>
66 #include <sys/device.h>
67 #include <sys/ioctl.h>
68 #include <sys/kernel.h>
69 #include <sys/proc.h>
70 #include <sys/signal.h>
71 #include <sys/signalvar.h>
72 #include <sys/time.h>
73 #include <sys/syslog.h>
74 #include <sys/select.h>
75 #include <sys/poll.h>
76 #include <sys/file.h>
77
78 #include <dev/ic/z8530reg.h>
79 #include <machine/z8530var.h>
80 #include <machine/vuid_event.h>
81 #include <machine/kbd.h>
82 #include <machine/kbio.h>
83 #include <dev/sun/event_var.h>
84 #include <dev/sun/kbd_xlate.h>
85 #include <dev/sun/kbdvar.h>
86
87 #include "locators.h"
88
89 /*
90 * Ideas:
91 * /dev/kbd is not a tty (plain device)
92 */
93
94 /* Prototypes */
95 static void kbd_new_layout __P((struct kbd_softc *));
96 static void kbd_repeat __P((void *));
97 static void kbd_set_leds __P((struct kbd_softc *, int));
98 static void kbd_update_leds __P((struct kbd_softc *));
99 static void kbd_was_reset __P((struct kbd_softc *));
100 static int kbd_drain_tx __P((struct kbd_softc *));
101 static int kbd_iopen __P((struct kbd_softc *));
102 static int kbd_iclose __P((struct kbd_softc *));
103
104 cdev_decl(kbd); /* open, close, read, write, ioctl, stop, ... */
105
106 extern struct cfdriver kbd_cd;
107
108 /****************************************************************
109 * Entry points for /dev/kbd
110 * (open,close,read,write,...)
111 ****************************************************************/
112
113 /*
114 * Open:
115 * Check exclusion, open actual device (_iopen),
116 * setup event channel, clear ASCII repeat stuff.
117 */
118 int
119 kbdopen(dev, flags, mode, p)
120 dev_t dev;
121 int flags, mode;
122 struct proc *p;
123 {
124 struct kbd_softc *k;
125 int error, unit;
126
127 unit = minor(dev);
128 if (unit >= kbd_cd.cd_ndevs)
129 return (ENXIO);
130 k = kbd_cd.cd_devs[unit];
131 if (k == NULL)
132 return (ENXIO);
133
134 /* Exclusive open required for /dev/kbd */
135 if (k->k_events.ev_io)
136 return (EBUSY);
137 k->k_events.ev_io = p;
138
139 if ((error = kbd_iopen(k)) != 0) {
140 k->k_events.ev_io = NULL;
141 return (error);
142 }
143 ev_init(&k->k_events);
144 k->k_evmode = 0; /* XXX: OK? */
145
146 if (k->k_repeating) {
147 k->k_repeating = 0;
148 callout_stop(&k->k_repeat_ch);
149 }
150
151 return (0);
152 }
153
154 /*
155 * Close:
156 * Turn off event mode, dump the queue, and close the keyboard
157 * unless it is supplying console input.
158 */
159 int
160 kbdclose(dev, flags, mode, p)
161 dev_t dev;
162 int flags, mode;
163 struct proc *p;
164 {
165 struct kbd_softc *k;
166
167 k = kbd_cd.cd_devs[minor(dev)];
168 k->k_evmode = 0;
169 ev_fini(&k->k_events);
170 k->k_events.ev_io = NULL;
171 return (0);
172 }
173
174 int
175 kbdread(dev, uio, flags)
176 dev_t dev;
177 struct uio *uio;
178 int flags;
179 {
180 struct kbd_softc *k;
181
182 k = kbd_cd.cd_devs[minor(dev)];
183 return (ev_read(&k->k_events, uio, flags));
184 }
185
186 /* this routine should not exist, but is convenient to write here for now */
187 int
188 kbdwrite(dev, uio, flags)
189 dev_t dev;
190 struct uio *uio;
191 int flags;
192 {
193
194 return (EOPNOTSUPP);
195 }
196
197 int
198 kbdpoll(dev, events, p)
199 dev_t dev;
200 int events;
201 struct proc *p;
202 {
203 struct kbd_softc *k;
204
205 k = kbd_cd.cd_devs[minor(dev)];
206 return (ev_poll(&k->k_events, events, p));
207 }
208
209 int
210 kbdkqfilter(dev, kn)
211 dev_t dev;
212 struct knote *kn;
213 {
214 struct kbd_softc *k;
215
216 k = kbd_cd.cd_devs[minor(dev)];
217 return (ev_kqfilter(&k->k_events, kn));
218 }
219
220 static int kbd_iockeymap __P((struct kbd_state *ks,
221 u_long cmd, struct kiockeymap *kio));
222
223 static int kbd_iocsled(struct kbd_softc *k, char *data);
224
225 #ifdef KIOCGETKEY
226 static int kbd_oldkeymap __P((struct kbd_state *ks,
227 u_long cmd, struct okiockey *okio));
228 #endif
229
230 int
231 kbdioctl(dev, cmd, data, flag, p)
232 dev_t dev;
233 u_long cmd;
234 caddr_t data;
235 int flag;
236 struct proc *p;
237 {
238 struct kbd_softc *k;
239 struct kbd_state *ks;
240 int error = 0;
241
242 k = kbd_cd.cd_devs[minor(dev)];
243 ks = &k->k_state;
244
245 switch (cmd) {
246
247 case KIOCTRANS: /* Set translation mode */
248 /* We only support "raw" mode on /dev/kbd */
249 if (*(int *)data != TR_UNTRANS_EVENT)
250 error = EINVAL;
251 break;
252
253 case KIOCGTRANS: /* Get translation mode */
254 /* We only support "raw" mode on /dev/kbd */
255 *(int *)data = TR_UNTRANS_EVENT;
256 break;
257
258 #ifdef KIOCGETKEY
259 case KIOCGETKEY: /* Get keymap entry (old format) */
260 error = kbd_oldkeymap(ks, cmd, (struct okiockey *)data);
261 break;
262 #endif /* KIOCGETKEY */
263
264 case KIOCSKEY: /* Set keymap entry */
265 /* fallthrough */
266 case KIOCGKEY: /* Get keymap entry */
267 error = kbd_iockeymap(ks, cmd, (struct kiockeymap *)data);
268 break;
269
270 case KIOCCMD: /* Send a command to the keyboard */
271 error = kbd_docmd(*(int *)data, 1);
272 break;
273
274 case KIOCTYPE: /* Get keyboard type */
275 *(int *)data = ks->kbd_id;
276 break;
277
278 case KIOCSDIRECT: /* where to send input */
279 k->k_evmode = *(int *)data;
280 break;
281
282 case KIOCLAYOUT: /* Get keyboard layout */
283 *(int *)data = ks->kbd_layout;
284 break;
285
286 case KIOCSLED:
287 error = kbd_iocsled(k, (char *)data);
288 break;
289
290 case KIOCGLED:
291 *(char *)data = ks->kbd_leds;
292 break;
293
294 case FIONBIO: /* we will remove this someday (soon???) */
295 break;
296
297 case FIOASYNC:
298 k->k_events.ev_async = *(int *)data != 0;
299 break;
300
301 case TIOCSPGRP:
302 if (*(int *)data != k->k_events.ev_io->p_pgid)
303 error = EPERM;
304 break;
305
306 default:
307 error = ENOTTY;
308 break;
309 }
310
311 return (error);
312 }
313
314 /****************************************************************
315 * ioctl helpers
316 ****************************************************************/
317
318 /*
319 * Get/Set keymap entry
320 */
321 static int
322 kbd_iockeymap(ks, cmd, kio)
323 struct kbd_state *ks;
324 u_long cmd;
325 struct kiockeymap *kio;
326 {
327 u_short *km;
328 u_int station;
329
330 switch (kio->kio_tablemask) {
331 case KIOC_NOMASK:
332 km = ks->kbd_k.k_normal;
333 break;
334 case KIOC_SHIFTMASK:
335 km = ks->kbd_k.k_shifted;
336 break;
337 case KIOC_CTRLMASK:
338 km = ks->kbd_k.k_control;
339 break;
340 case KIOC_UPMASK:
341 km = ks->kbd_k.k_release;
342 break;
343 default:
344 /* Silently ignore unsupported masks */
345 return (0);
346 }
347
348 /* Range-check the table position. */
349 station = kio->kio_station;
350 if (station >= KEYMAP_SIZE)
351 return (EINVAL);
352
353 switch (cmd) {
354
355 case KIOCGKEY: /* Get keymap entry */
356 kio->kio_entry = km[station];
357 break;
358
359 case KIOCSKEY: /* Set keymap entry */
360 km[station] = kio->kio_entry;
361 break;
362
363 default:
364 return(ENOTTY);
365 }
366 return (0);
367 }
368
369 #ifdef KIOCGETKEY
370 /*
371 * Get/Set keymap entry,
372 * old format (compatibility)
373 */
374 int
375 kbd_oldkeymap(ks, cmd, kio)
376 struct kbd_state *ks;
377 u_long cmd;
378 struct okiockey *kio;
379 {
380 int error = 0;
381
382 switch (cmd) {
383
384 case KIOCGETKEY:
385 if (kio->kio_station == 118) {
386 /*
387 * This is X11 asking if a type 3 keyboard is
388 * really a type 3 keyboard. Say yes, it is,
389 * by reporting key station 118 as a "hole".
390 * Note old (SunOS 3.5) definition of HOLE!
391 */
392 kio->kio_entry = 0xA2;
393 break;
394 }
395 /* fall through */
396
397 default:
398 error = ENOTTY;
399 break;
400 }
401
402 return (error);
403 }
404 #endif /* KIOCGETKEY */
405
406
407 /*
408 * keyboard command ioctl
409 * ``unimplemented commands are ignored'' (blech)
410 * This is also export to the fb driver.
411 */
412 int
413 kbd_docmd(cmd, isuser)
414 int cmd;
415 int isuser;
416 {
417 struct kbd_softc *k;
418 struct kbd_state *ks;
419 int error, s;
420
421 error = 0;
422 k = kbd_cd.cd_devs[0];
423 ks = &k->k_state;
424
425 switch (cmd) {
426
427 case KBD_CMD_BELL:
428 case KBD_CMD_NOBELL:
429 /* Supported by type 2, 3, and 4 keyboards */
430 break;
431
432 case KBD_CMD_CLICK:
433 case KBD_CMD_NOCLICK:
434 /* Unsupported by type 2 keyboards */
435 if (ks->kbd_id <= KB_SUN2)
436 return (0);
437 ks->kbd_click = (cmd == KBD_CMD_CLICK);
438 break;
439
440 default:
441 return (0);
442 }
443
444 s = spltty();
445
446 if (isuser)
447 error = kbd_drain_tx(k);
448
449 if (error == 0) {
450 kbd_output(k, cmd);
451 kbd_start_tx(k);
452 }
453
454 splx(s);
455
456 return (error);
457 }
458
459 /*
460 * Set LEDs ioctl.
461 */
462 static int
463 kbd_iocsled(k, data)
464 struct kbd_softc *k;
465 char *data;
466 {
467 int leds, error, s;
468
469 leds = *data;
470
471 s = spltty();
472 error = kbd_drain_tx(k);
473 if (error == 0) {
474 kbd_set_leds(k, leds);
475 }
476 splx(s);
477
478 return (error);
479 }
480
481
482 /****************************************************************
483 * middle layers:
484 * - keysym to ASCII sequence
485 * - raw key codes to keysym
486 ****************************************************************/
487
488 static void kbd_input_string __P((struct kbd_softc *, char *));
489 static void kbd_input_funckey __P((struct kbd_softc *, int));
490 static int kbd_input_keysym __P((struct kbd_softc *, int));
491
492 /*
493 * Initialization done by either kdcninit or kbd_iopen
494 */
495 void
496 kbd_xlate_init(ks)
497 struct kbd_state *ks;
498 {
499 struct keyboard *ktbls;
500 int id;
501
502 id = ks->kbd_id;
503 if (id < KBD_MIN_TYPE)
504 id = KBD_MIN_TYPE;
505 if (id > kbd_max_type)
506 id = kbd_max_type;
507 ktbls = keyboards[id];
508
509 ks->kbd_k = *ktbls; /* struct assignment */
510 ks->kbd_modbits = 0;
511 }
512
513 /*
514 * Turn keyboard up/down codes into a KEYSYM.
515 * Note that the "kd" driver uses this too!
516 */
517 int
518 kbd_code_to_keysym(ks, c)
519 struct kbd_state *ks;
520 int c;
521 {
522 u_short *km;
523 int keysym;
524
525 /*
526 * Get keymap pointer. One of these:
527 * release, control, shifted, normal, ...
528 */
529 if (KEY_UP(c))
530 km = ks->kbd_k.k_release;
531 else if (ks->kbd_modbits & KBMOD_CTRL_MASK)
532 km = ks->kbd_k.k_control;
533 else if (ks->kbd_modbits & KBMOD_SHIFT_MASK)
534 km = ks->kbd_k.k_shifted;
535 else
536 km = ks->kbd_k.k_normal;
537
538 if (km == NULL) {
539 /*
540 * Do not know how to translate yet.
541 * We will find out when a RESET comes along.
542 */
543 return (KEYSYM_NOP);
544 }
545 keysym = km[KEY_CODE(c)];
546
547 /*
548 * Post-processing for Caps-lock
549 */
550 if ((ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) &&
551 (KEYSYM_CLASS(keysym) == KEYSYM_ASCII) )
552 {
553 if (('a' <= keysym) && (keysym <= 'z'))
554 keysym -= ('a' - 'A');
555 }
556
557 /*
558 * Post-processing for Num-lock. All "function"
559 * keysyms get indirected through another table.
560 * (XXX: Only if numlock on. Want off also!)
561 */
562 if ((ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) &&
563 (KEYSYM_CLASS(keysym) == KEYSYM_FUNC) )
564 {
565 keysym = kbd_numlock_map[keysym & 0x3F];
566 }
567
568 return (keysym);
569 }
570
571 void
572 kbd_input_string(k, str)
573 struct kbd_softc *k;
574 char *str;
575 {
576
577 while (*str) {
578 (*k->k_cc->cc_upstream)(*str);
579 str++;
580 }
581 }
582
583 void
584 kbd_input_funckey(k, keysym)
585 struct kbd_softc *k;
586 int keysym;
587 {
588 int n;
589 char str[12];
590
591 /*
592 * Format the F-key sequence and send as a string.
593 * XXX: Ugly compatibility mappings.
594 */
595 n = 0xC0 + (keysym & 0x3F);
596 sprintf(str, "\033[%dz", n);
597 kbd_input_string(k, str);
598 }
599
600 /*
601 * This is called by kbd_input_raw() or by kb_repeat()
602 * to deliver ASCII input. Called at spltty().
603 *
604 * Return zero on success, else the keysym that we
605 * could not handle (so the caller may complain).
606 */
607 int
608 kbd_input_keysym(k, keysym)
609 struct kbd_softc *k;
610 int keysym;
611 {
612 struct kbd_state *ks = &k->k_state;
613 int data;
614
615 /* Check if a recipient has been configured */
616 if (k->k_cc == NULL)
617 return (0);
618
619 switch (KEYSYM_CLASS(keysym)) {
620
621 case KEYSYM_ASCII:
622 data = KEYSYM_DATA(keysym);
623 if (ks->kbd_modbits & KBMOD_META_MASK)
624 data |= 0x80;
625 (*k->k_cc->cc_upstream)(data);
626 break;
627
628 case KEYSYM_STRING:
629 data = keysym & 0xF;
630 kbd_input_string(k, kbd_stringtab[data]);
631 break;
632
633 case KEYSYM_FUNC:
634 kbd_input_funckey(k, keysym);
635 break;
636
637 case KEYSYM_CLRMOD:
638 data = 1 << (keysym & 0x1F);
639 ks->kbd_modbits &= ~data;
640 break;
641
642 case KEYSYM_SETMOD:
643 data = 1 << (keysym & 0x1F);
644 ks->kbd_modbits |= data;
645 break;
646
647 case KEYSYM_INVMOD:
648 data = 1 << (keysym & 0x1F);
649 ks->kbd_modbits ^= data;
650 kbd_update_leds(k);
651 break;
652
653 case KEYSYM_ALL_UP:
654 ks->kbd_modbits &= ~0xFFFF;
655 break;
656
657 case KEYSYM_SPECIAL:
658 if (keysym == KEYSYM_NOP)
659 break;
660 /* fall through */
661 default:
662 /* We could not handle it. */
663 return (keysym);
664 }
665 return (0);
666 }
667
668 /*
669 * This is the autorepeat timeout function.
670 * Called at splsoftclock().
671 */
672 static void
673 kbd_repeat(arg)
674 void *arg;
675 {
676 struct kbd_softc *k = (struct kbd_softc *)arg;
677 int s = spltty();
678
679 if (k->k_repeating && k->k_repeatsym >= 0) {
680 (void)kbd_input_keysym(k, k->k_repeatsym);
681 callout_reset(&k->k_repeat_ch, k->k_repeat_step,
682 kbd_repeat, k);
683 }
684 splx(s);
685 }
686
687 /*
688 * Called by our kbd_softint() routine on input,
689 * which passes the raw hardware scan codes.
690 * Called at spltty()
691 */
692 void
693 kbd_input_raw(k, c)
694 struct kbd_softc *k;
695 int c;
696 {
697 struct kbd_state *ks = &k->k_state;
698 struct firm_event *fe;
699 int put, keysym;
700
701 /* XXX - Input errors already handled. */
702
703 /* Are we expecting special input? */
704 if (ks->kbd_expect) {
705 if (ks->kbd_expect & KBD_EXPECT_IDCODE) {
706 /* We read a KBD_RESET last time. */
707 ks->kbd_id = c;
708 kbd_was_reset(k);
709 }
710 if (ks->kbd_expect & KBD_EXPECT_LAYOUT) {
711 /* We read a KBD_LAYOUT last time. */
712 ks->kbd_layout = c;
713 kbd_new_layout(k);
714 }
715 ks->kbd_expect = 0;
716 return;
717 }
718
719 /* Is this one of the "special" input codes? */
720 if (KBD_SPECIAL(c)) {
721 switch (c) {
722 case KBD_RESET:
723 ks->kbd_expect |= KBD_EXPECT_IDCODE;
724 /* Fake an "all-up" to resync. translation. */
725 c = KBD_IDLE;
726 break;
727
728 case KBD_LAYOUT:
729 ks->kbd_expect |= KBD_EXPECT_LAYOUT;
730 return;
731
732 case KBD_ERROR:
733 log(LOG_WARNING, "%s: received error indicator\n",
734 k->k_dev.dv_xname);
735 return;
736
737 case KBD_IDLE:
738 /* Let this go to the translator. */
739 break;
740 }
741 }
742
743 /*
744 * If /dev/kbd is not connected in event mode,
745 * translate and send upstream (to console).
746 */
747 if (!k->k_evmode) {
748
749 /* Any input stops auto-repeat (i.e. key release). */
750 if (k->k_repeating) {
751 k->k_repeating = 0;
752 callout_stop(&k->k_repeat_ch);
753 }
754
755 /* Translate this code to a keysym */
756 keysym = kbd_code_to_keysym(ks, c);
757
758 /* Pass up to the next layer. */
759 if (kbd_input_keysym(k, keysym)) {
760 log(LOG_WARNING, "%s: code=0x%x with mod=0x%x"
761 " produced unexpected keysym 0x%x\n",
762 k->k_dev.dv_xname, c,
763 ks->kbd_modbits, keysym);
764 /* No point in auto-repeat here. */
765 return;
766 }
767
768 /* Does this symbol get auto-repeat? */
769 if (KEYSYM_NOREPEAT(keysym))
770 return;
771
772 /* Setup for auto-repeat after initial delay. */
773 k->k_repeating = 1;
774 k->k_repeatsym = keysym;
775 callout_reset(&k->k_repeat_ch, k->k_repeat_start,
776 kbd_repeat, k);
777 return;
778 }
779
780 /*
781 * IDLEs confuse the MIT X11R4 server badly, so we must drop them.
782 * This is bad as it means the server will not automatically resync
783 * on all-up IDLEs, but I did not drop them before, and the server
784 * goes crazy when it comes time to blank the screen....
785 */
786 if (c == KBD_IDLE)
787 return;
788
789 /*
790 * Keyboard is generating events. Turn this keystroke into an
791 * event and put it in the queue. If the queue is full, the
792 * keystroke is lost (sorry!).
793 */
794 put = k->k_events.ev_put;
795 fe = &k->k_events.ev_q[put];
796 put = (put + 1) % EV_QSIZE;
797 if (put == k->k_events.ev_get) {
798 log(LOG_WARNING, "%s: event queue overflow\n",
799 k->k_dev.dv_xname); /* ??? */
800 return;
801 }
802 fe->id = KEY_CODE(c);
803 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
804 fe->time = time;
805 k->k_events.ev_put = put;
806 EV_WAKEUP(&k->k_events);
807 }
808
809 /****************************************************************/
810
811 /*
812 * Open/close routines called upon opening /dev/console
813 * if we serve console input.
814 */
815 int
816 kbd_cc_open(cc)
817 struct cons_channel *cc;
818 {
819 struct kbd_softc *k = (struct kbd_softc *)cc->cc_dev;
820 return (kbd_iopen(k));
821 }
822
823 int
824 kbd_cc_close(cc)
825 struct cons_channel *cc;
826 {
827 struct kbd_softc *k = (struct kbd_softc *)cc->cc_dev;
828 return (kbd_iclose(k));
829 }
830
831 /*
832 * Initialization to be done at first open.
833 * This is called from kbdopen() or kd_cc_open()
834 * Called with user context.
835 */
836 int
837 kbd_iopen(k)
838 struct kbd_softc *k;
839 {
840 struct kbd_state *ks;
841 int error, s;
842
843 if (k == NULL)
844 return (ENXIO);
845
846 ks = &k->k_state;
847
848 /* Tolerate extra calls. */
849 if (k->k_isopen)
850 return (0);
851
852 /* Open internal device */
853 if (k->k_deviopen)
854 (*k->k_deviopen)((struct device *)k, FREAD|FWRITE);
855
856 s = spltty();
857
858 /* Reset the keyboard and find out its type. */
859 kbd_output(k, KBD_CMD_RESET);
860 kbd_start_tx(k);
861 kbd_drain_tx(k);
862 /* The wakeup for this is in kbd_was_reset(). */
863 error = tsleep((caddr_t)&ks->kbd_id,
864 PZERO | PCATCH, devopn, hz);
865 if (error == EWOULDBLOCK) { /* no response */
866 error = 0;
867 log(LOG_ERR, "%s: reset failed\n",
868 k->k_dev.dv_xname);
869 /*
870 * Allow the open anyway (to keep getty happy)
871 * but assume the "least common denominator".
872 */
873 ks->kbd_id = KB_SUN2;
874 }
875
876 /* Initialize the table pointers for this type. */
877 kbd_xlate_init(ks);
878
879 /* Earlier than type 4 does not know "layout". */
880 if (ks->kbd_id < KB_SUN4)
881 goto out;
882
883 /* Ask for the layout. */
884 kbd_output(k, KBD_CMD_GETLAYOUT);
885 kbd_start_tx(k);
886 kbd_drain_tx(k);
887 /* The wakeup for this is in kbd_new_layout(). */
888 error = tsleep((caddr_t)&ks->kbd_layout,
889 PZERO | PCATCH, devopn, hz);
890 if (error == EWOULDBLOCK) { /* no response */
891 error = 0;
892 log(LOG_ERR, "%s: no response to get_layout\n",
893 k->k_dev.dv_xname);
894 ks->kbd_layout = 0;
895 }
896
897 out:
898 splx(s);
899
900 if (error == 0)
901 k->k_isopen = 1;
902
903 return (error);
904 }
905
906 int
907 kbd_iclose(k)
908 struct kbd_softc *k;
909 {
910 /* For now: */ return (0);
911 }
912
913 /*
914 * Called by kbd_input_raw, at spltty()
915 */
916 static void
917 kbd_was_reset(k)
918 struct kbd_softc *k;
919 {
920 struct kbd_state *ks = &k->k_state;
921
922 /*
923 * On first identification, wake up anyone waiting for type
924 * and set up the table pointers.
925 */
926 wakeup((caddr_t)&ks->kbd_id);
927
928 /* Restore keyclick, if necessary */
929 switch (ks->kbd_id) {
930
931 case KB_SUN2:
932 /* Type 2 keyboards don't support keyclick */
933 break;
934
935 case KB_SUN3:
936 /* Type 3 keyboards come up with keyclick on */
937 if (!ks->kbd_click) {
938 /* turn off the click */
939 kbd_output(k, KBD_CMD_NOCLICK);
940 kbd_start_tx(k);
941 }
942 break;
943
944 case KB_SUN4:
945 /* Type 4 keyboards come up with keyclick off */
946 if (ks->kbd_click) {
947 /* turn on the click */
948 kbd_output(k, KBD_CMD_CLICK);
949 kbd_start_tx(k);
950 }
951 break;
952 }
953
954 /* LEDs are off after reset. */
955 ks->kbd_leds = 0;
956 }
957
958 /*
959 * Called by kbd_input_raw, at spltty()
960 */
961 static void
962 kbd_new_layout(k)
963 struct kbd_softc *k;
964 {
965 struct kbd_state *ks = &k->k_state;
966
967 /*
968 * On first identification, wake up anyone waiting for type
969 * and set up the table pointers.
970 */
971 wakeup((caddr_t)&ks->kbd_layout);
972
973 /* XXX: switch decoding tables? */
974 }
975
976
977 /*
978 * Wait for output to finish.
979 * Called at spltty(). Has user context.
980 */
981 static int
982 kbd_drain_tx(k)
983 struct kbd_softc *k;
984 {
985 int error;
986
987 error = 0;
988
989 while (k->k_txflags & K_TXBUSY && !error) {
990 k->k_txflags |= K_TXWANT;
991 error = tsleep((caddr_t)&k->k_txflags,
992 PZERO | PCATCH, "kbdout", 0);
993 }
994
995 return (error);
996 }
997
998 /*
999 * Enqueue some output for the keyboard
1000 * Called at spltty().
1001 */
1002 void
1003 kbd_output(k, c)
1004 struct kbd_softc *k;
1005 int c; /* the data */
1006 {
1007 int put;
1008
1009 put = k->k_tbput;
1010 k->k_tbuf[put] = (u_char)c;
1011 put = (put + 1) & KBD_TX_RING_MASK;
1012
1013 /* Would overrun if increment makes (put==get). */
1014 if (put == k->k_tbget) {
1015 log(LOG_WARNING, "%s: output overrun\n",
1016 k->k_dev.dv_xname);
1017 } else {
1018 /* OK, really increment. */
1019 k->k_tbput = put;
1020 }
1021 }
1022
1023 /*
1024 * Start the sending data from the output queue
1025 * Called at spltty().
1026 */
1027 void
1028 kbd_start_tx(k)
1029 struct kbd_softc *k;
1030 {
1031 int get;
1032 u_char c;
1033
1034 if (k->k_txflags & K_TXBUSY)
1035 return;
1036
1037 /* Is there anything to send? */
1038 get = k->k_tbget;
1039 if (get == k->k_tbput) {
1040 /* Nothing to send. Wake drain waiters. */
1041 if (k->k_txflags & K_TXWANT) {
1042 k->k_txflags &= ~K_TXWANT;
1043 wakeup((caddr_t)&k->k_txflags);
1044 }
1045 return;
1046 }
1047
1048 /* Have something to send. */
1049 c = k->k_tbuf[get];
1050 get = (get + 1) & KBD_TX_RING_MASK;
1051 k->k_tbget = get;
1052 k->k_txflags |= K_TXBUSY;
1053
1054 k->k_write_data(k, c);
1055 }
1056
1057 /*
1058 * Called at spltty by:
1059 * kbd_update_leds, kbd_iocsled
1060 */
1061 static void
1062 kbd_set_leds(k, new_leds)
1063 struct kbd_softc *k;
1064 int new_leds;
1065 {
1066 struct kbd_state *ks = &k->k_state;
1067
1068 /* Don't send unless state changes. */
1069 if (ks->kbd_leds == new_leds)
1070 return;
1071
1072 ks->kbd_leds = new_leds;
1073
1074 /* Only type 4 and later has LEDs anyway. */
1075 if (ks->kbd_id < KB_SUN4)
1076 return;
1077
1078 kbd_output(k, KBD_CMD_SETLED);
1079 kbd_output(k, new_leds);
1080 kbd_start_tx(k);
1081 }
1082
1083 /*
1084 * Called at spltty by:
1085 * kbd_input_keysym
1086 */
1087 static void
1088 kbd_update_leds(k)
1089 struct kbd_softc *k;
1090 {
1091 struct kbd_state *ks = &k->k_state;
1092 char leds;
1093
1094 leds = ks->kbd_leds;
1095 leds &= ~(LED_CAPS_LOCK|LED_NUM_LOCK);
1096
1097 if (ks->kbd_modbits & (1 << KBMOD_CAPSLOCK))
1098 leds |= LED_CAPS_LOCK;
1099 if (ks->kbd_modbits & (1 << KBMOD_NUMLOCK))
1100 leds |= LED_NUM_LOCK;
1101
1102 kbd_set_leds(k, leds);
1103 }
1104