xref: /titanic_52/usr/src/uts/common/io/kbd.c (revision a83cadce5d3331b64803bfc641036cec23602c74)
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 	unsigned char shiftkey;		/* used for the new abort keys */
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 			if ((key == k->k_curkeyboard->k_newabort1) ||
1512 			    (key == k->k_curkeyboard->k_newabort1a)) {
1513 				k->k_state = NEWABORT1;
1514 				kbdd->shiftkey = key;
1515 			}
1516 		}
1517 #endif
1518 		kbduse(kbdd, key);
1519 		break;
1520 
1521 #if defined(__sparc)
1522 	case ABORT1:
1523 		if (k->k_curkeyboard) {
1524 			/*
1525 			 * Only recognize this as an abort sequence if
1526 			 * the "hardware" console is set to be this device.
1527 			 */
1528 			if (key == k->k_curkeyboard->k_abort2 &&
1529 			    rconsvp == wsconsvp) {
1530 				DELAY(100000);
1531 				abort_sequence_enter((char *)NULL);
1532 				k->k_state = NORMAL;
1533 				kbduse(kbdd, IDLEKEY);	/* fake */
1534 				return;
1535 			} else {
1536 				kbduse(kbdd, k->k_curkeyboard->k_abort1);
1537 				goto normalstate;
1538 			}
1539 		}
1540 		break;
1541 	case NEWABORT1:
1542 		if (k->k_curkeyboard) {
1543 			/*
1544 			 * Only recognize this as an abort sequence if
1545 			 * the "hardware" console is set to be this device.
1546 			 */
1547 			if (key == k->k_curkeyboard->k_newabort2 &&
1548 			    rconsvp == wsconsvp) {
1549 				DELAY(100000);
1550 				abort_sequence_enter((char *)NULL);
1551 				k->k_state = NORMAL;
1552 				kbdd->shiftkey |= RELEASED;
1553 				kbduse(kbdd, kbdd->shiftkey);
1554 				kbduse(kbdd, IDLEKEY);	/* fake */
1555 				return;
1556 			} else {
1557 				goto normalstate;
1558 			}
1559 		}
1560 		break;
1561 #endif
1562 
1563 	case COMPOSE1:
1564 	case COMPOSE2:
1565 	case FLTACCENT:
1566 		if (key != IDLEKEY)
1567 			kbduse(kbdd, key);
1568 		break;
1569 	}
1570 }
1571 
1572 static void
1573 kbdid(register struct kbddata *kbdd, int id)
1574 {
1575 	register struct keyboardstate *k;
1576 	int	i;
1577 
1578 	k = &kbdd->kbdd_state;
1579 
1580 	k->k_idstate = KID_OK;
1581 	k->k_shiftmask = 0;
1582 	k->k_buckybits = 0;
1583 
1584 	/*
1585 	 * Reset k_rptkey to IDLEKEY. We need to cancel
1586 	 * the autorepeat feature, if any.
1587 	 */
1588 	if (k->k_rptkey != IDLEKEY) {
1589 		if (kbdd->kbdd_rptid)
1590 			(void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
1591 		kbdd->kbdd_rptid = 0;
1592 		k->k_rptkey = IDLEKEY;
1593 	}
1594 
1595 	k->k_curkeyboard = NULL;
1596 	for (i = 0; keytables[i].table; i++) {
1597 		if (keytables[i].id == id) {
1598 			k->k_id = id;
1599 			k->k_curkeyboard = keytables[i].table;
1600 			break;
1601 		}
1602 	}
1603 	if (!k->k_curkeyboard) {
1604 		k->k_id = keytables[0].id;
1605 		k->k_curkeyboard = keytables[0].table;
1606 		cmn_err(CE_WARN, "kbd: Unknown keyboard type, "
1607 			"Type %d assumed", k->k_id);
1608 	}
1609 }
1610 
1611 /*
1612  * This routine determines which table we should look in to decode
1613  * the current keycode.
1614  */
1615 static struct keymap *
1616 settable(register struct kbddata *kbdd, register uint_t mask)
1617 {
1618 	register struct keyboard *kp;
1619 
1620 	kp = kbdd->kbdd_state.k_curkeyboard;
1621 	if (kp == NULL)
1622 		return (NULL);
1623 	if (mask & UPMASK)
1624 		return (kp->k_up);
1625 	if (mask & NUMLOCKMASK)
1626 		return (kp->k_numlock);
1627 	if (mask & CTRLMASK)
1628 		return (kp->k_control);
1629 	if (mask & ALTGRAPHMASK)
1630 		return (kp->k_altgraph);
1631 	if (mask & SHIFTMASK)
1632 		return (kp->k_shifted);
1633 	if (mask & CAPSMASK)
1634 		return (kp->k_caps);
1635 	return (kp->k_normal);
1636 }
1637 
1638 static void
1639 kbdrpt(void *arg)
1640 {
1641 	struct kbddata *kbdd = arg;
1642 	struct keyboardstate *k;
1643 
1644 	k = &kbdd->kbdd_state;
1645 #ifdef	KBD_DEBUG
1646 	if (kbd_rpt_debug)
1647 		printf("kbdrpt key %x\n", k->k_rptkey);
1648 #endif
1649 	kbdd->kbdd_rptid = 0;
1650 
1651 	kbdkeyreleased(kbdd, KEYOF(k->k_rptkey));
1652 	kbduse(kbdd, k->k_rptkey);
1653 	if (k->k_rptkey != IDLEKEY) {
1654 		kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt,
1655 		    kbdd, kbd_repeatrate);
1656 	}
1657 }
1658 
1659 static void
1660 kbdcancelrpt(register struct kbddata *kbdd)
1661 {
1662 	register struct keyboardstate *k;
1663 
1664 	k = &kbdd->kbdd_state;
1665 	if (k->k_rptkey != IDLEKEY) {
1666 		if (kbdd->kbdd_rptid)
1667 			(void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
1668 		kbdd->kbdd_rptid = 0;
1669 		k->k_rptkey = IDLEKEY;
1670 	}
1671 	ASSERT(kbdd->kbdd_rptid == 0);
1672 }
1673 
1674 static void
1675 kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q)
1676 {
1677 	register uchar_t key;
1678 	register unsigned newstate;
1679 	unsigned shiftmask;
1680 	register ushort_t entry, entrytype;
1681 	register char *cp, *bufp;
1682 	register struct keyboardstate *k;
1683 	ushort_t result_iso;
1684 	struct keymap *km;
1685 	Firm_event fe;
1686 	int i, ret_val;
1687 	char buf[14];
1688 
1689 	k = &kbdd->kbdd_state;
1690 	newstate = STATEOF(keycode);
1691 	key = KEYOF(keycode);
1692 
1693 #ifdef	KBD_DEBUG
1694 	if (kbd_input_debug) {
1695 		printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n",
1696 		    keycode, newstate, key);
1697 	}
1698 #endif
1699 
1700 	if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
1701 		if (newstate == PRESSED) {
1702 			bzero(&fe, sizeof (fe));
1703 			fe.id = key;
1704 			fe.value = 1;
1705 			kbdqueuepress(kbdd, key, &fe);
1706 		} else {
1707 			kbdkeyreleased(kbdd, key);
1708 		}
1709 		return;
1710 	}
1711 
1712 	shiftmask = k->k_shiftmask;
1713 	if (newstate == RELEASED)
1714 		shiftmask |= UPMASK;
1715 
1716 	km = settable(kbdd, shiftmask);
1717 	if (km == NULL) {		/* gross error */
1718 		kbdcancelrpt(kbdd);
1719 		return;
1720 	}
1721 
1722 	if (key >= KEYMAP_SIZE)
1723 		return;
1724 	entry = km->keymap[key];
1725 
1726 	if (entry == NONL) {
1727 		/*
1728 		 * NONL appears only in the Num Lock table, and indicates that
1729 		 * this key is not affected by Num Lock.  This means we should
1730 		 * ask for the table we would have gotten had Num Lock not been
1731 		 * down, and translate using that table.
1732 		 */
1733 		km = settable(kbdd, shiftmask & ~NUMLOCKMASK);
1734 		if (km == NULL) {		/* gross error */
1735 			kbdcancelrpt(kbdd);
1736 			return;
1737 		}
1738 		entry = km->keymap[key];
1739 	}
1740 	entrytype = (ushort_t)(entry & 0xFF00) >> 8;
1741 
1742 	if (entrytype == (SHIFTKEYS >> 8)) {
1743 		/*
1744 		 * Handle the state of toggle shifts specially.
1745 		 * Ups should be ignored, and downs should be mapped to ups if
1746 		 * that shift is currently on.
1747 		 */
1748 		if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) {
1749 			if ((1 << (entry & 0x0F)) & k->k_togglemask) {
1750 				newstate = RELEASED;	/* toggling off */
1751 			} else {
1752 				newstate = PRESSED;	/* toggling on */
1753 			}
1754 		}
1755 	} else {
1756 		/*
1757 		 * Handle Compose and floating accent key sequences
1758 		 */
1759 		if (k->k_state == COMPOSE1) {
1760 			if (newstate == RELEASED)
1761 				return;
1762 			if (entry < ASCII_SET_SIZE) {
1763 				if (kb_compose_map[entry] >= 0) {
1764 					kbdd->compose_key = entry;
1765 					k->k_state = COMPOSE2;
1766 					return;
1767 				}
1768 			}
1769 			k->k_state = NORMAL;
1770 			kbdd->led_state &= ~LED_COMPOSE;
1771 			kbdsetled(kbdd);
1772 			return;
1773 		} else if (k->k_state == COMPOSE2) {
1774 			if (newstate == RELEASED)
1775 				return;
1776 			k->k_state = NORMAL;	/* next state is "normal" */
1777 			kbdd->led_state &= ~LED_COMPOSE;
1778 			kbdsetled(kbdd);
1779 			if (entry < ASCII_SET_SIZE) {
1780 				if (kb_compose_map[entry] >= 0) {
1781 					if (kbdd->compose_key <= entry) {
1782 						ret_val = kbd_do_compose(
1783 							kbdd->compose_key,
1784 							entry,
1785 							&result_iso);
1786 					} else {
1787 						ret_val = kbd_do_compose(
1788 							entry,
1789 							kbdd->compose_key,
1790 							&result_iso);
1791 					}
1792 					if (ret_val == 1) {
1793 						if (kbdd->kbdd_translate ==
1794 								TR_EVENT) {
1795 							fe.id =
1796 							(kbdd->kbdd_compat ?
1797 							ISO_FIRST : EUC_FIRST)
1798 							+ result_iso;
1799 							fe.value = 1;
1800 							kbdqueueevent(
1801 								kbdd,
1802 								&fe);
1803 						} else if (
1804 							kbdd->kbdd_translate ==
1805 								TR_ASCII)
1806 							kbdputcode(
1807 								result_iso,
1808 								q);
1809 					}
1810 				}
1811 			}
1812 			return;
1813 		} else if (k->k_state == FLTACCENT) {
1814 			if (newstate == RELEASED)
1815 				return;
1816 			k->k_state = NORMAL;	/* next state is "normal" */
1817 			for (i = 0;
1818 			    (kb_fltaccent_table[i].fa_entry
1819 				!= kbdd->fltaccent_entry) ||
1820 			    (kb_fltaccent_table[i].ascii != entry);
1821 			    i++) {
1822 				if (kb_fltaccent_table[i].fa_entry == 0)
1823 					/* Invalid second key: ignore key */
1824 					return;
1825 			}
1826 			if (kbdd->kbdd_translate == TR_EVENT) {
1827 				fe.id = (kbdd->kbdd_compat ?
1828 					ISO_FIRST : EUC_FIRST)
1829 					+ kb_fltaccent_table[i].iso;
1830 				fe.value = 1;
1831 				kbdqueueevent(kbdd, &fe);
1832 			} else if (kbdd->kbdd_translate == TR_ASCII)
1833 				kbdputcode(kb_fltaccent_table[i].iso, q);
1834 			return;
1835 		}
1836 	}
1837 
1838 	/*
1839 	 * If the key is going down, and it's not one of the keys that doesn't
1840 	 * auto-repeat, set up the auto-repeat timeout.
1841 	 *
1842 	 * The keys that don't auto-repeat are the Compose key,
1843 	 * the shift keys, the "bucky bit" keys, the "floating accent" keys,
1844 	 * and the function keys when in TR_EVENT mode.
1845 	 */
1846 	if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) &&
1847 	    entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) &&
1848 	    entrytype != (FA_CLASS >> 8) &&
1849 	    !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) &&
1850 	    kbdd->kbdd_translate == TR_EVENT)) {
1851 		if (k->k_rptkey != keycode) {
1852 			kbdcancelrpt(kbdd);
1853 			kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd,
1854 			    kbd_repeatdelay);
1855 			k->k_rptkey = keycode;
1856 		}
1857 	} else if (key == KEYOF(k->k_rptkey))		/* key going up */
1858 		kbdcancelrpt(kbdd);
1859 	if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT))
1860 		kbdkeyreleased(kbdd, key);
1861 
1862 	/*
1863 	 * We assume here that keys other than shift keys and bucky keys have
1864 	 * entries in the "up" table that cause nothing to be done, and thus we
1865 	 * don't have to check for newstate == RELEASED.
1866 	 */
1867 	switch (entrytype) {
1868 
1869 	case 0x0:		/* regular key */
1870 		switch (kbdd->kbdd_translate) {
1871 
1872 		case TR_EVENT:
1873 			fe.id = entry | k->k_buckybits;
1874 			fe.value = 1;
1875 			kbdkeypressed(kbdd, key, &fe, entry);
1876 			break;
1877 
1878 		case TR_ASCII:
1879 			kbdputcode(entry | k->k_buckybits, q);
1880 			break;
1881 		}
1882 		break;
1883 
1884 	case SHIFTKEYS >> 8: {
1885 		uint_t shiftbit = 1 << (entry & 0x0F);
1886 
1887 		/* Modify toggle state (see toggle processing above) */
1888 		if (shiftbit & k->k_curkeyboard->k_toggleshifts) {
1889 			if (newstate == RELEASED) {
1890 				if (shiftbit == CAPSMASK) {
1891 					kbdd->led_state &= ~LED_CAPS_LOCK;
1892 					kbdsetled(kbdd);
1893 				} else if (shiftbit == NUMLOCKMASK) {
1894 					kbdd->led_state &= ~LED_NUM_LOCK;
1895 					kbdsetled(kbdd);
1896 				}
1897 				k->k_togglemask &= ~shiftbit;
1898 			} else {
1899 				if (shiftbit == CAPSMASK) {
1900 					kbdd->led_state |= LED_CAPS_LOCK;
1901 					kbdsetled(kbdd);
1902 				} else if (shiftbit == NUMLOCKMASK) {
1903 					kbdd->led_state |= LED_NUM_LOCK;
1904 					kbdsetled(kbdd);
1905 				}
1906 				k->k_togglemask |= shiftbit;
1907 			}
1908 		}
1909 
1910 		if (newstate == RELEASED)
1911 			k->k_shiftmask &= ~shiftbit;
1912 		else
1913 			k->k_shiftmask |= shiftbit;
1914 
1915 		if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
1916 			/*
1917 			 * Relying on ordinal correspondence between
1918 			 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1919 			 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1920 			 * correctly translate entry into fe.id.
1921 			 */
1922 			fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
1923 			fe.value = 1;
1924 			kbdkeypressed(kbdd, key, &fe, fe.id);
1925 		}
1926 		break;
1927 		}
1928 
1929 	case BUCKYBITS >> 8:
1930 		k->k_buckybits ^= 1 << (7 + (entry & 0x0F));
1931 		if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
1932 			/*
1933 			 * Relying on ordinal correspondence between
1934 			 * vuid_event.h SHIFT_META-SHIFT_TOP &
1935 			 * kbd.h METABIT-SYSTEMBIT in order to
1936 			 * correctly translate entry into fe.id.
1937 			 */
1938 			fe.id = SHIFT_META + (entry & 0x0F);
1939 			fe.value = 1;
1940 			kbdkeypressed(kbdd, key, &fe, fe.id);
1941 		}
1942 		break;
1943 
1944 	case FUNNY >> 8:
1945 		switch (entry) {
1946 		case NOP:
1947 			break;
1948 
1949 		case IDLE:
1950 			/* Fall thru into RESET code */
1951 			/* FALLTHRU */
1952 		case RESET:
1953 		gotreset:
1954 			k->k_shiftmask &= k->k_curkeyboard->k_idleshifts;
1955 			k->k_shiftmask |= k->k_togglemask;
1956 			k->k_buckybits &= k->k_curkeyboard->k_idlebuckys;
1957 			kbdcancelrpt(kbdd);
1958 			kbdreleaseall(kbdd);
1959 			break;
1960 
1961 		case ERROR:
1962 			cmn_err(CE_WARN, "kbd: Error detected");
1963 			goto gotreset;
1964 
1965 		case COMPOSE:
1966 			k->k_state = COMPOSE1;
1967 			kbdd->led_state |= LED_COMPOSE;
1968 			kbdsetled(kbdd);
1969 			break;
1970 		/*
1971 		 * Remember when adding new entries that,
1972 		 * if they should NOT auto-repeat,
1973 		 * they should be put into the IF statement
1974 		 * just above this switch block.
1975 		 */
1976 		default:
1977 			goto badentry;
1978 		}
1979 		break;
1980 
1981 	case FA_CLASS >> 8:
1982 		if (k->k_state == NORMAL) {
1983 			kbdd->fltaccent_entry = entry;
1984 			k->k_state = FLTACCENT;
1985 		}
1986 		return;
1987 
1988 	case STRING >> 8:
1989 		cp = &keystringtab[entry & 0x0F][0];
1990 		while (*cp != '\0') {
1991 			switch (kbdd->kbdd_translate) {
1992 
1993 			case TR_EVENT:
1994 				kbd_send_esc_event(*cp, kbdd);
1995 				break;
1996 
1997 			case TR_ASCII:
1998 				kbdputcode((uchar_t)*cp, q);
1999 				break;
2000 			}
2001 			cp++;
2002 		}
2003 		break;
2004 
2005 	case FUNCKEYS >> 8:
2006 		switch (kbdd->kbdd_translate) {
2007 
2008 		case TR_ASCII:
2009 			bufp = buf;
2010 			cp = strsetwithdecimal(bufp + 2,
2011 				(uint_t)((entry & 0x003F) + 192),
2012 				sizeof (buf) - 5);
2013 			*bufp++ = '\033'; /* Escape */
2014 			*bufp++ = '[';
2015 			while (*cp != '\0')
2016 				*bufp++ = *cp++;
2017 			*bufp++ = 'z';
2018 			*bufp = '\0';
2019 			kbdputbuf(buf, q);
2020 			break;
2021 
2022 		case TR_EVENT:
2023 			/*
2024 			 * Take advantage of the similar
2025 			 * ordering of kbd.h function keys and
2026 			 * vuid_event.h function keys to do a
2027 			 * simple translation to achieve a
2028 			 * mapping between the 2 different
2029 			 * address spaces.
2030 			 */
2031 			fe.id = (entry & 0x003F) + KEY_LEFTFIRST;
2032 			fe.value = 1;
2033 			/*
2034 			 * Assume "up" table only generates
2035 			 * shift changes.
2036 			 */
2037 			kbdkeypressed(kbdd, key, &fe, fe.id);
2038 			/*
2039 			 * Function key events can be expanded
2040 			 * by terminal emulator software to
2041 			 * produce the standard escape sequence
2042 			 * generated by the TR_ASCII case above
2043 			 * if a function key event is not used
2044 			 * by terminal emulator software
2045 			 * directly.
2046 			 */
2047 			break;
2048 		}
2049 		break;
2050 
2051 	/*
2052 	 * Remember when adding new entries that,
2053 	 * if they should NOT auto-repeat,
2054 	 * they should be put into the IF statement
2055 	 * just above this switch block.
2056 	 */
2057 	case PADKEYS >> 8:
2058 		switch (kbdd->kbdd_translate) {
2059 
2060 		case TR_ASCII:
2061 			kbdputcode(kb_numlock_table[entry&0x1F], q);
2062 			break;
2063 
2064 		case TR_EVENT:
2065 			/*
2066 			 * Take advantage of the similar
2067 			 * ordering of kbd.h keypad keys and
2068 			 * vuid_event.h keypad keys to do a
2069 			 * simple translation to achieve a
2070 			 * mapping between the 2 different
2071 			 * address spaces.
2072 			 */
2073 			fe.id = (entry & 0x001F) + VKEY_FIRSTPAD;
2074 			fe.value = 1;
2075 			/*
2076 			 * Assume "up" table only generates
2077 			 * shift changes.
2078 			 */
2079 			kbdkeypressed(kbdd, key, &fe, fe.id);
2080 			/*
2081 			 * Keypad key events can be expanded
2082 			 * by terminal emulator software to
2083 			 * produce the standard ascii character
2084 			 * generated by the TR_ASCII case above
2085 			 * if a keypad key event is not used
2086 			 * by terminal emulator software
2087 			 * directly.
2088 			 */
2089 			break;
2090 		}
2091 
2092 	badentry:
2093 		break;
2094 	}
2095 }
2096 
2097 static int
2098 kbd_do_compose(ushort_t first_entry, ushort_t second_entry,
2099 	ushort_t *result_iso_ptr)
2100 {
2101 	struct compose_sequence_t *ptr;
2102 
2103 	ptr = &kb_compose_table[kb_compose_map[first_entry]];
2104 	while (ptr->first == first_entry) {
2105 		if (ptr->second == second_entry) {
2106 			*result_iso_ptr = ptr->iso;
2107 			return (1);
2108 		}
2109 		ptr++;
2110 	}
2111 	return (0);
2112 }
2113 
2114 static void
2115 kbd_send_esc_event(char c, register struct kbddata *kbdd)
2116 {
2117 	Firm_event fe;
2118 
2119 	fe.id = c;
2120 	fe.value = 1;
2121 	fe.pair_type = FE_PAIR_NONE;
2122 	fe.pair = 0;
2123 	/*
2124 	 * Pretend as if each cp pushed and released
2125 	 * Calling kbdqueueevent avoids addr translation
2126 	 * and pair base determination of kbdkeypressed.
2127 	 */
2128 	kbdqueueevent(kbdd, &fe);
2129 	fe.value = 0;
2130 	kbdqueueevent(kbdd, &fe);
2131 }
2132 
2133 char *
2134 strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
2135 {
2136 	int	hradix = 5;
2137 	char	*bp;
2138 	int	lowbit;
2139 	char	*tab = "0123456789abcdef";
2140 
2141 	bp = buf + maxdigs;
2142 	*(--bp) = '\0';
2143 	while (val) {
2144 		lowbit = val & 1;
2145 		val = (val >> 1);
2146 		*(--bp) = tab[val % hradix * 2 + lowbit];
2147 		val /= hradix;
2148 	}
2149 	return (bp);
2150 }
2151 
2152 static void
2153 kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe,
2154     ushort_t base)
2155 {
2156 	register struct keyboardstate *k;
2157 	register short id_addr;
2158 
2159 	/* Set pair values */
2160 	if (fe->id < (ushort_t)VKEY_FIRST) {
2161 		/*
2162 		 * If CTRLed, find the ID that would have been used had it
2163 		 * not been CTRLed.
2164 		 */
2165 		k = &kbdd->kbdd_state;
2166 		if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) {
2167 			struct keymap *km;
2168 
2169 			km = settable(kbdd,
2170 			    k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK));
2171 			if (km == NULL)
2172 				return;
2173 			base = km->keymap[key_station];
2174 		}
2175 		if (base != fe->id) {
2176 			fe->pair_type = FE_PAIR_SET;
2177 			fe->pair = base;
2178 			goto send;
2179 		}
2180 	}
2181 	fe->pair_type = FE_PAIR_NONE;
2182 	fe->pair = 0;
2183 send:
2184 	/* Adjust event id address for multiple keyboard/workstation support */
2185 	switch (vuid_id_addr(fe->id)) {
2186 	case ASCII_FIRST:
2187 		id_addr = kbdd->kbdd_ascii_addr;
2188 		break;
2189 	case TOP_FIRST:
2190 		id_addr = kbdd->kbdd_top_addr;
2191 		break;
2192 	case VKEY_FIRST:
2193 		id_addr = kbdd->kbdd_vkey_addr;
2194 		break;
2195 	default:
2196 		id_addr = vuid_id_addr(fe->id);
2197 	}
2198 	fe->id = vuid_id_offset(fe->id) | id_addr;
2199 	kbdqueuepress(kbdd, key_station, fe);
2200 }
2201 
2202 static void
2203 kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe)
2204 {
2205 	register struct key_event *ke, *ke_free;
2206 	register int i;
2207 
2208 	if (key_station == IDLEKEY)
2209 		return;
2210 #ifdef	KBD_DEBUG
2211 	if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station);
2212 #endif
2213 	ke_free = 0;
2214 	/* Scan table of down key stations */
2215 	if (kbdd->kbdd_translate == TR_EVENT ||
2216 	    kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
2217 		for (i = 0, ke = kbdd->kbdd_downs;
2218 		    i < kbdd->kbdd_downs_entries;
2219 		    i++, ke++) {
2220 			/* Keycode already down? */
2221 			if (ke->key_station == key_station) {
2222 #ifdef	KBD_DEBUG
2223 	printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i);
2224 #endif
2225 				goto add_event;
2226 			}
2227 			if (ke->key_station == 0)
2228 				ke_free = ke;
2229 		}
2230 		if (ke_free) {
2231 			ke = ke_free;
2232 			goto add_event;
2233 		}
2234 		cmn_err(CE_WARN, "kbd: Too many keys down!");
2235 		ke = kbdd->kbdd_downs;
2236 	}
2237 add_event:
2238 	ke->key_station = key_station;
2239 	ke->event = *fe;
2240 	kbdqueueevent(kbdd, fe);
2241 }
2242 
2243 static void
2244 kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station)
2245 {
2246 	register struct key_event *ke;
2247 	register int i;
2248 
2249 	if (key_station == IDLEKEY)
2250 		return;
2251 #ifdef	KBD_DEBUG
2252 	if (kbd_input_debug)
2253 		printf("KBD RELEASE key=%d\n", key_station);
2254 #endif
2255 	if (kbdd->kbdd_translate != TR_EVENT &&
2256 	    kbdd->kbdd_translate != TR_UNTRANS_EVENT)
2257 		return;
2258 	/* Scan table of down key stations */
2259 	for (i = 0, ke = kbdd->kbdd_downs;
2260 	    i < kbdd->kbdd_downs_entries;
2261 	    i++, ke++) {
2262 		/* Found? */
2263 		if (ke->key_station == key_station) {
2264 			ke->key_station = 0;
2265 			ke->event.value = 0;
2266 			kbdqueueevent(kbdd, &ke->event);
2267 		}
2268 	}
2269 
2270 	/*
2271 	 * Ignore if couldn't find because may be called twice
2272 	 * for the same key station in the case of the kbdrpt
2273 	 * routine being called unnecessarily.
2274 	 */
2275 }
2276 
2277 static void
2278 kbdreleaseall(struct kbddata *kbdd)
2279 {
2280 	register struct key_event *ke;
2281 	register int i;
2282 
2283 #ifdef	KBD_DEBUG
2284 	if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n");
2285 #endif
2286 	/* Scan table of down key stations */
2287 	for (i = 0, ke = kbdd->kbdd_downs;
2288 	    i < kbdd->kbdd_downs_entries; i++, ke++) {
2289 		/* Key station not zero */
2290 		if (ke->key_station)
2291 			kbdkeyreleased(kbdd, ke->key_station);
2292 			/* kbdkeyreleased resets kbdd_downs entry */
2293 	}
2294 }
2295 
2296 /*
2297  * Pass a keycode up the stream, if you can, otherwise throw it away.
2298  */
2299 static void
2300 kbdputcode(uint_t code, queue_t *q)
2301 {
2302 	register mblk_t *bp;
2303 
2304 	if (!canput(q))
2305 		cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode");
2306 	else {
2307 		if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL)
2308 			cmn_err(CE_WARN,
2309 			    "kbdputcode: Can't allocate block for keycode");
2310 		else {
2311 			*bp->b_wptr++ = code;
2312 			putnext(q, bp);
2313 		}
2314 	}
2315 }
2316 
2317 /*
2318  * Pass  generated keycode sequence to upstream, if possible.
2319  */
2320 static void
2321 kbdputbuf(char *buf, queue_t *q)
2322 {
2323 	register mblk_t *bp;
2324 
2325 	if (!canput(q))
2326 		cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode");
2327 	else {
2328 		if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL)
2329 			cmn_err(CE_WARN,
2330 				"kbdputbuf: Can't allocate block for keycode");
2331 		else {
2332 			while (*buf) {
2333 				*bp->b_wptr++ = *buf;
2334 				buf++;
2335 			}
2336 			putnext(q, bp);
2337 		}
2338 	}
2339 }
2340 
2341 /*
2342  * Pass a VUID "firm event" up the stream, if you can.
2343  */
2344 static void
2345 kbdqueueevent(struct kbddata *kbdd, Firm_event *fe)
2346 {
2347 	register queue_t *q;
2348 	register mblk_t *bp;
2349 
2350 	if ((q = kbdd->kbdd_readq) == NULL)
2351 		return;
2352 	if (!canput(q)) {
2353 		if (kbd_overflow_msg)
2354 			cmn_err(CE_WARN,
2355 				"kbd: Buffer flushed when overflowed");
2356 		kbdflush(kbdd);
2357 		kbd_overflow_cnt++;
2358 	} else {
2359 		if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL)
2360 			cmn_err(CE_WARN,
2361 			    "kbdqueueevent: Can't allocate block for event");
2362 		else {
2363 #if 1 /* XX64 */
2364 			struct timeval now;
2365 
2366 			/*
2367 			 * XX64: This is something of a compromise.  It
2368 			 * seems justifiable based on the usage of these
2369 			 * timestamps as an ordering relation as opposed
2370 			 * to a strict timing thing.
2371 			 *
2372 			 * But should we restore Firm_event's time stamp
2373 			 * to be a timeval, and send 32-bit and 64-bit
2374 			 * events up the pipe?
2375 			 */
2376 			uniqtime(&now);
2377 			TIMEVAL_TO_TIMEVAL32(&fe->time, &now);
2378 #else
2379 			uniqtime(&fe->time);
2380 #endif
2381 			*(Firm_event *)bp->b_wptr = *fe;
2382 			bp->b_wptr += sizeof (Firm_event);
2383 			putnext(q, bp);
2384 		}
2385 	}
2386 }
2387