Home | History | Annotate | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 						/* SunOS-4.0 1.60	*/
     28 /*	From:	SunOS4.0	sundev/kbd.c	*/
     29 
     30 /*
     31  * Keyboard input streams module - handles conversion of up/down codes to
     32  * ASCII or event format.
     33  */
     34 #include <sys/types.h>
     35 #include <sys/param.h>
     36 #include <sys/sysmacros.h>
     37 #include <sys/signal.h>
     38 #include <sys/termios.h>
     39 #include <sys/termio.h>
     40 #include <sys/stream.h>
     41 #include <sys/stropts.h>
     42 #include <sys/strsun.h>
     43 #include <sys/kmem.h>
     44 #include <sys/file.h>
     45 #include <sys/uio.h>
     46 #include <sys/errno.h>
     47 #include <sys/time.h>
     48 #include <sys/consdev.h>
     49 #include <sys/kbd.h>
     50 #include <sys/kbio.h>
     51 #include <sys/kbdreg.h>
     52 #include <sys/vuid_event.h>
     53 #include <sys/debug.h>
     54 #include <sys/ddi.h>
     55 #include <sys/sunddi.h>
     56 #include <sys/policy.h>
     57 
     58 #include <sys/modctl.h>
     59 #include <sys/beep.h>
     60 #include <sys/int_limits.h>
     61 
     62 static struct streamtab kbd_info;
     63 
     64 static struct fmodsw fsw = {
     65 	"kb",
     66 	&kbd_info,
     67 	D_MP | D_MTPERMOD
     68 };
     69 
     70 /*
     71  * Module linkage information for the kernel.
     72  */
     73 
     74 static struct modlstrmod modlstrmod = {
     75 	&mod_strmodops, "streams module for keyboard", &fsw
     76 };
     77 
     78 static struct modlinkage modlinkage = {
     79 	MODREV_1, (void *)&modlstrmod, NULL
     80 };
     81 
     82 int
     83 _init(void)
     84 {
     85 	return (mod_install(&modlinkage));
     86 }
     87 
     88 int
     89 _fini(void)
     90 {
     91 	return (mod_remove(&modlinkage));
     92 }
     93 
     94 int
     95 _info(struct modinfo *modinfop)
     96 {
     97 	return (mod_info(&modlinkage, modinfop));
     98 }
     99 
    100 /*
    101  * For now these are shared.
    102  * These data structures are static (defined in keytables.c) thus
    103  * there is no need to perform any locking.
    104  */
    105 extern struct keyboards	keytables[];
    106 extern char keystringtab[16][KTAB_STRLEN];
    107 extern struct compose_sequence_t kb_compose_table[];
    108 extern signed char kb_compose_map[];
    109 extern struct fltaccent_sequence_t kb_fltaccent_table[];
    110 extern uchar_t kb_numlock_table[];
    111 
    112 /*
    113  * This value corresponds approximately to max 10 fingers
    114  */
    115 static int	kbd_downs_size = 15;
    116 
    117 typedef	struct	key_event {
    118 	uchar_t	key_station;	/* Physical key station associated with event */
    119 	Firm_event event;	/* Event that sent out on down */
    120 } Key_event;
    121 struct	kbddata {
    122 	queue_t	*kbdd_readq;
    123 	queue_t *kbdd_writeq;
    124 	mblk_t	*kbdd_iocpending;	/* "ioctl" awaiting buffer */
    125 	mblk_t	*kbdd_replypending;	/* "ioctl" reply awaiting result */
    126 	int	kbdd_flags;		/* random flags */
    127 	bufcall_id_t kbdd_bufcallid;	/* bufcall id */
    128 	timeout_id_t kbdd_rptid;	/* timeout id for kbdrpt() */
    129 	timeout_id_t kbdd_layoutid;	/* timeout id for kbdlayout() */
    130 	int	kbdd_iocid;		/* ID of "ioctl" being waited for */
    131 	int	kbdd_iocerror;		/* error return from "ioctl" */
    132 	struct	keyboardstate kbdd_state;
    133 					/*
    134 					 * State of keyboard & keyboard
    135 					 * specific settings, e.g., tables
    136 					 */
    137 	int	kbdd_translate;		/* Translate keycodes? */
    138 	int	kbdd_translatable;	/* Keyboard is translatable? */
    139 	int	kbdd_compat;		/* Generating pre-4.1 events? */
    140 	short	kbdd_ascii_addr;	/* Vuid_id_addr for ascii events */
    141 	short	kbdd_top_addr;		/* Vuid_id_addr for top events */
    142 	short	kbdd_vkey_addr;		/* Vuid_id_addr for vkey events */
    143 	struct	key_event *kbdd_downs;
    144 					/*
    145 					 * Table of key stations currently down
    146 					 * that have firm events that need
    147 					 * to be matched with up transitions
    148 					 * when kbdd_translate is TR_*EVENT
    149 					 */
    150 	int	kbdd_downs_entries; /* # of possible entries in kbdd_downs */
    151 	uint_t	kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */
    152 	ushort_t compose_key;		/* first compose key */
    153 	ushort_t fltaccent_entry;	/* floating accent keymap entry */
    154 	char	led_state;		/* current state of LEDs */
    155 	unsigned char shiftkey;		/* used for the new abort keys */
    156 };
    157 
    158 #define	KBD_OPEN	0x00000001 /* keyboard is open for business */
    159 #define	KBD_IOCWAIT	0x00000002 /* "open" waiting for "ioctl" to finish */
    160 
    161 #define	NO_HARD_RESET	0		/* don't do hard reset */
    162 #define	HARD_RESET	1		/* do hard reset */
    163 
    164 
    165 /*
    166  * Constants setup during the first open of a kbd (so that they can be patched
    167  * for debugging purposes).
    168  */
    169 static int kbd_repeatrate;
    170 static int kbd_repeatdelay;
    171 
    172 static int kbd_overflow_cnt;	/* Number of times kbd overflowed input q */
    173 static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */
    174 
    175 #ifdef	KBD_DEBUG
    176 int	kbd_debug = 0;
    177 int	kbd_ra_debug = 0;
    178 int	kbd_raw_debug = 0;
    179 int	kbd_rpt_debug = 0;
    180 int	kbd_input_debug = 0;
    181 #endif	/* KBD_DEBUG */
    182 
    183 static int	kbdopen(queue_t *, dev_t *, int, int, cred_t *);
    184 static int	kbdclose(queue_t *, int, cred_t *);
    185 static void	kbdwput(queue_t *, mblk_t *);
    186 static void	kbdrput(queue_t *, mblk_t *);
    187 
    188 static struct module_info kbdmiinfo = {
    189 	0,
    190 	"kb",
    191 	0,
    192 	INFPSZ,
    193 	2048,
    194 	128
    195 };
    196 
    197 static struct qinit kbdrinit = {
    198 	(int (*)())kbdrput,
    199 	(int (*)())NULL,
    200 	kbdopen,
    201 	kbdclose,
    202 	(int (*)())NULL,
    203 	&kbdmiinfo
    204 };
    205 
    206 static struct module_info kbdmoinfo = {
    207 	0,
    208 	"kb",
    209 	0,
    210 	INFPSZ,
    211 	2048,
    212 	128
    213 };
    214 
    215 static struct qinit kbdwinit = {
    216 	(int (*)())kbdwput,
    217 	(int (*)())NULL,
    218 	kbdopen,
    219 	kbdclose,
    220 	(int (*)())NULL,
    221 	&kbdmoinfo
    222 };
    223 
    224 static struct streamtab kbd_info = {
    225 	&kbdrinit,
    226 	&kbdwinit,
    227 	NULL,
    228 	NULL,
    229 };
    230 
    231 static void	kbdreioctl(void *);
    232 static void	kbdioctl(queue_t *, mblk_t *);
    233 static void	kbdflush(struct kbddata *);
    234 static void	kbduse(struct kbddata *, unsigned);
    235 static void	kbdsetled(struct kbddata *);
    236 static void	kbd_beep_off(void *arg);
    237 static void	kbd_beep_on(void *arg);
    238 static void	kbdcmd(queue_t *, char);
    239 static void	kbdreset(struct kbddata *, uint_t);
    240 static int	kbdsetkey(struct kbddata *, struct kiockey *,  cred_t *);
    241 static int	kbdgetkey(struct kbddata *, struct kiockey *);
    242 static int	kbdskey(struct kbddata *, struct kiockeymap *,  cred_t *);
    243 static int	kbdgkey(struct kbddata *, struct kiockeymap *);
    244 static void	kbdlayouttimeout(void *);
    245 static void	kbdinput(struct kbddata *, unsigned);
    246 static void	kbdid(struct kbddata *, int);
    247 static struct	keymap *settable(struct kbddata *, uint_t);
    248 static void	kbdrpt(void *);
    249 static void	kbdcancelrpt(struct kbddata *);
    250 static void	kbdtranslate(struct kbddata *, unsigned, queue_t *);
    251 static int	kbd_do_compose(ushort_t, ushort_t, ushort_t *);
    252 static void	kbd_send_esc_event(char, struct kbddata *);
    253 char		*strsetwithdecimal(char *, uint_t, uint_t);
    254 static void	kbdkeypressed(struct kbddata *, uchar_t, Firm_event *,
    255 								ushort_t);
    256 static void	kbdqueuepress(struct kbddata *, uchar_t, Firm_event *);
    257 static void	kbdkeyreleased(struct kbddata *, uchar_t);
    258 static void	kbdreleaseall(struct kbddata *);
    259 static void	kbdputcode(uint_t, queue_t *);
    260 static void	kbdputbuf(char *, queue_t *);
    261 static void	kbdqueueevent(struct kbddata *, Firm_event *);
    262 
    263 /*
    264  * Dummy qbufcall callback routine used by open and close.
    265  * The framework will wake up qwait_sig when we return from
    266  * this routine (as part of leaving the perimeters.)
    267  * (The framework enters the perimeters before calling the qbufcall() callback
    268  * and leaves the perimeters after the callback routine has executed. The
    269  * framework performs an implicit wakeup of any thread in qwait/qwait_sig
    270  * when it leaves the perimeter. See qwait(9E).)
    271  */
    272 /* ARGSUSED */
    273 static void dummy_callback(void *arg)
    274 {}
    275 
    276 
    277 /*
    278  * Open a keyboard.
    279  * Ttyopen sets line characteristics
    280  */
    281 /* ARGSUSED */
    282 static int
    283 kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
    284 {
    285 	register int  error;
    286 	register struct	kbddata *kbdd;
    287 	mblk_t *mp;
    288 	mblk_t *datap;
    289 	register struct iocblk *iocb;
    290 	register struct termios *cb;
    291 
    292 	/* Set these up only once so that they could be changed from adb */
    293 	if (!kbd_repeatrate) {
    294 		kbd_repeatrate = (hz+29)/30;
    295 		kbd_repeatdelay = hz/2;
    296 	}
    297 
    298 	if (q->q_ptr != NULL)
    299 		return (0);		/* already attached */
    300 
    301 	/*
    302 	 * Only allow open requests to succeed for privileged users.  This
    303 	 * necessary to prevent users from pushing the "kb" module again
    304 	 * on the stream associated with /dev/kbd.
    305 	 */
    306 	if (secpolicy_console(crp) != 0) {
    307 		return (EPERM);
    308 	}
    309 
    310 
    311 	switch (sflag) {
    312 
    313 	case MODOPEN:
    314 		break;
    315 
    316 	case CLONEOPEN:
    317 		return (EINVAL);	/* No Bozos! */
    318 	}
    319 
    320 	/* allocate keyboard */
    321 
    322 	kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP);
    323 
    324 
    325 	/*
    326 	 * Set up queue pointers, so that the "put" procedure will accept
    327 	 * the reply to the "ioctl" message we send down.
    328 	 */
    329 	q->q_ptr = kbdd;
    330 	WR(q)->q_ptr = kbdd;
    331 
    332 	qprocson(q);
    333 
    334 	/*
    335 	 * Setup tty modes.
    336 	 */
    337 	while ((mp = mkiocb(TCSETSF)) == NULL) {
    338 		timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI,
    339 		    dummy_callback, NULL);
    340 		if (!qwait_sig(q)) {
    341 			qunbufcall(q, id);
    342 			kmem_free(kbdd, sizeof (struct kbddata));
    343 			qprocsoff(q);
    344 
    345 			return (EINTR);
    346 		}
    347 	}
    348 	while ((datap = allocb(sizeof (struct termios), BPRI_HI)) ==
    349 	    NULL) {
    350 		timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI,
    351 		    dummy_callback, NULL);
    352 		if (!qwait_sig(q)) {
    353 			qunbufcall(q, id);
    354 			freemsg(mp);
    355 			kmem_free(kbdd, sizeof (struct kbddata));
    356 			qprocsoff(q);
    357 
    358 			return (EINTR);
    359 		}
    360 	}
    361 
    362 	iocb		= (struct iocblk *)mp->b_rptr;
    363 	iocb->ioc_count	= sizeof (struct termios);
    364 
    365 	cb = (struct termios *)datap->b_rptr;
    366 	cb->c_iflag = 0;
    367 	cb->c_oflag = 0;
    368 	cb->c_cflag = CREAD|CS8|B1200;
    369 	cb->c_lflag = 0;
    370 	bzero(cb->c_cc, NCCS);
    371 	datap->b_wptr += sizeof (struct termios);
    372 	mp->b_cont = datap;
    373 	kbdd->kbdd_flags |= KBD_IOCWAIT;	/* indicate that we're */
    374 	kbdd->kbdd_iocid = iocb->ioc_id;	/* waiting for this response */
    375 	putnext(WR(q), mp);
    376 
    377 	/*
    378 	 * Now wait for it.  Let our read queue put routine wake us up
    379 	 * when it arrives.
    380 	 */
    381 	while (kbdd->kbdd_flags & KBD_IOCWAIT) {
    382 		if (!qwait_sig(q)) {
    383 			error = EINTR;
    384 			goto error;
    385 		}
    386 	}
    387 	if ((error = kbdd->kbdd_iocerror) != 0)
    388 		goto error;
    389 
    390 	/*
    391 	 * Set up private data.
    392 	 */
    393 	kbdd->kbdd_readq = q;
    394 	kbdd->kbdd_writeq = WR(q);
    395 	kbdd->kbdd_iocpending = NULL;
    396 	kbdd->kbdd_translatable = TR_CAN;
    397 	kbdd->kbdd_translate = TR_ASCII;
    398 	kbdd->kbdd_compat = 1;
    399 	kbdd->kbdd_ascii_addr = ASCII_FIRST;
    400 	kbdd->kbdd_top_addr = TOP_FIRST;
    401 	kbdd->kbdd_vkey_addr = VKEY_FIRST;
    402 	/* Allocate dynamic memory for downs table */
    403 	kbdd->kbdd_downs_entries = kbd_downs_size;
    404 	kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event);
    405 	kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP);
    406 	kbdd->kbdd_flags = KBD_OPEN;
    407 	kbdd->led_state = 0;
    408 
    409 	/*
    410 	 * Reset kbd.
    411 	 */
    412 	kbdreset(kbdd, HARD_RESET);
    413 
    414 	(void) beep_init((void *)WR(q), kbd_beep_on, kbd_beep_off, NULL);
    415 
    416 	return (0);
    417 
    418 error:
    419 	qprocsoff(q);
    420 	kmem_free(kbdd, sizeof (struct kbddata));
    421 	return (error);
    422 }
    423 
    424 /*
    425  * Close a keyboard.
    426  */
    427 /* ARGSUSED1 */
    428 static int
    429 kbdclose(register queue_t *q, int flag, cred_t *crp)
    430 {
    431 	register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
    432 	register mblk_t *mp;
    433 
    434 	qprocsoff(q);
    435 	(void) beep_fini();
    436 	/*
    437 	 * Since we're about to destroy our private data, turn off
    438 	 * our open flag first, so we don't accept any more input
    439 	 * and try to use that data.
    440 	 */
    441 	kbdd->kbdd_flags = 0;
    442 
    443 	if ((mp = kbdd->kbdd_replypending) != NULL) {
    444 		/*
    445 		 * There was a KIOCLAYOUT pending; presumably, it timed out.
    446 		 * Throw the reply away.
    447 		 */
    448 		kbdd->kbdd_replypending = NULL;
    449 		freemsg(mp);
    450 	}
    451 
    452 	/* clear all timeouts */
    453 	if (kbdd->kbdd_bufcallid)
    454 		qunbufcall(q, kbdd->kbdd_bufcallid);
    455 	if (kbdd->kbdd_rptid)
    456 		(void) quntimeout(q, kbdd->kbdd_rptid);
    457 	if (kbdd->kbdd_layoutid)
    458 		(void) quntimeout(q, kbdd->kbdd_layoutid);
    459 	kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
    460 	kmem_free(kbdd, sizeof (struct kbddata));
    461 	return (0);
    462 }
    463 
    464 /*
    465  * Line discipline output queue put procedure: handles M_IOCTL
    466  * messages.
    467  */
    468 static void
    469 kbdwput(register queue_t *q, register mblk_t *mp)
    470 {
    471 	/*
    472 	 * Process M_FLUSH, and some M_IOCTL, messages here; pass
    473 	 * everything else down.
    474 	 */
    475 	switch (mp->b_datap->db_type) {
    476 
    477 	case M_FLUSH:
    478 		if (*mp->b_rptr & FLUSHW)
    479 			flushq(q, FLUSHDATA);
    480 		if (*mp->b_rptr & FLUSHR)
    481 			flushq(RD(q), FLUSHDATA);
    482 
    483 	default:
    484 		putnext(q, mp);	/* pass it down the line */
    485 		break;
    486 
    487 	case M_IOCTL:
    488 		kbdioctl(q, mp);
    489 		break;
    490 	}
    491 }
    492 
    493 
    494 static void
    495 kbdreioctl(void *kbdd_addr)
    496 {
    497 	struct kbddata *kbdd = kbdd_addr;
    498 	queue_t *q;
    499 	mblk_t *mp;
    500 
    501 	kbdd->kbdd_bufcallid = 0;
    502 	q = kbdd->kbdd_writeq;
    503 	if ((mp = kbdd->kbdd_iocpending) != NULL) {
    504 		kbdd->kbdd_iocpending = NULL;	/* not pending any more */
    505 		kbdioctl(q, mp);
    506 	}
    507 }
    508 
    509 static void
    510 kbdioctl(register queue_t *q, register mblk_t *mp)
    511 {
    512 	register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
    513 	register struct iocblk *iocp;
    514 	register short	new_translate;
    515 	register Vuid_addr_probe *addr_probe;
    516 	register short	*addr_ptr;
    517 	mblk_t *datap;
    518 	size_t	ioctlrespsize;
    519 	int	err = 0;
    520 	int	tmp;
    521 	int	cycles;
    522 	int	frequency;
    523 	int	msecs;
    524 
    525 	iocp = (struct iocblk *)mp->b_rptr;
    526 
    527 	switch (iocp->ioc_cmd) {
    528 
    529 	case VUIDSFORMAT:
    530 		err = miocpullup(mp, sizeof (int));
    531 		if (err != 0)
    532 			break;
    533 
    534 		new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
    535 		    TR_ASCII : TR_EVENT;
    536 		if (new_translate == kbdd->kbdd_translate)
    537 			break;
    538 		kbdd->kbdd_translate = new_translate;
    539 		goto output_format_change;
    540 
    541 	case KIOCTRANS:
    542 		err = miocpullup(mp, sizeof (int));
    543 		if (err != 0)
    544 			break;
    545 
    546 		new_translate = *(int *)mp->b_cont->b_rptr;
    547 		if (new_translate == kbdd->kbdd_translate)
    548 			break;
    549 		kbdd->kbdd_translate = new_translate;
    550 		goto output_format_change;
    551 
    552 	case KIOCCMD:
    553 		err = miocpullup(mp, sizeof (int));
    554 		if (err != 0)
    555 			break;
    556 
    557 		tmp = (char)(*(int *)mp->b_cont->b_rptr);
    558 		if (tmp == KBD_CMD_BELL)
    559 			(void) beeper_on(BEEP_TYPE4);
    560 		else if (tmp == KBD_CMD_NOBELL)
    561 			(void) beeper_off();
    562 		else
    563 			kbdcmd(q, tmp);
    564 		break;
    565 
    566 	case KIOCMKTONE:
    567 		if (iocp->ioc_count != TRANSPARENT) {
    568 			/*
    569 			 * We don't support non-transparent ioctls,
    570 			 * i.e. I_STR ioctls
    571 			 */
    572 			err = EINVAL;
    573 			break;
    574 		}
    575 		tmp = (int)(*(intptr_t *)mp->b_cont->b_rptr);
    576 		cycles = tmp & 0xffff;
    577 		msecs = (tmp >> 16) & 0xffff;
    578 
    579 		if (cycles == 0)
    580 			frequency = UINT16_MAX;
    581 		else if (cycles == UINT16_MAX)
    582 			frequency = 0;
    583 		else {
    584 			frequency = (PIT_HZ + cycles / 2) / cycles;
    585 			if (frequency > UINT16_MAX)
    586 				frequency = UINT16_MAX;
    587 		}
    588 
    589 		err = beep_mktone(frequency, msecs);
    590 		break;
    591 
    592 	case KIOCSLED:
    593 		err = miocpullup(mp, sizeof (uchar_t));
    594 		if (err != 0)
    595 			break;
    596 
    597 		kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr;
    598 		kbdsetled(kbdd);
    599 		break;
    600 
    601 	case KIOCGLED:
    602 		if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
    603 			ioctlrespsize = sizeof (int);
    604 			goto allocfailure;
    605 		}
    606 		*(uchar_t *)datap->b_wptr = kbdd->led_state;
    607 		datap->b_wptr += sizeof (uchar_t);
    608 		if (mp->b_cont)  /* free msg to prevent memory leak */
    609 			freemsg(mp->b_cont);
    610 		mp->b_cont = datap;
    611 		iocp->ioc_count = sizeof (uchar_t);
    612 		break;
    613 
    614 	case VUIDGFORMAT:
    615 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    616 			ioctlrespsize = sizeof (int);
    617 			goto allocfailure;
    618 		}
    619 		*(int *)datap->b_wptr =
    620 		    (kbdd->kbdd_translate == TR_EVENT ||
    621 		    kbdd->kbdd_translate == TR_UNTRANS_EVENT) ?
    622 		    VUID_FIRM_EVENT: VUID_NATIVE;
    623 		datap->b_wptr += sizeof (int);
    624 		if (mp->b_cont)  /* free msg to prevent memory leak */
    625 			freemsg(mp->b_cont);
    626 		mp->b_cont = datap;
    627 		iocp->ioc_count = sizeof (int);
    628 		break;
    629 
    630 	case KIOCGTRANS:
    631 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    632 			ioctlrespsize = sizeof (int);
    633 			goto allocfailure;
    634 		}
    635 		*(int *)datap->b_wptr = kbdd->kbdd_translate;
    636 		datap->b_wptr += sizeof (int);
    637 		if (mp->b_cont)  /* free msg to prevent memory leak */
    638 			freemsg(mp->b_cont);
    639 		mp->b_cont = datap;
    640 		iocp->ioc_count = sizeof (int);
    641 		break;
    642 
    643 	case VUIDSADDR:
    644 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
    645 		if (err != 0)
    646 			break;
    647 
    648 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
    649 		switch (addr_probe->base) {
    650 
    651 		case ASCII_FIRST:
    652 			addr_ptr = &kbdd->kbdd_ascii_addr;
    653 			break;
    654 
    655 		case TOP_FIRST:
    656 			addr_ptr = &kbdd->kbdd_top_addr;
    657 			break;
    658 
    659 		case VKEY_FIRST:
    660 			addr_ptr = &kbdd->kbdd_vkey_addr;
    661 			break;
    662 
    663 		default:
    664 			err = ENODEV;
    665 		}
    666 		if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
    667 			*addr_ptr = addr_probe->data.next;
    668 			goto output_format_change;
    669 		}
    670 		break;
    671 
    672 	case VUIDGADDR:
    673 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
    674 		if (err != 0)
    675 			break;
    676 
    677 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
    678 		switch (addr_probe->base) {
    679 
    680 		case ASCII_FIRST:
    681 			addr_probe->data.current = kbdd->kbdd_ascii_addr;
    682 			break;
    683 
    684 		case TOP_FIRST:
    685 			addr_probe->data.current = kbdd->kbdd_top_addr;
    686 			break;
    687 
    688 		case VKEY_FIRST:
    689 			addr_probe->data.current = kbdd->kbdd_vkey_addr;
    690 			break;
    691 
    692 		default:
    693 			err = ENODEV;
    694 		}
    695 		break;
    696 
    697 	case KIOCTRANSABLE:
    698 		err = miocpullup(mp, sizeof (int));
    699 		if (err != 0)
    700 			break;
    701 
    702 		if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) {
    703 			kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr;
    704 			kbdreset(kbdd, HARD_RESET);
    705 			goto output_format_change;
    706 		}
    707 		break;
    708 
    709 	case KIOCGTRANSABLE:
    710 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    711 			ioctlrespsize = sizeof (int);
    712 			goto allocfailure;
    713 		}
    714 		*(int *)datap->b_wptr = kbdd->kbdd_translatable;
    715 		datap->b_wptr += sizeof (int);
    716 		if (mp->b_cont)  /* free msg to prevent memory leak */
    717 			freemsg(mp->b_cont);
    718 		mp->b_cont = datap;
    719 		iocp->ioc_count = sizeof (int);
    720 		break;
    721 
    722 	case KIOCSCOMPAT:
    723 		err = miocpullup(mp, sizeof (int));
    724 		if (err != 0)
    725 			break;
    726 
    727 		kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr;
    728 		break;
    729 
    730 	case KIOCGCOMPAT:
    731 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    732 			ioctlrespsize = sizeof (int);
    733 			goto allocfailure;
    734 		}
    735 		*(int *)datap->b_wptr = kbdd->kbdd_compat;
    736 		datap->b_wptr += sizeof (int);
    737 		if (mp->b_cont)  /* free msg to prevent memory leak */
    738 			freemsg(mp->b_cont);
    739 		mp->b_cont = datap;
    740 		iocp->ioc_count = sizeof (int);
    741 		break;
    742 
    743 	case KIOCSETKEY:
    744 		err = miocpullup(mp, sizeof (struct kiockey));
    745 		if (err != 0)
    746 			break;
    747 
    748 		err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr,
    749 		    iocp->ioc_cr);
    750 		/*
    751 		 * Since this only affects any subsequent key presses,
    752 		 * don't goto output_format_change.  One might want to
    753 		 * toggle the keytable entries dynamically.
    754 		 */
    755 		break;
    756 
    757 	case KIOCGETKEY:
    758 		err = miocpullup(mp, sizeof (struct kiockey));
    759 		if (err != 0)
    760 			break;
    761 
    762 		err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr);
    763 		break;
    764 
    765 	case KIOCSKEY:
    766 		err = miocpullup(mp, sizeof (struct kiockeymap));
    767 		if (err != 0)
    768 			break;
    769 
    770 		err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr,
    771 		    iocp->ioc_cr);
    772 		/*
    773 		 * Since this only affects any subsequent key presses,
    774 		 * don't goto output_format_change.  One might want to
    775 		 * toggle the keytable entries dynamically.
    776 		 */
    777 		break;
    778 
    779 	case KIOCGKEY:
    780 		err = miocpullup(mp, sizeof (struct kiockeymap));
    781 		if (err != 0)
    782 			break;
    783 
    784 		err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr);
    785 		break;
    786 
    787 	case KIOCSDIRECT:
    788 		goto output_format_change;
    789 
    790 	case KIOCGDIRECT:
    791 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    792 			ioctlrespsize = sizeof (int);
    793 			goto allocfailure;
    794 		}
    795 		*(int *)datap->b_wptr = 1;	/* always direct */
    796 		datap->b_wptr += sizeof (int);
    797 		if (mp->b_cont) /* free msg to prevent memory leak */
    798 			freemsg(mp->b_cont);
    799 		mp->b_cont = datap;
    800 		iocp->ioc_count = sizeof (int);
    801 		break;
    802 
    803 	case KIOCTYPE:
    804 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    805 			ioctlrespsize = sizeof (int);
    806 			goto allocfailure;
    807 		}
    808 		*(int *)datap->b_wptr = kbdd->kbdd_state.k_id;
    809 		datap->b_wptr += sizeof (int);
    810 		if (mp->b_cont) /* free msg to prevent memory leak */
    811 			freemsg(mp->b_cont);
    812 		mp->b_cont = datap;
    813 		iocp->ioc_count = sizeof (int);
    814 		break;
    815 
    816 	case KIOCLAYOUT:
    817 		if ((datap = kbdd->kbdd_replypending) != NULL) {
    818 			/*
    819 			 * There was an earlier KIOCLAYOUT pending; presumably,
    820 			 * it timed out.  Throw the reply away.
    821 			 */
    822 			kbdd->kbdd_replypending = NULL;
    823 			freemsg(datap);
    824 		}
    825 
    826 		if (kbdd->kbdd_state.k_id == KB_SUN4 ||
    827 		    kbdd->kbdd_state.k_id == KB_PC) {
    828 			if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    829 				ioctlrespsize = sizeof (int);
    830 				goto allocfailure;
    831 			}
    832 			iocp->ioc_rval = 0;
    833 			iocp->ioc_error = 0;	/* brain rot */
    834 			iocp->ioc_count = sizeof (int);
    835 			if (mp->b_cont)   /* free msg to prevent memory leak */
    836 				freemsg(mp->b_cont);
    837 			mp->b_cont = datap;
    838 			mp->b_datap->db_type = M_IOCACK;
    839 			kbdd->kbdd_replypending = mp;
    840 			kbdcmd(q, (char)KBD_CMD_GETLAYOUT);
    841 			if (kbdd->kbdd_layoutid)
    842 				(void) quntimeout(q, kbdd->kbdd_layoutid);
    843 			kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout,
    844 			    kbdd, hz / 5);
    845 			return;		/* wait for reply from keyboard */
    846 		} else {
    847 			/*
    848 			 * Not a Type 4 keyboard; return an immediate error.
    849 			 */
    850 			err = EINVAL;
    851 			break;
    852 		}
    853 
    854 	case KIOCGRPTDELAY:
    855 		/*
    856 		 * Report the autorepeat delay, unit in millisecond
    857 		 */
    858 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    859 			ioctlrespsize = sizeof (int);
    860 			goto allocfailure;
    861 		}
    862 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay);
    863 		datap->b_wptr += sizeof (int);
    864 
    865 		/* free msg to prevent memory leak */
    866 		if (mp->b_cont != NULL)
    867 			freemsg(mp->b_cont);
    868 		mp->b_cont = datap;
    869 		iocp->ioc_count = sizeof (int);
    870 		break;
    871 
    872 	case KIOCSRPTDELAY:
    873 		/*
    874 		 * Set the autorepeat delay
    875 		 */
    876 		err = miocpullup(mp, sizeof (int));
    877 
    878 		if (err != 0)
    879 			break;
    880 
    881 		/* validate the input */
    882 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
    883 			err = EINVAL;
    884 			break;
    885 		}
    886 		kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
    887 		if (kbd_repeatdelay <= 0)
    888 			kbd_repeatdelay = 1;
    889 		break;
    890 
    891 	case KIOCGRPTRATE:
    892 		/*
    893 		 * Report the autorepeat rate
    894 		 */
    895 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    896 			ioctlrespsize = sizeof (int);
    897 			goto allocfailure;
    898 		}
    899 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate);
    900 		datap->b_wptr += sizeof (int);
    901 
    902 		/* free msg to prevent memory leak */
    903 		if (mp->b_cont != NULL)
    904 			freemsg(mp->b_cont);
    905 		mp->b_cont = datap;
    906 		iocp->ioc_count = sizeof (int);
    907 		break;
    908 
    909 	case KIOCSRPTRATE:
    910 		/*
    911 		 * Set the autorepeat rate
    912 		 */
    913 		err = miocpullup(mp, sizeof (int));
    914 
    915 		if (err != 0)
    916 			break;
    917 
    918 		/* validate the input */
    919 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
    920 			err = EINVAL;
    921 			break;
    922 		}
    923 		kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
    924 		if (kbd_repeatrate <= 0)
    925 			kbd_repeatrate = 1;
    926 		break;
    927 
    928 	default:
    929 		putnext(q, mp);	/* pass it down the line */
    930 		return;
    931 	}
    932 	goto done;
    933 
    934 output_format_change:
    935 	kbdflush(kbdd);
    936 
    937 done:
    938 	if (err != 0) {
    939 		iocp->ioc_rval = 0;
    940 		iocp->ioc_error = err;
    941 		mp->b_datap->db_type = M_IOCNAK;
    942 	} else {
    943 		iocp->ioc_rval = 0;
    944 		iocp->ioc_error = 0;	/* brain rot */
    945 		mp->b_datap->db_type = M_IOCACK;
    946 	}
    947 	qreply(q, mp);
    948 	return;
    949 
    950 allocfailure:
    951 	/*
    952 	 * We needed to allocate something to handle this "ioctl", but
    953 	 * couldn't; save this "ioctl" and arrange to get called back when
    954 	 * it's more likely that we can get what we need.
    955 	 * If there's already one being saved, throw it out, since it
    956 	 * must have timed out.
    957 	 */
    958 	if (kbdd->kbdd_iocpending != NULL)
    959 		freemsg(kbdd->kbdd_iocpending);
    960 	kbdd->kbdd_iocpending = mp;
    961 	if (kbdd->kbdd_bufcallid)
    962 		qunbufcall(q, kbdd->kbdd_bufcallid);
    963 	kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI,
    964 	    kbdreioctl, kbdd);
    965 }
    966 
    967 static void
    968 kbdflush(register struct kbddata *kbdd)
    969 {
    970 	register queue_t *q;
    971 
    972 	/* Flush pending data already sent upstream */
    973 	if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL)
    974 		(void) putnextctl1(q, M_FLUSH, FLUSHR);
    975 	/* Flush pending ups */
    976 	bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
    977 	kbdcancelrpt(kbdd);
    978 }
    979 
    980 /*
    981  * Pass keycode upstream, either translated or untranslated.
    982  */
    983 static void
    984 kbduse(register struct kbddata *kbdd, unsigned keycode)
    985 {
    986 	register queue_t *readq;
    987 
    988 #ifdef	KBD_DEBUG
    989 	if (kbd_input_debug) printf("KBD USE key=%d\n", keycode);
    990 #endif
    991 
    992 	if ((readq = kbdd->kbdd_readq) == NULL)
    993 		return;
    994 	if (!kbdd->kbdd_translatable ||
    995 	    kbdd->kbdd_translate == TR_NONE)
    996 		kbdputcode(keycode, readq);
    997 	else
    998 		kbdtranslate(kbdd, keycode, readq);
    999 }
   1000 
   1001 static void
   1002 kbd_beep_on(void *arg)
   1003 {
   1004 	kbdcmd((queue_t *)arg, KBD_CMD_BELL);
   1005 }
   1006 
   1007 
   1008 static void
   1009 kbd_beep_off(void *arg)
   1010 {
   1011 	kbdcmd((queue_t *)arg, KBD_CMD_NOBELL);
   1012 }
   1013 
   1014 
   1015 /*
   1016  * kbdclick is used to remember the current click value of the
   1017  * Sun-3 keyboard.  This brain damaged keyboard will reset the
   1018  * clicking to the "default" value after a reset command and
   1019  * there is no way to read out the current click value.  We
   1020  * cannot send a click command immediately after the reset
   1021  * command or the keyboard gets screwed up.  So we wait until
   1022  * we get the ID byte before we send back the click command.
   1023  * Unfortunately, this means that there is a small window
   1024  * where the keyboard can click when it really shouldn't be.
   1025  * A value of -1 means that kbdclick has not been initialized yet.
   1026  */
   1027 static int kbdclick = -1;
   1028 
   1029 /*
   1030  * Send command byte to keyboard, if you can.
   1031  */
   1032 static void
   1033 kbdcmd(register queue_t *q, char cmd)
   1034 {
   1035 	register mblk_t *bp;
   1036 
   1037 	if (canput(q)) {
   1038 		if ((bp = allocb(1, BPRI_MED)) == NULL)
   1039 			cmn_err(CE_WARN,
   1040 			    "kbdcmd: Can't allocate block for command");
   1041 		else {
   1042 			*bp->b_wptr++ = cmd;
   1043 			putnext(q, bp);
   1044 			if (cmd == KBD_CMD_NOCLICK)
   1045 				kbdclick = 0;
   1046 			else if (cmd == KBD_CMD_CLICK)
   1047 				kbdclick = 1;
   1048 		}
   1049 	}
   1050 }
   1051 
   1052 /*
   1053  * Update the keyboard LEDs to match the current keyboard state.
   1054  * Do this only on Type 4 keyboards; other keyboards don't support the
   1055  * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs).
   1056  */
   1057 static void
   1058 kbdsetled(register struct kbddata *kbdd)
   1059 {
   1060 	if (kbdd->kbdd_state.k_id == KB_SUN4 ||
   1061 	    kbdd->kbdd_state.k_id == KB_PC) {
   1062 		kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED);
   1063 		kbdcmd(kbdd->kbdd_writeq, kbdd->led_state);
   1064 	}
   1065 }
   1066 
   1067 /*
   1068  * Reset the keyboard
   1069  */
   1070 static void
   1071 kbdreset(register struct kbddata *kbdd, uint_t hard_reset)
   1072 {
   1073 	register struct keyboardstate *k;
   1074 
   1075 	k = &kbdd->kbdd_state;
   1076 	if (kbdd->kbdd_translatable) {
   1077 		k->k_idstate = KID_NONE;
   1078 		k->k_id = -1;
   1079 		k->k_state = NORMAL;
   1080 		if (hard_reset)
   1081 			kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET);
   1082 	} else {
   1083 		bzero(k, sizeof (struct keyboardstate));
   1084 		k->k_id = KB_ASCII;
   1085 		k->k_idstate = KID_OK;
   1086 	}
   1087 }
   1088 
   1089 /*
   1090  * Old special codes.
   1091  */
   1092 #define	OLD_SHIFTKEYS	0x80
   1093 #define	OLD_BUCKYBITS	0x90
   1094 #define	OLD_FUNNY	0xA0
   1095 #define	OLD_FA_UMLAUT	0xA9
   1096 #define	OLD_FA_CFLEX	0xAA
   1097 #define	OLD_FA_TILDE	0xAB
   1098 #define	OLD_FA_CEDILLA	0xAC
   1099 #define	OLD_FA_ACUTE	0xAD
   1100 #define	OLD_FA_GRAVE	0xAE
   1101 #define	OLD_ISOCHAR	0xAF
   1102 #define	OLD_S