1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 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_set_queue:
533  *      Set the overlying queue, to support multiplexors.
534  */
535 void
536 kbtrans_streams_set_queue(struct kbtrans *upper, queue_t *q)
537 {
538 
539 	upper->kbtrans_streams_readq = q;
540 }
541 
542 /*
543  * kbtrans_streams_get_queue:
544  *      Return the overlying queue.
545  */
546 queue_t *
547 kbtrans_streams_get_queue(struct kbtrans *upper)
548 {
549 	return (upper->kbtrans_streams_readq);
550 }
551 
552 /*
553  * kbtrans_streams_untimeout
554  *      Cancell all timeout
555  */
556 void
557 kbtrans_streams_untimeout(struct kbtrans *upper)
558 {
559 	/* clear all timeouts */
560 	if (upper->kbtrans_streams_bufcallid) {
561 		qunbufcall(upper->kbtrans_streams_readq,
562 			upper->kbtrans_streams_bufcallid);
563 		upper->kbtrans_streams_bufcallid = 0;
564 	}
565 	if (upper->kbtrans_streams_rptid) {
566 		(void) quntimeout(upper->kbtrans_streams_readq,
567 			upper->kbtrans_streams_rptid);
568 		upper->kbtrans_streams_rptid = 0;
569 	}
570 }
571 
572 /*
573  * kbtrans_reioctl:
574  * 	This function is set up as call-back function should an ioctl fail
575  * 	to allocate required resources.
576  */
577 static void
578 kbtrans_reioctl(void	*arg)
579 {
580 	struct kbtrans *upper = (struct kbtrans *)arg;
581 	mblk_t *mp;
582 
583 	upper->kbtrans_streams_bufcallid = 0;
584 
585 	if ((mp = upper->kbtrans_streams_iocpending) != NULL) {
586 		/* not pending any more */
587 		upper->kbtrans_streams_iocpending = NULL;
588 		(void) kbtrans_ioctl(upper, mp);
589 	}
590 }
591 
592 /*
593  * kbtrans_ioctl:
594  * 	process ioctls we recognize and own.  Otherwise, pass it down.
595  */
596 static enum kbtrans_message_response
597 kbtrans_ioctl(struct kbtrans *upper, register mblk_t *mp)
598 {
599 	register struct iocblk *iocp;
600 	register short	new_translate;
601 	register Vuid_addr_probe *addr_probe;
602 	register short	*addr_ptr;
603 	size_t	ioctlrespsize;
604 	int	err = 0;
605 	struct kbtrans_lower *lower;
606 	mblk_t *datap;
607 	int	translate;
608 
609 	static int kiocgetkey, kiocsetkey;
610 
611 	lower = &upper->kbtrans_lower;
612 
613 	iocp = (struct iocblk *)mp->b_rptr;
614 
615 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper,
616 		"kbtrans_ioctl: ioc_cmd 0x%x - ", iocp->ioc_cmd));
617 	switch (iocp->ioc_cmd) {
618 
619 	case VUIDSFORMAT:
620 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSFORMAT\n"));
621 
622 		err = miocpullup(mp, sizeof (int));
623 		if (err != 0)
624 			break;
625 		new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
626 		    TR_ASCII : TR_EVENT;
627 
628 		if (new_translate == upper->kbtrans_streams_translate_mode)
629 			break;
630 		upper->kbtrans_streams_translate_mode = new_translate;
631 
632 		kbtrans_set_translation_callback(upper);
633 
634 		kbtrans_flush(upper);
635 		break;
636 
637 	case KIOCTRANS:
638 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANS\n"));
639 		err = miocpullup(mp, sizeof (int));
640 		if (err != 0)
641 			break;
642 		new_translate = *(int *)mp->b_cont->b_rptr;
643 		if (new_translate == upper->kbtrans_streams_translate_mode)
644 			break;
645 		upper->kbtrans_streams_translate_mode = new_translate;
646 		kbtrans_set_translation_callback(upper);
647 
648 		kbtrans_flush(upper);
649 		break;
650 
651 	case KIOCSLED:
652 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSLED\n"));
653 
654 		err = miocpullup(mp, sizeof (uchar_t));
655 		if (err != 0)
656 			break;
657 		lower->kbtrans_led_state = *(uchar_t *)mp->b_cont->b_rptr;
658 
659 		kbtrans_setled(upper);
660 		break;
661 
662 	case KIOCGLED:
663 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGLED\n"));
664 		if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
665 			ioctlrespsize = sizeof (int);
666 			goto allocfailure;
667 		}
668 
669 		*(uchar_t *)datap->b_wptr = lower->kbtrans_led_state;
670 		datap->b_wptr += sizeof (uchar_t);
671 		if (mp->b_cont)
672 			freemsg(mp->b_cont);
673 		mp->b_cont = datap;
674 		iocp->ioc_count = sizeof (uchar_t);
675 		break;
676 
677 	case VUIDGFORMAT:
678 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGFORMAT\n"));
679 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
680 			ioctlrespsize = sizeof (int);
681 			goto allocfailure;
682 		}
683 		*(int *)datap->b_wptr =
684 		    (upper->kbtrans_streams_translate_mode == TR_EVENT ||
685 		    upper->kbtrans_streams_translate_mode == TR_UNTRANS_EVENT) ?
686 			VUID_FIRM_EVENT: VUID_NATIVE;
687 		datap->b_wptr += sizeof (int);
688 		if (mp->b_cont)  /* free msg to prevent memory leak */
689 			freemsg(mp->b_cont);
690 		mp->b_cont = datap;
691 		iocp->ioc_count = sizeof (int);
692 		break;
693 
694 	case KIOCGTRANS:
695 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANS\n"));
696 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
697 			ioctlrespsize = sizeof (int);
698 			goto allocfailure;
699 		}
700 		*(int *)datap->b_wptr = upper->kbtrans_streams_translate_mode;
701 		datap->b_wptr += sizeof (int);
702 		if (mp->b_cont)  /* free msg to prevent memory leak */
703 			freemsg(mp->b_cont);
704 		mp->b_cont = datap;
705 		iocp->ioc_count = sizeof (int);
706 		break;
707 
708 	case VUIDSADDR:
709 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSADDR\n"));
710 
711 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
712 		if (err != 0)
713 			break;
714 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
715 		switch (addr_probe->base) {
716 
717 		case ASCII_FIRST:
718 			addr_ptr = &upper->kbtrans_streams_vuid_addr.ascii;
719 			break;
720 
721 		case TOP_FIRST:
722 			addr_ptr = &upper->kbtrans_streams_vuid_addr.top;
723 			break;
724 
725 		case VKEY_FIRST:
726 			addr_ptr = &upper->kbtrans_streams_vuid_addr.vkey;
727 			break;
728 
729 		default:
730 			err = ENODEV;
731 		}
732 
733 		if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
734 			*addr_ptr = addr_probe->data.next;
735 			kbtrans_flush(upper);
736 		}
737 		break;
738 
739 	case VUIDGADDR:
740 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGADDR\n"));
741 
742 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
743 		if (err != 0)
744 			break;
745 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
746 		switch (addr_probe->base) {
747 
748 		case ASCII_FIRST:
749 			addr_probe->data.current =
750 				upper->kbtrans_streams_vuid_addr.ascii;
751 			break;
752 
753 		case TOP_FIRST:
754 			addr_probe->data.current =
755 				upper->kbtrans_streams_vuid_addr.top;
756 			break;
757 
758 		case VKEY_FIRST:
759 			addr_probe->data.current =
760 				upper->kbtrans_streams_vuid_addr.vkey;
761 			break;
762 
763 		default:
764 			err = ENODEV;
765 		}
766 		break;
767 
768 	case KIOCTRANSABLE:
769 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANSABLE\n"));
770 
771 		err = miocpullup(mp, sizeof (int));
772 		if (err != 0)
773 			break;
774 		/*
775 		 * called during console setup in kbconfig()
776 		 * If set to false, means we are a serial keyboard,
777 		 * and we should pass all data up without modification.
778 		 */
779 		translate = *(int *)mp->b_cont->b_rptr;
780 		if (upper->kbtrans_streams_translatable != translate)
781 			upper->kbtrans_streams_translatable = translate;
782 
783 		if (translate != TR_CAN)
784 			DPRINTF(PRINT_L4, PRINT_MASK_ALL, (upper,
785 			    "Cannot translate keyboard using tables.\n"));
786 		break;
787 
788 	case KIOCGTRANSABLE:
789 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANSABLE\n"));
790 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
791 			ioctlrespsize = sizeof (int);
792 			goto allocfailure;
793 		}
794 		*(int *)datap->b_wptr = upper->kbtrans_streams_translatable;
795 		datap->b_wptr += sizeof (int);
796 		if (mp->b_cont)  /* free msg to prevent memory leak */
797 			freemsg(mp->b_cont);
798 		mp->b_cont = datap;
799 		iocp->ioc_count = sizeof (int);
800 		break;
801 
802 	case KIOCSCOMPAT:
803 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSCOMPAT\n"));
804 
805 		err = miocpullup(mp, sizeof (int));
806 		if (err != 0)
807 			break;
808 		lower->kbtrans_compat = *(int *)mp->b_cont->b_rptr;
809 		break;
810 
811 	case KIOCGCOMPAT:
812 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGCOMPAT\n"));
813 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
814 			ioctlrespsize = sizeof (int);
815 			goto allocfailure;
816 		}
817 		*(int *)datap->b_wptr = lower->kbtrans_compat;
818 		datap->b_wptr += sizeof (int);
819 		if (mp->b_cont)  /* free msg to prevent memory leak */
820 			freemsg(mp->b_cont);
821 		mp->b_cont = datap;
822 		iocp->ioc_count = sizeof (int);
823 		break;
824 
825 	case KIOCSETKEY:
826 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSETKEY %d\n",
827 							kiocsetkey++));
828 		err = miocpullup(mp, sizeof (struct kiockey));
829 		if (err != 0)
830 			break;
831 		err = kbtrans_setkey(&upper->kbtrans_lower,
832 		    (struct kiockey *)mp->b_cont->b_rptr, iocp->ioc_cr);
833 		/*
834 		 * Since this only affects any subsequent key presses,
835 		 * don't flush soft state.  One might want to
836 		 * toggle the keytable entries dynamically.
837 		 */
838 		break;
839 
840 	case KIOCGETKEY:
841 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGETKEY %d\n",
842 							kiocgetkey++));
843 		err = miocpullup(mp, sizeof (struct kiockey));
844 		if (err != 0)
845 			break;
846 		err = kbtrans_getkey(&upper->kbtrans_lower,
847 		    (struct kiockey *)mp->b_cont->b_rptr);
848 		break;
849 
850 	case KIOCSKEY:
851 		err = miocpullup(mp, sizeof (struct kiockeymap));
852 		if (err != 0)
853 			break;
854 		err = kbtrans_skey(&upper->kbtrans_lower,
855 		    (struct kiockeymap *)mp->b_cont->b_rptr, iocp->ioc_cr);
856 		/*
857 		 * Since this only affects any subsequent key presses,
858 		 * don't flush soft state.  One might want to
859 		 * toggle the keytable entries dynamically.
860 		 */
861 		break;
862 
863 	case KIOCGKEY:
864 		err = miocpullup(mp, sizeof (struct kiockeymap));
865 		if (err != 0)
866 			break;
867 		err = kbtrans_gkey(&upper->kbtrans_lower,
868 		    (struct kiockeymap *)mp->b_cont->b_rptr);
869 		break;
870 
871 	case KIOCSDIRECT:
872 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSDIRECT\n"));
873 		kbtrans_flush(upper);
874 		break;
875 
876 	case KIOCGDIRECT:
877 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSGDIRECT\n"));
878 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
879 			ioctlrespsize = sizeof (int);
880 			goto allocfailure;
881 		}
882 		*(int *)datap->b_wptr = 1;	/* always direct */
883 		datap->b_wptr += sizeof (int);
884 		if (mp->b_cont) /* free msg to prevent memory leak */
885 			freemsg(mp->b_cont);
886 		mp->b_cont = datap;
887 		iocp->ioc_count = sizeof (int);
888 		break;
889 
890 	case KIOCTYPE:
891 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTYPE\n"));
892 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
893 			ioctlrespsize = sizeof (int);
894 			goto allocfailure;
895 		}
896 		*(int *)datap->b_wptr = upper->kbtrans_streams_id;
897 		datap->b_wptr += sizeof (int);
898 		if (mp->b_cont) /* free msg to prevent memory leak */
899 			freemsg(mp->b_cont);
900 		mp->b_cont = datap;
901 		iocp->ioc_count = sizeof (int);
902 		break;
903 
904 	case CONSSETABORTENABLE:
905 		/*
906 		 * Peek as it goes by; must be a TRANSPARENT ioctl.
907 		 */
908 		if (iocp->ioc_count != TRANSPARENT) {
909 			err = EINVAL;
910 			break;
911 		}
912 
913 		upper->kbtrans_streams_abortable =
914 		    (boolean_t)*(intptr_t *)mp->b_cont->b_rptr;
915 
916 		/*
917 		 * Let the hardware module see it too.
918 		 */
919 		return (KBTRANS_MESSAGE_NOT_HANDLED);
920 
921 	case KIOCGRPTDELAY:
922 		/*
923 		 * Report the autorepeat delay, unit in millisecond
924 		 */
925 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTDELAY\n"));
926 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
927 			ioctlrespsize = sizeof (int);
928 			goto allocfailure;
929 		}
930 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_delay);
931 		datap->b_wptr += sizeof (int);
932 
933 		/* free msg to prevent memory leak */
934 		if (mp->b_cont != NULL)
935 			freemsg(mp->b_cont);
936 		mp->b_cont = datap;
937 		iocp->ioc_count = sizeof (int);
938 		break;
939 
940 	case KIOCSRPTDELAY:
941 		/*
942 		 * Set the autorepeat delay
943 		 */
944 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTDELAY\n"));
945 		err = miocpullup(mp, sizeof (int));
946 
947 		if (err != 0)
948 			break;
949 
950 		/* validate the input */
951 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
952 			err = EINVAL;
953 			break;
954 		}
955 		kbtrans_repeat_delay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
956 		if (kbtrans_repeat_delay <= 0)
957 			kbtrans_repeat_delay = 1;
958 		break;
959 
960 	case KIOCGRPTRATE:
961 		/*
962 		 * Report the autorepeat rate
963 		 */
964 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTRATE\n"));
965 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
966 			ioctlrespsize = sizeof (int);
967 			goto allocfailure;
968 		}
969 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_rate);
970 		datap->b_wptr += sizeof (int);
971 
972 		/* free msg to prevent memory leak */
973 		if (mp->b_cont != NULL)
974 			freemsg(mp->b_cont);
975 		mp->b_cont = datap;
976 		iocp->ioc_count = sizeof (int);
977 		break;
978 
979 	case KIOCSRPTRATE:
980 		/*
981 		 * Set the autorepeat rate
982 		 */
983 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTRATE\n"));
984 		err = miocpullup(mp, sizeof (int));
985 
986 		if (err != 0)
987 			break;
988 
989 		/* validate the input */
990 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
991 			err = EINVAL;
992 			break;
993 		}
994 		kbtrans_repeat_rate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
995 		if (kbtrans_repeat_rate <= 0)
996 			kbtrans_repeat_rate = 1;
997 		break;
998 
999 	default:
1000 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "unknown\n"));
1001 		return (KBTRANS_MESSAGE_NOT_HANDLED);
1002 	} /* end switch */
1003 
1004 	if (err != 0) {
1005 		iocp->ioc_rval = 0;
1006 		iocp->ioc_error = err;
1007 		mp->b_datap->db_type = M_IOCNAK;
1008 	} else {
1009 		iocp->ioc_rval = 0;
1010 		iocp->ioc_error = 0;	/* brain rot */
1011 		mp->b_datap->db_type = M_IOCACK;
1012 	}
1013 	putnext(upper->kbtrans_streams_readq, mp);
1014 
1015 	return (KBTRANS_MESSAGE_HANDLED);
1016 
1017 allocfailure:
1018 	/*
1019 	 * We needed to allocate something to handle this "ioctl", but
1020 	 * couldn't; save this "ioctl" and arrange to get called back when
1021 	 * it's more likely that we can get what we need.
1022 	 * If there's already one being saved, throw it out, since it
1023 	 * must have timed out.
1024 	 */
1025 	if (upper->kbtrans_streams_iocpending != NULL)
1026 		freemsg(upper->kbtrans_streams_iocpending);
1027 	upper->kbtrans_streams_iocpending = mp;
1028 	if (upper->kbtrans_streams_bufcallid) {
1029 		qunbufcall(upper->kbtrans_streams_readq,
1030 			upper->kbtrans_streams_bufcallid);
1031 	}
1032 	upper->kbtrans_streams_bufcallid =
1033 		qbufcall(upper->kbtrans_streams_readq, ioctlrespsize, BPRI_HI,
1034 			kbtrans_reioctl, upper);
1035 	/*
1036 	 * This is a white lie... we *will* handle it, eventually.
1037 	 */
1038 	return (KBTRANS_MESSAGE_HANDLED);
1039 }
1040 
1041 /*
1042  * kbtrans_flush:
1043  *	Flush data upstream
1044  */
1045 static void
1046 kbtrans_flush(register struct kbtrans *upper)
1047 {
1048 	register queue_t *q;
1049 
1050 	/* Flush pending data already sent upstream */
1051 	if ((q = upper->kbtrans_streams_readq) != NULL && q->q_next != NULL)
1052 		(void) putnextctl1(q, M_FLUSH, FLUSHR);
1053 
1054 	/* Flush pending ups */
1055 	bzero(upper->kbtrans_streams_downs, upper->kbtrans_streams_downs_bytes);
1056 
1057 	kbtrans_cancelrpt(upper);
1058 }
1059 
1060 /*
1061  * kbtrans_setled:
1062  *	 Update the keyboard LEDs to match the current keyboard state.
1063  */
1064 static void
1065 kbtrans_setled(struct kbtrans *upper)
1066 {
1067 	upper->kbtrans_streams_hw_callbacks->kbtrans_streams_setled(
1068 		upper->kbtrans_streams_hw,
1069 		upper->kbtrans_lower.kbtrans_led_state);
1070 }
1071 
1072 /*
1073  * kbtrans_rpt:
1074  *	If a key is held down, this function is set up to be called
1075  * 	after kbtrans_repeat_rate time elapses.
1076  */
1077 static void
1078 kbtrans_rpt(void *arg)
1079 {
1080 	struct kbtrans	*upper = arg;
1081 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1082 
1083 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL,
1084 		"kbtrans_rpt: repeat key %X\n",
1085 		lower->kbtrans_repeatkey));
1086 
1087 	upper->kbtrans_streams_rptid = 0;
1088 
1089 	/*
1090 	 * NB:  polled code zaps kbtrans_repeatkey without cancelling
1091 	 * timeout.
1092 	 */
1093 	if (lower->kbtrans_repeatkey != 0) {
1094 		kbtrans_keyreleased(upper, lower->kbtrans_repeatkey);
1095 
1096 		kbtrans_processkey(lower,
1097 			upper->kbtrans_streams_callback,
1098 			lower->kbtrans_repeatkey,
1099 			KEY_PRESSED);
1100 
1101 		upper->kbtrans_streams_rptid =
1102 			qtimeout(upper->kbtrans_streams_readq, kbtrans_rpt,
1103 			    (caddr_t)upper, kbtrans_repeat_rate);
1104 	}
1105 }
1106 
1107 /*
1108  * kbtrans_cancelrpt:
1109  * 	Cancel the repeating key
1110  */
1111 static void
1112 kbtrans_cancelrpt(struct kbtrans	*upper)
1113 {
1114 	upper->kbtrans_lower.kbtrans_repeatkey = 0;
1115 
1116 	if (upper->kbtrans_streams_rptid != 0) {
1117 		(void) quntimeout(upper->kbtrans_streams_readq,
1118 				    upper->kbtrans_streams_rptid);
1119 		upper->kbtrans_streams_rptid = 0;
1120 	}
1121 }
1122 
1123 /*
1124  * kbtrans_send_esc_event:
1125  *	Send character up stream. Used for the case of
1126  *	sending strings upstream.
1127  */
1128 static void
1129 kbtrans_send_esc_event(char c, register struct kbtrans *upper)
1130 {
1131 	Firm_event fe;
1132 
1133 	fe.id = c;
1134 	fe.value = 1;
1135 	fe.pair_type = FE_PAIR_NONE;
1136 	fe.pair = 0;
1137 	/*
1138 	 * Pretend as if each cp pushed and released
1139 	 * Calling kbtrans_queueevent avoids addr translation
1140 	 * and pair base determination of kbtrans_keypressed.
1141 	 */
1142 	kbtrans_queueevent(upper, &fe);
1143 	fe.value = 0;
1144 	kbtrans_queueevent(upper, &fe);
1145 }
1146 
1147 /*
1148  * kbtrans_strsetwithdecimal:
1149  *	Used for expanding a function key to the ascii equivalent
1150  */
1151 static char *
1152 kbtrans_strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
1153 {
1154 	int	hradix = 5;
1155 	char	*bp;
1156 	int	lowbit;
1157 	char	*tab = "0123456789abcdef";
1158 
1159 	bp = buf + maxdigs;
1160 	*(--bp) = '\0';
1161 	while (val) {
1162 		lowbit = val & 1;
1163 		val = (val >> 1);
1164 		*(--bp) = tab[val % hradix * 2 + lowbit];
1165 		val /= hradix;
1166 	}
1167 	return (bp);
1168 }
1169 
1170 /*
1171  * kbtrans_keypressed:
1172  *	Modify Firm event to be sent up the stream
1173  */
1174 static void
1175 kbtrans_keypressed(struct kbtrans *upper, uchar_t key_station,
1176 		    Firm_event *fe, ushort_t base)
1177 {
1178 
1179 	register short	id_addr;
1180 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1181 
1182 	/* Set pair values */
1183 	if (fe->id < (ushort_t)VKEY_FIRST) {
1184 		/*
1185 		 * If CTRLed, find the ID that would have been used had it
1186 		 * not been CTRLed.
1187 		 */
1188 		if (lower->kbtrans_shiftmask & (CTRLMASK | CTLSMASK)) {
1189 			unsigned short *ke;
1190 			unsigned int mask;
1191 
1192 			mask = lower->kbtrans_shiftmask &
1193 				~(CTRLMASK | CTLSMASK | UPMASK);
1194 
1195 			ke = kbtrans_find_entry(lower, mask, key_station);
1196 			if (ke == NULL)
1197 				return;
1198 
1199 			base = *ke;
1200 		}
1201 		if (base != fe->id) {
1202 			fe->pair_type = FE_PAIR_SET;
1203 			fe->pair = (uchar_t)base;
1204 
1205 			goto send;
1206 		}
1207 	}
1208 	fe->pair_type = FE_PAIR_NONE;
1209 	fe->pair = 0;
1210 
1211 send:
1212 	/* Adjust event id address for multiple keyboard/workstation support */
1213 	switch (vuid_id_addr(fe->id)) {
1214 	case ASCII_FIRST:
1215 		id_addr = upper->kbtrans_streams_vuid_addr.ascii;
1216 		break;
1217 	case TOP_FIRST:
1218 		id_addr = upper->kbtrans_streams_vuid_addr.top;
1219 		break;
1220 	case VKEY_FIRST:
1221 		id_addr = upper->kbtrans_streams_vuid_addr.vkey;
1222 		break;
1223 	default:
1224 		id_addr = vuid_id_addr(fe->id);
1225 		break;
1226 	}
1227 	fe->id = vuid_id_offset(fe->id) | id_addr;
1228 
1229 	kbtrans_queuepress(upper, key_station, fe);
1230 }
1231 
1232 /*
1233  * kbtrans_queuepress:
1234  *	Add keypress to the "downs" table
1235  */
1236 static void
1237 kbtrans_queuepress(struct kbtrans *upper,
1238 		    uchar_t key_station, Firm_event *fe)
1239 {
1240 	register struct key_event *ke, *ke_free;
1241 	register int i;
1242 
1243 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "kbtrans_queuepress:"
1244 		" key=%d", key_station));
1245 
1246 	ke_free = 0;
1247 
1248 	/* Scan table of down key stations */
1249 
1250 	for (i = 0, ke = upper->kbtrans_streams_downs;
1251 	    i < upper->kbtrans_streams_num_downs_entries; i++, ke++) {
1252 
1253 		/* Keycode already down? */
1254 		if (ke->key_station == key_station) {
1255 
1256 			DPRINTF(PRINT_L0, PRINT_MASK_ALL,
1257 				(NULL, "kbtrans: Double "
1258 				"entry in downs table (%d,%d)!\n",
1259 				key_station, i));
1260 
1261 			goto add_event;
1262 		}
1263 
1264 		if (ke->key_station == 0)
1265 			ke_free = ke;
1266 	}
1267 
1268 	if (ke_free) {
1269 		ke = ke_free;
1270 		goto add_event;
1271 	}
1272 
1273 	ke = upper->kbtrans_streams_downs;
1274 
1275 add_event:
1276 	ke->key_station = key_station;
1277 	ke->event = *fe;
1278 	kbtrans_queueevent(upper, fe);
1279 }
1280 
1281 /*
1282  * kbtrans_keyreleased:
1283  * 	Remove entry from the downs table
1284  */
1285 static void
1286 kbtrans_keyreleased(register struct kbtrans *upper, uchar_t key_station)
1287 {
1288 	register struct key_event *ke;
1289 	register int i;
1290 
1291 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "RELEASE key=%d\n",
1292 		key_station));
1293 
1294 	if (upper->kbtrans_streams_translate_mode != TR_EVENT &&
1295 	    upper->kbtrans_streams_translate_mode != TR_UNTRANS_EVENT) {
1296 
1297 		return;
1298 	}
1299 
1300 	/* Scan table of down key stations */
1301 	for (i = 0, ke = upper->kbtrans_streams_downs;
1302 	    i < upper->kbtrans_streams_num_downs_entries;
1303 	    i++, ke++) {
1304 		/* Found? */
1305 		if (ke->key_station == key_station) {
1306 			ke->key_station = 0;
1307 			ke->event.value = 0;
1308 			kbtrans_queueevent(upper, &ke->event);
1309 		}
1310 	}
1311 
1312 	/*
1313 	 * Ignore if couldn't find because may be called twice
1314 	 * for the same key station in the case of the kbtrans_rpt
1315 	 * routine being called unnecessarily.
1316 	 */
1317 }
1318 
1319 
1320 /*
1321  * kbtrans_putcode:
1322  *	 Pass a keycode up the stream, if you can, otherwise throw it away.
1323  */
1324 static void
1325 kbtrans_putcode(register struct kbtrans *upper, uint_t code)
1326 {
1327 	register mblk_t *bp;
1328 
1329 	/*
1330 	 * If we can't send it up, then we just drop it.
1331 	 */
1332 	if (!canputnext(upper->kbtrans_streams_readq)) {
1333 
1334 		return;
1335 	}
1336 
1337 	/*
1338 	 * Allocate a messsage block to send up.
1339 	 */
1340 	if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) {
1341 
1342 		cmn_err(CE_WARN, "kbtrans_putcode: Can't allocate block\
1343 			for keycode.");
1344 
1345 		return;
1346 	}
1347 
1348 	/*
1349 	 * We will strip out any high order information here.
1350 	 */
1351 	/* NOTE the implicit cast here */
1352 	*bp->b_wptr++ = (uchar_t)code;
1353 
1354 	/*
1355 	 * Send the message up.
1356 	 */
1357 	(void) putnext(upper->kbtrans_streams_readq, bp);
1358 }
1359 
1360 
1361 /*
1362  * kbtrans_putbuf:
1363  *	Pass generated keycode sequence to upstream, if possible.
1364  */
1365 static void
1366 kbtrans_putbuf(char *buf, queue_t *q)
1367 {
1368 	register mblk_t *bp;
1369 
1370 	if (!canputnext(q)) {
1371 		cmn_err(CE_WARN, "kbtrans_putbuf: Can't put block for keycode");
1372 	} else {
1373 		if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) {
1374 			cmn_err(CE_WARN, "kbtrans_putbuf: "
1375 			    "Can't allocate block for keycode");
1376 		} else {
1377 			while (*buf) {
1378 				*bp->b_wptr++ = *buf;
1379 				buf++;
1380 			}
1381 			putnext(q, bp);
1382 		}
1383 	}
1384 }
1385 
1386 /*
1387  * kbtrans_queueevent:
1388  *	 Pass a VUID "firm event" up the stream, if you can.
1389  */
1390 static void
1391 kbtrans_queueevent(struct kbtrans *upper, Firm_event *fe)
1392 {
1393 	register queue_t *q;
1394 	register mblk_t *bp;
1395 
1396 	if ((q = upper->kbtrans_streams_readq) == NULL)
1397 
1398 		return;
1399 
1400 	if (!canputnext(q)) {
1401 		if (kbtrans_overflow_msg) {
1402 			DPRINTF(PRINT_L2, PRINT_MASK_ALL, (NULL,
1403 				"kbtrans: Buffer flushed when overflowed."));
1404 		}
1405 
1406 		kbtrans_flush(upper);
1407 		upper->kbtrans_overflow_cnt++;
1408 	} else {
1409 		if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) {
1410 			cmn_err(CE_WARN, "kbtrans_queueevent: Can't allocate \
1411 					block for event.");
1412 		} else {
1413 			uniqtime32(&fe->time);
1414 			 *(Firm_event *)bp->b_wptr = *fe;
1415 			bp->b_wptr += sizeof (Firm_event);
1416 			(void) putnext(q, bp);
1417 
1418 
1419 		}
1420 	}
1421 }
1422 
1423 /*
1424  * kbtrans_set_translation_callback:
1425  *	This code sets the translation_callback pointer based on the
1426  * 	translation mode.
1427  */
1428 static void
1429 kbtrans_set_translation_callback(register struct kbtrans *upper)
1430 {
1431 	switch (upper->kbtrans_streams_translate_mode) {
1432 
1433 	default:
1434 	case TR_ASCII:
1435 		upper->kbtrans_streams_callback = &ascii_callback;
1436 
1437 		break;
1438 
1439 	case TR_EVENT:
1440 		upper->kbtrans_streams_callback = &trans_event_callback;
1441 
1442 		break;
1443 
1444 	case TR_UNTRANS_EVENT:
1445 		upper->kbtrans_streams_callback = &untrans_event_callback;
1446 
1447 		break;
1448 	}
1449 }
1450 
1451 /*
1452  * kbtrans_untrans_keypressed_raw:
1453  *	This is the callback we get if we are in TR_UNTRANS_EVENT and a
1454  * 	key is pressed.  This code will just send the scancode up the
1455  * 	stream.
1456  */
1457 static void
1458 kbtrans_untrans_keypressed_raw(struct kbtrans *upper, kbtrans_key_t key)
1459 {
1460 	Firm_event	fe;
1461 
1462 	bzero(&fe, sizeof (fe));
1463 
1464 	/*
1465 	 * fill in the event
1466 	 */
1467 	fe.id = (unsigned short)key;
1468 	fe.value = 1;
1469 
1470 	/*
1471 	 * Send the event upstream.
1472 	 */
1473 	kbtrans_queuepress(upper, key, &fe);
1474 }
1475 
1476 /*
1477  * kbtrans_untrans_keyreleased_raw:
1478  *	This is the callback we get if we are in TR_UNTRANS_EVENT mode
1479  * 	and a key is released.  This code will just send the scancode up
1480  * 	the stream.
1481  */
1482 static void
1483 kbtrans_untrans_keyreleased_raw(struct kbtrans *upper, kbtrans_key_t key)
1484 {
1485 	/*
1486 	 * Deal with a key released event.
1487 	 */
1488 	kbtrans_keyreleased(upper, key);
1489 }
1490 
1491 /*
1492  * kbtrans_ascii_keypressed:
1493  *	This is the code if we are in TR_ASCII mode and a key
1494  * 	is pressed.  This is where we will do any special processing that
1495  * 	is specific to ASCII key translation.
1496  */
1497 /* ARGSUSED */
1498 static void
1499 kbtrans_ascii_keypressed(
1500     struct kbtrans	*upper,
1501     uint_t 		entrytype,
1502     kbtrans_key_t 	key,
1503     uint_t 		entry)
1504 {
1505 	register char	*cp;
1506 	register char	*bufp;
1507 	char		buf[14];
1508 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1509 
1510 	/*
1511 	 * Based on the type of key, we may need to do some ASCII
1512 	 * specific post processing.
1513 	 */
1514 	switch (entrytype) {
1515 
1516 	case BUCKYBITS:
1517 	case SHIFTKEYS:
1518 	case FUNNY:
1519 		/*
1520 		 * There is no ascii equivalent.  We will ignore these
1521 		 * keys
1522 		 */
1523 		return;
1524 
1525 	case FUNCKEYS:
1526 		/*
1527 		 * We need to expand this key to get the ascii
1528 		 * equivalent.  These are the function keys (F1, F2 ...)
1529 		 */
1530 		bufp = buf;
1531 		cp = kbtrans_strsetwithdecimal(bufp + 2,
1532 			(uint_t)((entry & 0x003F) + 192),
1533 			sizeof (buf) - 5);
1534 		*bufp++ = '\033'; /* Escape */
1535 		*bufp++ = '[';
1536 		while (*cp != '\0')
1537 			*bufp++ = *cp++;
1538 		*bufp++ = 'z';
1539 		*bufp = '\0';
1540 
1541 		/*
1542 		 * Send the result upstream.
1543 		 */
1544 		kbtrans_putbuf(buf, upper->kbtrans_streams_readq);
1545 
1546 		return;
1547 
1548 	case STRING:
1549 		/*
1550 		 * These are the multi byte keys (Home, Up, Down ...)
1551 		 */
1552 		cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
1553 
1554 		/*
1555 		 * Copy the string from the keystringtable, and send it
1556 		 * upstream a character at a time.
1557 		 */
1558 		while (*cp != '\0') {
1559 
1560 			kbtrans_putcode(upper, (uchar_t)*cp);
1561 
1562 			cp++;
1563 		}
1564 
1565 		return;
1566 
1567 	case PADKEYS:
1568 		/*
1569 		 * These are the keys on the keypad.  Look up the
1570 		 * answer in the kb_numlock_table and send it upstream.
1571 		 */
1572 		kbtrans_putcode(upper,
1573 			    lower->kbtrans_numlock_table[entry&0x1F]);
1574 
1575 		return;
1576 
1577 	case 0:	/* normal character */
1578 	default:
1579 		break;
1580 	}
1581 
1582 	/*
1583 	 * Send the byte upstream.
1584 	 */
1585 	kbtrans_putcode(upper, entry);
1586 
1587 }
1588 
1589 /*
1590  * kbtrans_ascii_keyreleased:
1591  *	This is the function if we are in TR_ASCII mode and a key
1592  * 	is released.  ASCII doesn't have the concept of released keys,
1593  * 	or make/break codes.  So there is nothing for us to do.
1594  */
1595 /* ARGSUSED */
1596 static void
1597 kbtrans_ascii_keyreleased(struct kbtrans *upper, kbtrans_key_t key)
1598 {
1599 	/* Nothing to do ... for now */
1600 }
1601 
1602 /*
1603  * kbtrans_ascii_setup_repeat:
1604  *	This is the function if we are in TR_ASCII mode and the
1605  * 	translation module has decided that a key needs to be repeated.
1606  */
1607 /* ARGSUSED */
1608 static void
1609 kbtrans_ascii_setup_repeat(
1610     struct kbtrans *upper,
1611     uint_t entrytype,
1612     kbtrans_key_t key)
1613 {
1614 	struct kbtrans_lower *lower = &upper->kbtrans_lower;
1615 
1616 	/*
1617 	 * Cancel any currently repeating keys.  This will be a new
1618 	 * key to repeat.
1619 	 */
1620 	kbtrans_cancelrpt(upper);
1621 
1622 	/*
1623 	 * Set the value of the key to be repeated.
1624 	 */
1625 	lower->kbtrans_repeatkey = key;
1626 
1627 	/*
1628 	 * Start the timeout for repeating this key.  kbtrans_rpt will
1629 	 * be called to repeat the key.
1630 	 */
1631 	upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq,
1632 		kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay);
1633 }
1634 
1635 /*
1636  * kbtrans_trans_event_keypressed:
1637  *	This is the function if we are in TR_EVENT mode and a key
1638  * 	is pressed.  This is where we will do any special processing that
1639  * 	is specific to EVENT key translation.
1640  */
1641 static void
1642 kbtrans_trans_event_keypressed(
1643 	struct kbtrans 	*upper,
1644 	uint_t 		entrytype,
1645 	kbtrans_key_t 	key,
1646 	uint_t 		entry)
1647 {
1648 	Firm_event	fe;
1649 	register char	*cp;
1650 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1651 
1652 	/*
1653 	 * Based on the type of key, we may need to do some EVENT
1654 	 * specific post processing.
1655 	 */
1656 	switch (entrytype) {
1657 
1658 	case SHIFTKEYS:
1659 		/*
1660 		 * Relying on ordinal correspondence between
1661 		 * vuid_event.h SHIFT_META-SHIFT_TOP &
1662 		 * kbd.h METABIT-SYSTEMBIT in order to
1663 		 * correctly translate entry into fe.id.
1664 		 */
1665 		fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
1666 		fe.value = 1;
1667 		kbtrans_keypressed(upper, key, &fe, fe.id);
1668 
1669 		return;
1670 
1671 	case BUCKYBITS:
1672 		/*
1673 		 * Relying on ordinal correspondence between
1674 		 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1675 		 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1676 		 * correctly translate entry into fe.id.
1677 		 */
1678 		fe.id = SHIFT_META + (entry & 0x0F);
1679 		fe.value = 1;
1680 		kbtrans_keypressed(upper, key, &fe, fe.id);
1681 
1682 		return;
1683 
1684 	case FUNCKEYS:
1685 		/*
1686 		 * Take advantage of the similar
1687 		 * ordering of kbd.h function keys and
1688 		 * vuid_event.h function keys to do a
1689 		 * simple translation to achieve a
1690 		 * mapping between the 2 different
1691 		 * address spaces.
1692 		 */
1693 		fe.id = KEY_LEFTFIRST + (entry & 0x003F);
1694 		fe.value = 1;
1695 
1696 		/*
1697 		 * Assume "up" table only generates
1698 		 * shift changes.
1699 		 */
1700 		kbtrans_keypressed(upper, key, &fe, fe.id);
1701 
1702 		/*
1703 		 * Function key events can be expanded
1704 		 * by terminal emulator software to
1705 		 * produce the standard escape sequence
1706 		 * generated by the TR_ASCII case above
1707 		 * if a function key event is not used
1708 		 * by terminal emulator software
1709 		 * directly.
1710 		 */
1711 		return;
1712 
1713 	case STRING:
1714 		/*
1715 		 * These are the multi byte keys (Home, Up, Down ...)
1716 		 */
1717 		cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
1718 
1719 		/*
1720 		 * Copy the string from the keystringtable, and send it
1721 		 * upstream a character at a time.
1722 		 */
1723 		while (*cp != '\0') {
1724 
1725 			kbtrans_send_esc_event(*cp, upper);
1726 
1727 			cp++;
1728 		}
1729 
1730 		return;
1731 
1732 	case PADKEYS:
1733 		/*
1734 		 * Take advantage of the similar
1735 		 * ordering of kbd.h keypad keys and
1736 		 * vuid_event.h keypad keys to do a
1737 		 * simple translation to achieve a
1738 		 * mapping between the 2 different
1739 		 * address spaces.
1740 		 */
1741 		fe.id = VKEY_FIRSTPAD + (entry & 0x001F);
1742 		fe.value = 1;
1743 
1744 		/*
1745 		 * Assume "up" table only generates
1746 		 * shift changes.
1747 		 */
1748 		kbtrans_keypressed(upper, key, &fe, fe.id);
1749 
1750 		/*
1751 		 * Keypad key events can be expanded
1752 		 * by terminal emulator software to
1753 		 * produce the standard ascii character
1754 		 * generated by the TR_ASCII case above
1755 		 * if a keypad key event is not used
1756 		 * by terminal emulator software
1757 		 * directly.
1758 		 */
1759 		return;
1760 
1761 	case FUNNY:
1762 		/*
1763 		 * These are not events.
1764 		 */
1765 		switch (entry) {
1766 		case IDLE:
1767 		case RESET:
1768 		case ERROR:
1769 			/*
1770 			 * Something has happened.  Mark all keys as released.
1771 			 */
1772 			kbtrans_streams_releaseall(upper);
1773 			break;
1774 		}
1775 
1776 		return;
1777 
1778 	case 0: /* normal character */
1779 	default:
1780 		break;
1781 	}
1782 
1783 	/*
1784 	 * Send the event upstream.
1785 	 */
1786 	fe.id = entry;
1787 
1788 	fe.value = 1;
1789 
1790 	kbtrans_queueevent(upper, &fe);
1791 }
1792 
1793 /*
1794  * kbtrans_trans_event_keyreleased:
1795  *	This is the function if we are in TR_EVENT mode and a key
1796  * 	is released.
1797  */
1798 /* ARGSUSED */
1799 static void
1800 kbtrans_trans_event_keyreleased(struct kbtrans *upper, kbtrans_key_t key)
1801 {
1802 	/*
1803 	 * Mark the key as released and send an event upstream.
1804 	 */
1805 	kbtrans_keyreleased(upper, key);
1806 }
1807 
1808 /*
1809  * kbtrans_trans_event_setup_repeat:
1810  *	This is the function if we are in TR_EVENT mode and the
1811  *	translation module has decided that a key needs to be repeated.
1812  * 	We will set a timeout to retranslate the repeat key.
1813  */
1814 static void
1815 kbtrans_trans_event_setup_repeat(
1816 	struct kbtrans	*upper,
1817 	uint_t 		entrytype,
1818 	kbtrans_key_t	key)
1819 {
1820 	struct kbtrans_lower *lower = &upper->kbtrans_lower;
1821 
1822 	/*
1823 	 * Function keys and keypad keys do not repeat when we are in
1824 	 * EVENT mode.
1825 	 */
1826 	if (entrytype == FUNCKEYS || entrytype == PADKEYS) {
1827 
1828 		return;
1829 	}
1830 
1831 	/*
1832 	 * Cancel any currently repeating keys.  This will be a new
1833 	 * key to repeat.
1834 	 */
1835 	kbtrans_cancelrpt(upper);
1836 
1837 	/*
1838 	 * Set the value of the key to be repeated.
1839 	 */
1840 	lower->kbtrans_repeatkey = key;
1841 
1842 	/*
1843 	 * Start the timeout for repeating this key.  kbtrans_rpt will
1844 	 * be called to repeat the key.
1845 	 */
1846 	upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq,
1847 		kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay);
1848 }
1849 
1850 /*
1851  * Administer the key tables.
1852  */
1853 
1854 /*
1855  * Old special codes.
1856  */
1857 #define	OLD_SHIFTKEYS	0x80
1858 #define	OLD_BUCKYBITS	0x90
1859 #define	OLD_FUNNY	0xA0
1860 #define	OLD_FA_UMLAUT	0xA9
1861 #define	OLD_FA_CFLEX	0xAA
1862 #define	OLD_FA_TILDE	0xAB
1863 #define	OLD_FA_CEDILLA	0xAC
1864 #define	OLD_FA_ACUTE	0xAD
1865 #define	OLD_FA_GRAVE	0xAE
1866 #define	OLD_ISOCHAR	0xAF
1867 #define	OLD_STRING	0xB0
1868 #define	OLD_LEFTFUNC	0xC0
1869 #define	OLD_RIGHTFUNC	0xD0
1870 #define	OLD_TOPFUNC	0xE0
1871 #define	OLD_BOTTOMFUNC	0xF0
1872 
1873 /*
1874  * Map old special codes to new ones.
1875  * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
1876  */
1877 static ushort_t  special_old_to_new[] = {
1878 	SHIFTKEYS,
1879 	BUCKYBITS,
1880 	FUNNY,
1881 	STRING,
1882 	LEFTFUNC,
1883 	RIGHTFUNC,
1884 	TOPFUNC,
1885 	BOTTOMFUNC,
1886 };
1887 
1888 
1889 /*
1890  * kbtrans_setkey:
1891  *	 Set individual keystation translation from old-style entry.
1892  */
1893 static int
1894 kbtrans_setkey(struct kbtrans_lower *lower, struct kiockey *key, cred_t *cr)
1895 {
1896 	int	strtabindex, i;
1897 	unsigned short	*ke;
1898 	register int tablemask;
1899 	register ushort_t entry;
1900 	register struct keyboard *kp;
1901 
1902 	kp = lower->kbtrans_keyboard;
1903 
1904 	if (key->kio_station >= kp->k_keymap_size)
1905 
1906 		return (EINVAL);
1907 
1908 	if (lower->kbtrans_keyboard == NULL)
1909 
1910 		return (EINVAL);
1911 
1912 	tablemask = key->kio_tablemask;
1913 
1914 	switch (tablemask) {
1915 	case KIOCABORT1:
1916 	case KIOCABORT1A:
1917 	case KIOCABORT2:
1918 		i = secpolicy_console(cr);
1919 		if (i != 0)
1920 			return (i);
1921 
1922 		switch (tablemask) {
1923 		case KIOCABORT1:
1924 			kp->k_abort1 = key->kio_station;
1925 			break;
1926 		case KIOCABORT1A:
1927 			kp->k_abort1a = key->kio_station;
1928 			break;
1929 		case KIOCABORT2:
1930 			kp->k_abort2 = key->kio_station;
1931 			break;
1932 		}
1933 		return (0);
1934 	}
1935 
1936 	if (tablemask & ALTGRAPHMASK)
1937 		return (EINVAL);
1938 
1939 	ke = kbtrans_find_entry(lower, (uint_t)tablemask, key->kio_station);
1940 	if (ke == NULL)
1941 		return (EINVAL);
1942 
1943 	if (key->kio_entry >= (uchar_t)OLD_STRING &&
1944 	    key->kio_entry <= (uchar_t)(OLD_STRING + 15)) {
1945 		strtabindex = key->kio_entry - OLD_STRING;
1946 		bcopy(key->kio_string,
1947 			lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN);
1948 		lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
1949 	}
1950 
1951 	entry = key->kio_entry;
1952 
1953 	/*
1954 	 * There's nothing we need do with OLD_ISOCHAR.
1955 	 */
1956 	if (entry != OLD_ISOCHAR) {
1957 		if (entry & 0x80) {
1958 			if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE)
1959 				entry = FA_CLASS + (entry & 0x0F) - 9;
1960 			else
1961 				entry =
1962 				    special_old_to_new[entry >> 4 & 0x07]
1963 				    + (entry & 0x0F);
1964 		}
1965 	}
1966 
1967 	*ke = entry;
1968 
1969 	return (0);
1970 }
1971 
1972 
1973 /*
1974  * Map new special codes to old ones.
1975  * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
1976  */
1977 static uchar_t   special_new_to_old[] = {
1978 	0,			/* normal */
1979 	OLD_SHIFTKEYS,		/* SHIFTKEYS */
1980 	OLD_BUCKYBITS,		/* BUCKYBITS */
1981 	OLD_FUNNY,		/* FUNNY */
1982 	OLD_FA_UMLAUT,		/* FA_CLASS */
1983 	OLD_STRING,		/* STRING */
1984 	OLD_LEFTFUNC,		/* FUNCKEYS */
1985 };
1986 
1987 
1988 /*
1989  * kbtrans_getkey:
1990  *	Get individual keystation translation as old-style entry.
1991  */
1992 static int
1993 kbtrans_getkey(struct kbtrans_lower *lower, struct kiockey *key)
1994 {
1995 	int	strtabindex;
1996 	unsigned short	*ke;
1997 	register ushort_t entry;
1998 	struct keyboard *kp;
1999 
2000 	kp = lower->kbtrans_keyboard;
2001 
2002 	if (key->kio_station >= kp->k_keymap_size)
2003 		return (EINVAL);
2004 
2005 	if (lower->kbtrans_keyboard == NULL)
2006 		return (EINVAL);
2007 
2008 	switch (key->kio_tablemask) {
2009 	case KIOCABORT1:
2010 		key->kio_station = kp->k_abort1;
2011 		return (0);
2012 	case KIOCABORT1A:
2013 		key->kio_station = kp->k_abort1a;
2014 		return (0);
2015 	case KIOCABORT2:
2016 		key->kio_station = kp->k_abort2;
2017 		return (0);
2018 	}
2019 
2020 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2021 		key->kio_station);
2022 	if (ke == NULL)
2023 		return (EINVAL);
2024 
2025 	entry = *ke;
2026 
2027 	if (entry & 0xFF00)
2028 		key->kio_entry =
2029 		    special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8]
2030 		    + (entry & 0x00FF);
2031 	else {
2032 		if (entry & 0x80)
2033 			key->kio_entry = (ushort_t)OLD_ISOCHAR;	/* you lose */
2034 		else
2035 			key->kio_entry = (ushort_t)entry;
2036 	}
2037 
2038 	if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) {
2039 		strtabindex = entry - STRING;
2040 		bcopy(lower->kbtrans_keystringtab[strtabindex],
2041 			key->kio_string, KTAB_STRLEN);
2042 	}
2043 	return (0);
2044 }
2045 
2046 
2047 /*
2048  * kbtrans_skey:
2049  *	Set individual keystation translation from new-style entry.
2050  */
2051 static int
2052 kbtrans_skey(struct kbtrans_lower *lower, struct kiockeymap *key, cred_t *cr)
2053 {
2054 	int	strtabindex, i;
2055 	unsigned short *ke;
2056 	struct keyboard *kp;
2057 
2058 	kp = lower->kbtrans_keyboard;
2059 
2060 	if (key->kio_station >= kp->k_keymap_size) {
2061 		return (EINVAL);
2062 
2063 	}
2064 
2065 	if (lower->kbtrans_keyboard == NULL) {
2066 		return (EINVAL);
2067 	}
2068 
2069 	switch (key->kio_tablemask) {
2070 	case KIOCABORT1:
2071 	case KIOCABORT1A:
2072 	case KIOCABORT2:
2073 		i = secpolicy_console(cr);
2074 		if (i != 0)
2075 			return (i);
2076 		switch (key->kio_tablemask) {
2077 		case KIOCABORT1:
2078 			kp->k_abort1 = key->kio_station;
2079 			break;
2080 		case KIOCABORT1A:
2081 			kp->k_abort1a = key->kio_station;
2082 			break;
2083 		case KIOCABORT2:
2084 			kp->k_abort2 = key->kio_station;
2085 			break;
2086 		}
2087 		return (0);
2088 	}
2089 
2090 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2091 		key->kio_station);
2092 	if (ke == NULL)
2093 		return (EINVAL);
2094 
2095 	if (key->kio_entry >= STRING &&
2096 	    key->kio_entry <= (ushort_t)(STRING + 15)) {
2097 		strtabindex = key->kio_entry-STRING;
2098 		bcopy(key->kio_string,
2099 			lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN);
2100 		lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
2101 	}
2102 
2103 	*ke = key->kio_entry;
2104 
2105 	return (0);
2106 }
2107 
2108 
2109 /*
2110  * kbtrans_gkey:
2111  *	Get individual keystation translation as new-style entry.
2112  */
2113 static int
2114 kbtrans_gkey(struct kbtrans_lower *lower, struct	kiockeymap *key)
2115 {
2116 	int	strtabindex;
2117 	unsigned short *ke;
2118 	struct keyboard *kp;
2119 
2120 	kp = lower->kbtrans_keyboard;
2121 
2122 	if (key->kio_station >= kp->k_keymap_size)
2123 		return (EINVAL);
2124 
2125 	if (lower->kbtrans_keyboard == NULL)
2126 		return (EINVAL);
2127 
2128 	switch (key->kio_tablemask) {
2129 	case KIOCABORT1:
2130 		key->kio_station = kp->k_abort1;
2131 		return (0);
2132 	case KIOCABORT1A:
2133 		key->kio_station = kp->k_abort1a;
2134 		return (0);
2135 	case KIOCABORT2:
2136 		key->kio_station = kp->k_abort2;
2137 		return (0);
2138 	}
2139 
2140 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2141 		key->kio_station);
2142 	if (ke == NULL)
2143 		return (EINVAL);
2144 
2145 	key->kio_entry = *ke;
2146 
2147 	if (key->kio_entry >= STRING &&
2148 	    key->kio_entry <= (ushort_t)(STRING + 15)) {
2149 		strtabindex = key->kio_entry-STRING;
2150 		bcopy(lower->kbtrans_keystringtab[strtabindex],
2151 			key->kio_string, KTAB_STRLEN);
2152 	}
2153 	return (0);
2154 }
2155