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