xref: /netbsd-src/sys/dev/sun/kbd.c (revision 481fca6e59249d8ffcf24fef7cfbe7b131bfb080)
1 /*	$NetBSD: kbd.c,v 1.26 2000/03/24 11:46:47 hannken 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_repeat_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