xref: /illumos-gate/usr/src/uts/common/io/kbtrans/kbtrans_streams.c (revision 17a5fa85fe0c34b1146222e40a80b42f2aae8500)
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 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Generic keyboard support:  streams and administration.
29  */
30 
31 #define	KEYMAP_SIZE_VARIABLE
32 
33 #include <sys/types.h>
34 #include <sys/cred.h>
35 #include <sys/stream.h>
36 #include <sys/stropts.h>
37 #include <sys/strsun.h>
38 #include <sys/ddi.h>
39 #include <sys/vuid_event.h>
40 #include <sys/modctl.h>
41 #include <sys/errno.h>
42 #include <sys/kmem.h>
43 #include <sys/cmn_err.h>
44 #include <sys/kbd.h>
45 #include <sys/kbio.h>
46 #include <sys/consdev.h>
47 #include <sys/kbtrans.h>
48 #include <sys/policy.h>
49 #include <sys/sunldi.h>
50 #include <sys/class.h>
51 #include <sys/spl.h>
52 #include "kbtrans_lower.h"
53 #include "kbtrans_streams.h"
54 
55 #ifdef DEBUG
56 int	kbtrans_errmask;
57 int	kbtrans_errlevel;
58 #endif
59 
60 #define	KB_NR_FUNCKEYS		12
61 
62 /*
63  * Repeat rates set in static variables so they can be tweeked with
64  * debugger.
65  */
66 static int kbtrans_repeat_count = -1;
67 static int kbtrans_repeat_rate;
68 static int kbtrans_repeat_delay;
69 
70 /* Printing message on q overflow */
71 static int kbtrans_overflow_msg = 1;
72 
73 /*
74  * This value corresponds approximately to max 10 fingers
75  */
76 static int	kbtrans_downs_size = 15;
77 
78 /*
79  * modload support
80  */
81 extern struct mod_ops mod_miscops;
82 
83 static struct modlmisc modlmisc	= {
84 	&mod_miscops,	/* Type	of module */
85 	"kbtrans (key translation)"
86 };
87 
88 static struct modlinkage modlinkage = {
89 	MODREV_1, (void	*)&modlmisc, NULL
90 };
91 
92 int
93 _init(void)
94 {
95 	return (mod_install(&modlinkage));
96 }
97 
98 int
99 _fini(void)
100 {
101 	return (mod_remove(&modlinkage));
102 }
103 
104 int
105 _info(struct modinfo *modinfop)
106 {
107 	return (mod_info(&modlinkage, modinfop));
108 }
109 
110 /*
111  * Internal Function Prototypes
112  */
113 static char *kbtrans_strsetwithdecimal(char *, uint_t, uint_t);
114 static void kbtrans_set_translation_callback(struct kbtrans *);
115 static void kbtrans_reioctl(void *);
116 static void kbtrans_send_esc_event(char, struct kbtrans *);
117 static void kbtrans_keypressed(struct kbtrans *, uchar_t, Firm_event *,
118     ushort_t);
119 static void kbtrans_putbuf(char *, queue_t *);
120 static void kbtrans_cancelrpt(struct kbtrans *);
121 static void kbtrans_queuepress(struct kbtrans *, uchar_t, Firm_event *);
122 static void kbtrans_putcode(register struct kbtrans *, uint_t);
123 static void kbtrans_keyreleased(struct kbtrans *, uchar_t);
124 static void kbtrans_queueevent(struct kbtrans *, Firm_event *);
125 static void kbtrans_untrans_keypressed_raw(struct kbtrans *, kbtrans_key_t);
126 static void kbtrans_untrans_keyreleased_raw(struct kbtrans *, kbtrans_key_t);
127 static void kbtrans_ascii_keypressed(struct kbtrans *, uint_t,
128     kbtrans_key_t, uint_t);
129 static void kbtrans_ascii_keyreleased(struct kbtrans *, kbtrans_key_t);
130 static void kbtrans_ascii_setup_repeat(struct kbtrans *, uint_t, kbtrans_key_t);
131 static void kbtrans_trans_event_keypressed(struct kbtrans *, uint_t,
132     kbtrans_key_t, uint_t);
133 static void kbtrans_trans_event_keyreleased(struct kbtrans *, kbtrans_key_t);
134 static void kbtrans_trans_event_setup_repeat(struct kbtrans *, uint_t,
135     kbtrans_key_t);
136 static void kbtrans_rpt(void *);
137 static void kbtrans_setled(struct kbtrans *);
138 static void kbtrans_flush(struct kbtrans *);
139 static enum kbtrans_message_response kbtrans_ioctl(struct kbtrans *, mblk_t *);
140 static int kbtrans_setkey(struct kbtrans_lower *, struct kiockey *, cred_t *);
141 static int kbtrans_getkey(struct kbtrans_lower *, struct kiockey *);
142 static int kbtrans_skey(struct kbtrans_lower *, struct kiockeymap *, cred_t *);
143 static int kbtrans_gkey(struct kbtrans_lower *, struct kiockeymap *);
144 
145 /*
146  * Keyboard Translation Mode (TR_NONE)
147  *
148  * Functions to be called when keyboard translation is turned off
149  * and up/down key codes are reported.
150  */
151 struct keyboard_callback	untrans_event_callback  = {
152 	kbtrans_untrans_keypressed_raw,
153 	kbtrans_untrans_keyreleased_raw,
154 	NULL,
155 	NULL,
156 	NULL,
157 	NULL,
158 	NULL,
159 };
160 
161 /*
162  * Keyboard Translation Mode (TR_ASCII)
163  *
164  * Functions to be called when ISO 8859/1 codes are reported
165  */
166 struct keyboard_callback	ascii_callback  = {
167 	NULL,
168 	NULL,
169 	kbtrans_ascii_keypressed,
170 	kbtrans_ascii_keyreleased,
171 	kbtrans_ascii_setup_repeat,
172 	kbtrans_cancelrpt,
173 	kbtrans_setled,
174 };
175 
176 /*
177  * Keyboard Translation Mode (TR_EVENT)
178  *
179  * Functions to be called when firm_events are reported.
180  */
181 struct keyboard_callback	trans_event_callback  = {
182 	NULL,
183 	NULL,
184 	kbtrans_trans_event_keypressed,
185 	kbtrans_trans_event_keyreleased,
186 	kbtrans_trans_event_setup_repeat,
187 	kbtrans_cancelrpt,
188 	kbtrans_setled,
189 };
190 
191 static void
192 progressbar_key_abort_thread(struct kbtrans *upper)
193 {
194 	ldi_ident_t li;
195 	extern void progressbar_key_abort(ldi_ident_t);
196 
197 	if (ldi_ident_from_stream(upper->kbtrans_streams_readq, &li) != 0) {
198 		cmn_err(CE_NOTE, "!ldi_ident_from_stream failed");
199 	} else {
200 		mutex_enter(&upper->progressbar_key_abort_lock);
201 		while (upper->progressbar_key_abort_flag == 0)
202 			cv_wait(&upper->progressbar_key_abort_cv,
203 			    &upper->progressbar_key_abort_lock);
204 		if (upper->progressbar_key_abort_flag == 1) {
205 			mutex_exit(&upper->progressbar_key_abort_lock);
206 			progressbar_key_abort(li);
207 		} else {
208 			mutex_exit(&upper->progressbar_key_abort_lock);
209 		}
210 		ldi_ident_release(li);
211 	}
212 
213 	thread_exit();
214 }
215 
216 /*
217  * kbtrans_streams_init:
218  *	Initialize the stream, keytables, callbacks, etc.
219  */
220 int
221 kbtrans_streams_init(queue_t *q, int sflag, struct kbtrans_hardware *hw,
222     struct kbtrans_callbacks *hw_cb, struct kbtrans **ret_kbd,
223     int initial_leds, int initial_led_mask)
224 {
225 	struct kbtrans *upper;
226 	struct kbtrans_lower *lower;
227 	kthread_t *tid;
228 
229 	/*
230 	 * Default to relatively generic tables.
231 	 */
232 	extern signed char			kb_compose_map[];
233 	extern struct compose_sequence_t	kb_compose_table[];
234 	extern struct fltaccent_sequence_t	kb_fltaccent_table[];
235 	extern char				keystringtab[][KTAB_STRLEN];
236 	extern unsigned char			kb_numlock_table[];
237 
238 	/* Set these up only once so that they could be changed from adb */
239 	if (!kbtrans_repeat_rate) {
240 		kbtrans_repeat_rate = (hz + 29) / 30;
241 		kbtrans_repeat_delay = hz / 2;
242 	}
243 
244 	switch (sflag) {
245 
246 	case MODOPEN:
247 		break;
248 
249 	case CLONEOPEN:
250 		DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (NULL,
251 		    "kbtrans_streams_init: Clone open not supported"));
252 
253 		return (EINVAL);
254 	}
255 
256 	/* allocate keyboard state structure */
257 	upper = kmem_zalloc(sizeof (struct kbtrans), KM_SLEEP);
258 
259 	*ret_kbd = upper;
260 
261 	upper->kbtrans_polled_buf[0] = '\0';
262 	upper->kbtrans_polled_pending_chars = upper->kbtrans_polled_buf;
263 
264 	upper->kbtrans_streams_hw = hw;
265 	upper->kbtrans_streams_hw_callbacks = hw_cb;
266 	upper->kbtrans_streams_readq = q;
267 	upper->kbtrans_streams_iocpending = NULL;
268 	upper->kbtrans_streams_translatable = TR_CAN;
269 	upper->kbtrans_overflow_cnt = 0;
270 	upper->kbtrans_streams_translate_mode = TR_ASCII;
271 
272 	/* Set the translation callback based on the translation type */
273 	kbtrans_set_translation_callback(upper);
274 
275 	lower = &upper->kbtrans_lower;
276 
277 	/*
278 	 * Set defaults for relatively generic tables.
279 	 */
280 	lower->kbtrans_compose_map = kb_compose_map;
281 	lower->kbtrans_compose_table = kb_compose_table;
282 	lower->kbtrans_fltaccent_table = kb_fltaccent_table;
283 	lower->kbtrans_numlock_table = kb_numlock_table;
284 	lower->kbtrans_keystringtab = keystringtab;
285 
286 	lower->kbtrans_upper = upper;
287 	lower->kbtrans_compat = 1;
288 
289 	/*
290 	 * We have a generic default for the LED state, and let the
291 	 * hardware-specific driver supply overrides.
292 	 */
293 	lower->kbtrans_led_state = 0;
294 	lower->kbtrans_led_state &= ~initial_led_mask;
295 	lower->kbtrans_led_state |= initial_leds;
296 	lower->kbtrans_togglemask = 0;
297 
298 	if (lower->kbtrans_led_state & LED_CAPS_LOCK)
299 		lower->kbtrans_togglemask |= CAPSMASK;
300 	if (lower->kbtrans_led_state & LED_NUM_LOCK)
301 		lower->kbtrans_togglemask |= NUMLOCKMASK;
302 
303 #if	defined(SCROLLMASK)
304 	if (lower->kbtrans_led_state & LED_SCROLL_LOCK)
305 		lower->kbtrans_togglemask |= SCROLLMASK;
306 #endif
307 
308 	lower->kbtrans_shiftmask = lower->kbtrans_togglemask;
309 
310 	upper->kbtrans_streams_vuid_addr.ascii = ASCII_FIRST;
311 	upper->kbtrans_streams_vuid_addr.top = TOP_FIRST;
312 	upper->kbtrans_streams_vuid_addr.vkey = VKEY_FIRST;
313 
314 	/* Allocate dynamic memory for downs table */
315 	upper->kbtrans_streams_num_downs_entries = kbtrans_downs_size;
316 	upper->kbtrans_streams_downs_bytes =
317 	    (uint32_t)(kbtrans_downs_size * sizeof (Key_event));
318 	upper->kbtrans_streams_downs =
319 	    kmem_zalloc(upper->kbtrans_streams_downs_bytes, KM_SLEEP);
320 	upper->kbtrans_streams_abortable = B_FALSE;
321 
322 	upper->kbtrans_streams_flags = KBTRANS_STREAMS_OPEN;
323 
324 	upper->progressbar_key_abort_flag = 0;
325 	cv_init(&upper->progressbar_key_abort_cv, NULL, CV_DEFAULT, NULL);
326 	/* this counts on no keyboards being above ipl 12 */
327 	mutex_init(&upper->progressbar_key_abort_lock, NULL, MUTEX_SPIN,
328 	    (void *)ipltospl(12));
329 	tid = thread_create(NULL, 0, progressbar_key_abort_thread, upper,
330 	    0, &p0, TS_RUN, minclsyspri);
331 	upper->progressbar_key_abort_t_did = tid->t_did;
332 
333 	DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (upper, "kbtrans_streams_init "
334 	    "exiting"));
335 	return (0);
336 }
337 
338 
339 /*
340  * kbtrans_streams_fini:
341  *	Free structures and uninitialize the stream
342  */
343 int
344 kbtrans_streams_fini(struct kbtrans *upper)
345 {
346 	/*
347 	 * Since we're about to destroy our private data, turn off
348 	 * our open flag first, so we don't accept any more input
349 	 * and try to use that data.
350 	 */
351 	upper->kbtrans_streams_flags = 0;
352 
353 	/* clear all timeouts */
354 	if (upper->kbtrans_streams_bufcallid) {
355 		qunbufcall(upper->kbtrans_streams_readq,
356 		    upper->kbtrans_streams_bufcallid);
357 	}
358 	if (upper->kbtrans_streams_rptid) {
359 		(void) quntimeout(upper->kbtrans_streams_readq,
360 		    upper->kbtrans_streams_rptid);
361 	}
362 	kmem_free(upper->kbtrans_streams_downs,
363 	    upper->kbtrans_streams_downs_bytes);
364 
365 	mutex_enter(&upper->progressbar_key_abort_lock);
366 	if (upper->progressbar_key_abort_flag == 0) {
367 		upper->progressbar_key_abort_flag = 2;
368 		cv_signal(&upper->progressbar_key_abort_cv);
369 		mutex_exit(&upper->progressbar_key_abort_lock);
370 		thread_join(upper->progressbar_key_abort_t_did);
371 	} else {
372 		mutex_exit(&upper->progressbar_key_abort_lock);
373 	}
374 	cv_destroy(&upper->progressbar_key_abort_cv);
375 	mutex_destroy(&upper->progressbar_key_abort_lock);
376 
377 	kmem_free(upper, sizeof (struct kbtrans));
378 
379 	DPRINTF(PRINT_L1, PRINT_MASK_CLOSE, (upper, "kbtrans_streams_fini "
380 	    "exiting"));
381 	return (0);
382 }
383 
384 /*
385  * kbtrans_streams_releaseall :
386  *	This function releases all the held keys.
387  */
388 void
389 kbtrans_streams_releaseall(struct kbtrans *upper)
390 {
391 	register struct key_event *ke;
392 	register int i;
393 
394 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "USBKBM RELEASE ALL\n"));
395 
396 	/* Scan table of down key stations */
397 	for (i = 0, ke = upper->kbtrans_streams_downs;
398 	    i < upper->kbtrans_streams_num_downs_entries; i++, ke++) {
399 
400 		/* Key station not zero */
401 		if (ke->key_station) {
402 
403 			kbtrans_keyreleased(upper, ke->key_station);
404 			/* kbtrans_keyreleased resets downs entry */
405 		}
406 	}
407 }
408 
409 /*
410  * kbtrans_streams_message:
411  *	keyboard module output queue put procedure: handles M_IOCTL
412  *	messages.
413  *
414  *	Return KBTRANS_MESSAGE_HANDLED if the message was handled by
415  *	kbtrans and KBTRANS_MESSAGE_NOT_HANDLED otherwise. If
416  *	KBTRANS_MESSAGE_HANDLED is returned, no further action is required.
417  *	If KBTRANS_MESSAGE_NOT_HANDLED is returned, the hardware module
418  *	is responsible for any action.
419  */
420 enum kbtrans_message_response
421 kbtrans_streams_message(struct kbtrans *upper, register mblk_t *mp)
422 {
423 	queue_t *q = upper->kbtrans_streams_readq;
424 	enum kbtrans_message_response ret;
425 
426 	DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper,
427 	    "kbtrans_streams_message entering"));
428 	/*
429 	 * Process M_FLUSH, and some M_IOCTL, messages here; pass
430 	 * everything else down.
431 	 */
432 	switch (mp->b_datap->db_type) {
433 
434 	case M_IOCTL:
435 		ret = kbtrans_ioctl(upper, mp);
436 		break;
437 
438 	case M_FLUSH:
439 		if (*mp->b_rptr & FLUSHW)
440 			flushq(q, FLUSHDATA);
441 		if (*mp->b_rptr & FLUSHR)
442 			flushq(RD(q), FLUSHDATA);
443 		/*
444 		 * White lie:  we say we didn't handle the message,
445 		 * so that it gets handled by our client.
446 		 */
447 		ret = KBTRANS_MESSAGE_NOT_HANDLED;
448 		break;
449 
450 	default:
451 		ret = KBTRANS_MESSAGE_NOT_HANDLED;
452 		break;
453 
454 	}
455 	DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper,
456 	    "kbtrans_streams_message exiting\n"));
457 
458 	return (ret);
459 }
460 
461 /*
462  * kbtrans_streams_key:
463  *	When a key is pressed or released, the hardware module should
464  *	call kbtrans, passing the key number and its new
465  *	state.  kbtrans is responsible for autorepeat handling;
466  *	the hardware module should report only actual press/release
467  *	events, suppressing any hardware-generated autorepeat.
468  */
469 void
470 kbtrans_streams_key(struct kbtrans *upper, kbtrans_key_t key,
471     enum keystate state)
472 {
473 	struct kbtrans_lower *lower;
474 	struct keyboard *kp;
475 
476 	lower = &upper->kbtrans_lower;
477 	kp = lower->kbtrans_keyboard;
478 
479 	/* trigger switch back to text mode */
480 	mutex_enter(&upper->progressbar_key_abort_lock);
481 	if (upper->progressbar_key_abort_flag == 0) {
482 		upper->progressbar_key_abort_flag = 1;
483 		cv_signal(&upper->progressbar_key_abort_cv);
484 	}
485 	mutex_exit(&upper->progressbar_key_abort_lock);
486 
487 	if (upper->kbtrans_streams_abortable) {
488 		switch (upper->kbtrans_streams_abort_state) {
489 		case ABORT_NORMAL:
490 			if (state != KEY_PRESSED)
491 				break;
492 
493 			if (key == (kbtrans_key_t)kp->k_abort1 ||
494 			    key == (kbtrans_key_t)kp->k_abort1a) {
495 				upper->kbtrans_streams_abort_state =
496 				    ABORT_ABORT1_RECEIVED;
497 				upper->kbtrans_streams_abort1_key = key;
498 				return;
499 			}
500 			/* Shift key needs to be sent to upper immediately */
501 			if (key == (kbtrans_key_t)kp->k_newabort1 ||
502 			    key == (kbtrans_key_t)kp->k_newabort1a) {
503 				upper->kbtrans_streams_abort_state =
504 				    NEW_ABORT_ABORT1_RECEIVED;
505 				upper->kbtrans_streams_new_abort1_key = key;
506 			}
507 			break;
508 		case ABORT_ABORT1_RECEIVED:
509 			upper->kbtrans_streams_abort_state = ABORT_NORMAL;
510 			if (state == KEY_PRESSED &&
511 			    key == (kbtrans_key_t)kp->k_abort2) {
512 				abort_sequence_enter((char *)NULL);
513 				return;
514 			} else {
515 				kbtrans_processkey(lower,
516 				    upper->kbtrans_streams_callback,
517 				    upper->kbtrans_streams_abort1_key,
518 				    KEY_PRESSED);
519 			}
520 			break;
521 		case NEW_ABORT_ABORT1_RECEIVED:
522 			upper->kbtrans_streams_abort_state = ABORT_NORMAL;
523 			if (state == KEY_PRESSED &&
524 			    key == (kbtrans_key_t)kp->k_newabort2) {
525 				abort_sequence_enter((char *)NULL);
526 				kbtrans_processkey(lower,
527 				    upper->kbtrans_streams_callback,
528 				    upper->kbtrans_streams_new_abort1_key,
529 				    KEY_RELEASED);
530 				return;
531 			}
532 		}
533 	}
534 
535 	kbtrans_processkey(lower, upper->kbtrans_streams_callback, key, state);
536 }
537 
538 /*
539  * kbtrans_streams_set_keyboard:
540  *	At any time after calling kbtrans_streams_init, the hardware
541  *	module should make this call to report the id of the keyboard
542  *	attached. id is the keyboard type, typically KB_SUN4,
543  *	KB_PC, or KB_USB.
544  */
545 void
546 kbtrans_streams_set_keyboard(struct kbtrans *upper, int id, struct keyboard *k)
547 {
548 	upper->kbtrans_lower.kbtrans_keyboard = k;
549 	upper->kbtrans_streams_id = id;
550 }
551 
552 /*
553  * kbtrans_streams_has_reset:
554  *	At any time between kbtrans_streams_init and kbtrans_streams_fini,
555  *	the hardware module can call this routine to report that the
556  *	keyboard has been reset, e.g. by being unplugged and reattached.
557  */
558 /*ARGSUSED*/
559 void
560 kbtrans_streams_has_reset(struct kbtrans *upper)
561 {
562 	/*
563 	 * If this routine is implemented it should probably (a)
564 	 * simulate releases of all pressed keys and (b) call
565 	 * the hardware module to set the LEDs.
566 	 */
567 }
568 
569 /*
570  * kbtrans_streams_enable:
571  *	This is the routine that is called back when the the stream is ready
572  *	to take messages.
573  */
574 void
575 kbtrans_streams_enable(struct kbtrans *upper)
576 {
577 	/* Set the LED's */
578 	kbtrans_setled(upper);
579 }
580 
581 /*
582  * kbtrans_streams_setled():
583  *	This is the routine that is called to only update the led state
584  *	in kbtrans.
585  */
586 void
587 kbtrans_streams_setled(struct kbtrans *upper, int led_state)
588 {
589 	struct kbtrans_lower *lower;
590 
591 	lower = &upper->kbtrans_lower;
592 	lower->kbtrans_led_state = (uchar_t)led_state;
593 
594 	if (lower->kbtrans_led_state & LED_CAPS_LOCK)
595 		lower->kbtrans_togglemask |= CAPSMASK;
596 	if (lower->kbtrans_led_state & LED_NUM_LOCK)
597 		lower->kbtrans_togglemask |= NUMLOCKMASK;
598 
599 #if	defined(SCROLLMASK)
600 	if (lower->kbtrans_led_state & LED_SCROLL_LOCK)
601 		lower->kbtrans_togglemask |= SCROLLMASK;
602 #endif
603 
604 	lower->kbtrans_shiftmask = lower->kbtrans_togglemask;
605 
606 }
607 
608 /*
609  * kbtrans_streams_set_queue:
610  *      Set the overlying queue, to support multiplexors.
611  */
612 void
613 kbtrans_streams_set_queue(struct kbtrans *upper, queue_t *q)
614 {
615 
616 	upper->kbtrans_streams_readq = q;
617 }
618 
619 /*
620  * kbtrans_streams_get_queue:
621  *      Return the overlying queue.
622  */
623 queue_t *
624 kbtrans_streams_get_queue(struct kbtrans *upper)
625 {
626 	return (upper->kbtrans_streams_readq);
627 }
628 
629 /*
630  * kbtrans_streams_untimeout
631  *      Cancell all timeout
632  */
633 void
634 kbtrans_streams_untimeout(struct kbtrans *upper)
635 {
636 	/* clear all timeouts */
637 	if (upper->kbtrans_streams_bufcallid) {
638 		qunbufcall(upper->kbtrans_streams_readq,
639 		    upper->kbtrans_streams_bufcallid);
640 		upper->kbtrans_streams_bufcallid = 0;
641 	}
642 	if (upper->kbtrans_streams_rptid) {
643 		(void) quntimeout(upper->kbtrans_streams_readq,
644 		    upper->kbtrans_streams_rptid);
645 		upper->kbtrans_streams_rptid = 0;
646 	}
647 }
648 
649 /*
650  * kbtrans_reioctl:
651  *	This function is set up as call-back function should an ioctl fail
652  *	to allocate required resources.
653  */
654 static void
655 kbtrans_reioctl(void	*arg)
656 {
657 	struct kbtrans *upper = (struct kbtrans *)arg;
658 	mblk_t *mp;
659 
660 	upper->kbtrans_streams_bufcallid = 0;
661 
662 	if ((mp = upper->kbtrans_streams_iocpending) != NULL) {
663 		/* not pending any more */
664 		upper->kbtrans_streams_iocpending = NULL;
665 		(void) kbtrans_ioctl(upper, mp);
666 	}
667 }
668 
669 /*
670  * kbtrans_ioctl:
671  *	process ioctls we recognize and own.  Otherwise, pass it down.
672  */
673 static enum kbtrans_message_response
674 kbtrans_ioctl(struct kbtrans *upper, register mblk_t *mp)
675 {
676 	register struct iocblk *iocp;
677 	register short	new_translate;
678 	register Vuid_addr_probe *addr_probe;
679 	register short	*addr_ptr;
680 	size_t	ioctlrespsize;
681 	int	err = 0;
682 	struct kbtrans_lower *lower;
683 	mblk_t *datap;
684 	int	translate;
685 
686 	static int kiocgetkey, kiocsetkey;
687 
688 	lower = &upper->kbtrans_lower;
689 
690 	iocp = (struct iocblk *)mp->b_rptr;
691 
692 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper,
693 	    "kbtrans_ioctl: ioc_cmd 0x%x - ", iocp->ioc_cmd));
694 	switch (iocp->ioc_cmd) {
695 
696 	case VUIDSFORMAT:
697 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSFORMAT\n"));
698 
699 		err = miocpullup(mp, sizeof (int));
700 		if (err != 0)
701 			break;
702 		new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
703 		    TR_ASCII : TR_EVENT;
704 
705 		if (new_translate == upper->kbtrans_streams_translate_mode)
706 			break;
707 		upper->kbtrans_streams_translate_mode = new_translate;
708 
709 		kbtrans_set_translation_callback(upper);
710 
711 		kbtrans_flush(upper);
712 		break;
713 
714 	case KIOCTRANS:
715 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANS\n"));
716 		err = miocpullup(mp, sizeof (int));
717 		if (err != 0)
718 			break;
719 		new_translate = *(int *)mp->b_cont->b_rptr;
720 		if (new_translate == upper->kbtrans_streams_translate_mode)
721 			break;
722 		upper->kbtrans_streams_translate_mode = new_translate;
723 		kbtrans_set_translation_callback(upper);
724 
725 		kbtrans_flush(upper);
726 		break;
727 
728 	case KIOCSLED:
729 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSLED\n"));
730 
731 		err = miocpullup(mp, sizeof (uchar_t));
732 		if (err != 0)
733 			break;
734 		lower->kbtrans_led_state = *(uchar_t *)mp->b_cont->b_rptr;
735 
736 		kbtrans_setled(upper);
737 		break;
738 
739 	case KIOCGLED:
740 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGLED\n"));
741 		if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
742 			ioctlrespsize = sizeof (int);
743 			goto allocfailure;
744 		}
745 
746 		*(uchar_t *)datap->b_wptr = lower->kbtrans_led_state;
747 		datap->b_wptr += sizeof (uchar_t);
748 		if (mp->b_cont)
749 			freemsg(mp->b_cont);
750 		mp->b_cont = datap;
751 		iocp->ioc_count = sizeof (uchar_t);
752 		break;
753 
754 	case VUIDGFORMAT:
755 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGFORMAT\n"));
756 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
757 			ioctlrespsize = sizeof (int);
758 			goto allocfailure;
759 		}
760 		*(int *)datap->b_wptr =
761 		    (upper->kbtrans_streams_translate_mode == TR_EVENT ||
762 		    upper->kbtrans_streams_translate_mode == TR_UNTRANS_EVENT) ?
763 		    VUID_FIRM_EVENT: VUID_NATIVE;
764 		datap->b_wptr += sizeof (int);
765 		if (mp->b_cont)  /* free msg to prevent memory leak */
766 			freemsg(mp->b_cont);
767 		mp->b_cont = datap;
768 		iocp->ioc_count = sizeof (int);
769 		break;
770 
771 	case KIOCGTRANS:
772 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANS\n"));
773 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
774 			ioctlrespsize = sizeof (int);
775 			goto allocfailure;
776 		}
777 		*(int *)datap->b_wptr = upper->kbtrans_streams_translate_mode;
778 		datap->b_wptr += sizeof (int);
779 		if (mp->b_cont)  /* free msg to prevent memory leak */
780 			freemsg(mp->b_cont);
781 		mp->b_cont = datap;
782 		iocp->ioc_count = sizeof (int);
783 		break;
784 
785 	case VUIDSADDR:
786 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSADDR\n"));
787 
788 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
789 		if (err != 0)
790 			break;
791 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
792 		switch (addr_probe->base) {
793 
794 		case ASCII_FIRST:
795 			addr_ptr = &upper->kbtrans_streams_vuid_addr.ascii;
796 			break;
797 
798 		case TOP_FIRST:
799 			addr_ptr = &upper->kbtrans_streams_vuid_addr.top;
800 			break;
801 
802 		case VKEY_FIRST:
803 			addr_ptr = &upper->kbtrans_streams_vuid_addr.vkey;
804 			break;
805 
806 		default:
807 			err = ENODEV;
808 		}
809 
810 		if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
811 			*addr_ptr = addr_probe->data.next;
812 			kbtrans_flush(upper);
813 		}
814 		break;
815 
816 	case VUIDGADDR:
817 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGADDR\n"));
818 
819 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
820 		if (err != 0)
821 			break;
822 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
823 		switch (addr_probe->base) {
824 
825 		case ASCII_FIRST:
826 			addr_probe->data.current =
827 			    upper->kbtrans_streams_vuid_addr.ascii;
828 			break;
829 
830 		case TOP_FIRST:
831 			addr_probe->data.current =
832 			    upper->kbtrans_streams_vuid_addr.top;
833 			break;
834 
835 		case VKEY_FIRST:
836 			addr_probe->data.current =
837 			    upper->kbtrans_streams_vuid_addr.vkey;
838 			break;
839 
840 		default:
841 			err = ENODEV;
842 		}
843 		break;
844 
845 	case KIOCTRANSABLE:
846 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANSABLE\n"));
847 
848 		err = miocpullup(mp, sizeof (int));
849 		if (err != 0)
850 			break;
851 		/*
852 		 * called during console setup in kbconfig()
853 		 * If set to false, means we are a serial keyboard,
854 		 * and we should pass all data up without modification.
855 		 */
856 		translate = *(int *)mp->b_cont->b_rptr;
857 		if (upper->kbtrans_streams_translatable != translate)
858 			upper->kbtrans_streams_translatable = translate;
859 
860 		if (translate != TR_CAN)
861 			DPRINTF(PRINT_L4, PRINT_MASK_ALL, (upper,
862 			    "Cannot translate keyboard using tables.\n"));
863 		break;
864 
865 	case KIOCGTRANSABLE:
866 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANSABLE\n"));
867 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
868 			ioctlrespsize = sizeof (int);
869 			goto allocfailure;
870 		}
871 		*(int *)datap->b_wptr = upper->kbtrans_streams_translatable;
872 		datap->b_wptr += sizeof (int);
873 		if (mp->b_cont)  /* free msg to prevent memory leak */
874 			freemsg(mp->b_cont);
875 		mp->b_cont = datap;
876 		iocp->ioc_count = sizeof (int);
877 		break;
878 
879 	case KIOCSCOMPAT:
880 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSCOMPAT\n"));
881 
882 		err = miocpullup(mp, sizeof (int));
883 		if (err != 0)
884 			break;
885 		lower->kbtrans_compat = *(int *)mp->b_cont->b_rptr;
886 		break;
887 
888 	case KIOCGCOMPAT:
889 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGCOMPAT\n"));
890 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
891 			ioctlrespsize = sizeof (int);
892 			goto allocfailure;
893 		}
894 		*(int *)datap->b_wptr = lower->kbtrans_compat;
895 		datap->b_wptr += sizeof (int);
896 		if (mp->b_cont)  /* free msg to prevent memory leak */
897 			freemsg(mp->b_cont);
898 		mp->b_cont = datap;
899 		iocp->ioc_count = sizeof (int);
900 		break;
901 
902 	case KIOCSETKEY:
903 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSETKEY %d\n",
904 		    kiocsetkey++));
905 		err = miocpullup(mp, sizeof (struct kiockey));
906 		if (err != 0)
907 			break;
908 		err = kbtrans_setkey(&upper->kbtrans_lower,
909 		    (struct kiockey *)mp->b_cont->b_rptr, iocp->ioc_cr);
910 		/*
911 		 * Since this only affects any subsequent key presses,
912 		 * don't flush soft state.  One might want to
913 		 * toggle the keytable entries dynamically.
914 		 */
915 		break;
916 
917 	case KIOCGETKEY:
918 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGETKEY %d\n",
919 		    kiocgetkey++));
920 		err = miocpullup(mp, sizeof (struct kiockey));
921 		if (err != 0)
922 			break;
923 		err = kbtrans_getkey(&upper->kbtrans_lower,
924 		    (struct kiockey *)mp->b_cont->b_rptr);
925 		break;
926 
927 	case KIOCSKEY:
928 		err = miocpullup(mp, sizeof (struct kiockeymap));
929 		if (err != 0)
930 			break;
931 		err = kbtrans_skey(&upper->kbtrans_lower,
932 		    (struct kiockeymap *)mp->b_cont->b_rptr, iocp->ioc_cr);
933 		/*
934 		 * Since this only affects any subsequent key presses,
935 		 * don't flush soft state.  One might want to
936 		 * toggle the keytable entries dynamically.
937 		 */
938 		break;
939 
940 	case KIOCGKEY:
941 		err = miocpullup(mp, sizeof (struct kiockeymap));
942 		if (err != 0)
943 			break;
944 		err = kbtrans_gkey(&upper->kbtrans_lower,
945 		    (struct kiockeymap *)mp->b_cont->b_rptr);
946 		break;
947 
948 	case KIOCSDIRECT:
949 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSDIRECT\n"));
950 		kbtrans_flush(upper);
951 		break;
952 
953 	case KIOCGDIRECT:
954 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSGDIRECT\n"));
955 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
956 			ioctlrespsize = sizeof (int);
957 			goto allocfailure;
958 		}
959 		*(int *)datap->b_wptr = 1;	/* always direct */
960 		datap->b_wptr += sizeof (int);
961 		if (mp->b_cont) /* free msg to prevent memory leak */
962 			freemsg(mp->b_cont);
963 		mp->b_cont = datap;
964 		iocp->ioc_count = sizeof (int);
965 		break;
966 
967 	case KIOCTYPE:
968 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTYPE\n"));
969 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
970 			ioctlrespsize = sizeof (int);
971 			goto allocfailure;
972 		}
973 		*(int *)datap->b_wptr = upper->kbtrans_streams_id;
974 		datap->b_wptr += sizeof (int);
975 		if (mp->b_cont) /* free msg to prevent memory leak */
976 			freemsg(mp->b_cont);
977 		mp->b_cont = datap;
978 		iocp->ioc_count = sizeof (int);
979 		break;
980 
981 	case CONSSETABORTENABLE:
982 		/*
983 		 * Peek as it goes by; must be a TRANSPARENT ioctl.
984 		 */
985 		if (iocp->ioc_count != TRANSPARENT) {
986 			err = EINVAL;
987 			break;
988 		}
989 
990 		upper->kbtrans_streams_abortable =
991 		    (boolean_t)*(intptr_t *)mp->b_cont->b_rptr;
992 
993 		/*
994 		 * Let the hardware module see it too.
995 		 */
996 		return (KBTRANS_MESSAGE_NOT_HANDLED);
997 
998 	case KIOCGRPTCOUNT:
999 		/*
1000 		 * Report the autorepeat count
1001 		 */
1002 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTCOUNT\n"));
1003 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
1004 			ioctlrespsize = sizeof (int);
1005 			goto allocfailure;
1006 		}
1007 		*(int *)datap->b_wptr = kbtrans_repeat_count;
1008 		datap->b_wptr += sizeof (int);
1009 
1010 		/* free msg to prevent memory leak */
1011 		if (mp->b_cont != NULL)
1012 			freemsg(mp->b_cont);
1013 		mp->b_cont = datap;
1014 		iocp->ioc_count = sizeof (int);
1015 		break;
1016 
1017 	case KIOCSRPTCOUNT:
1018 		/*
1019 		 * Set the autorepeat count
1020 		 */
1021 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTCOUNT\n"));
1022 		err = miocpullup(mp, sizeof (int));
1023 
1024 		if (err != 0)
1025 			break;
1026 
1027 		/* validate the input */
1028 		if (*(int *)mp->b_cont->b_rptr < -1) {
1029 			err = EINVAL;
1030 			break;
1031 		}
1032 		kbtrans_repeat_count = (*(int *)mp->b_cont->b_rptr);
1033 		break;
1034 
1035 	case KIOCGRPTDELAY:
1036 		/*
1037 		 * Report the autorepeat delay, unit in millisecond
1038 		 */
1039 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTDELAY\n"));
1040 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
1041 			ioctlrespsize = sizeof (int);
1042 			goto allocfailure;
1043 		}
1044 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_delay);
1045 		datap->b_wptr += sizeof (int);
1046 
1047 		/* free msg to prevent memory leak */
1048 		if (mp->b_cont != NULL)
1049 			freemsg(mp->b_cont);
1050 		mp->b_cont = datap;
1051 		iocp->ioc_count = sizeof (int);
1052 		break;
1053 
1054 	case KIOCSRPTDELAY:
1055 		/*
1056 		 * Set the autorepeat delay
1057 		 */
1058 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTDELAY\n"));
1059 		err = miocpullup(mp, sizeof (int));
1060 
1061 		if (err != 0)
1062 			break;
1063 
1064 		/* validate the input */
1065 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
1066 			err = EINVAL;
1067 			break;
1068 		}
1069 		kbtrans_repeat_delay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
1070 		if (kbtrans_repeat_delay <= 0)
1071 			kbtrans_repeat_delay = 1;
1072 		break;
1073 
1074 	case KIOCGRPTRATE:
1075 		/*
1076 		 * Report the autorepeat rate
1077 		 */
1078 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTRATE\n"));
1079 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
1080 			ioctlrespsize = sizeof (int);
1081 			goto allocfailure;
1082 		}
1083 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_rate);
1084 		datap->b_wptr += sizeof (int);
1085 
1086 		/* free msg to prevent memory leak */
1087 		if (mp->b_cont != NULL)
1088 			freemsg(mp->b_cont);
1089 		mp->b_cont = datap;
1090 		iocp->ioc_count = sizeof (int);
1091 		break;
1092 
1093 	case KIOCSRPTRATE:
1094 		/*
1095 		 * Set the autorepeat rate
1096 		 */
1097 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTRATE\n"));
1098 		err = miocpullup(mp, sizeof (int));
1099 
1100 		if (err != 0)
1101 			break;
1102 
1103 		/* validate the input */
1104 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
1105 			err = EINVAL;
1106 			break;
1107 		}
1108 		kbtrans_repeat_rate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
1109 		if (kbtrans_repeat_rate <= 0)
1110 			kbtrans_repeat_rate = 1;
1111 		break;
1112 
1113 	default:
1114 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "unknown\n"));
1115 		return (KBTRANS_MESSAGE_NOT_HANDLED);
1116 	} /* end switch */
1117 
1118 	if (err != 0) {
1119 		iocp->ioc_rval = 0;
1120 		iocp->ioc_error = err;
1121 		mp->b_datap->db_type = M_IOCNAK;
1122 	} else {
1123 		iocp->ioc_rval = 0;
1124 		iocp->ioc_error = 0;	/* brain rot */
1125 		mp->b_datap->db_type = M_IOCACK;
1126 	}
1127 	putnext(upper->kbtrans_streams_readq, mp);
1128 
1129 	return (KBTRANS_MESSAGE_HANDLED);
1130 
1131 allocfailure:
1132 	/*
1133 	 * We needed to allocate something to handle this "ioctl", but
1134 	 * couldn't; save this "ioctl" and arrange to get called back when
1135 	 * it's more likely that we can get what we need.
1136 	 * If there's already one being saved, throw it out, since it
1137 	 * must have timed out.
1138 	 */
1139 	if (upper->kbtrans_streams_iocpending != NULL)
1140 		freemsg(upper->kbtrans_streams_iocpending);
1141 	upper->kbtrans_streams_iocpending = mp;
1142 	if (upper->kbtrans_streams_bufcallid) {
1143 		qunbufcall(upper->kbtrans_streams_readq,
1144 		    upper->kbtrans_streams_bufcallid);
1145 	}
1146 	upper->kbtrans_streams_bufcallid =
1147 	    qbufcall(upper->kbtrans_streams_readq, ioctlrespsize, BPRI_HI,
1148 	    kbtrans_reioctl, upper);
1149 	/*
1150 	 * This is a white lie... we *will* handle it, eventually.
1151 	 */
1152 	return (KBTRANS_MESSAGE_HANDLED);
1153 }
1154 
1155 /*
1156  * kbtrans_flush:
1157  *	Flush data upstream
1158  */
1159 static void
1160 kbtrans_flush(register struct kbtrans *upper)
1161 {
1162 	register queue_t *q;
1163 
1164 	/* Flush pending data already sent upstream */
1165 	if ((q = upper->kbtrans_streams_readq) != NULL && q->q_next != NULL)
1166 		(void) putnextctl1(q, M_FLUSH, FLUSHR);
1167 
1168 	/* Flush pending ups */
1169 	bzero(upper->kbtrans_streams_downs, upper->kbtrans_streams_downs_bytes);
1170 
1171 	kbtrans_cancelrpt(upper);
1172 }
1173 
1174 /*
1175  * kbtrans_setled:
1176  *	 Update the keyboard LEDs to match the current keyboard state.
1177  */
1178 static void
1179 kbtrans_setled(struct kbtrans *upper)
1180 {
1181 	upper->kbtrans_streams_hw_callbacks->kbtrans_streams_setled(
1182 	    upper->kbtrans_streams_hw,
1183 	    upper->kbtrans_lower.kbtrans_led_state);
1184 }
1185 
1186 /*
1187  * kbtrans_rpt:
1188  *	If a key is held down, this function is set up to be called
1189  *	after kbtrans_repeat_rate time elapses.
1190  */
1191 static void
1192 kbtrans_rpt(void *arg)
1193 {
1194 	struct kbtrans	*upper = arg;
1195 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1196 
1197 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL,
1198 	    "kbtrans_rpt: repeat key %X\n",
1199 	    lower->kbtrans_repeatkey));
1200 
1201 	upper->kbtrans_streams_rptid = 0;
1202 	upper->kbtrans_streams_count++;
1203 
1204 	/*
1205 	 * NB:  polled code zaps kbtrans_repeatkey without cancelling
1206 	 * timeout.
1207 	 */
1208 	if (kbtrans_repeat_count > 0) {
1209 		/* If limit is set and reached, stop there. */
1210 		if (upper->kbtrans_streams_count > kbtrans_repeat_count)
1211 			lower->kbtrans_repeatkey = 0;
1212 	}
1213 
1214 	if (lower->kbtrans_repeatkey != 0) {
1215 		kbtrans_keyreleased(upper, lower->kbtrans_repeatkey);
1216 
1217 		kbtrans_processkey(lower,
1218 		    upper->kbtrans_streams_callback,
1219 		    lower->kbtrans_repeatkey,
1220 		    KEY_PRESSED);
1221 
1222 		upper->kbtrans_streams_rptid =
1223 		    qtimeout(upper->kbtrans_streams_readq, kbtrans_rpt,
1224 		    (caddr_t)upper, kbtrans_repeat_rate);
1225 	}
1226 }
1227 
1228 /*
1229  * kbtrans_cancelrpt:
1230  *	Cancel the repeating key
1231  */
1232 static void
1233 kbtrans_cancelrpt(struct kbtrans	*upper)
1234 {
1235 	upper->kbtrans_lower.kbtrans_repeatkey = 0;
1236 
1237 	if (upper->kbtrans_streams_rptid != 0) {
1238 		(void) quntimeout(upper->kbtrans_streams_readq,
1239 		    upper->kbtrans_streams_rptid);
1240 		upper->kbtrans_streams_rptid = 0;
1241 	}
1242 }
1243 
1244 /*
1245  * kbtrans_send_esc_event:
1246  *	Send character up stream. Used for the case of
1247  *	sending strings upstream.
1248  */
1249 static void
1250 kbtrans_send_esc_event(char c, register struct kbtrans *upper)
1251 {
1252 	Firm_event fe;
1253 
1254 	fe.id = c;
1255 	fe.value = 1;
1256 	fe.pair_type = FE_PAIR_NONE;
1257 	fe.pair = 0;
1258 	/*
1259 	 * Pretend as if each cp pushed and released
1260 	 * Calling kbtrans_queueevent avoids addr translation
1261 	 * and pair base determination of kbtrans_keypressed.
1262 	 */
1263 	kbtrans_queueevent(upper, &fe);
1264 	fe.value = 0;
1265 	kbtrans_queueevent(upper, &fe);
1266 }
1267 
1268 /*
1269  * kbtrans_strsetwithdecimal:
1270  *	Used for expanding a function key to the ascii equivalent
1271  */
1272 static char *
1273 kbtrans_strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
1274 {
1275 	int	hradix = 5;
1276 	char	*bp;
1277 	int	lowbit;
1278 	char	*tab = "0123456789abcdef";
1279 
1280 	bp = buf + maxdigs;
1281 	*(--bp) = '\0';
1282 	while (val) {
1283 		lowbit = val & 1;
1284 		val = (val >> 1);
1285 		*(--bp) = tab[val % hradix * 2 + lowbit];
1286 		val /= hradix;
1287 	}
1288 	return (bp);
1289 }
1290 
1291 /*
1292  * kbtrans_keypressed:
1293  *	Modify Firm event to be sent up the stream
1294  */
1295 static void
1296 kbtrans_keypressed(struct kbtrans *upper, uchar_t key_station,
1297     Firm_event *fe, ushort_t base)
1298 {
1299 
1300 	register short	id_addr;
1301 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1302 
1303 	/* Set pair values */
1304 	if (fe->id < (ushort_t)VKEY_FIRST) {
1305 		/*
1306 		 * If CTRLed, find the ID that would have been used had it
1307 		 * not been CTRLed.
1308 		 */
1309 		if (lower->kbtrans_shiftmask & (CTRLMASK | CTLSMASK)) {
1310 			keymap_entry_t *ke;
1311 			unsigned int mask;
1312 
1313 			mask = lower->kbtrans_shiftmask &
1314 			    ~(CTRLMASK | CTLSMASK | UPMASK);
1315 
1316 			ke = kbtrans_find_entry(lower, mask, key_station);
1317 			if (ke == NULL)
1318 				return;
1319 
1320 			base = *ke;
1321 		}
1322 		if (base != fe->id) {
1323 			fe->pair_type = FE_PAIR_SET;
1324 			fe->pair = (uchar_t)base;
1325 
1326 			goto send;
1327 		}
1328 	}
1329 	fe->pair_type = FE_PAIR_NONE;
1330 	fe->pair = 0;
1331 
1332 send:
1333 	/* Adjust event id address for multiple keyboard/workstation support */
1334 	switch (vuid_id_addr(fe->id)) {
1335 	case ASCII_FIRST:
1336 		id_addr = upper->kbtrans_streams_vuid_addr.ascii;
1337 		break;
1338 	case TOP_FIRST:
1339 		id_addr = upper->kbtrans_streams_vuid_addr.top;
1340 		break;
1341 	case VKEY_FIRST:
1342 		id_addr = upper->kbtrans_streams_vuid_addr.vkey;
1343 		break;
1344 	default:
1345 		id_addr = vuid_id_addr(fe->id);
1346 		break;
1347 	}
1348 	fe->id = vuid_id_offset(fe->id) | id_addr;
1349 
1350 	kbtrans_queuepress(upper, key_station, fe);
1351 }
1352 
1353 /*
1354  * kbtrans_queuepress:
1355  *	Add keypress to the "downs" table
1356  */
1357 static void
1358 kbtrans_queuepress(struct kbtrans *upper,
1359     uchar_t key_station, Firm_event *fe)
1360 {
1361 	register struct key_event *ke, *ke_free;
1362 	register int i;
1363 
1364 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "kbtrans_queuepress:"
1365 	    " key=%d", key_station));
1366 
1367 	ke_free = 0;
1368 
1369 	/* Scan table of down key stations */
1370 
1371 	for (i = 0, ke = upper->kbtrans_streams_downs;
1372 	    i < upper->kbtrans_streams_num_downs_entries; i++, ke++) {
1373 
1374 		/* Keycode already down? */
1375 		if (ke->key_station == key_station) {
1376 
1377 			DPRINTF(PRINT_L0, PRINT_MASK_ALL,
1378 			    (NULL, "kbtrans: Double "
1379 			    "entry in downs table (%d,%d)!\n",
1380 			    key_station, i));
1381 
1382 			goto add_event;
1383 		}
1384 
1385 		if (ke->key_station == 0)
1386 			ke_free = ke;
1387 	}
1388 
1389 	if (ke_free) {
1390 		ke = ke_free;
1391 		goto add_event;
1392 	}
1393 
1394 	ke = upper->kbtrans_streams_downs;
1395 
1396 add_event:
1397 	ke->key_station = key_station;
1398 	ke->event = *fe;
1399 	kbtrans_queueevent(upper, fe);
1400 }
1401 
1402 /*
1403  * kbtrans_keyreleased:
1404  *	Remove entry from the downs table
1405  */
1406 static void
1407 kbtrans_keyreleased(register struct kbtrans *upper, uchar_t key_station)
1408 {
1409 	register struct key_event *ke;
1410 	register int i;
1411 
1412 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "RELEASE key=%d\n",
1413 	    key_station));
1414 
1415 	if (upper->kbtrans_streams_translate_mode != TR_EVENT &&
1416 	    upper->kbtrans_streams_translate_mode != TR_UNTRANS_EVENT) {
1417 
1418 		return;
1419 	}
1420 
1421 	/* Scan table of down key stations */
1422 	for (i = 0, ke = upper->kbtrans_streams_downs;
1423 	    i < upper->kbtrans_streams_num_downs_entries;
1424 	    i++, ke++) {
1425 		/* Found? */
1426 		if (ke->key_station == key_station) {
1427 			ke->key_station = 0;
1428 			ke->event.value = 0;
1429 			kbtrans_queueevent(upper, &ke->event);
1430 		}
1431 	}
1432 
1433 	/*
1434 	 * Ignore if couldn't find because may be called twice
1435 	 * for the same key station in the case of the kbtrans_rpt
1436 	 * routine being called unnecessarily.
1437 	 */
1438 }
1439 
1440 
1441 /*
1442  * kbtrans_putcode:
1443  *	 Pass a keycode up the stream, if you can, otherwise throw it away.
1444  */
1445 static void
1446 kbtrans_putcode(register struct kbtrans *upper, uint_t code)
1447 {
1448 	register mblk_t *bp;
1449 
1450 	/*
1451 	 * If we can't send it up, then we just drop it.
1452 	 */
1453 	if (!canputnext(upper->kbtrans_streams_readq)) {
1454 
1455 		return;
1456 	}
1457 
1458 	/*
1459 	 * Allocate a messsage block to send up.
1460 	 */
1461 	if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) {
1462 
1463 		cmn_err(CE_WARN, "kbtrans_putcode: Can't allocate block\
1464 			for keycode.");
1465 
1466 		return;
1467 	}
1468 
1469 	/*
1470 	 * We will strip out any high order information here.
1471 	 * Convert to UTF-8.
1472 	 */
1473 	code = KEYCHAR(code);
1474 	if (code < 0x80) {
1475 		*bp->b_wptr++ = (char)code;
1476 	} else if (code < 0x800) {
1477 		*bp->b_wptr++ = 0xc0 | (code >> 6);
1478 		*bp->b_wptr++ = 0x80 | (code & 0x3f);
1479 	} else if (code < 0x10000) {
1480 		*bp->b_wptr++ = 0xe0 | (code >> 12);
1481 		*bp->b_wptr++ = 0x80 | ((code >> 6) & 0x3f);
1482 		*bp->b_wptr++ = 0x80 | (code & 0x3f);
1483 	} else {
1484 		*bp->b_wptr++ = 0xf0 | (code >> 18);
1485 		*bp->b_wptr++ = 0x80 | ((code >> 12) & 0x3f);
1486 		*bp->b_wptr++ = 0x80 | ((code >> 6) & 0x3f);
1487 		*bp->b_wptr++ = 0x80 | (code & 0x3f);
1488 	}
1489 
1490 	/*
1491 	 * Send the message up.
1492 	 */
1493 	(void) putnext(upper->kbtrans_streams_readq, bp);
1494 }
1495 
1496 
1497 /*
1498  * kbtrans_putbuf:
1499  *	Pass generated keycode sequence to upstream, if possible.
1500  */
1501 static void
1502 kbtrans_putbuf(char *buf, queue_t *q)
1503 {
1504 	register mblk_t *bp;
1505 
1506 	if (!canputnext(q)) {
1507 		cmn_err(CE_WARN, "kbtrans_putbuf: Can't put block for keycode");
1508 	} else {
1509 		if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) {
1510 			cmn_err(CE_WARN, "kbtrans_putbuf: "
1511 			    "Can't allocate block for keycode");
1512 		} else {
1513 			while (*buf) {
1514 				*bp->b_wptr++ = *buf;
1515 				buf++;
1516 			}
1517 			putnext(q, bp);
1518 		}
1519 	}
1520 }
1521 
1522 /*
1523  * kbtrans_queueevent:
1524  *	 Pass a VUID "firm event" up the stream, if you can.
1525  */
1526 static void
1527 kbtrans_queueevent(struct kbtrans *upper, Firm_event *fe)
1528 {
1529 	register queue_t *q;
1530 	register mblk_t *bp;
1531 
1532 	if ((q = upper->kbtrans_streams_readq) == NULL)
1533 
1534 		return;
1535 
1536 	if (!canputnext(q)) {
1537 		if (kbtrans_overflow_msg) {
1538 			DPRINTF(PRINT_L2, PRINT_MASK_ALL, (NULL,
1539 			    "kbtrans: Buffer flushed when overflowed."));
1540 		}
1541 
1542 		kbtrans_flush(upper);
1543 		upper->kbtrans_overflow_cnt++;
1544 	} else {
1545 		if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) {
1546 			cmn_err(CE_WARN, "kbtrans_queueevent: Can't allocate \
1547 					block for event.");
1548 		} else {
1549 			uniqtime32(&fe->time);
1550 			*(Firm_event *)bp->b_wptr = *fe;
1551 			bp->b_wptr += sizeof (Firm_event);
1552 			(void) putnext(q, bp);
1553 
1554 
1555 		}
1556 	}
1557 }
1558 
1559 /*
1560  * kbtrans_set_translation_callback:
1561  *	This code sets the translation_callback pointer based on the
1562  *	translation mode.
1563  */
1564 static void
1565 kbtrans_set_translation_callback(register struct kbtrans *upper)
1566 {
1567 	switch (upper->kbtrans_streams_translate_mode) {
1568 
1569 	default:
1570 	case TR_ASCII:
1571 		upper->vt_switch_keystate = VT_SWITCH_KEY_NONE;
1572 
1573 		/* Discard any obsolete CTRL/ALT/SHIFT keys */
1574 		upper->kbtrans_lower.kbtrans_shiftmask &=
1575 		    ~(CTRLMASK | ALTMASK | SHIFTMASK);
1576 		upper->kbtrans_lower.kbtrans_togglemask &=
1577 		    ~(CTRLMASK | ALTMASK | SHIFTMASK);
1578 
1579 		upper->kbtrans_streams_callback = &ascii_callback;
1580 
1581 		break;
1582 
1583 	case TR_EVENT:
1584 		upper->kbtrans_streams_callback = &trans_event_callback;
1585 
1586 		break;
1587 
1588 	case TR_UNTRANS_EVENT:
1589 		upper->kbtrans_streams_callback = &untrans_event_callback;
1590 
1591 		break;
1592 	}
1593 }
1594 
1595 /*
1596  * kbtrans_untrans_keypressed_raw:
1597  *	This is the callback we get if we are in TR_UNTRANS_EVENT and a
1598  *	key is pressed.  This code will just send the scancode up the
1599  *	stream.
1600  */
1601 static void
1602 kbtrans_untrans_keypressed_raw(struct kbtrans *upper, kbtrans_key_t key)
1603 {
1604 	Firm_event	fe;
1605 
1606 	bzero(&fe, sizeof (fe));
1607 
1608 	/*
1609 	 * fill in the event
1610 	 */
1611 	fe.id = (unsigned short)key;
1612 	fe.value = 1;
1613 
1614 	/*
1615 	 * Send the event upstream.
1616 	 */
1617 	kbtrans_queuepress(upper, key, &fe);
1618 }
1619 
1620 /*
1621  * kbtrans_untrans_keyreleased_raw:
1622  *	This is the callback we get if we are in TR_UNTRANS_EVENT mode
1623  *	and a key is released.  This code will just send the scancode up
1624  *	the stream.
1625  */
1626 static void
1627 kbtrans_untrans_keyreleased_raw(struct kbtrans *upper, kbtrans_key_t key)
1628 {
1629 	/*
1630 	 * Deal with a key released event.
1631 	 */
1632 	kbtrans_keyreleased(upper, key);
1633 }
1634 
1635 /*
1636  * kbtrans_vt_compose:
1637  *   To compose the key sequences for virtual terminal switching.
1638  *
1639  *   'ALTL + F#'                for 1-12 terminals
1640  *   'ALTGR + F#'               for 13-24 terminals
1641  *   'ALT + UPARROW'            for last terminal
1642  *   'ALT + LEFTARROW'          for previous terminal
1643  *   'ALT + RIGHTARROW'         for next terminal
1644  *
1645  * the vt switching message is encoded as:
1646  *
1647  *   -------------------------------------------------------------
1648  *   |  \033  |  'Q'  |  vtno + 'A'  |  opcode  |  'z'  |  '\0'  |
1649  *   -------------------------------------------------------------
1650  *
1651  * opcode:
1652  *   'B'    to switch to previous terminal
1653  *   'F'    to switch to next terminal
1654  *   'L'    to switch to last terminal
1655  *   'H'    to switch to the terminal as specified by vtno,
1656  *          which is from 1 to 24.
1657  *
1658  * Here keyid is the keycode of UPARROW, LEFTARROW, or RIGHTARROW
1659  * when it is a kind of arrow key as indicated by is_arrow_key,
1660  * otherwise it indicates a function key and keyid is the number
1661  * corresponding to that function key.
1662  */
1663 static void
1664 kbtrans_vt_compose(struct kbtrans *upper, unsigned short keyid,
1665     boolean_t is_arrow_key, char *buf)
1666 {
1667 	char		*bufp;
1668 
1669 	bufp = buf;
1670 	*bufp++ = '\033'; /* Escape */
1671 	*bufp++ = 'Q';
1672 	if (is_arrow_key) {
1673 		*bufp++ = 'A';
1674 		switch (keyid) {
1675 		case UPARROW: /* last vt */
1676 			*bufp++ = 'L';
1677 			break;
1678 		case LEFTARROW: /* previous vt */
1679 			*bufp++ = 'B';
1680 			break;
1681 		case RIGHTARROW: /* next vt */
1682 			*bufp++ = 'F';
1683 			break;
1684 		default:
1685 			break;
1686 		}
1687 	} else {
1688 		/* this is funckey specifying vtno for switch */
1689 		*bufp++ = keyid +
1690 		    (upper->vt_switch_keystate - VT_SWITCH_KEY_ALT) *
1691 		    KB_NR_FUNCKEYS + 'A';
1692 		*bufp++ = 'H';
1693 	}
1694 	*bufp++ = 'z';
1695 	*bufp = '\0';
1696 
1697 	/*
1698 	 * Send the result upstream.
1699 	 */
1700 	kbtrans_putbuf(buf, upper->kbtrans_streams_readq);
1701 
1702 }
1703 
1704 /*
1705  * kbtrans_ascii_keypressed:
1706  *	This is the code if we are in TR_ASCII mode and a key
1707  *	is pressed.  This is where we will do any special processing that
1708  *	is specific to ASCII key translation.
1709  */
1710 /* ARGSUSED */
1711 static void
1712 kbtrans_ascii_keypressed(struct kbtrans *upper, uint_t entrytype,
1713     kbtrans_key_t  key, uint_t entry)
1714 {
1715 	register char	*cp;
1716 	register char	*bufp;
1717 	char		buf[14];
1718 	unsigned short		keyid;
1719 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1720 
1721 	/*
1722 	 * Based on the type of key, we may need to do some ASCII
1723 	 * specific post processing. Note that the translated entry
1724 	 * is constructed as the actual keycode plus entrytype. See
1725 	 * sys/kbd.h for details of each entrytype.
1726 	 */
1727 	switch (entrytype) {
1728 
1729 	case BUCKYBITS:
1730 		return;
1731 
1732 	case SHIFTKEYS:
1733 		keyid = entry & 0xFF;
1734 		if (keyid == ALT) {
1735 			upper->vt_switch_keystate = VT_SWITCH_KEY_ALT;
1736 		} else if (keyid == ALTGRAPH) {
1737 			upper->vt_switch_keystate = VT_SWITCH_KEY_ALTGR;
1738 		}
1739 		return;
1740 
1741 	case FUNNY:
1742 		/*
1743 		 * There is no ascii equivalent.  We will ignore these
1744 		 * keys
1745 		 */
1746 		return;
1747 
1748 	case FUNCKEYS:
1749 		if (upper->vt_switch_keystate > VT_SWITCH_KEY_NONE) {
1750 			if (entry >= TOPFUNC &&
1751 			    entry < (TOPFUNC + KB_NR_FUNCKEYS)) {
1752 
1753 				/*
1754 				 * keyid is the number correspoding to F#
1755 				 * and its value is from 1 to 12.
1756 				 */
1757 				keyid = (entry & 0xF) + 1;
1758 
1759 				kbtrans_vt_compose(upper, keyid, B_FALSE, buf);
1760 				return;
1761 			}
1762 		}
1763 
1764 		/*
1765 		 * We need to expand this key to get the ascii
1766 		 * equivalent.  These are the function keys (F1, F2 ...)
1767 		 */
1768 		bufp = buf;
1769 		cp = kbtrans_strsetwithdecimal(bufp + 2,
1770 		    (uint_t)((entry & 0x003F) + 192),
1771 		    sizeof (buf) - 5);
1772 		*bufp++ = '\033'; /* Escape */
1773 		*bufp++ = '[';
1774 		while (*cp != '\0')
1775 			*bufp++ = *cp++;
1776 		*bufp++ = 'z';
1777 		*bufp = '\0';
1778 
1779 		/*
1780 		 * Send the result upstream.
1781 		 */
1782 		kbtrans_putbuf(buf, upper->kbtrans_streams_readq);
1783 
1784 		return;
1785 
1786 	case STRING:
1787 		if (upper->vt_switch_keystate > VT_SWITCH_KEY_NONE) {
1788 			keyid = entry & 0xFF;
1789 			if (keyid == UPARROW ||
1790 			    keyid == RIGHTARROW ||
1791 			    keyid == LEFTARROW) {
1792 
1793 				kbtrans_vt_compose(upper, keyid, B_TRUE, buf);
1794 				return;
1795 			}
1796 		}
1797 
1798 		/*
1799 		 * These are the multi byte keys (Home, Up, Down ...)
1800 		 */
1801 		cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
1802 
1803 		/*
1804 		 * Copy the string from the keystringtable, and send it
1805 		 * upstream a character at a time.
1806 		 */
1807 		while (*cp != '\0') {
1808 
1809 			kbtrans_putcode(upper, (uchar_t)*cp);
1810 
1811 			cp++;
1812 		}
1813 
1814 		return;
1815 
1816 	case PADKEYS:
1817 		/*
1818 		 * These are the keys on the keypad.  Look up the
1819 		 * answer in the kb_numlock_table and send it upstream.
1820 		 */
1821 		kbtrans_putcode(upper,
1822 		    lower->kbtrans_numlock_table[entry&0x1F]);
1823 
1824 		return;
1825 
1826 	case 0:	/* normal character */
1827 	default:
1828 		break;
1829 	}
1830 
1831 	/*
1832 	 * Send the char upstream.
1833 	 */
1834 	kbtrans_putcode(upper, entry);
1835 
1836 }
1837 
1838 #define	KB_SCANCODE_ALT		0xe2
1839 #define	KB_SCANCODE_ALTGRAPH	0xe6
1840 
1841 /*
1842  * kbtrans_ascii_keyreleased:
1843  *	This is the function if we are in TR_ASCII mode and a key
1844  *	is released.  ASCII doesn't have the concept of released keys,
1845  *	or make/break codes.  So there is nothing for us to do except
1846  *      checking 'Alt/AltGraph' release key in order to reset the state
1847  *      of vt switch key sequence.
1848  */
1849 /* ARGSUSED */
1850 static void
1851 kbtrans_ascii_keyreleased(struct kbtrans *upper, kbtrans_key_t key)
1852 {
1853 	if (key == KB_SCANCODE_ALT || key == KB_SCANCODE_ALTGRAPH) {
1854 		upper->vt_switch_keystate = VT_SWITCH_KEY_NONE;
1855 	}
1856 }
1857 
1858 /*
1859  * kbtrans_ascii_setup_repeat:
1860  *	This is the function if we are in TR_ASCII mode and the
1861  *	translation module has decided that a key needs to be repeated.
1862  */
1863 /* ARGSUSED */
1864 static void
1865 kbtrans_ascii_setup_repeat(struct kbtrans *upper, uint_t entrytype,
1866     kbtrans_key_t key)
1867 {
1868 	struct kbtrans_lower *lower = &upper->kbtrans_lower;
1869 
1870 	/*
1871 	 * Cancel any currently repeating keys.  This will be a new
1872 	 * key to repeat.
1873 	 */
1874 	kbtrans_cancelrpt(upper);
1875 
1876 	/*
1877 	 * Set the value of the key to be repeated.
1878 	 */
1879 	lower->kbtrans_repeatkey = key;
1880 
1881 	/*
1882 	 * Start the timeout for repeating this key.  kbtrans_rpt will
1883 	 * be called to repeat the key.
1884 	 */
1885 	upper->kbtrans_streams_count = 0;
1886 	upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq,
1887 	    kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay);
1888 }
1889 
1890 /*
1891  * kbtrans_trans_event_keypressed:
1892  *	This is the function if we are in TR_EVENT mode and a key
1893  *	is pressed.  This is where we will do any special processing that
1894  *	is specific to EVENT key translation.
1895  */
1896 static void
1897 kbtrans_trans_event_keypressed(struct kbtrans *upper, uint_t entrytype,
1898     kbtrans_key_t key, uint_t entry)
1899 {
1900 	Firm_event	fe;
1901 	register char	*cp;
1902 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1903 
1904 	/*
1905 	 * Based on the type of key, we may need to do some EVENT
1906 	 * specific post processing.
1907 	 */
1908 	switch (entrytype) {
1909 
1910 	case SHIFTKEYS:
1911 		/*
1912 		 * Relying on ordinal correspondence between
1913 		 * vuid_event.h SHIFT_META-SHIFT_TOP &
1914 		 * kbd.h METABIT-SYSTEMBIT in order to
1915 		 * correctly translate entry into fe.id.
1916 		 */
1917 		fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
1918 		fe.value = 1;
1919 		kbtrans_keypressed(upper, key, &fe, fe.id);
1920 
1921 		return;
1922 
1923 	case BUCKYBITS:
1924 		/*
1925 		 * Relying on ordinal correspondence between
1926 		 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1927 		 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1928 		 * correctly translate entry into fe.id.
1929 		 */
1930 		fe.id = SHIFT_META + (entry & 0x0F);
1931 		fe.value = 1;
1932 		kbtrans_keypressed(upper, key, &fe, fe.id);
1933 
1934 		return;
1935 
1936 	case FUNCKEYS:
1937 		/*
1938 		 * Take advantage of the similar
1939 		 * ordering of kbd.h function keys and
1940 		 * vuid_event.h function keys to do a
1941 		 * simple translation to achieve a
1942 		 * mapping between the 2 different
1943 		 * address spaces.
1944 		 */
1945 		fe.id = KEY_LEFTFIRST + (entry & 0x003F);
1946 		fe.value = 1;
1947 
1948 		/*
1949 		 * Assume "up" table only generates
1950 		 * shift changes.
1951 		 */
1952 		kbtrans_keypressed(upper, key, &fe, fe.id);
1953 
1954 		/*
1955 		 * Function key events can be expanded
1956 		 * by terminal emulator software to
1957 		 * produce the standard escape sequence
1958 		 * generated by the TR_ASCII case above
1959 		 * if a function key event is not used
1960 		 * by terminal emulator software
1961 		 * directly.
1962 		 */
1963 		return;
1964 
1965 	case STRING:
1966 		/*
1967 		 * These are the multi byte keys (Home, Up, Down ...)
1968 		 */
1969 		cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
1970 
1971 		/*
1972 		 * Copy the string from the keystringtable, and send it
1973 		 * upstream a character at a time.
1974 		 */
1975 		while (*cp != '\0') {
1976 
1977 			kbtrans_send_esc_event(*cp, upper);
1978 
1979 			cp++;
1980 		}
1981 
1982 		return;
1983 
1984 	case PADKEYS:
1985 		/*
1986 		 * Take advantage of the similar
1987 		 * ordering of kbd.h keypad keys and
1988 		 * vuid_event.h keypad keys to do a
1989 		 * simple translation to achieve a
1990 		 * mapping between the 2 different
1991 		 * address spaces.
1992 		 */
1993 		fe.id = VKEY_FIRSTPAD + (entry & 0x001F);
1994 		fe.value = 1;
1995 
1996 		/*
1997 		 * Assume "up" table only generates
1998 		 * shift changes.
1999 		 */
2000 		kbtrans_keypressed(upper, key, &fe, fe.id);
2001 
2002 		/*
2003 		 * Keypad key events can be expanded
2004 		 * by terminal emulator software to
2005 		 * produce the standard ascii character
2006 		 * generated by the TR_ASCII case above
2007 		 * if a keypad key event is not used
2008 		 * by terminal emulator software
2009 		 * directly.
2010 		 */
2011 		return;
2012 
2013 	case FUNNY:
2014 		/*
2015 		 * These are not events.
2016 		 */
2017 		switch (entry) {
2018 		case IDLE:
2019 		case RESET:
2020 		case ERROR:
2021 			/*
2022 			 * Something has happened.  Mark all keys as released.
2023 			 */
2024 			kbtrans_streams_releaseall(upper);
2025 			break;
2026 		}
2027 
2028 		return;
2029 
2030 	case 0: /* normal character */
2031 	default:
2032 		break;
2033 	}
2034 
2035 	/*
2036 	 * Send the event upstream.
2037 	 */
2038 	fe.id = entry;
2039 
2040 	fe.value = 1;
2041 
2042 	kbtrans_queueevent(upper, &fe);
2043 }
2044 
2045 /*
2046  * kbtrans_trans_event_keyreleased:
2047  *	This is the function if we are in TR_EVENT mode and a key
2048  *	is released.
2049  */
2050 /* ARGSUSED */
2051 static void
2052 kbtrans_trans_event_keyreleased(struct kbtrans *upper, kbtrans_key_t key)
2053 {
2054 	/*
2055 	 * Mark the key as released and send an event upstream.
2056 	 */
2057 	kbtrans_keyreleased(upper, key);
2058 }
2059 
2060 /*
2061  * kbtrans_trans_event_setup_repeat:
2062  *	This is the function if we are in TR_EVENT mode and the
2063  *	translation module has decided that a key needs to be repeated.
2064  *	We will set a timeout to retranslate the repeat key.
2065  */
2066 static void
2067 kbtrans_trans_event_setup_repeat(struct kbtrans *upper, uint_t entrytype,
2068     kbtrans_key_t key)
2069 {
2070 	struct kbtrans_lower *lower = &upper->kbtrans_lower;
2071 
2072 	/*
2073 	 * Function keys and keypad keys do not repeat when we are in
2074 	 * EVENT mode.
2075 	 */
2076 	if (entrytype == FUNCKEYS || entrytype == PADKEYS) {
2077 
2078 		return;
2079 	}
2080 
2081 	/*
2082 	 * Cancel any currently repeating keys.  This will be a new
2083 	 * key to repeat.
2084 	 */
2085 	kbtrans_cancelrpt(upper);
2086 
2087 	/*
2088 	 * Set the value of the key to be repeated.
2089 	 */
2090 	lower->kbtrans_repeatkey = key;
2091 
2092 	/*
2093 	 * Start the timeout for repeating this key.  kbtrans_rpt will
2094 	 * be called to repeat the key.
2095 	 */
2096 	upper->kbtrans_streams_count = 0;
2097 	upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq,
2098 	    kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay);
2099 }
2100 
2101 /*
2102  * Administer the key tables.
2103  */
2104 
2105 /*
2106  * Old special codes.
2107  */
2108 #define	OLD_SHIFTKEYS	0x80
2109 #define	OLD_BUCKYBITS	0x90
2110 #define	OLD_FUNNY	0xA0
2111 #define	OLD_FA_UMLAUT	0xA9
2112 #define	OLD_FA_CFLEX	0xAA
2113 #define	OLD_FA_TILDE	0xAB
2114 #define	OLD_FA_CEDILLA	0xAC
2115 #define	OLD_FA_ACUTE	0xAD
2116 #define	OLD_FA_GRAVE	0xAE
2117 #define	OLD_ISOCHAR	0xAF
2118 #define	OLD_STRING	0xB0
2119 #define	OLD_LEFTFUNC	0xC0
2120 #define	OLD_RIGHTFUNC	0xD0
2121 #define	OLD_TOPFUNC	0xE0
2122 #define	OLD_BOTTOMFUNC	0xF0
2123 
2124 /*
2125  * Map old special codes to new ones.
2126  * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
2127  */
2128 static keymap_entry_t  special_old_to_new[] = {
2129 	SHIFTKEYS,
2130 	BUCKYBITS,
2131 	FUNNY,
2132 	STRING,
2133 	LEFTFUNC,
2134 	RIGHTFUNC,
2135 	TOPFUNC,
2136 	BOTTOMFUNC,
2137 };
2138 
2139 
2140 /*
2141  * kbtrans_setkey:
2142  *	 Set individual keystation translation from old-style entry.
2143  */
2144 static int
2145 kbtrans_setkey(struct kbtrans_lower *lower, struct kiockey *key, cred_t *cr)
2146 {
2147 	int	strtabindex, i;
2148 	keymap_entry_t	*ke;
2149 	register int tablemask;
2150 	register keymap_entry_t entry;
2151 	register struct keyboard *kp;
2152 
2153 	kp = lower->kbtrans_keyboard;
2154 
2155 	if (key->kio_station >= kp->k_keymap_size)
2156 		return (EINVAL);
2157 
2158 	if (lower->kbtrans_keyboard == NULL)
2159 
2160 		return (EINVAL);
2161 
2162 	tablemask = key->kio_tablemask;
2163 
2164 	switch (tablemask) {
2165 	case KIOCABORT1:
2166 	case KIOCABORT1A:
2167 	case KIOCABORT2:
2168 		i = secpolicy_console(cr);
2169 		if (i != 0)
2170 			return (i);
2171 
2172 		switch (tablemask) {
2173 		case KIOCABORT1:
2174 			kp->k_abort1 = key->kio_station;
2175 			break;
2176 		case KIOCABORT1A:
2177 			kp->k_abort1a = key->kio_station;
2178 			break;
2179 		case KIOCABORT2:
2180 			kp->k_abort2 = key->kio_station;
2181 			break;
2182 		}
2183 		return (0);
2184 	}
2185 
2186 	if (tablemask & ALTGRAPHMASK)
2187 		return (EINVAL);
2188 
2189 	ke = kbtrans_find_entry(lower, (uint_t)tablemask, key->kio_station);
2190 	if (ke == NULL)
2191 		return (EINVAL);
2192 
2193 	if (key->kio_entry >= (uchar_t)OLD_STRING &&
2194 	    key->kio_entry <= (uchar_t)(OLD_STRING + 15)) {
2195 		strtabindex = key->kio_entry - OLD_STRING;
2196 		bcopy(key->kio_string,
2197 		    lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN);
2198 		lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
2199 	}
2200 
2201 	entry = key->kio_entry;
2202 
2203 	/*
2204 	 * There's nothing we need do with OLD_ISOCHAR.
2205 	 */
2206 	if (entry != OLD_ISOCHAR) {
2207 		if (entry & 0x80) {
2208 			if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE)
2209 				entry = FA_CLASS + (entry & 0x0F) - 9;
2210 			else
2211 				entry =
2212 				    special_old_to_new[entry >> 4 & 0x07]
2213 				    + (entry & 0x0F);
2214 		}
2215 	}
2216 
2217 	*ke = entry;
2218 
2219 	return (0);
2220 }
2221 
2222 
2223 /*
2224  * Map new special codes to old ones.
2225  * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
2226  */
2227 static uchar_t   special_new_to_old[] = {
2228 	0,			/* normal */
2229 	OLD_SHIFTKEYS,		/* SHIFTKEYS */
2230 	OLD_BUCKYBITS,		/* BUCKYBITS */
2231 	OLD_FUNNY,		/* FUNNY */
2232 	OLD_FA_UMLAUT,		/* FA_CLASS */
2233 	OLD_STRING,		/* STRING */
2234 	OLD_LEFTFUNC,		/* FUNCKEYS */
2235 };
2236 
2237 
2238 /*
2239  * kbtrans_getkey:
2240  *	Get individual keystation translation as old-style entry.
2241  */
2242 static int
2243 kbtrans_getkey(struct kbtrans_lower *lower, struct kiockey *key)
2244 {
2245 	int	strtabindex;
2246 	keymap_entry_t	*ke;
2247 	register keymap_entry_t entry;
2248 	struct keyboard *kp;
2249 
2250 	kp = lower->kbtrans_keyboard;
2251 
2252 	if (key->kio_station >= kp->k_keymap_size)
2253 		return (EINVAL);
2254 
2255 	if (lower->kbtrans_keyboard == NULL)
2256 		return (EINVAL);
2257 
2258 	switch (key->kio_tablemask) {
2259 	case KIOCABORT1:
2260 		key->kio_station = kp->k_abort1;
2261 		return (0);
2262 	case KIOCABORT1A:
2263 		key->kio_station = kp->k_abort1a;
2264 		return (0);
2265 	case KIOCABORT2:
2266 		key->kio_station = kp->k_abort2;
2267 		return (0);
2268 	}
2269 
2270 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2271 	    key->kio_station);
2272 	if (ke == NULL)
2273 		return (EINVAL);
2274 
2275 	entry = *ke;
2276 
2277 	if (entry & 0xFF00)
2278 		key->kio_entry =
2279 		    special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8]
2280 		    + (entry & 0x00FF);
2281 	else {
2282 		if (entry & 0x80)
2283 			key->kio_entry = (ushort_t)OLD_ISOCHAR;	/* you lose */
2284 		else
2285 			key->kio_entry = (ushort_t)entry;
2286 	}
2287 
2288 	if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) {
2289 		strtabindex = entry - STRING;
2290 		bcopy(lower->kbtrans_keystringtab[strtabindex],
2291 		    key->kio_string, KTAB_STRLEN);
2292 	}
2293 	return (0);
2294 }
2295 
2296 
2297 /*
2298  * kbtrans_skey:
2299  *	Set individual keystation translation from new-style entry.
2300  */
2301 static int
2302 kbtrans_skey(struct kbtrans_lower *lower, struct kiockeymap *key, cred_t *cr)
2303 {
2304 	int	strtabindex, i;
2305 	keymap_entry_t *ke;
2306 	struct keyboard *kp;
2307 
2308 	kp = lower->kbtrans_keyboard;
2309 
2310 	if (key->kio_station >= kp->k_keymap_size) {
2311 		return (EINVAL);
2312 
2313 	}
2314 
2315 	if (lower->kbtrans_keyboard == NULL) {
2316 		return (EINVAL);
2317 	}
2318 
2319 	switch (key->kio_tablemask) {
2320 	case KIOCABORT1:
2321 	case KIOCABORT1A:
2322 	case KIOCABORT2:
2323 		i = secpolicy_console(cr);
2324 		if (i != 0)
2325 			return (i);
2326 		switch (key->kio_tablemask) {
2327 		case KIOCABORT1:
2328 			kp->k_abort1 = key->kio_station;
2329 			break;
2330 		case KIOCABORT1A:
2331 			kp->k_abort1a = key->kio_station;
2332 			break;
2333 		case KIOCABORT2:
2334 			kp->k_abort2 = key->kio_station;
2335 			break;
2336 		}
2337 		return (0);
2338 	}
2339 
2340 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2341 	    key->kio_station);
2342 	if (ke == NULL)
2343 		return (EINVAL);
2344 
2345 	if (key->kio_entry >= STRING &&
2346 	    key->kio_entry <= (STRING + 15)) {
2347 		strtabindex = key->kio_entry-STRING;
2348 		bcopy(key->kio_string,
2349 		    lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN);
2350 		lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
2351 	}
2352 
2353 	*ke = key->kio_entry;
2354 
2355 	return (0);
2356 }
2357 
2358 
2359 /*
2360  * kbtrans_gkey:
2361  *	Get individual keystation translation as new-style entry.
2362  */
2363 static int
2364 kbtrans_gkey(struct kbtrans_lower *lower, struct kiockeymap *key)
2365 {
2366 	int	strtabindex;
2367 	keymap_entry_t *ke;
2368 	struct keyboard *kp;
2369 
2370 	kp = lower->kbtrans_keyboard;
2371 
2372 	if (key->kio_station >= kp->k_keymap_size)
2373 		return (EINVAL);
2374 
2375 	if (lower->kbtrans_keyboard == NULL)
2376 		return (EINVAL);
2377 
2378 	switch (key->kio_tablemask) {
2379 	case KIOCABORT1:
2380 		key->kio_station = kp->k_abort1;
2381 		return (0);
2382 	case KIOCABORT1A:
2383 		key->kio_station = kp->k_abort1a;
2384 		return (0);
2385 	case KIOCABORT2:
2386 		key->kio_station = kp->k_abort2;
2387 		return (0);
2388 	}
2389 
2390 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2391 	    key->kio_station);
2392 	if (ke == NULL)
2393 		return (EINVAL);
2394 
2395 	key->kio_entry = *ke;
2396 
2397 	if (key->kio_entry >= STRING &&
2398 	    key->kio_entry <= (STRING + 15)) {
2399 		strtabindex = key->kio_entry-STRING;
2400 		bcopy(lower->kbtrans_keystringtab[strtabindex],
2401 		    key->kio_string, KTAB_STRLEN);
2402 	}
2403 	return (0);
2404 }
2405