xref: /titanic_50/usr/src/uts/common/io/kbd.c (revision 9113a79cf228b8f7bd509b1328adf88659dfe218)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 						/* SunOS-4.0 1.60	*/
28 /*	From:	SunOS4.0	sundev/kbd.c	*/
29 
30 /*
31  * Keyboard input streams module - handles conversion of up/down codes to
32  * ASCII or event format.
33  */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/sysmacros.h>
37 #include <sys/signal.h>
38 #include <sys/termios.h>
39 #include <sys/termio.h>
40 #include <sys/stream.h>
41 #include <sys/stropts.h>
42 #include <sys/strsun.h>
43 #include <sys/kmem.h>
44 #include <sys/file.h>
45 #include <sys/uio.h>
46 #include <sys/errno.h>
47 #include <sys/time.h>
48 #include <sys/consdev.h>
49 #include <sys/kbd.h>
50 #include <sys/kbio.h>
51 #include <sys/kbdreg.h>
52 #include <sys/vuid_event.h>
53 #include <sys/debug.h>
54 #include <sys/ddi.h>
55 #include <sys/sunddi.h>
56 #include <sys/policy.h>
57 
58 #include <sys/modctl.h>
59 
60 static struct streamtab kbd_info;
61 
62 static struct fmodsw fsw = {
63 	"kb",
64 	&kbd_info,
65 	D_MP | D_MTPERMOD
66 };
67 
68 /*
69  * Module linkage information for the kernel.
70  */
71 
72 static struct modlstrmod modlstrmod = {
73 	&mod_strmodops, "streams module for keyboard", &fsw
74 };
75 
76 static struct modlinkage modlinkage = {
77 	MODREV_1, (void *)&modlstrmod, NULL
78 };
79 
80 int
81 _init(void)
82 {
83 	return (mod_install(&modlinkage));
84 }
85 
86 int
87 _fini(void)
88 {
89 	return (mod_remove(&modlinkage));
90 }
91 
92 int
93 _info(struct modinfo *modinfop)
94 {
95 	return (mod_info(&modlinkage, modinfop));
96 }
97 
98 /*
99  * For now these are shared.
100  * These data structures are static (defined in keytables.c) thus
101  * there is no need to perform any locking.
102  */
103 extern struct keyboards	keytables[];
104 extern char keystringtab[16][KTAB_STRLEN];
105 extern struct compose_sequence_t kb_compose_table[];
106 extern signed char kb_compose_map[];
107 extern struct fltaccent_sequence_t kb_fltaccent_table[];
108 extern uchar_t kb_numlock_table[];
109 
110 /*
111  * This value corresponds approximately to max 10 fingers
112  */
113 static int	kbd_downs_size = 15;
114 
115 typedef	struct	key_event {
116 	uchar_t	key_station;	/* Physical key station associated with event */
117 	Firm_event event;	/* Event that sent out on down */
118 } Key_event;
119 struct	kbddata {
120 	queue_t	*kbdd_readq;
121 	queue_t *kbdd_writeq;
122 	mblk_t	*kbdd_iocpending;	/* "ioctl" awaiting buffer */
123 	mblk_t	*kbdd_replypending;	/* "ioctl" reply awaiting result */
124 	int	kbdd_flags;		/* random flags */
125 	bufcall_id_t kbdd_bufcallid;	/* bufcall id */
126 	timeout_id_t kbdd_rptid;	/* timeout id for kbdrpt() */
127 	timeout_id_t kbdd_layoutid;	/* timeout id for kbdlayout() */
128 	int	kbdd_iocid;		/* ID of "ioctl" being waited for */
129 	int	kbdd_iocerror;		/* error return from "ioctl" */
130 	struct	keyboardstate kbdd_state;
131 					/*
132 					 * State of keyboard & keyboard
133 					 * specific settings, e.g., tables
134 					 */
135 	int	kbdd_translate;		/* Translate keycodes? */
136 	int	kbdd_translatable;	/* Keyboard is translatable? */
137 	int	kbdd_compat;		/* Generating pre-4.1 events? */
138 	short	kbdd_ascii_addr;	/* Vuid_id_addr for ascii events */
139 	short	kbdd_top_addr;		/* Vuid_id_addr for top events */
140 	short	kbdd_vkey_addr;		/* Vuid_id_addr for vkey events */
141 	struct	key_event *kbdd_downs;
142 					/*
143 					 * Table of key stations currently down
144 					 * that have firm events that need
145 					 * to be matched with up transitions
146 					 * when kbdd_translate is TR_*EVENT
147 					 */
148 	int	kbdd_downs_entries; /* # of possible entries in kbdd_downs */
149 	uint_t	kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */
150 	ushort_t compose_key;		/* first compose key */
151 	ushort_t fltaccent_entry;	/* floating accent keymap entry */
152 	char	led_state;		/* current state of LEDs */
153 };
154 
155 #define	KBD_OPEN	0x00000001 /* keyboard is open for business */
156 #define	KBD_IOCWAIT	0x00000002 /* "open" waiting for "ioctl" to finish */
157 
158 #define	NO_HARD_RESET	0		/* don't do hard reset */
159 #define	HARD_RESET	1		/* do hard reset */
160 
161 
162 /*
163  * Constants setup during the first open of a kbd (so that they can be patched
164  * for debugging purposes).
165  */
166 static int kbd_repeatrate;
167 static int kbd_repeatdelay;
168 
169 static int kbd_overflow_cnt;	/* Number of times kbd overflowed input q */
170 static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */
171 
172 #ifdef	KBD_DEBUG
173 int	kbd_debug = 0;
174 int	kbd_ra_debug = 0;
175 int	kbd_raw_debug = 0;
176 int	kbd_rpt_debug = 0;
177 int	kbd_input_debug = 0;
178 #endif	/* KBD_DEBUG */
179 
180 static int	kbdopen(queue_t *, dev_t *, int, int, cred_t *);
181 static int	kbdclose(queue_t *, int, cred_t *);
182 static void	kbdwput(queue_t *, mblk_t *);
183 static void	kbdrput(queue_t *, mblk_t *);
184 
185 static struct module_info kbdmiinfo = {
186 	0,
187 	"kb",
188 	0,
189 	INFPSZ,
190 	2048,
191 	128
192 };
193 
194 static struct qinit kbdrinit = {
195 	(int (*)())kbdrput,
196 	(int (*)())NULL,
197 	kbdopen,
198 	kbdclose,
199 	(int (*)())NULL,
200 	&kbdmiinfo
201 };
202 
203 static struct module_info kbdmoinfo = {
204 	0,
205 	"kb",
206 	0,
207 	INFPSZ,
208 	2048,
209 	128
210 };
211 
212 static struct qinit kbdwinit = {
213 	(int (*)())kbdwput,
214 	(int (*)())NULL,
215 	kbdopen,
216 	kbdclose,
217 	(int (*)())NULL,
218 	&kbdmoinfo
219 };
220 
221 static struct streamtab kbd_info = {
222 	&kbdrinit,
223 	&kbdwinit,
224 	NULL,
225 	NULL,
226 };
227 
228 static void	kbdreioctl(void *);
229 static void	kbdioctl(queue_t *, mblk_t *);
230 static void	kbdflush(struct kbddata *);
231 static void	kbduse(struct kbddata *, unsigned);
232 static void	kbdsetled(struct kbddata *);
233 static void	kbdcmd(queue_t *, char);
234 static void	kbdreset(struct kbddata *, uint_t);
235 static int	kbdsetkey(struct kbddata *, struct kiockey *,  cred_t *);
236 static int	kbdgetkey(struct kbddata *, struct kiockey *);
237 static int	kbdskey(struct kbddata *, struct kiockeymap *,  cred_t *);
238 static int	kbdgkey(struct kbddata *, struct kiockeymap *);
239 static void	kbdlayouttimeout(void *);
240 static void	kbdinput(struct kbddata *, unsigned);
241 static void	kbdid(struct kbddata *, int);
242 static struct	keymap *settable(struct kbddata *, uint_t);
243 static void	kbdrpt(void *);
244 static void	kbdcancelrpt(struct kbddata *);
245 static void	kbdtranslate(struct kbddata *, unsigned, queue_t *);
246 static int	kbd_do_compose(ushort_t, ushort_t, ushort_t *);
247 static void	kbd_send_esc_event(char, struct kbddata *);
248 char		*strsetwithdecimal(char *, uint_t, uint_t);
249 static void	kbdkeypressed(struct kbddata *, uchar_t, Firm_event *,
250 								ushort_t);
251 static void	kbdqueuepress(struct kbddata *, uchar_t, Firm_event *);
252 static void	kbdkeyreleased(struct kbddata *, uchar_t);
253 static void	kbdreleaseall(struct kbddata *);
254 static void	kbdputcode(uint_t, queue_t *);
255 static void	kbdputbuf(char *, queue_t *);
256 static void	kbdqueueevent(struct kbddata *, Firm_event *);
257 
258 /*
259  * Dummy qbufcall callback routine used by open and close.
260  * The framework will wake up qwait_sig when we return from
261  * this routine (as part of leaving the perimeters.)
262  * (The framework enters the perimeters before calling the qbufcall() callback
263  * and leaves the perimeters after the callback routine has executed. The
264  * framework performs an implicit wakeup of any thread in qwait/qwait_sig
265  * when it leaves the perimeter. See qwait(9E).)
266  */
267 /* ARGSUSED */
268 static void dummy_callback(void *arg)
269 {}
270 
271 
272 /*
273  * Open a keyboard.
274  * Ttyopen sets line characteristics
275  */
276 /* ARGSUSED */
277 static int
278 kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
279 {
280 	register int  error;
281 	register struct	kbddata *kbdd;
282 	mblk_t *mp;
283 	mblk_t *datap;
284 	register struct iocblk *iocb;
285 	register struct termios *cb;
286 
287 	/* Set these up only once so that they could be changed from adb */
288 	if (!kbd_repeatrate) {
289 		kbd_repeatrate = (hz+29)/30;
290 		kbd_repeatdelay = hz/2;
291 	}
292 
293 	if (q->q_ptr != NULL)
294 		return (0);		/* already attached */
295 
296 	/*
297 	 * Only allow open requests to succeed for privileged users.  This
298 	 * necessary to prevent users from pushing the "kb" module again
299 	 * on the stream associated with /dev/kbd.
300 	 */
301 	if (secpolicy_console(crp) != 0) {
302 		return (EPERM);
303 	}
304 
305 
306 	switch (sflag) {
307 
308 	case MODOPEN:
309 		break;
310 
311 	case CLONEOPEN:
312 		return (EINVAL);	/* No Bozos! */
313 	}
314 
315 	/* allocate keyboard */
316 
317 	kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP);
318 
319 
320 	/*
321 	 * Set up queue pointers, so that the "put" procedure will accept
322 	 * the reply to the "ioctl" message we send down.
323 	 */
324 	q->q_ptr = kbdd;
325 	WR(q)->q_ptr = kbdd;
326 
327 	qprocson(q);
328 
329 	/*
330 	 * Setup tty modes.
331 	 */
332 	while ((mp = mkiocb(TCSETSF)) == NULL) {
333 		timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI,
334 		    dummy_callback, NULL);
335 		if (!qwait_sig(q)) {
336 			qunbufcall(q, id);
337 			kmem_free(kbdd, sizeof (struct kbddata));
338 			qprocsoff(q);
339 
340 			return (EINTR);
341 		}
342 	}
343 	while ((datap = allocb(sizeof (struct termios), BPRI_HI)) ==
344 		NULL) {
345 		timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI,
346 		    dummy_callback, NULL);
347 		if (!qwait_sig(q)) {
348 			qunbufcall(q, id);
349 			freemsg(mp);
350 			kmem_free(kbdd, sizeof (struct kbddata));
351 			qprocsoff(q);
352 
353 			return (EINTR);
354 		}
355 	}
356 
357 	iocb		= (struct iocblk *)mp->b_rptr;
358 	iocb->ioc_count	= sizeof (struct termios);
359 
360 	cb = (struct termios *)datap->b_rptr;
361 	cb->c_iflag = 0;
362 	cb->c_oflag = 0;
363 	cb->c_cflag = CREAD|CS8|B1200;
364 	cb->c_lflag = 0;
365 	bzero(cb->c_cc, NCCS);
366 	datap->b_wptr += sizeof (struct termios);
367 	mp->b_cont = datap;
368 	kbdd->kbdd_flags |= KBD_IOCWAIT;	/* indicate that we're */
369 	kbdd->kbdd_iocid = iocb->ioc_id;	/* waiting for this response */
370 	putnext(WR(q), mp);
371 
372 	/*
373 	 * Now wait for it.  Let our read queue put routine wake us up
374 	 * when it arrives.
375 	 */
376 	while (kbdd->kbdd_flags & KBD_IOCWAIT) {
377 		if (!qwait_sig(q)) {
378 			error = EINTR;
379 			goto error;
380 		}
381 	}
382 	if ((error = kbdd->kbdd_iocerror) != 0)
383 		goto error;
384 
385 	/*
386 	 * Set up private data.
387 	 */
388 	kbdd->kbdd_readq = q;
389 	kbdd->kbdd_writeq = WR(q);
390 	kbdd->kbdd_iocpending = NULL;
391 	kbdd->kbdd_translatable = TR_CAN;
392 	kbdd->kbdd_translate = TR_ASCII;
393 	kbdd->kbdd_compat = 1;
394 	kbdd->kbdd_ascii_addr = ASCII_FIRST;
395 	kbdd->kbdd_top_addr = TOP_FIRST;
396 	kbdd->kbdd_vkey_addr = VKEY_FIRST;
397 	/* Allocate dynamic memory for downs table */
398 	kbdd->kbdd_downs_entries = kbd_downs_size;
399 	kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event);
400 	kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP);
401 	kbdd->kbdd_flags = KBD_OPEN;
402 	kbdd->led_state = 0;
403 
404 	/*
405 	 * Reset kbd.
406 	 */
407 	kbdreset(kbdd, HARD_RESET);
408 
409 	return (0);
410 
411 error:
412 	qprocsoff(q);
413 	kmem_free(kbdd, sizeof (struct kbddata));
414 	return (error);
415 }
416 
417 /*
418  * Close a keyboard.
419  */
420 /* ARGSUSED1 */
421 static int
422 kbdclose(register queue_t *q, int flag, cred_t *crp)
423 {
424 	register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
425 	register mblk_t *mp;
426 
427 	qprocsoff(q);
428 	/*
429 	 * Since we're about to destroy our private data, turn off
430 	 * our open flag first, so we don't accept any more input
431 	 * and try to use that data.
432 	 */
433 	kbdd->kbdd_flags = 0;
434 
435 	if ((mp = kbdd->kbdd_replypending) != NULL) {
436 		/*
437 		 * There was a KIOCLAYOUT pending; presumably, it timed out.
438 		 * Throw the reply away.
439 		 */
440 		kbdd->kbdd_replypending = NULL;
441 		freemsg(mp);
442 	}
443 
444 	/* clear all timeouts */
445 	if (kbdd->kbdd_bufcallid)
446 		qunbufcall(q, kbdd->kbdd_bufcallid);
447 	if (kbdd->kbdd_rptid)
448 		(void) quntimeout(q, kbdd->kbdd_rptid);
449 	if (kbdd->kbdd_layoutid)
450 		(void) quntimeout(q, kbdd->kbdd_layoutid);
451 	kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
452 	kmem_free(kbdd, sizeof (struct kbddata));
453 	return (0);
454 }
455 
456 /*
457  * Line discipline output queue put procedure: handles M_IOCTL
458  * messages.
459  */
460 static void
461 kbdwput(register queue_t *q, register mblk_t *mp)
462 {
463 	/*
464 	 * Process M_FLUSH, and some M_IOCTL, messages here; pass
465 	 * everything else down.
466 	 */
467 	switch (mp->b_datap->db_type) {
468 
469 	case M_FLUSH:
470 		if (*mp->b_rptr & FLUSHW)
471 			flushq(q, FLUSHDATA);
472 		if (*mp->b_rptr & FLUSHR)
473 			flushq(RD(q), FLUSHDATA);
474 
475 	default:
476 		putnext(q, mp);	/* pass it down the line */
477 		break;
478 
479 	case M_IOCTL:
480 		kbdioctl(q, mp);
481 		break;
482 	}
483 }
484 
485 
486 static void
487 kbdreioctl(void *kbdd_addr)
488 {
489 	struct kbddata *kbdd = kbdd_addr;
490 	queue_t *q;
491 	mblk_t *mp;
492 
493 	kbdd->kbdd_bufcallid = 0;
494 	q = kbdd->kbdd_writeq;
495 	if ((mp = kbdd->kbdd_iocpending) != NULL) {
496 		kbdd->kbdd_iocpending = NULL;	/* not pending any more */
497 		kbdioctl(q, mp);
498 	}
499 }
500 
501 static void
502 kbdioctl(register queue_t *q, register mblk_t *mp)
503 {
504 	register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
505 	register struct iocblk *iocp;
506 	register short	new_translate;
507 	register Vuid_addr_probe *addr_probe;
508 	register short	*addr_ptr;
509 	mblk_t *datap;
510 	size_t	ioctlrespsize;
511 	int	err = 0;
512 
513 	iocp = (struct iocblk *)mp->b_rptr;
514 
515 	switch (iocp->ioc_cmd) {
516 
517 	case VUIDSFORMAT:
518 		err = miocpullup(mp, sizeof (int));
519 		if (err != 0)
520 			break;
521 
522 		new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
523 		    TR_ASCII : TR_EVENT;
524 		if (new_translate == kbdd->kbdd_translate)
525 			break;
526 		kbdd->kbdd_translate = new_translate;
527 		goto output_format_change;
528 
529 	case KIOCTRANS:
530 		err = miocpullup(mp, sizeof (int));
531 		if (err != 0)
532 			break;
533 
534 		new_translate = *(int *)mp->b_cont->b_rptr;
535 		if (new_translate == kbdd->kbdd_translate)
536 			break;
537 		kbdd->kbdd_translate = new_translate;
538 		goto output_format_change;
539 
540 	case KIOCCMD:
541 		err = miocpullup(mp, sizeof (int));
542 		if (err != 0)
543 			break;
544 
545 		kbdcmd(q, (char)(*(int *)mp->b_cont->b_rptr));
546 		break;
547 
548 	case KIOCSLED:
549 		err = miocpullup(mp, sizeof (uchar_t));
550 		if (err != 0)
551 			break;
552 
553 		kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr;
554 		kbdsetled(kbdd);
555 		break;
556 
557 	case KIOCGLED:
558 		if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
559 			ioctlrespsize = sizeof (int);
560 			goto allocfailure;
561 		}
562 		*(uchar_t *)datap->b_wptr = kbdd->led_state;
563 		datap->b_wptr += sizeof (uchar_t);
564 		if (mp->b_cont)  /* free msg to prevent memory leak */
565 			freemsg(mp->b_cont);
566 		mp->b_cont = datap;
567 		iocp->ioc_count = sizeof (uchar_t);
568 		break;
569 
570 	case VUIDGFORMAT:
571 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
572 			ioctlrespsize = sizeof (int);
573 			goto allocfailure;
574 		}
575 		*(int *)datap->b_wptr =
576 		    (kbdd->kbdd_translate == TR_EVENT ||
577 		    kbdd->kbdd_translate == TR_UNTRANS_EVENT) ?
578 			VUID_FIRM_EVENT: VUID_NATIVE;
579 		datap->b_wptr += sizeof (int);
580 		if (mp->b_cont)  /* free msg to prevent memory leak */
581 			freemsg(mp->b_cont);
582 		mp->b_cont = datap;
583 		iocp->ioc_count = sizeof (int);
584 		break;
585 
586 	case KIOCGTRANS:
587 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
588 			ioctlrespsize = sizeof (int);
589 			goto allocfailure;
590 		}
591 		*(int *)datap->b_wptr = kbdd->kbdd_translate;
592 		datap->b_wptr += sizeof (int);
593 		if (mp->b_cont)  /* free msg to prevent memory leak */
594 			freemsg(mp->b_cont);
595 		mp->b_cont = datap;
596 		iocp->ioc_count = sizeof (int);
597 		break;
598 
599 	case VUIDSADDR:
600 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
601 		if (err != 0)
602 			break;
603 
604 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
605 		switch (addr_probe->base) {
606 
607 		case ASCII_FIRST:
608 			addr_ptr = &kbdd->kbdd_ascii_addr;
609 			break;
610 
611 		case TOP_FIRST:
612 			addr_ptr = &kbdd->kbdd_top_addr;
613 			break;
614 
615 		case VKEY_FIRST:
616 			addr_ptr = &kbdd->kbdd_vkey_addr;
617 			break;
618 
619 		default:
620 			err = ENODEV;
621 		}
622 		if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
623 			*addr_ptr = addr_probe->data.next;
624 			goto output_format_change;
625 		}
626 		break;
627 
628 	case VUIDGADDR:
629 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
630 		if (err != 0)
631 			break;
632 
633 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
634 		switch (addr_probe->base) {
635 
636 		case ASCII_FIRST:
637 			addr_probe->data.current = kbdd->kbdd_ascii_addr;
638 			break;
639 
640 		case TOP_FIRST:
641 			addr_probe->data.current = kbdd->kbdd_top_addr;
642 			break;
643 
644 		case VKEY_FIRST:
645 			addr_probe->data.current = kbdd->kbdd_vkey_addr;
646 			break;
647 
648 		default:
649 			err = ENODEV;
650 		}
651 		break;
652 
653 	case KIOCTRANSABLE:
654 		err = miocpullup(mp, sizeof (int));
655 		if (err != 0)
656 			break;
657 
658 		if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) {
659 			kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr;
660 			kbdreset(kbdd, HARD_RESET);
661 			goto output_format_change;
662 		}
663 		break;
664 
665 	case KIOCGTRANSABLE:
666 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
667 			ioctlrespsize = sizeof (int);
668 			goto allocfailure;
669 		}
670 		*(int *)datap->b_wptr = kbdd->kbdd_translatable;
671 		datap->b_wptr += sizeof (int);
672 		if (mp->b_cont)  /* free msg to prevent memory leak */
673 			freemsg(mp->b_cont);
674 		mp->b_cont = datap;
675 		iocp->ioc_count = sizeof (int);
676 		break;
677 
678 	case KIOCSCOMPAT:
679 		err = miocpullup(mp, sizeof (int));
680 		if (err != 0)
681 			break;
682 
683 		kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr;
684 		break;
685 
686 	case KIOCGCOMPAT:
687 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
688 			ioctlrespsize = sizeof (int);
689 			goto allocfailure;
690 		}
691 		*(int *)datap->b_wptr = kbdd->kbdd_compat;
692 		datap->b_wptr += sizeof (int);
693 		if (mp->b_cont)  /* free msg to prevent memory leak */
694 			freemsg(mp->b_cont);
695 		mp->b_cont = datap;
696 		iocp->ioc_count = sizeof (int);
697 		break;
698 
699 	case KIOCSETKEY:
700 		err = miocpullup(mp, sizeof (struct kiockey));
701 		if (err != 0)
702 			break;
703 
704 		err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr,
705 		    iocp->ioc_cr);
706 		/*
707 		 * Since this only affects any subsequent key presses,
708 		 * don't goto output_format_change.  One might want to
709 		 * toggle the keytable entries dynamically.
710 		 */
711 		break;
712 
713 	case KIOCGETKEY:
714 		err = miocpullup(mp, sizeof (struct kiockey));
715 		if (err != 0)
716 			break;
717 
718 		err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr);
719 		break;
720 
721 	case KIOCSKEY:
722 		err = miocpullup(mp, sizeof (struct kiockeymap));
723 		if (err != 0)
724 			break;
725 
726 		err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr,
727 		    iocp->ioc_cr);
728 		/*
729 		 * Since this only affects any subsequent key presses,
730 		 * don't goto output_format_change.  One might want to
731 		 * toggle the keytable entries dynamically.
732 		 */
733 		break;
734 
735 	case KIOCGKEY:
736 		err = miocpullup(mp, sizeof (struct kiockeymap));
737 		if (err != 0)
738 			break;
739 
740 		err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr);
741 		break;
742 
743 	case KIOCSDIRECT:
744 		goto output_format_change;
745 
746 	case KIOCGDIRECT:
747 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
748 			ioctlrespsize = sizeof (int);
749 			goto allocfailure;
750 		}
751 		*(int *)datap->b_wptr = 1;	/* always direct */
752 		datap->b_wptr += sizeof (int);
753 		if (mp->b_cont) /* free msg to prevent memory leak */
754 			freemsg(mp->b_cont);
755 		mp->b_cont = datap;
756 		iocp->ioc_count = sizeof (int);
757 		break;
758 
759 	case KIOCTYPE:
760 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
761 			ioctlrespsize = sizeof (int);
762 			goto allocfailure;
763 		}
764 		*(int *)datap->b_wptr = kbdd->kbdd_state.k_id;
765 		datap->b_wptr += sizeof (int);
766 		if (mp->b_cont) /* free msg to prevent memory leak */
767 			freemsg(mp->b_cont);
768 		mp->b_cont = datap;
769 		iocp->ioc_count = sizeof (int);
770 		break;
771 
772 	case KIOCLAYOUT:
773 		if ((datap = kbdd->kbdd_replypending) != NULL) {
774 			/*
775 			 * There was an earlier KIOCLAYOUT pending; presumably,
776 			 * it timed out.  Throw the reply away.
777 			 */
778 			kbdd->kbdd_replypending = NULL;
779 			freemsg(datap);
780 		}
781 
782 		if (kbdd->kbdd_state.k_id == KB_SUN4 ||
783 		    kbdd->kbdd_state.k_id == KB_PC) {
784 			if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
785 				ioctlrespsize = sizeof (int);
786 				goto allocfailure;
787 			}
788 			iocp->ioc_rval = 0;
789 			iocp->ioc_error = 0;	/* brain rot */
790 			iocp->ioc_count = sizeof (int);
791 			if (mp->b_cont)   /* free msg to prevent memory leak */
792 				freemsg(mp->b_cont);
793 			mp->b_cont = datap;
794 			mp->b_datap->db_type = M_IOCACK;
795 			kbdd->kbdd_replypending = mp;
796 			kbdcmd(q, (char)KBD_CMD_GETLAYOUT);
797 			if (kbdd->kbdd_layoutid)
798 				(void) quntimeout(q, kbdd->kbdd_layoutid);
799 			kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout,
800 			    kbdd, hz / 5);
801 			return;		/* wait for reply from keyboard */
802 		} else {
803 			/*
804 			 * Not a Type 4 keyboard; return an immediate error.
805 			 */
806 			err = EINVAL;
807 			break;
808 		}
809 
810 	case KIOCGRPTDELAY:
811 		/*
812 		 * Report the autorepeat delay, unit in millisecond
813 		 */
814 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
815 			ioctlrespsize = sizeof (int);
816 			goto allocfailure;
817 		}
818 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay);
819 		datap->b_wptr += sizeof (int);
820 
821 		/* free msg to prevent memory leak */
822 		if (mp->b_cont != NULL)
823 			freemsg(mp->b_cont);
824 		mp->b_cont = datap;
825 		iocp->ioc_count = sizeof (int);
826 		break;
827 
828 	case KIOCSRPTDELAY:
829 		/*
830 		 * Set the autorepeat delay
831 		 */
832 		err = miocpullup(mp, sizeof (int));
833 
834 		if (err != 0)
835 			break;
836 
837 		/* validate the input */
838 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
839 			err = EINVAL;
840 			break;
841 		}
842 		kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
843 		if (kbd_repeatdelay <= 0)
844 			kbd_repeatdelay = 1;
845 		break;
846 
847 	case KIOCGRPTRATE:
848 		/*
849 		 * Report the autorepeat rate
850 		 */
851 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
852 			ioctlrespsize = sizeof (int);
853 			goto allocfailure;
854 		}
855 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate);
856 		datap->b_wptr += sizeof (int);
857 
858 		/* free msg to prevent memory leak */
859 		if (mp->b_cont != NULL)
860 			freemsg(mp->b_cont);
861 		mp->b_cont = datap;
862 		iocp->ioc_count = sizeof (int);
863 		break;
864 
865 	case KIOCSRPTRATE:
866 		/*
867 		 * Set the autorepeat rate
868 		 */
869 		err = miocpullup(mp, sizeof (int));
870 
871 		if (err != 0)
872 			break;
873 
874 		/* validate the input */
875 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
876 			err = EINVAL;
877 			break;
878 		}
879 		kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
880 		if (kbd_repeatrate <= 0)
881 			kbd_repeatrate = 1;
882 		break;
883 
884 	default:
885 		putnext(q, mp);	/* pass it down the line */
886 		return;
887 	}
888 	goto done;
889 
890 output_format_change:
891 	kbdflush(kbdd);
892 
893 done:
894 	if (err != 0) {
895 		iocp->ioc_rval = 0;
896 		iocp->ioc_error = err;
897 		mp->b_datap->db_type = M_IOCNAK;
898 	} else {
899 		iocp->ioc_rval = 0;
900 		iocp->ioc_error = 0;	/* brain rot */
901 		mp->b_datap->db_type = M_IOCACK;
902 	}
903 	qreply(q, mp);
904 	return;
905 
906 allocfailure:
907 	/*
908 	 * We needed to allocate something to handle this "ioctl", but
909 	 * couldn't; save this "ioctl" and arrange to get called back when
910 	 * it's more likely that we can get what we need.
911 	 * If there's already one being saved, throw it out, since it
912 	 * must have timed out.
913 	 */
914 	if (kbdd->kbdd_iocpending != NULL)
915 		freemsg(kbdd->kbdd_iocpending);
916 	kbdd->kbdd_iocpending = mp;
917 	if (kbdd->kbdd_bufcallid)
918 		qunbufcall(q, kbdd->kbdd_bufcallid);
919 	kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI,
920 	    kbdreioctl, kbdd);
921 }
922 
923 static void
924 kbdflush(register struct kbddata *kbdd)
925 {
926 	register queue_t *q;
927 
928 	/* Flush pending data already sent upstream */
929 	if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL)
930 		(void) putnextctl1(q, M_FLUSH, FLUSHR);
931 	/* Flush pending ups */
932 	bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
933 	kbdcancelrpt(kbdd);
934 }
935 
936 /*
937  * Pass keycode upstream, either translated or untranslated.
938  */
939 static void
940 kbduse(register struct kbddata *kbdd, unsigned keycode)
941 {
942 	register queue_t *readq;
943 
944 #ifdef	KBD_DEBUG
945 	if (kbd_input_debug) printf("KBD USE key=%d\n", keycode);
946 #endif
947 
948 	if ((readq = kbdd->kbdd_readq) == NULL)
949 		return;
950 	if (!kbdd->kbdd_translatable ||
951 	    kbdd->kbdd_translate == TR_NONE)
952 		kbdputcode(keycode, readq);
953 	else
954 		kbdtranslate(kbdd, keycode, readq);
955 }
956 
957 /*
958  * kbdclick is used to remember the current click value of the
959  * Sun-3 keyboard.  This brain damaged keyboard will reset the
960  * clicking to the "default" value after a reset command and
961  * there is no way to read out the current click value.  We
962  * cannot send a click command immediately after the reset
963  * command or the keyboard gets screwed up.  So we wait until
964  * we get the ID byte before we send back the click command.
965  * Unfortunately, this means that there is a small window
966  * where the keyboard can click when it really shouldn't be.
967  * A value of -1 means that kbdclick has not been initialized yet.
968  */
969 static int kbdclick = -1;
970 
971 /*
972  * Send command byte to keyboard, if you can.
973  */
974 static void
975 kbdcmd(register queue_t *q, char cmd)
976 {
977 	register mblk_t *bp;
978 
979 	if (canput(q)) {
980 		if ((bp = allocb(1, BPRI_MED)) == NULL)
981 			cmn_err(CE_WARN,
982 				"kbdcmd: Can't allocate block for command");
983 		else {
984 			*bp->b_wptr++ = cmd;
985 			putnext(q, bp);
986 			if (cmd == KBD_CMD_NOCLICK)
987 				kbdclick = 0;
988 			else if (cmd == KBD_CMD_CLICK)
989 				kbdclick = 1;
990 		}
991 	}
992 }
993 
994 /*
995  * Update the keyboard LEDs to match the current keyboard state.
996  * Do this only on Type 4 keyboards; other keyboards don't support the
997  * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs).
998  */
999 static void
1000 kbdsetled(register struct kbddata *kbdd)
1001 {
1002 	if (kbdd->kbdd_state.k_id == KB_SUN4 ||
1003 	    kbdd->kbdd_state.k_id == KB_PC) {
1004 		kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED);
1005 		kbdcmd(kbdd->kbdd_writeq, kbdd->led_state);
1006 	}
1007 }
1008 
1009 /*
1010  * Reset the keyboard
1011  */
1012 static void
1013 kbdreset(register struct kbddata *kbdd, uint_t hard_reset)
1014 {
1015 	register struct keyboardstate *k;
1016 
1017 	k = &kbdd->kbdd_state;
1018 	if (kbdd->kbdd_translatable) {
1019 		k->k_idstate = KID_NONE;
1020 		k->k_id = -1;
1021 		k->k_state = NORMAL;
1022 		if (hard_reset)
1023 			kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET);
1024 	} else {
1025 		bzero(k, sizeof (struct keyboardstate));
1026 		k->k_id = KB_ASCII;
1027 		k->k_idstate = KID_OK;
1028 	}
1029 }
1030 
1031 /*
1032  * Old special codes.
1033  */
1034 #define	OLD_SHIFTKEYS	0x80
1035 #define	OLD_BUCKYBITS	0x90
1036 #define	OLD_FUNNY	0xA0
1037 #define	OLD_FA_UMLAUT	0xA9
1038 #define	OLD_FA_CFLEX	0xAA
1039 #define	OLD_FA_TILDE	0xAB
1040 #define	OLD_FA_CEDILLA	0xAC
1041 #define	OLD_FA_ACUTE	0xAD
1042 #define	OLD_FA_GRAVE	0xAE
1043 #define	OLD_ISOCHAR	0xAF
1044 #define	OLD_STRING	0xB0
1045 #define	OLD_LEFTFUNC	0xC0
1046 #define	OLD_RIGHTFUNC	0xD0
1047 #define	OLD_TOPFUNC	0xE0
1048 #define	OLD_BOTTOMFUNC	0xF0
1049 
1050 /*
1051  * Map old special codes to new ones.
1052  * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
1053  */
1054 static ushort_t	special_old_to_new[] = {
1055 	SHIFTKEYS,
1056 	BUCKYBITS,
1057 	FUNNY,
1058 	STRING,
1059 	LEFTFUNC,
1060 	RIGHTFUNC,
1061 	TOPFUNC,
1062 	BOTTOMFUNC,
1063 };
1064 
1065 /*
1066  * Set individual keystation translation from old-style entry.
1067  * TODO: Have each keyboard own own translation tables.
1068  */
1069 static int
1070 kbdsetkey(register struct kbddata *kbdd, struct kiockey *key, cred_t *cr)
1071 {
1072 	int	strtabindex, i;
1073 	struct	keymap *km;
1074 	register int tablemask;
1075 	register ushort_t entry;
1076 
1077 	if (key->kio_station >= KEYMAP_SIZE)
1078 		return (EINVAL);
1079 	if (kbdd->kbdd_state.k_curkeyboard == NULL)
1080 		return (EINVAL);
1081 	tablemask = key->kio_tablemask;
1082 	if (tablemask == KIOCABORT1) {
1083 		if (secpolicy_console(cr) != 0)
1084 			return (EPERM);
1085 		kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station;
1086 		return (0);
1087 	}
1088 	if (tablemask == KIOCABORT2) {
1089 		if (secpolicy_console(cr) != 0)
1090 			return (EPERM);
1091 		kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station;
1092 		return (0);
1093 	}
1094 	if ((tablemask & ALTGRAPHMASK) ||
1095 	    (km = settable(kbdd, (uint_t)tablemask)) == NULL)
1096 		return (EINVAL);
1097 	if (key->kio_entry >= (uchar_t)OLD_STRING &&
1098 	    key->kio_entry <= (uchar_t)(OLD_STRING + 15)) {
1099 		strtabindex = key->kio_entry - OLD_STRING;
1100 		for (i = 0; i < KTAB_STRLEN; i++)
1101 			keystringtab[strtabindex][i] = key->kio_string[i];
1102 		keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
1103 	}
1104 	entry = key->kio_entry;
1105 	/*
1106 	 * There's nothing we need do with OLD_ISOCHAR.
1107 	 */
1108 	if (entry != OLD_ISOCHAR) {
1109 		if (entry & 0x80) {
1110 			if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE)
1111 				entry = FA_CLASS + (entry & 0x0F) - 9;
1112 			else
1113 				entry =
1114 				    special_old_to_new[entry >> 4 & 0x07]
1115 				    + (entry & 0x0F);
1116 		}
1117 	}
1118 	km->keymap[key->kio_station] = entry;
1119 	return (0);
1120 }
1121 
1122 /*
1123  * Map new special codes to old ones.
1124  * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
1125  */
1126 static uchar_t	special_new_to_old[] = {
1127 	0,			/* normal */
1128 	OLD_SHIFTKEYS,		/* SHIFTKEYS */
1129 	OLD_BUCKYBITS,		/* BUCKYBITS */
1130 	OLD_FUNNY,		/* FUNNY */
1131 	OLD_FA_UMLAUT,		/* FA_CLASS */
1132 	OLD_STRING,		/* STRING */
1133 	OLD_LEFTFUNC,		/* FUNCKEYS */
1134 };
1135 
1136 /*
1137  * Get individual keystation translation as old-style entry.
1138  */
1139 static int
1140 kbdgetkey(register struct kbddata *kbdd, struct	kiockey *key)
1141 {
1142 	int	strtabindex, i;
1143 	struct	keymap *km;
1144 	register ushort_t entry;
1145 
1146 	if (key->kio_station >= KEYMAP_SIZE)
1147 		return (EINVAL);
1148 	if (kbdd->kbdd_state.k_curkeyboard == NULL)
1149 		return (EINVAL);
1150 	if (key->kio_tablemask == KIOCABORT1) {
1151 		key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1;
1152 		return (0);
1153 	}
1154 	if (key->kio_tablemask == KIOCABORT2) {
1155 		key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2;
1156 		return (0);
1157 	}
1158 	if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
1159 		return (EINVAL);
1160 	entry = km->keymap[key->kio_station];
1161 	if (entry & 0xFF00)
1162 		key->kio_entry =
1163 		    special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8]
1164 		    + (entry & 0x00FF);
1165 	else {
1166 		if (entry & 0x80)
1167 			key->kio_entry = (ushort_t)OLD_ISOCHAR;	/* you lose */
1168 		else
1169 			key->kio_entry = (ushort_t)entry;
1170 	}
1171 	if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) {
1172 		strtabindex = entry - STRING;
1173 		for (i = 0; i < KTAB_STRLEN; i++)
1174 			key->kio_string[i] = keystringtab[strtabindex][i];
1175 	}
1176 	return (0);
1177 }
1178 
1179 /*
1180  * Set individual keystation translation from new-style entry.
1181  * TODO: Have each keyboard own own translation tables.
1182  */
1183 static int
1184 kbdskey(register struct kbddata *kbdd, struct kiockeymap *key, cred_t *cr)
1185 {
1186 	int	strtabindex, i;
1187 	struct	keymap *km;
1188 
1189 	if (key->kio_station >= KEYMAP_SIZE)
1190 		return (EINVAL);
1191 	if (kbdd->kbdd_state.k_curkeyboard == NULL)
1192 		return (EINVAL);
1193 	if (key->kio_tablemask == KIOCABORT1) {
1194 		if (secpolicy_console(cr) != 0)
1195 			return (EPERM);
1196 		kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station;
1197 		return (0);
1198 	}
1199 	if (key->kio_tablemask == KIOCABORT2) {
1200 		if (secpolicy_console(cr) != 0)
1201 			return (EPERM);
1202 		kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station;
1203 		return (0);
1204 	}
1205 	if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
1206 		return (EINVAL);
1207 	if (key->kio_entry >= STRING &&
1208 	    key->kio_entry <= (ushort_t)(STRING + 15)) {
1209 		strtabindex = key->kio_entry-STRING;
1210 		for (i = 0; i < KTAB_STRLEN; i++)
1211 			keystringtab[strtabindex][i] = key->kio_string[i];
1212 		keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
1213 	}
1214 	km->keymap[key->kio_station] = key->kio_entry;
1215 	return (0);
1216 }
1217 
1218 /*
1219  * Get individual keystation translation as new-style entry.
1220  */
1221 static int
1222 kbdgkey(register struct kbddata *kbdd, struct	kiockeymap *key)
1223 {
1224 	int	strtabindex, i;
1225 	struct	keymap *km;
1226 
1227 	if (key->kio_station >= KEYMAP_SIZE)
1228 		return (EINVAL);
1229 	if (kbdd->kbdd_state.k_curkeyboard == NULL)
1230 		return (EINVAL);
1231 	if (key->kio_tablemask == KIOCABORT1) {
1232 		key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1;
1233 		return (0);
1234 	}
1235 	if (key->kio_tablemask == KIOCABORT2) {
1236 		key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2;
1237 		return (0);
1238 	}
1239 	if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
1240 		return (EINVAL);
1241 	key->kio_entry = km->keymap[key->kio_station];
1242 	if (key->kio_entry >= STRING &&
1243 	    key->kio_entry <= (ushort_t)(STRING + 15)) {
1244 		strtabindex = key->kio_entry-STRING;
1245 		for (i = 0; i < KTAB_STRLEN; i++)
1246 			key->kio_string[i] = keystringtab[strtabindex][i];
1247 	}
1248 	return (0);
1249 }
1250 
1251 static void
1252 kbdlayouttimeout(void *arg)
1253 {
1254 	struct kbddata *kbdd = arg;
1255 	mblk_t *mp;
1256 
1257 	kbdd->kbdd_layoutid = 0;
1258 
1259 	/*
1260 	 * Timed out waiting for reply to "get keyboard layout" command.
1261 	 * Return an ETIME error.
1262 	 */
1263 	if ((mp = kbdd->kbdd_replypending) != NULL) {
1264 		kbdd->kbdd_replypending = NULL;
1265 		mp->b_datap->db_type = M_IOCNAK;
1266 		((struct iocblk *)mp->b_rptr)->ioc_error = ETIME;
1267 		putnext(kbdd->kbdd_readq, mp);
1268 	}
1269 }
1270 
1271 /*
1272  * Put procedure for input from driver end of stream (read queue).
1273  */
1274 static void
1275 kbdrput(register queue_t *q, register mblk_t *mp)
1276 {
1277 	struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
1278 	register mblk_t *bp;
1279 	register uchar_t *readp;
1280 	struct iocblk *iocp;
1281 
1282 	if (kbdd == 0) {
1283 		freemsg(mp);	/* nobody's listening */
1284 		return;
1285 	}
1286 
1287 	switch (mp->b_datap->db_type) {
1288 
1289 	case M_FLUSH:
1290 		if (*mp->b_rptr & FLUSHW)
1291 			flushq(WR(q), FLUSHDATA);
1292 		if (*mp->b_rptr & FLUSHR)
1293 			flushq(q, FLUSHDATA);
1294 
1295 	default:
1296 		putnext(q, mp);
1297 		return;
1298 
1299 	case M_BREAK:
1300 		/*
1301 		 * Will get M_BREAK only if this is not the system
1302 		 * keyboard, otherwise serial port will eat break
1303 		 * and call kmdb/OBP, without passing anything up.
1304 		 */
1305 		freemsg(mp);
1306 		return;
1307 
1308 	case M_IOCACK:
1309 	case M_IOCNAK:
1310 		/*
1311 		 * If we are doing an "ioctl" ourselves, check if this
1312 		 * is the reply to that code.  If so, wake up the
1313 		 * "open" routine, and toss the reply, otherwise just
1314 		 * pass it up.
1315 		 */
1316 		iocp = (struct iocblk *)mp->b_rptr;
1317 		if (!(kbdd->kbdd_flags & KBD_IOCWAIT) ||
1318 		    iocp->ioc_id != kbdd->kbdd_iocid) {
1319 			/*
1320 			 * This isn't the reply we're looking for.  Move along.
1321 			 */
1322 			if (kbdd->kbdd_flags & KBD_OPEN)
1323 				putnext(q, mp);
1324 			else
1325 				freemsg(mp);	/* not ready to listen */
1326 		} else {
1327 			kbdd->kbdd_flags &= ~KBD_IOCWAIT;
1328 			kbdd->kbdd_iocerror = iocp->ioc_error;
1329 			freemsg(mp);
1330 		}
1331 		return;
1332 
1333 	case M_DATA:
1334 		if (!(kbdd->kbdd_flags & KBD_OPEN)) {
1335 			freemsg(mp);	/* not read to listen */
1336 			return;
1337 		}
1338 		break;
1339 	}
1340 
1341 	/*
1342 	 * A data message, consisting of bytes from the keyboard.
1343 	 * Ram them through our state machine.
1344 	 */
1345 	bp = mp;
1346 
1347 	do {
1348 		readp = bp->b_rptr;
1349 		while (readp < bp->b_wptr)
1350 			kbdinput(kbdd, *readp++);
1351 		bp->b_rptr = readp;
1352 	} while ((bp = bp->b_cont) != NULL);	/* next block, if any */
1353 
1354 	freemsg(mp);
1355 }
1356 
1357 /*
1358  * A keypress was received. Process it through the state machine
1359  * to check for aborts.
1360  */
1361 static void
1362 kbdinput(register struct kbddata *kbdd, register unsigned key)
1363 {
1364 	register struct keyboardstate *k;
1365 	register mblk_t *mp;
1366 
1367 	k = &kbdd->kbdd_state;
1368 #ifdef	KBD_DEBUG
1369 	if (kbd_input_debug)
1370 		printf("kbdinput key %x\n", key);
1371 #endif
1372 
1373 	switch (k->k_idstate) {
1374 
1375 	case KID_NONE:
1376 		if (key == RESETKEY) {
1377 			k->k_idstate = KID_GOT_PREFACE;
1378 		} else  {
1379 			kbdreset(kbdd, HARD_RESET);
1380 			/* allows hot plug of kbd after booting without kbd */
1381 		}
1382 		return;
1383 
1384 	case KID_GOT_PREFACE:
1385 		kbdid(kbdd, (int)key);
1386 
1387 		/*
1388 		 * We just did a reset command to a Type 3 or Type 4
1389 		 * keyboard which sets the click back to the default
1390 		 * (which is currently ON!).  We use the kbdclick
1391 		 * variable to see if the keyboard should be turned on
1392 		 * or off.  If it has not been set, then we use the
1393 		 * keyboard-click? property.
1394 		 */
1395 		switch (kbdclick) {
1396 		case 0:
1397 			kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK);
1398 			break;
1399 		case 1:
1400 			kbdcmd(kbdd->kbdd_writeq, KBD_CMD_CLICK);
1401 			break;
1402 		case -1:
1403 		default:
1404 			{
1405 				char wrkbuf[8];
1406 				int len;
1407 
1408 				kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK);
1409 
1410 				bzero(wrkbuf, 8);
1411 				len = 7;
1412 				if (ddi_getlongprop_buf(DDI_DEV_T_ANY,
1413 				    ddi_root_node(), 0, "keyboard-click?",
1414 				    (caddr_t)wrkbuf, &len) ==
1415 				    DDI_PROP_SUCCESS &&
1416 				    len > 0 && len < 8) {
1417 					if (strcmp(wrkbuf, "true") == 0) {
1418 						kbdcmd(kbdd->kbdd_writeq,
1419 							KBD_CMD_CLICK);
1420 					}
1421 				}
1422 			}
1423 			break;
1424 		}
1425 		/*
1426 		 * A keyboard reset clears the LEDs.
1427 		 * Restore the LEDs from the last value we set
1428 		 * them to.
1429 		 */
1430 		kbdsetled(kbdd);
1431 		return;
1432 
1433 	case KID_OK:
1434 		switch (key) {
1435 
1436 #if	defined(KBD_PRESSED_PREFIX)
1437 		case KBD_PRESSED_PREFIX:
1438 			k->k_idstate = KID_GOT_PRESSED;
1439 			return;
1440 #endif
1441 
1442 #if	defined(KBD_RELEASED_PREFIX)
1443 		case KBD_RELEASED_PREFIX:
1444 			k->k_idstate = KID_GOT_RELEASED;
1445 			return;
1446 #endif
1447 
1448 		case 0:
1449 			kbdreset(kbdd, HARD_RESET);
1450 			return;
1451 
1452 		/*
1453 		 * we want to check for ID only if we are in
1454 		 * translatable mode.
1455 		 */
1456 		case RESETKEY:
1457 			kbdreset(kbdd, NO_HARD_RESET);
1458 			if (k->k_idstate == KID_NONE) {
1459 				k->k_idstate = KID_GOT_PREFACE;
1460 			}
1461 			return;
1462 
1463 		case LAYOUTKEY:
1464 			k->k_idstate = KID_GOT_LAYOUT;
1465 			return;
1466 		}
1467 		break;
1468 
1469 #if	defined(KBD_PRESSED_PREFIX)
1470 	case KID_GOT_PRESSED:
1471 		key = BUILDKEY(key, PRESSED);
1472 		k->k_idstate = KID_OK;
1473 		break;
1474 #endif
1475 #if	defined(KBD_RELEASED_PREFIX)
1476 	case KID_GOT_RELEASED:
1477 		key = BUILDKEY(key, RELEASED);
1478 		k->k_idstate = KID_OK;
1479 		break;
1480 #endif
1481 
1482 	case KID_GOT_LAYOUT:
1483 		if (kbdd->kbdd_layoutid)
1484 			(void) quntimeout(kbdd->kbdd_readq,
1485 			    kbdd->kbdd_layoutid);
1486 		if ((mp = kbdd->kbdd_replypending) != NULL) {
1487 			kbdd->kbdd_replypending = NULL;
1488 			*(int *)mp->b_cont->b_wptr = key;
1489 			mp->b_cont->b_wptr += sizeof (int);
1490 			putnext(kbdd->kbdd_readq, mp);
1491 		}
1492 		k->k_idstate = KID_OK;
1493 		return;
1494 	}
1495 
1496 	switch (k->k_state) {
1497 
1498 #if defined(__sparc)
1499 	normalstate:
1500 		k->k_state = NORMAL;
1501 		/* FALLTHRU */
1502 #endif
1503 	case NORMAL:
1504 #if defined(__sparc)
1505 		if (k->k_curkeyboard) {
1506 			if (key == k->k_curkeyboard->k_abort1) {
1507 				k->k_state = ABORT1;
1508 				break;
1509 			}
1510 			if ((key == k->k_curkeyboard->k_newabort1) ||
1511 			    (key == k->k_curkeyboard->k_newabort1a)) {
1512 				k->k_state = NEWABORT1;
1513 				break;
1514 			}
1515 		}
1516 #endif
1517 		kbduse(kbdd, key);
1518 		break;
1519 
1520 #if defined(__sparc)
1521 	case ABORT1:
1522 		if (k->k_curkeyboard) {
1523 			/*
1524 			 * Only recognize this as an abort sequence if
1525 			 * the "hardware" console is set to be this device.
1526 			 */
1527 			if (key == k->k_curkeyboard->k_abort2 &&
1528 			    rconsvp == wsconsvp) {
1529 				DELAY(100000);
1530 				abort_sequence_enter((char *)NULL);
1531 				k->k_state = NORMAL;
1532 				kbduse(kbdd, IDLEKEY);	/* fake */
1533 				return;
1534 			} else {
1535 				kbduse(kbdd, k->k_curkeyboard->k_abort1);
1536 				goto normalstate;
1537 			}
1538 		}
1539 		break;
1540 	case NEWABORT1:
1541 		if (k->k_curkeyboard) {
1542 			/*
1543 			 * Only recognize this as an abort sequence if
1544 			 * the "hardware" console is set to be this device.
1545 			 */
1546 			if (key == k->k_curkeyboard->k_newabort2 &&
1547 			    rconsvp == wsconsvp) {
1548 				DELAY(100000);
1549 				abort_sequence_enter((char *)NULL);
1550 				k->k_state = NORMAL;
1551 				kbduse(kbdd, IDLEKEY);	/* fake */
1552 				return;
1553 			} else {
1554 				kbduse(kbdd, k->k_curkeyboard->k_newabort1);
1555 				goto normalstate;
1556 			}
1557 		}
1558 		break;
1559 #endif
1560 
1561 	case COMPOSE1:
1562 	case COMPOSE2:
1563 	case FLTACCENT:
1564 		if (key != IDLEKEY)
1565 			kbduse(kbdd, key);
1566 		break;
1567 	}
1568 }
1569 
1570 static void
1571 kbdid(register struct kbddata *kbdd, int id)
1572 {
1573 	register struct keyboardstate *k;
1574 	int	i;
1575 
1576 	k = &kbdd->kbdd_state;
1577 
1578 	k->k_idstate = KID_OK;
1579 	k->k_shiftmask = 0;
1580 	k->k_buckybits = 0;
1581 
1582 	/*
1583 	 * Reset k_rptkey to IDLEKEY. We need to cancel
1584 	 * the autorepeat feature, if any.
1585 	 */
1586 	if (k->k_rptkey != IDLEKEY) {
1587 		if (kbdd->kbdd_rptid)
1588 			(void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
1589 		kbdd->kbdd_rptid = 0;
1590 		k->k_rptkey = IDLEKEY;
1591 	}
1592 
1593 	k->k_curkeyboard = NULL;
1594 	for (i = 0; keytables[i].table; i++) {
1595 		if (keytables[i].id == id) {
1596 			k->k_id = id;
1597 			k->k_curkeyboard = keytables[i].table;
1598 			break;
1599 		}
1600 	}
1601 	if (!k->k_curkeyboard) {
1602 		k->k_id = keytables[0].id;
1603 		k->k_curkeyboard = keytables[0].table;
1604 		cmn_err(CE_WARN, "kbd: Unknown keyboard type, "
1605 			"Type %d assumed", k->k_id);
1606 	}
1607 }
1608 
1609 /*
1610  * This routine determines which table we should look in to decode
1611  * the current keycode.
1612  */
1613 static struct keymap *
1614 settable(register struct kbddata *kbdd, register uint_t mask)
1615 {
1616 	register struct keyboard *kp;
1617 
1618 	kp = kbdd->kbdd_state.k_curkeyboard;
1619 	if (kp == NULL)
1620 		return (NULL);
1621 	if (mask & UPMASK)
1622 		return (kp->k_up);
1623 	if (mask & NUMLOCKMASK)
1624 		return (kp->k_numlock);
1625 	if (mask & CTRLMASK)
1626 		return (kp->k_control);
1627 	if (mask & ALTGRAPHMASK)
1628 		return (kp->k_altgraph);
1629 	if (mask & SHIFTMASK)
1630 		return (kp->k_shifted);
1631 	if (mask & CAPSMASK)
1632 		return (kp->k_caps);
1633 	return (kp->k_normal);
1634 }
1635 
1636 static void
1637 kbdrpt(void *arg)
1638 {
1639 	struct kbddata *kbdd = arg;
1640 	struct keyboardstate *k;
1641 
1642 	k = &kbdd->kbdd_state;
1643 #ifdef	KBD_DEBUG
1644 	if (kbd_rpt_debug)
1645 		printf("kbdrpt key %x\n", k->k_rptkey);
1646 #endif
1647 	kbdd->kbdd_rptid = 0;
1648 
1649 	kbdkeyreleased(kbdd, KEYOF(k->k_rptkey));
1650 	kbduse(kbdd, k->k_rptkey);
1651 	if (k->k_rptkey != IDLEKEY) {
1652 		kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt,
1653 		    kbdd, kbd_repeatrate);
1654 	}
1655 }
1656 
1657 static void
1658 kbdcancelrpt(register struct kbddata *kbdd)
1659 {
1660 	register struct keyboardstate *k;
1661 
1662 	k = &kbdd->kbdd_state;
1663 	if (k->k_rptkey != IDLEKEY) {
1664 		if (kbdd->kbdd_rptid)
1665 			(void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
1666 		kbdd->kbdd_rptid = 0;
1667 		k->k_rptkey = IDLEKEY;
1668 	}
1669 	ASSERT(kbdd->kbdd_rptid == 0);
1670 }
1671 
1672 static void
1673 kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q)
1674 {
1675 	register uchar_t key;
1676 	register unsigned newstate;
1677 	unsigned shiftmask;
1678 	register ushort_t entry, entrytype;
1679 	register char *cp, *bufp;
1680 	register struct keyboardstate *k;
1681 	ushort_t result_iso;
1682 	struct keymap *km;
1683 	Firm_event fe;
1684 	int i, ret_val;
1685 	char buf[14];
1686 
1687 	k = &kbdd->kbdd_state;
1688 	newstate = STATEOF(keycode);
1689 	key = KEYOF(keycode);
1690 
1691 #ifdef	KBD_DEBUG
1692 	if (kbd_input_debug) {
1693 		printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n",
1694 		    keycode, newstate, key);
1695 	}
1696 #endif
1697 
1698 	if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
1699 		if (newstate == PRESSED) {
1700 			bzero(&fe, sizeof (fe));
1701 			fe.id = key;
1702 			fe.value = 1;
1703 			kbdqueuepress(kbdd, key, &fe);
1704 		} else {
1705 			kbdkeyreleased(kbdd, key);
1706 		}
1707 		return;
1708 	}
1709 
1710 	shiftmask = k->k_shiftmask;
1711 	if (newstate == RELEASED)
1712 		shiftmask |= UPMASK;
1713 
1714 	km = settable(kbdd, shiftmask);
1715 	if (km == NULL) {		/* gross error */
1716 		kbdcancelrpt(kbdd);
1717 		return;
1718 	}
1719 
1720 	if (key >= KEYMAP_SIZE)
1721 		return;
1722 	entry = km->keymap[key];
1723 
1724 	if (entry == NONL) {
1725 		/*
1726 		 * NONL appears only in the Num Lock table, and indicates that
1727 		 * this key is not affected by Num Lock.  This means we should
1728 		 * ask for the table we would have gotten had Num Lock not been
1729 		 * down, and translate using that table.
1730 		 */
1731 		km = settable(kbdd, shiftmask & ~NUMLOCKMASK);
1732 		if (km == NULL) {		/* gross error */
1733 			kbdcancelrpt(kbdd);
1734 			return;
1735 		}
1736 		entry = km->keymap[key];
1737 	}
1738 	entrytype = (ushort_t)(entry & 0xFF00) >> 8;
1739 
1740 	if (entrytype == (SHIFTKEYS >> 8)) {
1741 		/*
1742 		 * Handle the state of toggle shifts specially.
1743 		 * Ups should be ignored, and downs should be mapped to ups if
1744 		 * that shift is currently on.
1745 		 */
1746 		if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) {
1747 			if ((1 << (entry & 0x0F)) & k->k_togglemask) {
1748 				newstate = RELEASED;	/* toggling off */
1749 			} else {
1750 				newstate = PRESSED;	/* toggling on */
1751 			}
1752 		}
1753 	} else {
1754 		/*
1755 		 * Handle Compose and floating accent key sequences
1756 		 */
1757 		if (k->k_state == COMPOSE1) {
1758 			if (newstate == RELEASED)
1759 				return;
1760 			if (entry < ASCII_SET_SIZE) {
1761 				if (kb_compose_map[entry] >= 0) {
1762 					kbdd->compose_key = entry;
1763 					k->k_state = COMPOSE2;
1764 					return;
1765 				}
1766 			}
1767 			k->k_state = NORMAL;
1768 			kbdd->led_state &= ~LED_COMPOSE;
1769 			kbdsetled(kbdd);
1770 			return;
1771 		} else if (k->k_state == COMPOSE2) {
1772 			if (newstate == RELEASED)
1773 				return;
1774 			k->k_state = NORMAL;	/* next state is "normal" */
1775 			kbdd->led_state &= ~LED_COMPOSE;
1776 			kbdsetled(kbdd);
1777 			if (entry < ASCII_SET_SIZE) {
1778 				if (kb_compose_map[entry] >= 0) {
1779 					if (kbdd->compose_key <= entry) {
1780 						ret_val = kbd_do_compose(
1781 							kbdd->compose_key,
1782 							entry,
1783 							&result_iso);
1784 					} else {
1785 						ret_val = kbd_do_compose(
1786 							entry,
1787 							kbdd->compose_key,
1788 							&result_iso);
1789 					}
1790 					if (ret_val == 1) {
1791 						if (kbdd->kbdd_translate ==
1792 								TR_EVENT) {
1793 							fe.id =
1794 							(kbdd->kbdd_compat ?
1795 							ISO_FIRST : EUC_FIRST)
1796 							+ result_iso;
1797 							fe.value = 1;
1798 							kbdqueueevent(
1799 								kbdd,
1800 								&fe);
1801 						} else if (
1802 							kbdd->kbdd_translate ==
1803 								TR_ASCII)
1804 							kbdputcode(
1805 								result_iso,
1806 								q);
1807 					}
1808 				}
1809 			}
1810 			return;
1811 		} else if (k->k_state == FLTACCENT) {
1812 			if (newstate == RELEASED)
1813 				return;
1814 			k->k_state = NORMAL;	/* next state is "normal" */
1815 			for (i = 0;
1816 			    (kb_fltaccent_table[i].fa_entry
1817 				!= kbdd->fltaccent_entry) ||
1818 			    (kb_fltaccent_table[i].ascii != entry);
1819 			    i++) {
1820 				if (kb_fltaccent_table[i].fa_entry == 0)
1821 					/* Invalid second key: ignore key */
1822 					return;
1823 			}
1824 			if (kbdd->kbdd_translate == TR_EVENT) {
1825 				fe.id = (kbdd->kbdd_compat ?
1826 					ISO_FIRST : EUC_FIRST)
1827 					+ kb_fltaccent_table[i].iso;
1828 				fe.value = 1;
1829 				kbdqueueevent(kbdd, &fe);
1830 			} else if (kbdd->kbdd_translate == TR_ASCII)
1831 				kbdputcode(kb_fltaccent_table[i].iso, q);
1832 			return;
1833 		}
1834 	}
1835 
1836 	/*
1837 	 * If the key is going down, and it's not one of the keys that doesn't
1838 	 * auto-repeat, set up the auto-repeat timeout.
1839 	 *
1840 	 * The keys that don't auto-repeat are the Compose key,
1841 	 * the shift keys, the "bucky bit" keys, the "floating accent" keys,
1842 	 * and the function keys when in TR_EVENT mode.
1843 	 */
1844 	if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) &&
1845 	    entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) &&
1846 	    entrytype != (FA_CLASS >> 8) &&
1847 	    !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) &&
1848 	    kbdd->kbdd_translate == TR_EVENT)) {
1849 		if (k->k_rptkey != keycode) {
1850 			kbdcancelrpt(kbdd);
1851 			kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd,
1852 			    kbd_repeatdelay);
1853 			k->k_rptkey = keycode;
1854 		}
1855 	} else if (key == KEYOF(k->k_rptkey))		/* key going up */
1856 		kbdcancelrpt(kbdd);
1857 	if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT))
1858 		kbdkeyreleased(kbdd, key);
1859 
1860 	/*
1861 	 * We assume here that keys other than shift keys and bucky keys have
1862 	 * entries in the "up" table that cause nothing to be done, and thus we
1863 	 * don't have to check for newstate == RELEASED.
1864 	 */
1865 	switch (entrytype) {
1866 
1867 	case 0x0:		/* regular key */
1868 		switch (kbdd->kbdd_translate) {
1869 
1870 		case TR_EVENT:
1871 			fe.id = entry | k->k_buckybits;
1872 			fe.value = 1;
1873 			kbdkeypressed(kbdd, key, &fe, entry);
1874 			break;
1875 
1876 		case TR_ASCII:
1877 			kbdputcode(entry | k->k_buckybits, q);
1878 			break;
1879 		}
1880 		break;
1881 
1882 	case SHIFTKEYS >> 8: {
1883 		uint_t shiftbit = 1 << (entry & 0x0F);
1884 
1885 		/* Modify toggle state (see toggle processing above) */
1886 		if (shiftbit & k->k_curkeyboard->k_toggleshifts) {
1887 			if (newstate == RELEASED) {
1888 				if (shiftbit == CAPSMASK) {
1889 					kbdd->led_state &= ~LED_CAPS_LOCK;
1890 					kbdsetled(kbdd);
1891 				} else if (shiftbit == NUMLOCKMASK) {
1892 					kbdd->led_state &= ~LED_NUM_LOCK;
1893 					kbdsetled(kbdd);
1894 				}
1895 				k->k_togglemask &= ~shiftbit;
1896 			} else {
1897 				if (shiftbit == CAPSMASK) {
1898 					kbdd->led_state |= LED_CAPS_LOCK;
1899 					kbdsetled(kbdd);
1900 				} else if (shiftbit == NUMLOCKMASK) {
1901 					kbdd->led_state |= LED_NUM_LOCK;
1902 					kbdsetled(kbdd);
1903 				}
1904 				k->k_togglemask |= shiftbit;
1905 			}
1906 		}
1907 
1908 		if (newstate == RELEASED)
1909 			k->k_shiftmask &= ~shiftbit;
1910 		else
1911 			k->k_shiftmask |= shiftbit;
1912 
1913 		if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
1914 			/*
1915 			 * Relying on ordinal correspondence between
1916 			 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1917 			 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1918 			 * correctly translate entry into fe.id.
1919 			 */
1920 			fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
1921 			fe.value = 1;
1922 			kbdkeypressed(kbdd, key, &fe, fe.id);
1923 		}
1924 		break;
1925 		}
1926 
1927 	case BUCKYBITS >> 8:
1928 		k->k_buckybits ^= 1 << (7 + (entry & 0x0F));
1929 		if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
1930 			/*
1931 			 * Relying on ordinal correspondence between
1932 			 * vuid_event.h SHIFT_META-SHIFT_TOP &
1933 			 * kbd.h METABIT-SYSTEMBIT in order to
1934 			 * correctly translate entry into fe.id.
1935 			 */
1936 			fe.id = SHIFT_META + (entry & 0x0F);
1937 			fe.value = 1;
1938 			kbdkeypressed(kbdd, key, &fe, fe.id);
1939 		}
1940 		break;
1941 
1942 	case FUNNY >> 8:
1943 		switch (entry) {
1944 		case NOP:
1945 			break;
1946 
1947 		case IDLE:
1948 			/* Fall thru into RESET code */
1949 			/* FALLTHRU */
1950 		case RESET:
1951 		gotreset:
1952 			k->k_shiftmask &= k->k_curkeyboard->k_idleshifts;
1953 			k->k_shiftmask |= k->k_togglemask;
1954 			k->k_buckybits &= k->k_curkeyboard->k_idlebuckys;
1955 			kbdcancelrpt(kbdd);
1956 			kbdreleaseall(kbdd);
1957 			break;
1958 
1959 		case ERROR:
1960 			cmn_err(CE_WARN, "kbd: Error detected");
1961 			goto gotreset;
1962 
1963 		case COMPOSE:
1964 			k->k_state = COMPOSE1;
1965 			kbdd->led_state |= LED_COMPOSE;
1966 			kbdsetled(kbdd);
1967 			break;
1968 		/*
1969 		 * Remember when adding new entries that,
1970 		 * if they should NOT auto-repeat,
1971 		 * they should be put into the IF statement
1972 		 * just above this switch block.
1973 		 */
1974 		default:
1975 			goto badentry;
1976 		}
1977 		break;
1978 
1979 	case FA_CLASS >> 8:
1980 		if (k->k_state == NORMAL) {
1981 			kbdd->fltaccent_entry = entry;
1982 			k->k_state = FLTACCENT;
1983 		}
1984 		return;
1985 
1986 	case STRING >> 8:
1987 		cp = &keystringtab[entry & 0x0F][0];
1988 		while (*cp != '\0') {
1989 			switch (kbdd->kbdd_translate) {
1990 
1991 			case TR_EVENT:
1992 				kbd_send_esc_event(*cp, kbdd);
1993 				break;
1994 
1995 			case TR_ASCII:
1996 				kbdputcode((uchar_t)*cp, q);
1997 				break;
1998 			}
1999 			cp++;
2000 		}
2001 		break;
2002 
2003 	case FUNCKEYS >> 8:
2004 		switch (kbdd->kbdd_translate) {
2005 
2006 		case TR_ASCII:
2007 			bufp = buf;
2008 			cp = strsetwithdecimal(bufp + 2,
2009 				(uint_t)((entry & 0x003F) + 192),
2010 				sizeof (buf) - 5);
2011 			*bufp++ = '\033'; /* Escape */
2012 			*bufp++ = '[';
2013 			while (*cp != '\0')
2014 				*bufp++ = *cp++;
2015 			*bufp++ = 'z';
2016 			*bufp = '\0';
2017 			kbdputbuf(buf, q);
2018 			break;
2019 
2020 		case TR_EVENT:
2021 			/*
2022 			 * Take advantage of the similar
2023 			 * ordering of kbd.h function keys and
2024 			 * vuid_event.h function keys to do a
2025 			 * simple translation to achieve a
2026 			 * mapping between the 2 different
2027 			 * address spaces.
2028 			 */
2029 			fe.id = (entry & 0x003F) + KEY_LEFTFIRST;
2030 			fe.value = 1;
2031 			/*
2032 			 * Assume "up" table only generates
2033 			 * shift changes.
2034 			 */
2035 			kbdkeypressed(kbdd, key, &fe, fe.id);
2036 			/*
2037 			 * Function key events can be expanded
2038 			 * by terminal emulator software to
2039 			 * produce the standard escape sequence
2040 			 * generated by the TR_ASCII case above
2041 			 * if a function key event is not used
2042 			 * by terminal emulator software
2043 			 * directly.
2044 			 */
2045 			break;
2046 		}
2047 		break;
2048 
2049 	/*
2050 	 * Remember when adding new entries that,
2051 	 * if they should NOT auto-repeat,
2052 	 * they should be put into the IF statement
2053 	 * just above this switch block.
2054 	 */
2055 	case PADKEYS >> 8:
2056 		switch (kbdd->kbdd_translate) {
2057 
2058 		case TR_ASCII:
2059 			kbdputcode(kb_numlock_table[entry&0x1F], q);
2060 			break;
2061 
2062 		case TR_EVENT:
2063 			/*
2064 			 * Take advantage of the similar
2065 			 * ordering of kbd.h keypad keys and
2066 			 * vuid_event.h keypad keys to do a
2067 			 * simple translation to achieve a
2068 			 * mapping between the 2 different
2069 			 * address spaces.
2070 			 */
2071 			fe.id = (entry & 0x001F) + VKEY_FIRSTPAD;
2072 			fe.value = 1;
2073 			/*
2074 			 * Assume "up" table only generates
2075 			 * shift changes.
2076 			 */
2077 			kbdkeypressed(kbdd, key, &fe, fe.id);
2078 			/*
2079 			 * Keypad key events can be expanded
2080 			 * by terminal emulator software to
2081 			 * produce the standard ascii character
2082 			 * generated by the TR_ASCII case above
2083 			 * if a keypad key event is not used
2084 			 * by terminal emulator software
2085 			 * directly.
2086 			 */
2087 			break;
2088 		}
2089 
2090 	badentry:
2091 		break;
2092 	}
2093 }
2094 
2095 static int
2096 kbd_do_compose(ushort_t first_entry, ushort_t second_entry,
2097 	ushort_t *result_iso_ptr)
2098 {
2099 	struct compose_sequence_t *ptr;
2100 
2101 	ptr = &kb_compose_table[kb_compose_map[first_entry]];
2102 	while (ptr->first == first_entry) {
2103 		if (ptr->second == second_entry) {
2104 			*result_iso_ptr = ptr->iso;
2105 			return (1);
2106 		}
2107 		ptr++;
2108 	}
2109 	return (0);
2110 }
2111 
2112 static void
2113 kbd_send_esc_event(char c, register struct kbddata *kbdd)
2114 {
2115 	Firm_event fe;
2116 
2117 	fe.id = c;
2118 	fe.value = 1;
2119 	fe.pair_type = FE_PAIR_NONE;
2120 	fe.pair = 0;
2121 	/*
2122 	 * Pretend as if each cp pushed and released
2123 	 * Calling kbdqueueevent avoids addr translation
2124 	 * and pair base determination of kbdkeypressed.
2125 	 */
2126 	kbdqueueevent(kbdd, &fe);
2127 	fe.value = 0;
2128 	kbdqueueevent(kbdd, &fe);
2129 }
2130 
2131 char *
2132 strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
2133 {
2134 	int	hradix = 5;
2135 	char	*bp;
2136 	int	lowbit;
2137 	char	*tab = "0123456789abcdef";
2138 
2139 	bp = buf + maxdigs;
2140 	*(--bp) = '\0';
2141 	while (val) {
2142 		lowbit = val & 1;
2143 		val = (val >> 1);
2144 		*(--bp) = tab[val % hradix * 2 + lowbit];
2145 		val /= hradix;
2146 	}
2147 	return (bp);
2148 }
2149 
2150 static void
2151 kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe,
2152     ushort_t base)
2153 {
2154 	register struct keyboardstate *k;
2155 	register short id_addr;
2156 
2157 	/* Set pair values */
2158 	if (fe->id < (ushort_t)VKEY_FIRST) {
2159 		/*
2160 		 * If CTRLed, find the ID that would have been used had it
2161 		 * not been CTRLed.
2162 		 */
2163 		k = &kbdd->kbdd_state;
2164 		if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) {
2165 			struct keymap *km;
2166 
2167 			km = settable(kbdd,
2168 			    k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK));
2169 			if (km == NULL)
2170 				return;
2171 			base = km->keymap[key_station];
2172 		}
2173 		if (base != fe->id) {
2174 			fe->pair_type = FE_PAIR_SET;
2175 			fe->pair = base;
2176 			goto send;
2177 		}
2178 	}
2179 	fe->pair_type = FE_PAIR_NONE;
2180 	fe->pair = 0;
2181 send:
2182 	/* Adjust event id address for multiple keyboard/workstation support */
2183 	switch (vuid_id_addr(fe->id)) {
2184 	case ASCII_FIRST:
2185 		id_addr = kbdd->kbdd_ascii_addr;
2186 		break;
2187 	case TOP_FIRST:
2188 		id_addr = kbdd->kbdd_top_addr;
2189 		break;
2190 	case VKEY_FIRST:
2191 		id_addr = kbdd->kbdd_vkey_addr;
2192 		break;
2193 	default:
2194 		id_addr = vuid_id_addr(fe->id);
2195 	}
2196 	fe->id = vuid_id_offset(fe->id) | id_addr;
2197 	kbdqueuepress(kbdd, key_station, fe);
2198 }
2199 
2200 static void
2201 kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe)
2202 {
2203 	register struct key_event *ke, *ke_free;
2204 	register int i;
2205 
2206 	if (key_station == IDLEKEY)
2207 		return;
2208 #ifdef	KBD_DEBUG
2209 	if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station);
2210 #endif
2211 	ke_free = 0;
2212 	/* Scan table of down key stations */
2213 	if (kbdd->kbdd_translate == TR_EVENT ||
2214 	    kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
2215 		for (i = 0, ke = kbdd->kbdd_downs;
2216 		    i < kbdd->kbdd_downs_entries;
2217 		    i++, ke++) {
2218 			/* Keycode already down? */
2219 			if (ke->key_station == key_station) {
2220 #ifdef	KBD_DEBUG
2221 	printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i);
2222 #endif
2223 				goto add_event;
2224 			}
2225 			if (ke->key_station == 0)
2226 				ke_free = ke;
2227 		}
2228 		if (ke_free) {
2229 			ke = ke_free;
2230 			goto add_event;
2231 		}
2232 		cmn_err(CE_WARN, "kbd: Too many keys down!");
2233 		ke = kbdd->kbdd_downs;
2234 	}
2235 add_event:
2236 	ke->key_station = key_station;
2237 	ke->event = *fe;
2238 	kbdqueueevent(kbdd, fe);
2239 }
2240 
2241 static void
2242 kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station)
2243 {
2244 	register struct key_event *ke;
2245 	register int i;
2246 
2247 	if (key_station == IDLEKEY)
2248 		return;
2249 #ifdef	KBD_DEBUG
2250 	if (kbd_input_debug)
2251 		printf("KBD RELEASE key=%d\n", key_station);
2252 #endif
2253 	if (kbdd->kbdd_translate != TR_EVENT &&
2254 	    kbdd->kbdd_translate != TR_UNTRANS_EVENT)
2255 		return;
2256 	/* Scan table of down key stations */
2257 	for (i = 0, ke = kbdd->kbdd_downs;
2258 	    i < kbdd->kbdd_downs_entries;
2259 	    i++, ke++) {
2260 		/* Found? */
2261 		if (ke->key_station == key_station) {
2262 			ke->key_station = 0;
2263 			ke->event.value = 0;
2264 			kbdqueueevent(kbdd, &ke->event);
2265 		}
2266 	}
2267 
2268 	/*
2269 	 * Ignore if couldn't find because may be called twice
2270 	 * for the same key station in the case of the kbdrpt
2271 	 * routine being called unnecessarily.
2272 	 */
2273 }
2274 
2275 static void
2276 kbdreleaseall(struct kbddata *kbdd)
2277 {
2278 	register struct key_event *ke;
2279 	register int i;
2280 
2281 #ifdef	KBD_DEBUG
2282 	if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n");
2283 #endif
2284 	/* Scan table of down key stations */
2285 	for (i = 0, ke = kbdd->kbdd_downs;
2286 	    i < kbdd->kbdd_downs_entries; i++, ke++) {
2287 		/* Key station not zero */
2288 		if (ke->key_station)
2289 			kbdkeyreleased(kbdd, ke->key_station);
2290 			/* kbdkeyreleased resets kbdd_downs entry */
2291 	}
2292 }
2293 
2294 /*
2295  * Pass a keycode up the stream, if you can, otherwise throw it away.
2296  */
2297 static void
2298 kbdputcode(uint_t code, queue_t *q)
2299 {
2300 	register mblk_t *bp;
2301 
2302 	if (!canput(q))
2303 		cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode");
2304 	else {
2305 		if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL)
2306 			cmn_err(CE_WARN,
2307 			    "kbdputcode: Can't allocate block for keycode");
2308 		else {
2309 			*bp->b_wptr++ = code;
2310 			putnext(q, bp);
2311 		}
2312 	}
2313 }
2314 
2315 /*
2316  * Pass  generated keycode sequence to upstream, if possible.
2317  */
2318 static void
2319 kbdputbuf(char *buf, queue_t *q)
2320 {
2321 	register mblk_t *bp;
2322 
2323 	if (!canput(q))
2324 		cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode");
2325 	else {
2326 		if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL)
2327 			cmn_err(CE_WARN,
2328 				"kbdputbuf: Can't allocate block for keycode");
2329 		else {
2330 			while (*buf) {
2331 				*bp->b_wptr++ = *buf;
2332 				buf++;
2333 			}
2334 			putnext(q, bp);
2335 		}
2336 	}
2337 }
2338 
2339 /*
2340  * Pass a VUID "firm event" up the stream, if you can.
2341  */
2342 static void
2343 kbdqueueevent(struct kbddata *kbdd, Firm_event *fe)
2344 {
2345 	register queue_t *q;
2346 	register mblk_t *bp;
2347 
2348 	if ((q = kbdd->kbdd_readq) == NULL)
2349 		return;
2350 	if (!canput(q)) {
2351 		if (kbd_overflow_msg)
2352 			cmn_err(CE_WARN,
2353 				"kbd: Buffer flushed when overflowed");
2354 		kbdflush(kbdd);
2355 		kbd_overflow_cnt++;
2356 	} else {
2357 		if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL)
2358 			cmn_err(CE_WARN,
2359 			    "kbdqueueevent: Can't allocate block for event");
2360 		else {
2361 #if 1 /* XX64 */
2362 			struct timeval now;
2363 
2364 			/*
2365 			 * XX64: This is something of a compromise.  It
2366 			 * seems justifiable based on the usage of these
2367 			 * timestamps as an ordering relation as opposed
2368 			 * to a strict timing thing.
2369 			 *
2370 			 * But should we restore Firm_event's time stamp
2371 			 * to be a timeval, and send 32-bit and 64-bit
2372 			 * events up the pipe?
2373 			 */
2374 			uniqtime(&now);
2375 			TIMEVAL_TO_TIMEVAL32(&fe->time, &now);
2376 #else
2377 			uniqtime(&fe->time);
2378 #endif
2379 			*(Firm_event *)bp->b_wptr = *fe;
2380 			bp->b_wptr += sizeof (Firm_event);
2381 			putnext(q, bp);
2382 		}
2383 	}
2384 }
2385