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