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