10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53505Sqz150045 * Common Development and Distribution License (the "License").
63505Sqz150045 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
223505Sqz150045 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate /* SunOS-4.0 1.60 */
280Sstevel@tonic-gate /* From: SunOS4.0 sundev/kbd.c */
290Sstevel@tonic-gate
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate * Keyboard input streams module - handles conversion of up/down codes to
320Sstevel@tonic-gate * ASCII or event format.
330Sstevel@tonic-gate */
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #include <sys/param.h>
360Sstevel@tonic-gate #include <sys/sysmacros.h>
370Sstevel@tonic-gate #include <sys/signal.h>
380Sstevel@tonic-gate #include <sys/termios.h>
390Sstevel@tonic-gate #include <sys/termio.h>
400Sstevel@tonic-gate #include <sys/stream.h>
410Sstevel@tonic-gate #include <sys/stropts.h>
420Sstevel@tonic-gate #include <sys/strsun.h>
430Sstevel@tonic-gate #include <sys/kmem.h>
440Sstevel@tonic-gate #include <sys/file.h>
450Sstevel@tonic-gate #include <sys/uio.h>
460Sstevel@tonic-gate #include <sys/errno.h>
470Sstevel@tonic-gate #include <sys/time.h>
480Sstevel@tonic-gate #include <sys/consdev.h>
490Sstevel@tonic-gate #include <sys/kbd.h>
500Sstevel@tonic-gate #include <sys/kbio.h>
510Sstevel@tonic-gate #include <sys/kbdreg.h>
520Sstevel@tonic-gate #include <sys/vuid_event.h>
530Sstevel@tonic-gate #include <sys/debug.h>
540Sstevel@tonic-gate #include <sys/ddi.h>
550Sstevel@tonic-gate #include <sys/sunddi.h>
560Sstevel@tonic-gate #include <sys/policy.h>
570Sstevel@tonic-gate
580Sstevel@tonic-gate #include <sys/modctl.h>
59*5129Smarx #include <sys/beep.h>
60*5129Smarx #include <sys/int_limits.h>
610Sstevel@tonic-gate
620Sstevel@tonic-gate static struct streamtab kbd_info;
630Sstevel@tonic-gate
640Sstevel@tonic-gate static struct fmodsw fsw = {
650Sstevel@tonic-gate "kb",
660Sstevel@tonic-gate &kbd_info,
670Sstevel@tonic-gate D_MP | D_MTPERMOD
680Sstevel@tonic-gate };
690Sstevel@tonic-gate
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate * Module linkage information for the kernel.
720Sstevel@tonic-gate */
730Sstevel@tonic-gate
740Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
750Sstevel@tonic-gate &mod_strmodops, "streams module for keyboard", &fsw
760Sstevel@tonic-gate };
770Sstevel@tonic-gate
780Sstevel@tonic-gate static struct modlinkage modlinkage = {
790Sstevel@tonic-gate MODREV_1, (void *)&modlstrmod, NULL
800Sstevel@tonic-gate };
810Sstevel@tonic-gate
820Sstevel@tonic-gate int
_init(void)830Sstevel@tonic-gate _init(void)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate return (mod_install(&modlinkage));
860Sstevel@tonic-gate }
870Sstevel@tonic-gate
880Sstevel@tonic-gate int
_fini(void)890Sstevel@tonic-gate _fini(void)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate return (mod_remove(&modlinkage));
920Sstevel@tonic-gate }
930Sstevel@tonic-gate
940Sstevel@tonic-gate int
_info(struct modinfo * modinfop)950Sstevel@tonic-gate _info(struct modinfo *modinfop)
960Sstevel@tonic-gate {
970Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
980Sstevel@tonic-gate }
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate * For now these are shared.
1020Sstevel@tonic-gate * These data structures are static (defined in keytables.c) thus
1030Sstevel@tonic-gate * there is no need to perform any locking.
1040Sstevel@tonic-gate */
1050Sstevel@tonic-gate extern struct keyboards keytables[];
1060Sstevel@tonic-gate extern char keystringtab[16][KTAB_STRLEN];
1070Sstevel@tonic-gate extern struct compose_sequence_t kb_compose_table[];
1080Sstevel@tonic-gate extern signed char kb_compose_map[];
1090Sstevel@tonic-gate extern struct fltaccent_sequence_t kb_fltaccent_table[];
1100Sstevel@tonic-gate extern uchar_t kb_numlock_table[];
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate * This value corresponds approximately to max 10 fingers
1140Sstevel@tonic-gate */
1150Sstevel@tonic-gate static int kbd_downs_size = 15;
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate typedef struct key_event {
1180Sstevel@tonic-gate uchar_t key_station; /* Physical key station associated with event */
1190Sstevel@tonic-gate Firm_event event; /* Event that sent out on down */
1200Sstevel@tonic-gate } Key_event;
1210Sstevel@tonic-gate struct kbddata {
1220Sstevel@tonic-gate queue_t *kbdd_readq;
1230Sstevel@tonic-gate queue_t *kbdd_writeq;
1240Sstevel@tonic-gate mblk_t *kbdd_iocpending; /* "ioctl" awaiting buffer */
1250Sstevel@tonic-gate mblk_t *kbdd_replypending; /* "ioctl" reply awaiting result */
1260Sstevel@tonic-gate int kbdd_flags; /* random flags */
1270Sstevel@tonic-gate bufcall_id_t kbdd_bufcallid; /* bufcall id */
1280Sstevel@tonic-gate timeout_id_t kbdd_rptid; /* timeout id for kbdrpt() */
1290Sstevel@tonic-gate timeout_id_t kbdd_layoutid; /* timeout id for kbdlayout() */
1300Sstevel@tonic-gate int kbdd_iocid; /* ID of "ioctl" being waited for */
1310Sstevel@tonic-gate int kbdd_iocerror; /* error return from "ioctl" */
1320Sstevel@tonic-gate struct keyboardstate kbdd_state;
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate * State of keyboard & keyboard
1350Sstevel@tonic-gate * specific settings, e.g., tables
1360Sstevel@tonic-gate */
1370Sstevel@tonic-gate int kbdd_translate; /* Translate keycodes? */
1380Sstevel@tonic-gate int kbdd_translatable; /* Keyboard is translatable? */
1390Sstevel@tonic-gate int kbdd_compat; /* Generating pre-4.1 events? */
1400Sstevel@tonic-gate short kbdd_ascii_addr; /* Vuid_id_addr for ascii events */
1410Sstevel@tonic-gate short kbdd_top_addr; /* Vuid_id_addr for top events */
1420Sstevel@tonic-gate short kbdd_vkey_addr; /* Vuid_id_addr for vkey events */
1430Sstevel@tonic-gate struct key_event *kbdd_downs;
1440Sstevel@tonic-gate /*
1450Sstevel@tonic-gate * Table of key stations currently down
1460Sstevel@tonic-gate * that have firm events that need
1470Sstevel@tonic-gate * to be matched with up transitions
1480Sstevel@tonic-gate * when kbdd_translate is TR_*EVENT
1490Sstevel@tonic-gate */
1500Sstevel@tonic-gate int kbdd_downs_entries; /* # of possible entries in kbdd_downs */
1510Sstevel@tonic-gate uint_t kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */
1520Sstevel@tonic-gate ushort_t compose_key; /* first compose key */
1530Sstevel@tonic-gate ushort_t fltaccent_entry; /* floating accent keymap entry */
1540Sstevel@tonic-gate char led_state; /* current state of LEDs */
1553927Sqz150045 unsigned char shiftkey; /* used for the new abort keys */
1560Sstevel@tonic-gate };
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate #define KBD_OPEN 0x00000001 /* keyboard is open for business */
1590Sstevel@tonic-gate #define KBD_IOCWAIT 0x00000002 /* "open" waiting for "ioctl" to finish */
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate #define NO_HARD_RESET 0 /* don't do hard reset */
1620Sstevel@tonic-gate #define HARD_RESET 1 /* do hard reset */
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate /*
1660Sstevel@tonic-gate * Constants setup during the first open of a kbd (so that they can be patched
1670Sstevel@tonic-gate * for debugging purposes).
1680Sstevel@tonic-gate */
1690Sstevel@tonic-gate static int kbd_repeatrate;
1700Sstevel@tonic-gate static int kbd_repeatdelay;
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate static int kbd_overflow_cnt; /* Number of times kbd overflowed input q */
1730Sstevel@tonic-gate static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate #ifdef KBD_DEBUG
1760Sstevel@tonic-gate int kbd_debug = 0;
1770Sstevel@tonic-gate int kbd_ra_debug = 0;
1780Sstevel@tonic-gate int kbd_raw_debug = 0;
1790Sstevel@tonic-gate int kbd_rpt_debug = 0;
1800Sstevel@tonic-gate int kbd_input_debug = 0;
1810Sstevel@tonic-gate #endif /* KBD_DEBUG */
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate static int kbdopen(queue_t *, dev_t *, int, int, cred_t *);
1840Sstevel@tonic-gate static int kbdclose(queue_t *, int, cred_t *);
1850Sstevel@tonic-gate static void kbdwput(queue_t *, mblk_t *);
1860Sstevel@tonic-gate static void kbdrput(queue_t *, mblk_t *);
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate static struct module_info kbdmiinfo = {
1890Sstevel@tonic-gate 0,
1900Sstevel@tonic-gate "kb",
1910Sstevel@tonic-gate 0,
1920Sstevel@tonic-gate INFPSZ,
1930Sstevel@tonic-gate 2048,
1940Sstevel@tonic-gate 128
1950Sstevel@tonic-gate };
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate static struct qinit kbdrinit = {
1980Sstevel@tonic-gate (int (*)())kbdrput,
1990Sstevel@tonic-gate (int (*)())NULL,
2000Sstevel@tonic-gate kbdopen,
2010Sstevel@tonic-gate kbdclose,
2020Sstevel@tonic-gate (int (*)())NULL,
2030Sstevel@tonic-gate &kbdmiinfo
2040Sstevel@tonic-gate };
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate static struct module_info kbdmoinfo = {
2070Sstevel@tonic-gate 0,
2080Sstevel@tonic-gate "kb",
2090Sstevel@tonic-gate 0,
2100Sstevel@tonic-gate INFPSZ,
2110Sstevel@tonic-gate 2048,
2120Sstevel@tonic-gate 128
2130Sstevel@tonic-gate };
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate static struct qinit kbdwinit = {
2160Sstevel@tonic-gate (int (*)())kbdwput,
2170Sstevel@tonic-gate (int (*)())NULL,
2180Sstevel@tonic-gate kbdopen,
2190Sstevel@tonic-gate kbdclose,
2200Sstevel@tonic-gate (int (*)())NULL,
2210Sstevel@tonic-gate &kbdmoinfo
2220Sstevel@tonic-gate };
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate static struct streamtab kbd_info = {
2250Sstevel@tonic-gate &kbdrinit,
2260Sstevel@tonic-gate &kbdwinit,
2270Sstevel@tonic-gate NULL,
2280Sstevel@tonic-gate NULL,
2290Sstevel@tonic-gate };
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate static void kbdreioctl(void *);
2320Sstevel@tonic-gate static void kbdioctl(queue_t *, mblk_t *);
2330Sstevel@tonic-gate static void kbdflush(struct kbddata *);
2340Sstevel@tonic-gate static void kbduse(struct kbddata *, unsigned);
2350Sstevel@tonic-gate static void kbdsetled(struct kbddata *);
236*5129Smarx static void kbd_beep_off(void *arg);
237*5129Smarx static void kbd_beep_on(void *arg);
2380Sstevel@tonic-gate static void kbdcmd(queue_t *, char);
2390Sstevel@tonic-gate static void kbdreset(struct kbddata *, uint_t);
2400Sstevel@tonic-gate static int kbdsetkey(struct kbddata *, struct kiockey *, cred_t *);
2410Sstevel@tonic-gate static int kbdgetkey(struct kbddata *, struct kiockey *);
2420Sstevel@tonic-gate static int kbdskey(struct kbddata *, struct kiockeymap *, cred_t *);
2430Sstevel@tonic-gate static int kbdgkey(struct kbddata *, struct kiockeymap *);
2440Sstevel@tonic-gate static void kbdlayouttimeout(void *);
2450Sstevel@tonic-gate static void kbdinput(struct kbddata *, unsigned);
2460Sstevel@tonic-gate static void kbdid(struct kbddata *, int);
2470Sstevel@tonic-gate static struct keymap *settable(struct kbddata *, uint_t);
2480Sstevel@tonic-gate static void kbdrpt(void *);
2490Sstevel@tonic-gate static void kbdcancelrpt(struct kbddata *);
2500Sstevel@tonic-gate static void kbdtranslate(struct kbddata *, unsigned, queue_t *);
2510Sstevel@tonic-gate static int kbd_do_compose(ushort_t, ushort_t, ushort_t *);
2520Sstevel@tonic-gate static void kbd_send_esc_event(char, struct kbddata *);
2530Sstevel@tonic-gate char *strsetwithdecimal(char *, uint_t, uint_t);
2540Sstevel@tonic-gate static void kbdkeypressed(struct kbddata *, uchar_t, Firm_event *,
2550Sstevel@tonic-gate ushort_t);
2560Sstevel@tonic-gate static void kbdqueuepress(struct kbddata *, uchar_t, Firm_event *);
2570Sstevel@tonic-gate static void kbdkeyreleased(struct kbddata *, uchar_t);
2580Sstevel@tonic-gate static void kbdreleaseall(struct kbddata *);
2590Sstevel@tonic-gate static void kbdputcode(uint_t, queue_t *);
2600Sstevel@tonic-gate static void kbdputbuf(char *, queue_t *);
2610Sstevel@tonic-gate static void kbdqueueevent(struct kbddata *, Firm_event *);
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /*
2640Sstevel@tonic-gate * Dummy qbufcall callback routine used by open and close.
2650Sstevel@tonic-gate * The framework will wake up qwait_sig when we return from
2660Sstevel@tonic-gate * this routine (as part of leaving the perimeters.)
2670Sstevel@tonic-gate * (The framework enters the perimeters before calling the qbufcall() callback
2680Sstevel@tonic-gate * and leaves the perimeters after the callback routine has executed. The
2690Sstevel@tonic-gate * framework performs an implicit wakeup of any thread in qwait/qwait_sig
2700Sstevel@tonic-gate * when it leaves the perimeter. See qwait(9E).)
2710Sstevel@tonic-gate */
2720Sstevel@tonic-gate /* ARGSUSED */
dummy_callback(void * arg)2730Sstevel@tonic-gate static void dummy_callback(void *arg)
2740Sstevel@tonic-gate {}
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate /*
2780Sstevel@tonic-gate * Open a keyboard.
2790Sstevel@tonic-gate * Ttyopen sets line characteristics
2800Sstevel@tonic-gate */
2810Sstevel@tonic-gate /* ARGSUSED */
2820Sstevel@tonic-gate static int
kbdopen(queue_t * q,dev_t * devp,int oflag,int sflag,cred_t * crp)2830Sstevel@tonic-gate kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate register int error;
2860Sstevel@tonic-gate register struct kbddata *kbdd;
2870Sstevel@tonic-gate mblk_t *mp;
2880Sstevel@tonic-gate mblk_t *datap;
2890Sstevel@tonic-gate register struct iocblk *iocb;
2900Sstevel@tonic-gate register struct termios *cb;
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate /* Set these up only once so that they could be changed from adb */
2930Sstevel@tonic-gate if (!kbd_repeatrate) {
2940Sstevel@tonic-gate kbd_repeatrate = (hz+29)/30;
2950Sstevel@tonic-gate kbd_repeatdelay = hz/2;
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate if (q->q_ptr != NULL)
2990Sstevel@tonic-gate return (0); /* already attached */
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate /*
3020Sstevel@tonic-gate * Only allow open requests to succeed for privileged users. This
3030Sstevel@tonic-gate * necessary to prevent users from pushing the "kb" module again
3040Sstevel@tonic-gate * on the stream associated with /dev/kbd.
3050Sstevel@tonic-gate */
3060Sstevel@tonic-gate if (secpolicy_console(crp) != 0) {
3070Sstevel@tonic-gate return (EPERM);
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate switch (sflag) {
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate case MODOPEN:
3140Sstevel@tonic-gate break;
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate case CLONEOPEN:
3170Sstevel@tonic-gate return (EINVAL); /* No Bozos! */
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate /* allocate keyboard */
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP);
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate /*
3260Sstevel@tonic-gate * Set up queue pointers, so that the "put" procedure will accept
3270Sstevel@tonic-gate * the reply to the "ioctl" message we send down.
3280Sstevel@tonic-gate */
3290Sstevel@tonic-gate q->q_ptr = kbdd;
3300Sstevel@tonic-gate WR(q)->q_ptr = kbdd;
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate qprocson(q);
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate /*
3350Sstevel@tonic-gate * Setup tty modes.
3360Sstevel@tonic-gate */
3370Sstevel@tonic-gate while ((mp = mkiocb(TCSETSF)) == NULL) {
3380Sstevel@tonic-gate timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI,
3390Sstevel@tonic-gate dummy_callback, NULL);
3400Sstevel@tonic-gate if (!qwait_sig(q)) {
3410Sstevel@tonic-gate qunbufcall(q, id);
3420Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata));
3430Sstevel@tonic-gate qprocsoff(q);
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate return (EINTR);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate while ((datap = allocb(sizeof (struct termios), BPRI_HI)) ==
349*5129Smarx NULL) {
3500Sstevel@tonic-gate timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI,
3510Sstevel@tonic-gate dummy_callback, NULL);
3520Sstevel@tonic-gate if (!qwait_sig(q)) {
3530Sstevel@tonic-gate qunbufcall(q, id);
3540Sstevel@tonic-gate freemsg(mp);
3550Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata));
3560Sstevel@tonic-gate qprocsoff(q);
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate return (EINTR);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate iocb = (struct iocblk *)mp->b_rptr;
3630Sstevel@tonic-gate iocb->ioc_count = sizeof (struct termios);
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate cb = (struct termios *)datap->b_rptr;
3660Sstevel@tonic-gate cb->c_iflag = 0;
3670Sstevel@tonic-gate cb->c_oflag = 0;
3680Sstevel@tonic-gate cb->c_cflag = CREAD|CS8|B1200;
3690Sstevel@tonic-gate cb->c_lflag = 0;
3700Sstevel@tonic-gate bzero(cb->c_cc, NCCS);
3710Sstevel@tonic-gate datap->b_wptr += sizeof (struct termios);
3720Sstevel@tonic-gate mp->b_cont = datap;
3730Sstevel@tonic-gate kbdd->kbdd_flags |= KBD_IOCWAIT; /* indicate that we're */
3740Sstevel@tonic-gate kbdd->kbdd_iocid = iocb->ioc_id; /* waiting for this response */
3750Sstevel@tonic-gate putnext(WR(q), mp);
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate /*
3780Sstevel@tonic-gate * Now wait for it. Let our read queue put routine wake us up
3790Sstevel@tonic-gate * when it arrives.
3800Sstevel@tonic-gate */
3810Sstevel@tonic-gate while (kbdd->kbdd_flags & KBD_IOCWAIT) {
3820Sstevel@tonic-gate if (!qwait_sig(q)) {
3830Sstevel@tonic-gate error = EINTR;
3840Sstevel@tonic-gate goto error;
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate if ((error = kbdd->kbdd_iocerror) != 0)
3880Sstevel@tonic-gate goto error;
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate * Set up private data.
3920Sstevel@tonic-gate */
3930Sstevel@tonic-gate kbdd->kbdd_readq = q;
3940Sstevel@tonic-gate kbdd->kbdd_writeq = WR(q);
3950Sstevel@tonic-gate kbdd->kbdd_iocpending = NULL;
3960Sstevel@tonic-gate kbdd->kbdd_translatable = TR_CAN;
3970Sstevel@tonic-gate kbdd->kbdd_translate = TR_ASCII;
3980Sstevel@tonic-gate kbdd->kbdd_compat = 1;
3990Sstevel@tonic-gate kbdd->kbdd_ascii_addr = ASCII_FIRST;
4000Sstevel@tonic-gate kbdd->kbdd_top_addr = TOP_FIRST;
4010Sstevel@tonic-gate kbdd->kbdd_vkey_addr = VKEY_FIRST;
4020Sstevel@tonic-gate /* Allocate dynamic memory for downs table */
4030Sstevel@tonic-gate kbdd->kbdd_downs_entries = kbd_downs_size;
4040Sstevel@tonic-gate kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event);
4050Sstevel@tonic-gate kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP);
4060Sstevel@tonic-gate kbdd->kbdd_flags = KBD_OPEN;
4070Sstevel@tonic-gate kbdd->led_state = 0;
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate * Reset kbd.
4110Sstevel@tonic-gate */
4120Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET);
4130Sstevel@tonic-gate
414*5129Smarx (void) beep_init((void *)WR(q), kbd_beep_on, kbd_beep_off, NULL);
415*5129Smarx
4160Sstevel@tonic-gate return (0);
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate error:
4190Sstevel@tonic-gate qprocsoff(q);
4200Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata));
4210Sstevel@tonic-gate return (error);
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate /*
4250Sstevel@tonic-gate * Close a keyboard.
4260Sstevel@tonic-gate */
4270Sstevel@tonic-gate /* ARGSUSED1 */
4280Sstevel@tonic-gate static int
kbdclose(register queue_t * q,int flag,cred_t * crp)4290Sstevel@tonic-gate kbdclose(register queue_t *q, int flag, cred_t *crp)
4300Sstevel@tonic-gate {
4310Sstevel@tonic-gate register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
4320Sstevel@tonic-gate register mblk_t *mp;
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate qprocsoff(q);
435*5129Smarx (void) beep_fini();
4360Sstevel@tonic-gate /*
4370Sstevel@tonic-gate * Since we're about to destroy our private data, turn off
4380Sstevel@tonic-gate * our open flag first, so we don't accept any more input
4390Sstevel@tonic-gate * and try to use that data.
4400Sstevel@tonic-gate */
4410Sstevel@tonic-gate kbdd->kbdd_flags = 0;
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) {
4440Sstevel@tonic-gate /*
4450Sstevel@tonic-gate * There was a KIOCLAYOUT pending; presumably, it timed out.
4460Sstevel@tonic-gate * Throw the reply away.
4470Sstevel@tonic-gate */
4480Sstevel@tonic-gate kbdd->kbdd_replypending = NULL;
4490Sstevel@tonic-gate freemsg(mp);
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate /* clear all timeouts */
4530Sstevel@tonic-gate if (kbdd->kbdd_bufcallid)
4540Sstevel@tonic-gate qunbufcall(q, kbdd->kbdd_bufcallid);
4550Sstevel@tonic-gate if (kbdd->kbdd_rptid)
4560Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_rptid);
4570Sstevel@tonic-gate if (kbdd->kbdd_layoutid)
4580Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_layoutid);
4590Sstevel@tonic-gate kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
4600Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata));
4610Sstevel@tonic-gate return (0);
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate /*
4650Sstevel@tonic-gate * Line discipline output queue put procedure: handles M_IOCTL
4660Sstevel@tonic-gate * messages.
4670Sstevel@tonic-gate */
4680Sstevel@tonic-gate static void
kbdwput(register queue_t * q,register mblk_t * mp)4690Sstevel@tonic-gate kbdwput(register queue_t *q, register mblk_t *mp)
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate /*
4720Sstevel@tonic-gate * Process M_FLUSH, and some M_IOCTL, messages here; pass
4730Sstevel@tonic-gate * everything else down.
4740Sstevel@tonic-gate */
4750Sstevel@tonic-gate switch (mp->b_datap->db_type) {
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate case M_FLUSH:
4780Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW)
4790Sstevel@tonic-gate flushq(q, FLUSHDATA);
4800Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR)
4810Sstevel@tonic-gate flushq(RD(q), FLUSHDATA);
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate default:
4840Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */
4850Sstevel@tonic-gate break;
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate case M_IOCTL:
4880Sstevel@tonic-gate kbdioctl(q, mp);
4890Sstevel@tonic-gate break;
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate static void
kbdreioctl(void * kbdd_addr)4950Sstevel@tonic-gate kbdreioctl(void *kbdd_addr)
4960Sstevel@tonic-gate {
4970Sstevel@tonic-gate struct kbddata *kbdd = kbdd_addr;
4980Sstevel@tonic-gate queue_t *q;
4990Sstevel@tonic-gate mblk_t *mp;
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate kbdd->kbdd_bufcallid = 0;
5020Sstevel@tonic-gate q = kbdd->kbdd_writeq;
5030Sstevel@tonic-gate if ((mp = kbdd->kbdd_iocpending) != NULL) {
5040Sstevel@tonic-gate kbdd->kbdd_iocpending = NULL; /* not pending any more */
5050Sstevel@tonic-gate kbdioctl(q, mp);
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate static void
kbdioctl(register queue_t * q,register mblk_t * mp)5100Sstevel@tonic-gate kbdioctl(register queue_t *q, register mblk_t *mp)
5110Sstevel@tonic-gate {
5120Sstevel@tonic-gate register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
5130Sstevel@tonic-gate register struct iocblk *iocp;
5140Sstevel@tonic-gate register short new_translate;
5150Sstevel@tonic-gate register Vuid_addr_probe *addr_probe;
5160Sstevel@tonic-gate register short *addr_ptr;
5170Sstevel@tonic-gate mblk_t *datap;
5180Sstevel@tonic-gate size_t ioctlrespsize;
5190Sstevel@tonic-gate int err = 0;
520*5129Smarx int tmp;
521*5129Smarx int cycles;
522*5129Smarx int frequency;
523*5129Smarx int msecs;
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate switch (iocp->ioc_cmd) {
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate case VUIDSFORMAT:
5300Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
5310Sstevel@tonic-gate if (err != 0)
5320Sstevel@tonic-gate break;
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
5350Sstevel@tonic-gate TR_ASCII : TR_EVENT;
5360Sstevel@tonic-gate if (new_translate == kbdd->kbdd_translate)
5370Sstevel@tonic-gate break;
5380Sstevel@tonic-gate kbdd->kbdd_translate = new_translate;
5390Sstevel@tonic-gate goto output_format_change;
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate case KIOCTRANS:
5420Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
5430Sstevel@tonic-gate if (err != 0)
5440Sstevel@tonic-gate break;
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate new_translate = *(int *)mp->b_cont->b_rptr;
5470Sstevel@tonic-gate if (new_translate == kbdd->kbdd_translate)
5480Sstevel@tonic-gate break;
5490Sstevel@tonic-gate kbdd->kbdd_translate = new_translate;
5500Sstevel@tonic-gate goto output_format_change;
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate case KIOCCMD:
5530Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
5540Sstevel@tonic-gate if (err != 0)
5550Sstevel@tonic-gate break;
5560Sstevel@tonic-gate
557*5129Smarx tmp = (char)(*(int *)mp->b_cont->b_rptr);
558*5129Smarx if (tmp == KBD_CMD_BELL)
559*5129Smarx (void) beeper_on(BEEP_TYPE4);
560*5129Smarx else if (tmp == KBD_CMD_NOBELL)
561*5129Smarx (void) beeper_off();
562*5129Smarx else
563*5129Smarx kbdcmd(q, tmp);
564*5129Smarx break;
565*5129Smarx
566*5129Smarx case KIOCMKTONE:
567*5129Smarx if (iocp->ioc_count != TRANSPARENT) {
568*5129Smarx /*
569*5129Smarx * We don't support non-transparent ioctls,
570*5129Smarx * i.e. I_STR ioctls
571*5129Smarx */
572*5129Smarx err = EINVAL;
573*5129Smarx break;
574*5129Smarx }
575*5129Smarx tmp = (int)(*(intptr_t *)mp->b_cont->b_rptr);
576*5129Smarx cycles = tmp & 0xffff;
577*5129Smarx msecs = (tmp >> 16) & 0xffff;
578*5129Smarx
579*5129Smarx if (cycles == 0)
580*5129Smarx frequency = UINT16_MAX;
581*5129Smarx else if (cycles == UINT16_MAX)
582*5129Smarx frequency = 0;
583*5129Smarx else {
584*5129Smarx frequency = (PIT_HZ + cycles / 2) / cycles;
585*5129Smarx if (frequency > UINT16_MAX)
586*5129Smarx frequency = UINT16_MAX;
587*5129Smarx }
588*5129Smarx
589*5129Smarx err = beep_mktone(frequency, msecs);
5900Sstevel@tonic-gate break;
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate case KIOCSLED:
5930Sstevel@tonic-gate err = miocpullup(mp, sizeof (uchar_t));
5940Sstevel@tonic-gate if (err != 0)
5950Sstevel@tonic-gate break;
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr;
5980Sstevel@tonic-gate kbdsetled(kbdd);
5990Sstevel@tonic-gate break;
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate case KIOCGLED:
6020Sstevel@tonic-gate if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
6030Sstevel@tonic-gate ioctlrespsize = sizeof (int);
6040Sstevel@tonic-gate goto allocfailure;
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate *(uchar_t *)datap->b_wptr = kbdd->led_state;
6070Sstevel@tonic-gate datap->b_wptr += sizeof (uchar_t);
6080Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */
6090Sstevel@tonic-gate freemsg(mp->b_cont);
6100Sstevel@tonic-gate mp->b_cont = datap;
6110Sstevel@tonic-gate iocp->ioc_count = sizeof (uchar_t);
6120Sstevel@tonic-gate break;
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate case VUIDGFORMAT:
6150Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
6160Sstevel@tonic-gate ioctlrespsize = sizeof (int);
6170Sstevel@tonic-gate goto allocfailure;
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate *(int *)datap->b_wptr =
6200Sstevel@tonic-gate (kbdd->kbdd_translate == TR_EVENT ||
6210Sstevel@tonic-gate kbdd->kbdd_translate == TR_UNTRANS_EVENT) ?
622*5129Smarx VUID_FIRM_EVENT: VUID_NATIVE;
6230Sstevel@tonic-gate datap->b_wptr += sizeof (int);
6240Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */
6250Sstevel@tonic-gate freemsg(mp->b_cont);
6260Sstevel@tonic-gate mp->b_cont = datap;
6270Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
6280Sstevel@tonic-gate break;
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate case KIOCGTRANS:
6310Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
6320Sstevel@tonic-gate ioctlrespsize = sizeof (int);
6330Sstevel@tonic-gate goto allocfailure;
6340Sstevel@tonic-gate }
6350Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_translate;
6360Sstevel@tonic-gate datap->b_wptr += sizeof (int);
6370Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */
6380Sstevel@tonic-gate freemsg(mp->b_cont);
6390Sstevel@tonic-gate mp->b_cont = datap;
6400Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
6410Sstevel@tonic-gate break;
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate case VUIDSADDR:
6440Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe));
6450Sstevel@tonic-gate if (err != 0)
6460Sstevel@tonic-gate break;
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
6490Sstevel@tonic-gate switch (addr_probe->base) {
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate case ASCII_FIRST:
6520Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_ascii_addr;
6530Sstevel@tonic-gate break;
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate case TOP_FIRST:
6560Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_top_addr;
6570Sstevel@tonic-gate break;
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate case VKEY_FIRST:
6600Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_vkey_addr;
6610Sstevel@tonic-gate break;
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate default:
6640Sstevel@tonic-gate err = ENODEV;
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
6670Sstevel@tonic-gate *addr_ptr = addr_probe->data.next;
6680Sstevel@tonic-gate goto output_format_change;
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate break;
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate case VUIDGADDR:
6730Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe));
6740Sstevel@tonic-gate if (err != 0)
6750Sstevel@tonic-gate break;
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
6780Sstevel@tonic-gate switch (addr_probe->base) {
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate case ASCII_FIRST:
6810Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_ascii_addr;
6820Sstevel@tonic-gate break;
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate case TOP_FIRST:
6850Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_top_addr;
6860Sstevel@tonic-gate break;
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate case VKEY_FIRST:
6890Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_vkey_addr;
6900Sstevel@tonic-gate break;
6910Sstevel@tonic-gate
6920Sstevel@tonic-gate default:
6930Sstevel@tonic-gate err = ENODEV;
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate break;
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate case KIOCTRANSABLE:
6980Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
6990Sstevel@tonic-gate if (err != 0)
7000Sstevel@tonic-gate break;
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) {
7030Sstevel@tonic-gate kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr;
7040Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET);
7050Sstevel@tonic-gate goto output_format_change;
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate break;
7080Sstevel@tonic-gate
7090Sstevel@tonic-gate case KIOCGTRANSABLE:
7100Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
7110Sstevel@tonic-gate ioctlrespsize = sizeof (int);
7120Sstevel@tonic-gate goto allocfailure;
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_translatable;
7150Sstevel@tonic-gate datap->b_wptr += sizeof (int);
7160Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */
7170Sstevel@tonic-gate freemsg(mp->b_cont);
7180Sstevel@tonic-gate mp->b_cont = datap;
7190Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
7200Sstevel@tonic-gate break;
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate case KIOCSCOMPAT:
7230Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
7240Sstevel@tonic-gate if (err != 0)
7250Sstevel@tonic-gate break;
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr;
7280Sstevel@tonic-gate break;
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate case KIOCGCOMPAT:
7310Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
7320Sstevel@tonic-gate ioctlrespsize = sizeof (int);
7330Sstevel@tonic-gate goto allocfailure;
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_compat;
7360Sstevel@tonic-gate datap->b_wptr += sizeof (int);
7370Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */
7380Sstevel@tonic-gate freemsg(mp->b_cont);
7390Sstevel@tonic-gate mp->b_cont = datap;
7400Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
7410Sstevel@tonic-gate break;
7420Sstevel@tonic-gate
7430Sstevel@tonic-gate case KIOCSETKEY:
7440Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey));
7450Sstevel@tonic-gate if (err != 0)
7460Sstevel@tonic-gate break;
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr,
7490Sstevel@tonic-gate iocp->ioc_cr);
7500Sstevel@tonic-gate /*
7510Sstevel@tonic-gate * Since this only affects any subsequent key presses,
7520Sstevel@tonic-gate * don't goto output_format_change. One might want to
7530Sstevel@tonic-gate * toggle the keytable entries dynamically.
7540Sstevel@tonic-gate */
7550Sstevel@tonic-gate break;
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate case KIOCGETKEY:
7580Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey));
7590Sstevel@tonic-gate if (err != 0)
7600Sstevel@tonic-gate break;
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr);
7630Sstevel@tonic-gate break;
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate case KIOCSKEY:
7660Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap));
7670Sstevel@tonic-gate if (err != 0)
7680Sstevel@tonic-gate break;
7690Sstevel@tonic-gate
7700Sstevel@tonic-gate err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr,
7710Sstevel@tonic-gate iocp->ioc_cr);
7720Sstevel@tonic-gate /*
7730Sstevel@tonic-gate * Since this only affects any subsequent key presses,
7740Sstevel@tonic-gate * don't goto output_format_change. One might want to
7750Sstevel@tonic-gate * toggle the keytable entries dynamically.
7760Sstevel@tonic-gate */
7770Sstevel@tonic-gate break;
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate case KIOCGKEY:
7800Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap));
7810Sstevel@tonic-gate if (err != 0)
7820Sstevel@tonic-gate break;
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr);
7850Sstevel@tonic-gate break;
7860Sstevel@tonic-gate
7870Sstevel@tonic-gate case KIOCSDIRECT:
7880Sstevel@tonic-gate goto output_format_change;
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate case KIOCGDIRECT:
7910Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
7920Sstevel@tonic-gate ioctlrespsize = sizeof (int);
7930Sstevel@tonic-gate goto allocfailure;
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate *(int *)datap->b_wptr = 1; /* always direct */
7960Sstevel@tonic-gate datap->b_wptr += sizeof (int);
7970Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */
7980Sstevel@tonic-gate freemsg(mp->b_cont);
7990Sstevel@tonic-gate mp->b_cont = datap;
8000Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
8010Sstevel@tonic-gate break;
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate case KIOCTYPE:
8040Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
8050Sstevel@tonic-gate ioctlrespsize = sizeof (int);
8060Sstevel@tonic-gate goto allocfailure;
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_state.k_id;
8090Sstevel@tonic-gate datap->b_wptr += sizeof (int);
8100Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */
8110Sstevel@tonic-gate freemsg(mp->b_cont);
8120Sstevel@tonic-gate mp->b_cont = datap;
8130Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
8140Sstevel@tonic-gate break;
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate case KIOCLAYOUT:
8170Sstevel@tonic-gate if ((datap = kbdd->kbdd_replypending) != NULL) {
8180Sstevel@tonic-gate /*
8190Sstevel@tonic-gate * There was an earlier KIOCLAYOUT pending; presumably,
8200Sstevel@tonic-gate * it timed out. Throw the reply away.
8210Sstevel@tonic-gate */
8220Sstevel@tonic-gate kbdd->kbdd_replypending = NULL;
8230Sstevel@tonic-gate freemsg(datap);
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate if (kbdd->kbdd_state.k_id == KB_SUN4 ||
8270Sstevel@tonic-gate kbdd->kbdd_state.k_id == KB_PC) {
8280Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
8290Sstevel@tonic-gate ioctlrespsize = sizeof (int);
8300Sstevel@tonic-gate goto allocfailure;
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate iocp->ioc_rval = 0;
8330Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */
8340Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
8350Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */
8360Sstevel@tonic-gate freemsg(mp->b_cont);
8370Sstevel@tonic-gate mp->b_cont = datap;
8380Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
8390Sstevel@tonic-gate kbdd->kbdd_replypending = mp;
8400Sstevel@tonic-gate kbdcmd(q, (char)KBD_CMD_GETLAYOUT);
8410Sstevel@tonic-gate if (kbdd->kbdd_layoutid)
8420Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_layoutid);
8430Sstevel@tonic-gate kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout,
8440Sstevel@tonic-gate kbdd, hz / 5);
8450Sstevel@tonic-gate return; /* wait for reply from keyboard */
8460Sstevel@tonic-gate } else {
8470Sstevel@tonic-gate /*
8480Sstevel@tonic-gate * Not a Type 4 keyboard; return an immediate error.
8490Sstevel@tonic-gate */
8500Sstevel@tonic-gate err = EINVAL;
8510Sstevel@tonic-gate break;
8520Sstevel@tonic-gate }
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate case KIOCGRPTDELAY:
8550Sstevel@tonic-gate /*
8560Sstevel@tonic-gate * Report the autorepeat delay, unit in millisecond
8570Sstevel@tonic-gate */
8580Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
8590Sstevel@tonic-gate ioctlrespsize = sizeof (int);
8600Sstevel@tonic-gate goto allocfailure;
8610Sstevel@tonic-gate }
8620Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay);
8630Sstevel@tonic-gate datap->b_wptr += sizeof (int);
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate /* free msg to prevent memory leak */
8660Sstevel@tonic-gate if (mp->b_cont != NULL)
8670Sstevel@tonic-gate freemsg(mp->b_cont);
8680Sstevel@tonic-gate mp->b_cont = datap;
8690Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
8700Sstevel@tonic-gate break;
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate case KIOCSRPTDELAY:
8730Sstevel@tonic-gate /*
8740Sstevel@tonic-gate * Set the autorepeat delay
8750Sstevel@tonic-gate */
8760Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
8770Sstevel@tonic-gate
8780Sstevel@tonic-gate if (err != 0)
8790Sstevel@tonic-gate break;
8800Sstevel@tonic-gate
8810Sstevel@tonic-gate /* validate the input */
8820Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
8830Sstevel@tonic-gate err = EINVAL;
8840Sstevel@tonic-gate break;
8850Sstevel@tonic-gate }
8860Sstevel@tonic-gate kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
8870Sstevel@tonic-gate if (kbd_repeatdelay <= 0)
8880Sstevel@tonic-gate kbd_repeatdelay = 1;
8890Sstevel@tonic-gate break;
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate case KIOCGRPTRATE:
8920Sstevel@tonic-gate /*
8930Sstevel@tonic-gate * Report the autorepeat rate
8940Sstevel@tonic-gate */
8950Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
8960Sstevel@tonic-gate ioctlrespsize = sizeof (int);
8970Sstevel@tonic-gate goto allocfailure;
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate);
9000Sstevel@tonic-gate datap->b_wptr += sizeof (int);
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate /* free msg to prevent memory leak */
9030Sstevel@tonic-gate if (mp->b_cont != NULL)
9040Sstevel@tonic-gate freemsg(mp->b_cont);
9050Sstevel@tonic-gate mp->b_cont = datap;
9060Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
9070Sstevel@tonic-gate break;
9080Sstevel@tonic-gate
9090Sstevel@tonic-gate case KIOCSRPTRATE:
9100Sstevel@tonic-gate /*
9110Sstevel@tonic-gate * Set the autorepeat rate
9120Sstevel@tonic-gate */
9130Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate if (err != 0)
9160Sstevel@tonic-gate break;
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate /* validate the input */
9190Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
9200Sstevel@tonic-gate err = EINVAL;
9210Sstevel@tonic-gate break;
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
9240Sstevel@tonic-gate if (kbd_repeatrate <= 0)
9250Sstevel@tonic-gate kbd_repeatrate = 1;
9260Sstevel@tonic-gate break;
9270Sstevel@tonic-gate
9280Sstevel@tonic-gate default:
9290Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */
9300Sstevel@tonic-gate return;
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate goto done;
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate output_format_change:
9350Sstevel@tonic-gate kbdflush(kbdd);
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate done:
9380Sstevel@tonic-gate if (err != 0) {
9390Sstevel@tonic-gate iocp->ioc_rval = 0;
9400Sstevel@tonic-gate iocp->ioc_error = err;
9410Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK;
9420Sstevel@tonic-gate } else {
9430Sstevel@tonic-gate iocp->ioc_rval = 0;
9440Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */
9450Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate qreply(q, mp);
9480Sstevel@tonic-gate return;
9490Sstevel@tonic-gate
9500Sstevel@tonic-gate allocfailure:
9510Sstevel@tonic-gate /*
9520Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but
9530Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when
9540Sstevel@tonic-gate * it's more likely that we can get what we need.
9550Sstevel@tonic-gate * If there's already one being saved, throw it out, since it
9560Sstevel@tonic-gate * must have timed out.
9570Sstevel@tonic-gate */
9580Sstevel@tonic-gate if (kbdd->kbdd_iocpending != NULL)
9590Sstevel@tonic-gate freemsg(kbdd->kbdd_iocpending);
9600Sstevel@tonic-gate kbdd->kbdd_iocpending = mp;
9610Sstevel@tonic-gate if (kbdd->kbdd_bufcallid)
9620Sstevel@tonic-gate qunbufcall(q, kbdd->kbdd_bufcallid);
9630Sstevel@tonic-gate kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI,
9640Sstevel@tonic-gate kbdreioctl, kbdd);
9650Sstevel@tonic-gate }
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate static void
kbdflush(register struct kbddata * kbdd)9680Sstevel@tonic-gate kbdflush(register struct kbddata *kbdd)
9690Sstevel@tonic-gate {
9700Sstevel@tonic-gate register queue_t *q;
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate /* Flush pending data already sent upstream */
9730Sstevel@tonic-gate if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL)
9740Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHR);
9750Sstevel@tonic-gate /* Flush pending ups */
9760Sstevel@tonic-gate bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
9770Sstevel@tonic-gate kbdcancelrpt(kbdd);
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate /*
9810Sstevel@tonic-gate * Pass keycode upstream, either translated or untranslated.
9820Sstevel@tonic-gate */
9830Sstevel@tonic-gate static void
kbduse(register struct kbddata * kbdd,unsigned keycode)9840Sstevel@tonic-gate kbduse(register struct kbddata *kbdd, unsigned keycode)
9850Sstevel@tonic-gate {
9860Sstevel@tonic-gate register queue_t *readq;
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate #ifdef KBD_DEBUG
9890Sstevel@tonic-gate if (kbd_input_debug) printf("KBD USE key=%d\n", keycode);
9900Sstevel@tonic-gate #endif
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate if ((readq = kbdd->kbdd_readq) == NULL)
9930Sstevel@tonic-gate return;
9940Sstevel@tonic-gate if (!kbdd->kbdd_translatable ||
9950Sstevel@tonic-gate kbdd->kbdd_translate == TR_NONE)
9960Sstevel@tonic-gate kbdputcode(keycode, readq);
9970Sstevel@tonic-gate else
9980Sstevel@tonic-gate kbdtranslate(kbdd, keycode, readq);
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate
1001*5129Smarx static void
kbd_beep_on(void * arg)1002*5129Smarx kbd_beep_on(void *arg)
1003*5129Smarx {
1004*5129Smarx kbdcmd((queue_t *)arg, KBD_CMD_BELL);
1005*5129Smarx }
1006*5129Smarx
1007*5129Smarx
1008*5129Smarx static void
kbd_beep_off(void * arg)1009*5129Smarx kbd_beep_off(void *arg)
1010*5129Smarx {
1011*5129Smarx kbdcmd((queue_t *)arg, KBD_CMD_NOBELL);
1012*5129Smarx }
1013*5129Smarx
1014*5129Smarx
10150Sstevel@tonic-gate /*
10160Sstevel@tonic-gate * kbdclick is used to remember the current click value of the
10170Sstevel@tonic-gate * Sun-3 keyboard. This brain damaged keyboard will reset the
10180Sstevel@tonic-gate * clicking to the "default" value after a reset command and
10190Sstevel@tonic-gate * there is no way to read out the current click value. We
10200Sstevel@tonic-gate * cannot send a click command immediately after the reset
10210Sstevel@tonic-gate * command or the keyboard gets screwed up. So we wait until
10220Sstevel@tonic-gate * we get the ID byte before we send back the click command.
10230Sstevel@tonic-gate * Unfortunately, this means that there is a small window
10240Sstevel@tonic-gate * where the keyboard can click when it really shouldn't be.
10250Sstevel@tonic-gate * A value of -1 means that kbdclick has not been initialized yet.
10260Sstevel@tonic-gate */
10270Sstevel@tonic-gate static int kbdclick = -1;
10280Sstevel@tonic-gate
10290Sstevel@tonic-gate /*
10300Sstevel@tonic-gate * Send command byte to keyboard, if you can.
10310Sstevel@tonic-gate */
10320Sstevel@tonic-gate static void
kbdcmd(register queue_t * q,char cmd)10330Sstevel@tonic-gate kbdcmd(register queue_t *q, char cmd)
10340Sstevel@tonic-gate {
10350Sstevel@tonic-gate register mblk_t *bp;
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate if (canput(q)) {
10380Sstevel@tonic-gate if ((bp = allocb(1, BPRI_MED)) == NULL)
10390Sstevel@tonic-gate cmn_err(CE_WARN,
1040*5129Smarx "kbdcmd: Can't allocate block for command");
10410Sstevel@tonic-gate else {
10420Sstevel@tonic-gate *bp->b_wptr++ = cmd;
10430Sstevel@tonic-gate putnext(q, bp);
10440Sstevel@tonic-gate if (cmd == KBD_CMD_NOCLICK)
10450Sstevel@tonic-gate kbdclick = 0;
10460Sstevel@tonic-gate else if (cmd == KBD_CMD_CLICK)
10470Sstevel@tonic-gate kbdclick = 1;
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate }
10500Sstevel@tonic-gate }
10510Sstevel@tonic-gate
10520Sstevel@tonic-gate /*
10530Sstevel@tonic-gate * Update the keyboard LEDs to match the current keyboard state.
10540Sstevel@tonic-gate * Do this only on Type 4 keyboards; other keyboards don't support the
10550Sstevel@tonic-gate * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs).
10560Sstevel@tonic-gate */
10570Sstevel@tonic-gate static void
kbdsetled(register struct kbddata * kbdd)10580Sstevel@tonic-gate kbdsetled(register struct kbddata *kbdd)
10590Sstevel@tonic-gate {
10600Sstevel@tonic-gate if (kbdd->kbdd_state.k_id == KB_SUN4 ||
10610Sstevel@tonic-gate kbdd->kbdd_state.k_id == KB_PC) {
10620Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED);
10630Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, kbdd->led_state);
10640Sstevel@tonic-gate }
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate /*
10680Sstevel@tonic-gate * Reset the keyboard
10690Sstevel@tonic-gate */
10700Sstevel@tonic-gate static void
kbdreset(register struct kbddata * kbdd,uint_t hard_reset)10710Sstevel@tonic-gate kbdreset(register struct kbddata *kbdd, uint_t hard_reset)
10720Sstevel@tonic-gate {
10730Sstevel@tonic-gate register struct keyboardstate *k;
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate k = &kbdd->kbdd_state;
10760Sstevel@tonic-gate if (kbdd->kbdd_translatable) {
10770Sstevel@tonic-gate k->k_idstate = KID_NONE;
10780Sstevel@tonic-gate k->k_id = -1;
10790Sstevel@tonic-gate k->k_state = NORMAL;
10800Sstevel@tonic-gate if (hard_reset)
10810Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET);
10820Sstevel@tonic-gate } else {
10830Sstevel@tonic-gate bzero(k, sizeof (struct keyboardstate));
10840Sstevel@tonic-gate k->k_id = KB_ASCII;
10850Sstevel@tonic-gate k->k_idstate = KID_OK;
10860Sstevel@tonic-gate }
10870Sstevel@tonic-gate }
10880Sstevel@tonic-gate
10890Sstevel@tonic-gate /*
10900Sstevel@tonic-gate * Old special codes.
10910Sstevel@tonic-gate */
10920Sstevel@tonic-gate #define OLD_SHIFTKEYS 0x80
10930Sstevel@tonic-gate #define OLD_BUCKYBITS 0x90
10940Sstevel@tonic-gate #define OLD_FUNNY 0xA0
10950Sstevel@tonic-gate #define OLD_FA_UMLAUT 0xA9
10960Sstevel@tonic-gate #define OLD_FA_CFLEX 0xAA
10970Sstevel@tonic-gate #define OLD_FA_TILDE 0xAB
10980Sstevel@tonic-gate #define OLD_FA_CEDILLA 0xAC
10990Sstevel@tonic-gate #define OLD_FA_ACUTE 0xAD
11000Sstevel@tonic-gate #define OLD_FA_GRAVE 0xAE
11010Sstevel@tonic-gate #define OLD_ISOCHAR 0xAF
11020Sstevel@tonic-gate #define OLD_STRING 0xB0
11030Sstevel@tonic-gate #define OLD_LEFTFUNC 0xC0
11040Sstevel@tonic-gate #define OLD_RIGHTFUNC 0xD0
11050Sstevel@tonic-gate #define OLD_TOPFUNC 0xE0
11060Sstevel@tonic-gate #define OLD_BOTTOMFUNC 0xF0
11070Sstevel@tonic-gate
11080Sstevel@tonic-gate /*
11090Sstevel@tonic-gate * Map old special codes to new ones.
11100Sstevel@tonic-gate * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
11110Sstevel@tonic-gate */
11120Sstevel@tonic-gate static ushort_t special_old_to_new[] = {
11130Sstevel@tonic-gate SHIFTKEYS,
11140Sstevel@tonic-gate BUCKYBITS,
11150Sstevel@tonic-gate FUNNY,
11160Sstevel@tonic-gate STRING,
11170Sstevel@tonic-gate LEFTFUNC,
11180Sstevel@tonic-gate RIGHTFUNC,
11190Sstevel@tonic-gate TOPFUNC,
11200Sstevel@tonic-gate BOTTOMFUNC,
11210Sstevel@tonic-gate };
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate /*
11240Sstevel@tonic-gate * Set individual keystation translation from old-style entry.
11250Sstevel@tonic-gate * TODO: Have each keyboard own own translation tables.
11260Sstevel@tonic-gate */
11270Sstevel@tonic-gate static int
kbdsetkey(register struct kbddata * kbdd,struct kiockey * key,cred_t * cr)11280Sstevel@tonic-gate kbdsetkey(register struct kbddata *kbdd, struct kiockey *key, cred_t *cr)
11290Sstevel@tonic-gate {
11300Sstevel@tonic-gate int strtabindex, i;
11310Sstevel@tonic-gate struct keymap *km;
11320Sstevel@tonic-gate register int tablemask;
11330Sstevel@tonic-gate register ushort_t entry;
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE)
11360Sstevel@tonic-gate return (EINVAL);
11370Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL)
11380Sstevel@tonic-gate return (EINVAL);
11390Sstevel@tonic-gate tablemask = key->kio_tablemask;
11400Sstevel@tonic-gate if (tablemask == KIOCABORT1) {
11410Sstevel@tonic-gate if (secpolicy_console(cr) != 0)
11420Sstevel@tonic-gate return (EPERM);
11430Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station;
11440Sstevel@tonic-gate return (0);
11450Sstevel@tonic-gate }
11460Sstevel@tonic-gate if (tablemask == KIOCABORT2) {
11470Sstevel@tonic-gate if (secpolicy_console(cr) != 0)
11480Sstevel@tonic-gate return (EPERM);
11490Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station;
11500Sstevel@tonic-gate return (0);
11510Sstevel@tonic-gate }
11520Sstevel@tonic-gate if ((tablemask & ALTGRAPHMASK) ||
11530Sstevel@tonic-gate (km = settable(kbdd, (uint_t)tablemask)) == NULL)
11540Sstevel@tonic-gate return (EINVAL);
11550Sstevel@tonic-gate if (key->kio_entry >= (uchar_t)OLD_STRING &&
11560Sstevel@tonic-gate key->kio_entry <= (uchar_t)(OLD_STRING + 15)) {
11570Sstevel@tonic-gate strtabindex = key->kio_entry - OLD_STRING;
11580Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++)
11590Sstevel@tonic-gate keystringtab[strtabindex][i] = key->kio_string[i];
11600Sstevel@tonic-gate keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate entry = key->kio_entry;
11630Sstevel@tonic-gate /*
11640Sstevel@tonic-gate * There's nothing we need do with OLD_ISOCHAR.
11650Sstevel@tonic-gate */
11660Sstevel@tonic-gate if (entry != OLD_ISOCHAR) {
11670Sstevel@tonic-gate if (entry & 0x80) {
11680Sstevel@tonic-gate if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE)
11690Sstevel@tonic-gate entry = FA_CLASS + (entry & 0x0F) - 9;
11700Sstevel@tonic-gate else
11710Sstevel@tonic-gate entry =
11720Sstevel@tonic-gate special_old_to_new[entry >> 4 & 0x07]
11730Sstevel@tonic-gate + (entry & 0x0F);
11740Sstevel@tonic-gate }
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate km->keymap[key->kio_station] = entry;
11770Sstevel@tonic-gate return (0);
11780Sstevel@tonic-gate }
11790Sstevel@tonic-gate
11800Sstevel@tonic-gate /*
11810Sstevel@tonic-gate * Map new special codes to old ones.
11820Sstevel@tonic-gate * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
11830Sstevel@tonic-gate */
11840Sstevel@tonic-gate static uchar_t special_new_to_old[] = {
11850Sstevel@tonic-gate 0, /* normal */
11860Sstevel@tonic-gate OLD_SHIFTKEYS, /* SHIFTKEYS */
11870Sstevel@tonic-gate OLD_BUCKYBITS, /* BUCKYBITS */
11880Sstevel@tonic-gate OLD_FUNNY, /* FUNNY */
11890Sstevel@tonic-gate OLD_FA_UMLAUT, /* FA_CLASS */
11900Sstevel@tonic-gate OLD_STRING, /* STRING */
11910Sstevel@tonic-gate OLD_LEFTFUNC, /* FUNCKEYS */
11920Sstevel@tonic-gate };
11930Sstevel@tonic-gate
11940Sstevel@tonic-gate /*
11950Sstevel@tonic-gate * Get individual keystation translation as old-style entry.
11960Sstevel@tonic-gate */
11970Sstevel@tonic-gate static int
kbdgetkey(register struct kbddata * kbdd,struct kiockey * key)11980Sstevel@tonic-gate kbdgetkey(register struct kbddata *kbdd, struct kiockey *key)
11990Sstevel@tonic-gate {
12000Sstevel@tonic-gate int strtabindex, i;
12010Sstevel@tonic-gate struct keymap *km;
12020Sstevel@tonic-gate register ushort_t entry;
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE)
12050Sstevel@tonic-gate return (EINVAL);
12060Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL)
12070Sstevel@tonic-gate return (EINVAL);
12080Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) {
12090Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1;
12100Sstevel@tonic-gate return (0);
12110Sstevel@tonic-gate }
12120Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) {
12130Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2;
12140Sstevel@tonic-gate return (0);
12150Sstevel@tonic-gate }
12160Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
12170Sstevel@tonic-gate return (EINVAL);
12180Sstevel@tonic-gate entry = km->keymap[key->kio_station];
12190Sstevel@tonic-gate if (entry & 0xFF00)
12200Sstevel@tonic-gate key->kio_entry =
12210Sstevel@tonic-gate special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8]
12220Sstevel@tonic-gate + (entry & 0x00FF);
12230Sstevel@tonic-gate else {
12240Sstevel@tonic-gate if (entry & 0x80)
12250Sstevel@tonic-gate key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */
12260Sstevel@tonic-gate else
12270Sstevel@tonic-gate key->kio_entry = (ushort_t)entry;
12280Sstevel@tonic-gate }
12290Sstevel@tonic-gate if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) {
12300Sstevel@tonic-gate strtabindex = entry - STRING;
12310Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++)
12320Sstevel@tonic-gate key->kio_string[i] = keystringtab[strtabindex][i];
12330Sstevel@tonic-gate }
12340Sstevel@tonic-gate return (0);
12350Sstevel@tonic-gate }
12360Sstevel@tonic-gate
12370Sstevel@tonic-gate /*
12380Sstevel@tonic-gate * Set individual keystation translation from new-style entry.
12390Sstevel@tonic-gate * TODO: Have each keyboard own own translation tables.
12400Sstevel@tonic-gate */
12410Sstevel@tonic-gate static int
kbdskey(register struct kbddata * kbdd,struct kiockeymap * key,cred_t * cr)12420Sstevel@tonic-gate kbdskey(register struct kbddata *kbdd, struct kiockeymap *key, cred_t *cr)
12430Sstevel@tonic-gate {
12440Sstevel@tonic-gate int strtabindex, i;
12450Sstevel@tonic-gate struct keymap *km;
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE)
12480Sstevel@tonic-gate return (EINVAL);
12490Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL)
12500Sstevel@tonic-gate return (EINVAL);
12510Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) {
12520Sstevel@tonic-gate if (secpolicy_console(cr) != 0)
12530Sstevel@tonic-gate return (EPERM);
12540Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station;
12550Sstevel@tonic-gate return (0);
12560Sstevel@tonic-gate }
12570Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) {
12580Sstevel@tonic-gate if (secpolicy_console(cr) != 0)
12590Sstevel@tonic-gate return (EPERM);
12600Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station;
12610Sstevel@tonic-gate return (0);
12620Sstevel@tonic-gate }
12630Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
12640Sstevel@tonic-gate return (EINVAL);
12650Sstevel@tonic-gate if (key->kio_entry >= STRING &&
12660Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) {
12670Sstevel@tonic-gate strtabindex = key->kio_entry-STRING;
12680Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++)
12690Sstevel@tonic-gate keystringtab[strtabindex][i] = key->kio_string[i];
12700Sstevel@tonic-gate keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate km->keymap[key->kio_station] = key->kio_entry;
12730Sstevel@tonic-gate return (0);
12740Sstevel@tonic-gate }
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate /*
12770Sstevel@tonic-gate * Get individual keystation translation as new-style entry.
12780Sstevel@tonic-gate */
12790Sstevel@tonic-gate static int
kbdgkey(register struct kbddata * kbdd,struct kiockeymap * key)12800Sstevel@tonic-gate kbdgkey(register struct kbddata *kbdd, struct kiockeymap *key)
12810Sstevel@tonic-gate {
12820Sstevel@tonic-gate int strtabindex, i;
12830Sstevel@tonic-gate struct keymap *km;
12840Sstevel@tonic-gate
12850Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE)
12860Sstevel@tonic-gate return (EINVAL);
12870Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL)
12880Sstevel@tonic-gate return (EINVAL);
12890Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) {
12900Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1;
12910Sstevel@tonic-gate return (0);
12920Sstevel@tonic-gate }
12930Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) {
12940Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2;
12950Sstevel@tonic-gate return (0);
12960Sstevel@tonic-gate }
12970Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
12980Sstevel@tonic-gate return (EINVAL);
12990Sstevel@tonic-gate key->kio_entry = km->keymap[key->kio_station];
13000Sstevel@tonic-gate if (key->kio_entry >= STRING &&
13010Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) {
13020Sstevel@tonic-gate strtabindex = key->kio_entry-STRING;
13030Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++)
13040Sstevel@tonic-gate key->kio_string[i] = keystringtab[strtabindex][i];
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate return (0);
13070Sstevel@tonic-gate }
13080Sstevel@tonic-gate
13090Sstevel@tonic-gate static void
kbdlayouttimeout(void * arg)13100Sstevel@tonic-gate kbdlayouttimeout(void *arg)
13110Sstevel@tonic-gate {
13120Sstevel@tonic-gate struct kbddata *kbdd = arg;
13130Sstevel@tonic-gate mblk_t *mp;
13140Sstevel@tonic-gate
13150Sstevel@tonic-gate kbdd->kbdd_layoutid = 0;
13160Sstevel@tonic-gate
13170Sstevel@tonic-gate /*
13180Sstevel@tonic-gate * Timed out waiting for reply to "get keyboard layout" command.
13190Sstevel@tonic-gate * Return an ETIME error.
13200Sstevel@tonic-gate */
13210Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) {
13220Sstevel@tonic-gate kbdd->kbdd_replypending = NULL;
13230Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK;
13240Sstevel@tonic-gate ((struct iocblk *)mp->b_rptr)->ioc_error = ETIME;
13250Sstevel@tonic-gate putnext(kbdd->kbdd_readq, mp);
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate }
13280Sstevel@tonic-gate
13290Sstevel@tonic-gate /*
13300Sstevel@tonic-gate * Put procedure for input from driver end of stream (read queue).
13310Sstevel@tonic-gate */
13320Sstevel@tonic-gate static void
kbdrput(register queue_t * q,register mblk_t * mp)13330Sstevel@tonic-gate kbdrput(register queue_t *q, register mblk_t *mp)
13340Sstevel@tonic-gate {
13350Sstevel@tonic-gate struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
13360Sstevel@tonic-gate register mblk_t *bp;
13370Sstevel@tonic-gate register uchar_t *readp;
13380Sstevel@tonic-gate struct iocblk *iocp;
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate if (kbdd == 0) {
13410Sstevel@tonic-gate freemsg(mp); /* nobody's listening */
13420Sstevel@tonic-gate return;
13430Sstevel@tonic-gate }
13440Sstevel@tonic-gate
13450Sstevel@tonic-gate switch (mp->b_datap->db_type) {
13460Sstevel@tonic-gate
13470Sstevel@tonic-gate case M_FLUSH:
13480Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW)
13490Sstevel@tonic-gate flushq(WR(q), FLUSHDATA);
13500Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR)
13510Sstevel@tonic-gate flushq(q, FLUSHDATA);
13520Sstevel@tonic-gate
13530Sstevel@tonic-gate default:
13540Sstevel@tonic-gate putnext(q, mp);
13550Sstevel@tonic-gate return;
13560Sstevel@tonic-gate
13570Sstevel@tonic-gate case M_BREAK:
13580Sstevel@tonic-gate /*
13590Sstevel@tonic-gate * Will get M_BREAK only if this is not the system
13600Sstevel@tonic-gate * keyboard, otherwise serial port will eat break
13610Sstevel@tonic-gate * and call kmdb/OBP, without passing anything up.
13620Sstevel@tonic-gate */
13630Sstevel@tonic-gate freemsg(mp);
13640Sstevel@tonic-gate return;
13650Sstevel@tonic-gate
13660Sstevel@tonic-gate case M_IOCACK:
13670Sstevel@tonic-gate case M_IOCNAK:
13680Sstevel@tonic-gate /*
13690Sstevel@tonic-gate * If we are doing an "ioctl" ourselves, check if this
13700Sstevel@tonic-gate * is the reply to that code. If so, wake up the
13710Sstevel@tonic-gate * "open" routine, and toss the reply, otherwise just
13720Sstevel@tonic-gate * pass it up.
13730Sstevel@tonic-gate */
13740Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
13750Sstevel@tonic-gate if (!(kbdd->kbdd_flags & KBD_IOCWAIT) ||
13760Sstevel@tonic-gate iocp->ioc_id != kbdd->kbdd_iocid) {
13770Sstevel@tonic-gate /*
13780Sstevel@tonic-gate * This isn't the reply we're looking for. Move along.
13790Sstevel@tonic-gate */
13800Sstevel@tonic-gate if (kbdd->kbdd_flags & KBD_OPEN)
13810Sstevel@tonic-gate putnext(q, mp);
13820Sstevel@tonic-gate else
13830Sstevel@tonic-gate freemsg(mp); /* not ready to listen */
13840Sstevel@tonic-gate } else {
13850Sstevel@tonic-gate kbdd->kbdd_flags &= ~KBD_IOCWAIT;
13860Sstevel@tonic-gate kbdd->kbdd_iocerror = iocp->ioc_error;
13870Sstevel@tonic-gate freemsg(mp);
13880Sstevel@tonic-gate }
13890Sstevel@tonic-gate return;
13900Sstevel@tonic-gate
13910Sstevel@tonic-gate case M_DATA:
13920Sstevel@tonic-gate if (!(kbdd->kbdd_flags & KBD_OPEN)) {
13930Sstevel@tonic-gate freemsg(mp); /* not read to listen */
13940Sstevel@tonic-gate return;
13950Sstevel@tonic-gate }
13960Sstevel@tonic-gate break;
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate
13990Sstevel@tonic-gate /*
14000Sstevel@tonic-gate * A data message, consisting of bytes from the keyboard.
14010Sstevel@tonic-gate * Ram them through our state machine.
14020Sstevel@tonic-gate */
14030Sstevel@tonic-gate bp = mp;
14040Sstevel@tonic-gate
14050Sstevel@tonic-gate do {
14060Sstevel@tonic-gate readp = bp->b_rptr;
14070Sstevel@tonic-gate while (readp < bp->b_wptr)
14080Sstevel@tonic-gate kbdinput(kbdd, *readp++);
14090Sstevel@tonic-gate bp->b_rptr = readp;
14100Sstevel@tonic-gate } while ((bp = bp->b_cont) != NULL); /* next block, if any */
14110Sstevel@tonic-gate
14120Sstevel@tonic-gate freemsg(mp);
14130Sstevel@tonic-gate }
14140Sstevel@tonic-gate
14150Sstevel@tonic-gate /*
14160Sstevel@tonic-gate * A keypress was received. Process it through the state machine
14170Sstevel@tonic-gate * to check for aborts.
14180Sstevel@tonic-gate */
14190Sstevel@tonic-gate static void
kbdinput(register struct kbddata * kbdd,register unsigned key)14200Sstevel@tonic-gate kbdinput(register struct kbddata *kbdd, register unsigned key)
14210Sstevel@tonic-gate {
14220Sstevel@tonic-gate register struct keyboardstate *k;
14230Sstevel@tonic-gate register mblk_t *mp;
14240Sstevel@tonic-gate
14250Sstevel@tonic-gate k = &kbdd->kbdd_state;
14260Sstevel@tonic-gate #ifdef KBD_DEBUG
14270Sstevel@tonic-gate if (kbd_input_debug)
14280Sstevel@tonic-gate printf("kbdinput key %x\n", key);
14290Sstevel@tonic-gate #endif
14300Sstevel@tonic-gate
14310Sstevel@tonic-gate switch (k->k_idstate) {
14320Sstevel@tonic-gate
14330Sstevel@tonic-gate case KID_NONE:
14340Sstevel@tonic-gate if (key == RESETKEY) {
14350Sstevel@tonic-gate k->k_idstate = KID_GOT_PREFACE;
14360Sstevel@tonic-gate } else {
14370Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET);
14380Sstevel@tonic-gate /* allows hot plug of kbd after booting without kbd */
14390Sstevel@tonic-gate }
14400Sstevel@tonic-gate return;
14410Sstevel@tonic-gate
14420Sstevel@tonic-gate case KID_GOT_PREFACE:
14430Sstevel@tonic-gate kbdid(kbdd, (int)key);
14440Sstevel@tonic-gate
14450Sstevel@tonic-gate /*
14460Sstevel@tonic-gate * We just did a reset command to a Type 3 or Type 4
14470Sstevel@tonic-gate * keyboard which sets the click back to the default
14480Sstevel@tonic-gate * (which is currently ON!). We use the kbdclick
14490Sstevel@tonic-gate * variable to see if the keyboard should be turned on
14500Sstevel@tonic-gate * or off. If it has not been set, then we use the
14510Sstevel@tonic-gate * keyboard-click? property.
14520Sstevel@tonic-gate */
14530Sstevel@tonic-gate switch (kbdclick) {
14540Sstevel@tonic-gate case 0:
14550Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK);
14560Sstevel@tonic-gate break;
14570Sstevel@tonic-gate case 1:
14580Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_CLICK);
14590Sstevel@tonic-gate break;
14600Sstevel@tonic-gate case -1:
14610Sstevel@tonic-gate default:
14620Sstevel@tonic-gate {
14630Sstevel@tonic-gate char wrkbuf[8];
14640Sstevel@tonic-gate int len;
14650Sstevel@tonic-gate
14660Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK);
14670Sstevel@tonic-gate
14680Sstevel@tonic-gate bzero(wrkbuf, 8);
14690Sstevel@tonic-gate len = 7;
14700Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY,
14710Sstevel@tonic-gate ddi_root_node(), 0, "keyboard-click?",
14720Sstevel@tonic-gate (caddr_t)wrkbuf, &len) ==
14730Sstevel@tonic-gate DDI_PROP_SUCCESS &&
14740Sstevel@tonic-gate len > 0 && len < 8) {
14750Sstevel@tonic-gate if (strcmp(wrkbuf, "true") == 0) {
14760Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq,
1477*5129Smarx KBD_CMD_CLICK);
14780Sstevel@tonic-gate }
14790Sstevel@tonic-gate }
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate break;
14820Sstevel@tonic-gate }
14830Sstevel@tonic-gate /*
14840Sstevel@tonic-gate * A keyboard reset clears the LEDs.
14850Sstevel@tonic-gate * Restore the LEDs from the last value we set
14860Sstevel@tonic-gate * them to.
14870Sstevel@tonic-gate */
14880Sstevel@tonic-gate kbdsetled(kbdd);
14890Sstevel@tonic-gate return;
14900Sstevel@tonic-gate
14910Sstevel@tonic-gate case KID_OK:
14920Sstevel@tonic-gate switch (key) {
14930Sstevel@tonic-gate
14940Sstevel@tonic-gate #if defined(KBD_PRESSED_PREFIX)
14950Sstevel@tonic-gate case KBD_PRESSED_PREFIX:
14960Sstevel@tonic-gate k->k_idstate = KID_GOT_PRESSED;
14970Sstevel@tonic-gate return;
14980Sstevel@tonic-gate #endif
14990Sstevel@tonic-gate
15000Sstevel@tonic-gate #if defined(KBD_RELEASED_PREFIX)
15010Sstevel@tonic-gate case KBD_RELEASED_PREFIX:
15020Sstevel@tonic-gate k->k_idstate = KID_GOT_RELEASED;
15030Sstevel@tonic-gate return;
15040Sstevel@tonic-gate #endif
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate case 0:
15070Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET);
15080Sstevel@tonic-gate return;
15090Sstevel@tonic-gate
15100Sstevel@tonic-gate /*
15110Sstevel@tonic-gate * we want to check for ID only if we are in
15120Sstevel@tonic-gate * translatable mode.
15130Sstevel@tonic-gate */
15140Sstevel@tonic-gate case RESETKEY:
15150Sstevel@tonic-gate kbdreset(kbdd, NO_HARD_RESET);
15160Sstevel@tonic-gate if (k->k_idstate == KID_NONE) {
15170Sstevel@tonic-gate k->k_idstate = KID_GOT_PREFACE;
15180Sstevel@tonic-gate }
15190Sstevel@tonic-gate return;
15200Sstevel@tonic-gate
15210Sstevel@tonic-gate case LAYOUTKEY:
15220Sstevel@tonic-gate k->k_idstate = KID_GOT_LAYOUT;
15230Sstevel@tonic-gate return;
15240Sstevel@tonic-gate }
15250Sstevel@tonic-gate break;
15260Sstevel@tonic-gate
15270Sstevel@tonic-gate #if defined(KBD_PRESSED_PREFIX)
15280Sstevel@tonic-gate case KID_GOT_PRESSED:
15290Sstevel@tonic-gate key = BUILDKEY(key, PRESSED);
15300Sstevel@tonic-gate k->k_idstate = KID_OK;
15310Sstevel@tonic-gate break;
15320Sstevel@tonic-gate #endif
15330Sstevel@tonic-gate #if defined(KBD_RELEASED_PREFIX)
15340Sstevel@tonic-gate case KID_GOT_RELEASED:
15350Sstevel@tonic-gate key = BUILDKEY(key, RELEASED);
15360Sstevel@tonic-gate k->k_idstate = KID_OK;
15370Sstevel@tonic-gate break;
15380Sstevel@tonic-gate #endif
15390Sstevel@tonic-gate
15400Sstevel@tonic-gate case KID_GOT_LAYOUT:
15410Sstevel@tonic-gate if (kbdd->kbdd_layoutid)
15420Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq,
15430Sstevel@tonic-gate kbdd->kbdd_layoutid);
15440Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) {
15450Sstevel@tonic-gate kbdd->kbdd_replypending = NULL;
15460Sstevel@tonic-gate *(int *)mp->b_cont->b_wptr = key;
15470Sstevel@tonic-gate mp->b_cont->b_wptr += sizeof (int);
15480Sstevel@tonic-gate putnext(kbdd->kbdd_readq, mp);
15490Sstevel@tonic-gate }
15500Sstevel@tonic-gate k->k_idstate = KID_OK;
15510Sstevel@tonic-gate return;
15520Sstevel@tonic-gate }
15530Sstevel@tonic-gate
15540Sstevel@tonic-gate switch (k->k_state) {
15550Sstevel@tonic-gate
15560Sstevel@tonic-gate #if defined(__sparc)
15570Sstevel@tonic-gate normalstate:
15580Sstevel@tonic-gate k->k_state = NORMAL;
15590Sstevel@tonic-gate /* FALLTHRU */
15600Sstevel@tonic-gate #endif
15610Sstevel@tonic-gate case NORMAL:
15620Sstevel@tonic-gate #if defined(__sparc)
15630Sstevel@tonic-gate if (k->k_curkeyboard) {
15640Sstevel@tonic-gate if (key == k->k_curkeyboard->k_abort1) {
15650Sstevel@tonic-gate k->k_state = ABORT1;
15660Sstevel@tonic-gate break;
15670Sstevel@tonic-gate }
15683505Sqz150045 if ((key == k->k_curkeyboard->k_newabort1) ||
15693505Sqz150045 (key == k->k_curkeyboard->k_newabort1a)) {
15703505Sqz150045 k->k_state = NEWABORT1;
15713927Sqz150045 kbdd->shiftkey = key;
15723505Sqz150045 }
15730Sstevel@tonic-gate }
15740Sstevel@tonic-gate #endif
15750Sstevel@tonic-gate kbduse(kbdd, key);
15760Sstevel@tonic-gate break;
15770Sstevel@tonic-gate
15780Sstevel@tonic-gate #if defined(__sparc)
15790Sstevel@tonic-gate case ABORT1:
15800Sstevel@tonic-gate if (k->k_curkeyboard) {
15810Sstevel@tonic-gate /*
15820Sstevel@tonic-gate * Only recognize this as an abort sequence if
15830Sstevel@tonic-gate * the "hardware" console is set to be this device.
15840Sstevel@tonic-gate */
15850Sstevel@tonic-gate if (key == k->k_curkeyboard->k_abort2 &&
15860Sstevel@tonic-gate rconsvp == wsconsvp) {
15870Sstevel@tonic-gate DELAY(100000);
15880Sstevel@tonic-gate abort_sequence_enter((char *)NULL);
15890Sstevel@tonic-gate k->k_state = NORMAL;
15900Sstevel@tonic-gate kbduse(kbdd, IDLEKEY); /* fake */
15910Sstevel@tonic-gate return;
15920Sstevel@tonic-gate } else {
15930Sstevel@tonic-gate kbduse(kbdd, k->k_curkeyboard->k_abort1);
15940Sstevel@tonic-gate goto normalstate;
15950Sstevel@tonic-gate }
15960Sstevel@tonic-gate }
15970Sstevel@tonic-gate break;
15983505Sqz150045 case NEWABORT1:
15993505Sqz150045 if (k->k_curkeyboard) {
16003505Sqz150045 /*
16013505Sqz150045 * Only recognize this as an abort sequence if
16023505Sqz150045 * the "hardware" console is set to be this device.
16033505Sqz150045 */
16043505Sqz150045 if (key == k->k_curkeyboard->k_newabort2 &&
16053505Sqz150045 rconsvp == wsconsvp) {
16063505Sqz150045 DELAY(100000);
16073505Sqz150045 abort_sequence_enter((char *)NULL);
16083505Sqz150045 k->k_state = NORMAL;
16093927Sqz150045 kbdd->shiftkey |= RELEASED;
16103927Sqz150045 kbduse(kbdd, kbdd->shiftkey);
16113505Sqz150045 kbduse(kbdd, IDLEKEY); /* fake */
16123505Sqz150045 return;
16133505Sqz150045 } else {
16143505Sqz150045 goto normalstate;
16153505Sqz150045 }
16163505Sqz150045 }
16173505Sqz150045 break;
16180Sstevel@tonic-gate #endif
16190Sstevel@tonic-gate
16200Sstevel@tonic-gate case COMPOSE1:
16210Sstevel@tonic-gate case COMPOSE2:
16220Sstevel@tonic-gate case FLTACCENT:
16230Sstevel@tonic-gate if (key != IDLEKEY)
16240Sstevel@tonic-gate kbduse(kbdd, key);
16250Sstevel@tonic-gate break;
16260Sstevel@tonic-gate }
16270Sstevel@tonic-gate }
16280Sstevel@tonic-gate
16290Sstevel@tonic-gate static void
kbdid(register struct kbddata * kbdd,int id)16300Sstevel@tonic-gate kbdid(register struct kbddata *kbdd, int id)
16310Sstevel@tonic-gate {
16320Sstevel@tonic-gate register struct keyboardstate *k;
16330Sstevel@tonic-gate int i;
16340Sstevel@tonic-gate
16350Sstevel@tonic-gate k = &kbdd->kbdd_state;
16360Sstevel@tonic-gate
16370Sstevel@tonic-gate k->k_idstate = KID_OK;
16380Sstevel@tonic-gate k->k_shiftmask = 0;
16390Sstevel@tonic-gate k->k_buckybits = 0;
16400Sstevel@tonic-gate
16410Sstevel@tonic-gate /*
16420Sstevel@tonic-gate * Reset k_rptkey to IDLEKEY. We need to cancel
16430Sstevel@tonic-gate * the autorepeat feature, if any.
16440Sstevel@tonic-gate */
16450Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) {
16460Sstevel@tonic-gate if (kbdd->kbdd_rptid)
16470Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
16480Sstevel@tonic-gate kbdd->kbdd_rptid = 0;
16490Sstevel@tonic-gate k->k_rptkey = IDLEKEY;
16500Sstevel@tonic-gate }
16510Sstevel@tonic-gate
16520Sstevel@tonic-gate k->k_curkeyboard = NULL;
16530Sstevel@tonic-gate for (i = 0; keytables[i].table; i++) {
16540Sstevel@tonic-gate if (keytables[i].id == id) {
16550Sstevel@tonic-gate k->k_id = id;
16560Sstevel@tonic-gate k->k_curkeyboard = keytables[i].table;
16570Sstevel@tonic-gate break;
16580Sstevel@tonic-gate }
16590Sstevel@tonic-gate }
16600Sstevel@tonic-gate if (!k->k_curkeyboard) {
16610Sstevel@tonic-gate k->k_id = keytables[0].id;
16620Sstevel@tonic-gate k->k_curkeyboard = keytables[0].table;
16630Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Unknown keyboard type, "
1664*5129Smarx "Type %d assumed", k->k_id);
16650Sstevel@tonic-gate }
16660Sstevel@tonic-gate }
16670Sstevel@tonic-gate
16680Sstevel@tonic-gate /*
16690Sstevel@tonic-gate * This routine determines which table we should look in to decode
16700Sstevel@tonic-gate * the current keycode.
16710Sstevel@tonic-gate */
16720Sstevel@tonic-gate static struct keymap *
settable(register struct kbddata * kbdd,register uint_t mask)16730Sstevel@tonic-gate settable(register struct kbddata *kbdd, register uint_t mask)
16740Sstevel@tonic-gate {
16750Sstevel@tonic-gate register struct keyboard *kp;
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate kp = kbdd->kbdd_state.k_curkeyboard;
16780Sstevel@tonic-gate if (kp == NULL)
16790Sstevel@tonic-gate return (NULL);
16800Sstevel@tonic-gate if (mask & UPMASK)
16810Sstevel@tonic-gate return (kp->k_up);
16820Sstevel@tonic-gate if (mask & NUMLOCKMASK)
16830Sstevel@tonic-gate return (kp->k_numlock);
16840Sstevel@tonic-gate if (mask & CTRLMASK)
16850Sstevel@tonic-gate return (kp->k_control);
16860Sstevel@tonic-gate if (mask & ALTGRAPHMASK)
16870Sstevel@tonic-gate return (kp->k_altgraph);
16880Sstevel@tonic-gate if (mask & SHIFTMASK)
16890Sstevel@tonic-gate return (kp->k_shifted);
16900Sstevel@tonic-gate if (mask & CAPSMASK)
16910Sstevel@tonic-gate return (kp->k_caps);
16920Sstevel@tonic-gate return (kp->k_normal);
16930Sstevel@tonic-gate }
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate static void
kbdrpt(void * arg)16960Sstevel@tonic-gate kbdrpt(void *arg)
16970Sstevel@tonic-gate {
16980Sstevel@tonic-gate struct kbddata *kbdd = arg;
16990Sstevel@tonic-gate struct keyboardstate *k;
17000Sstevel@tonic-gate
17010Sstevel@tonic-gate k = &kbdd->kbdd_state;
17020Sstevel@tonic-gate #ifdef KBD_DEBUG
17030Sstevel@tonic-gate if (kbd_rpt_debug)
17040Sstevel@tonic-gate printf("kbdrpt key %x\n", k->k_rptkey);
17050Sstevel@tonic-gate #endif
17060Sstevel@tonic-gate kbdd->kbdd_rptid = 0;
17070Sstevel@tonic-gate
17080Sstevel@tonic-gate kbdkeyreleased(kbdd, KEYOF(k->k_rptkey));
17090Sstevel@tonic-gate kbduse(kbdd, k->k_rptkey);
17100Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) {
17110Sstevel@tonic-gate kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt,
17120Sstevel@tonic-gate kbdd, kbd_repeatrate);
17130Sstevel@tonic-gate }
17140Sstevel@tonic-gate }
17150Sstevel@tonic-gate
17160Sstevel@tonic-gate static void
kbdcancelrpt(register struct kbddata * kbdd)17170Sstevel@tonic-gate kbdcancelrpt(register struct kbddata *kbdd)
17180Sstevel@tonic-gate {
17190Sstevel@tonic-gate register struct keyboardstate *k;
17200Sstevel@tonic-gate
17210Sstevel@tonic-gate k = &kbdd->kbdd_state;
17220Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) {
17230Sstevel@tonic-gate if (kbdd->kbdd_rptid)
17240Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
17250Sstevel@tonic-gate kbdd->kbdd_rptid = 0;
17260Sstevel@tonic-gate k->k_rptkey = IDLEKEY;
17270Sstevel@tonic-gate }
17280Sstevel@tonic-gate ASSERT(kbdd->kbdd_rptid == 0);
17290Sstevel@tonic-gate }
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate static void
kbdtranslate(struct kbddata * kbdd,unsigned keycode,queue_t * q)17320Sstevel@tonic-gate kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q)
17330Sstevel@tonic-gate {
17340Sstevel@tonic-gate register uchar_t key;
17350Sstevel@tonic-gate register unsigned newstate;
17360Sstevel@tonic-gate unsigned shiftmask;
17370Sstevel@tonic-gate register ushort_t entry, entrytype;
17380Sstevel@tonic-gate register char *cp, *bufp;
17390Sstevel@tonic-gate register struct keyboardstate *k;
17400Sstevel@tonic-gate ushort_t result_iso;
17410Sstevel@tonic-gate struct keymap *km;
17420Sstevel@tonic-gate Firm_event fe;
17430Sstevel@tonic-gate int i, ret_val;
17440Sstevel@tonic-gate char buf[14];
17450Sstevel@tonic-gate
17460Sstevel@tonic-gate k = &kbdd->kbdd_state;
17470Sstevel@tonic-gate newstate = STATEOF(keycode);
17480Sstevel@tonic-gate key = KEYOF(keycode);
17490Sstevel@tonic-gate
17500Sstevel@tonic-gate #ifdef KBD_DEBUG
17510Sstevel@tonic-gate if (kbd_input_debug) {
17520Sstevel@tonic-gate printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n",
17530Sstevel@tonic-gate keycode, newstate, key);
17540Sstevel@tonic-gate }
17550Sstevel@tonic-gate #endif
17560Sstevel@tonic-gate
17570Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
17580Sstevel@tonic-gate if (newstate == PRESSED) {
17590Sstevel@tonic-gate bzero(&fe, sizeof (fe));
17600Sstevel@tonic-gate fe.id = key;
17610Sstevel@tonic-gate fe.value = 1;
17620Sstevel@tonic-gate kbdqueuepress(kbdd, key, &fe);
17630Sstevel@tonic-gate } else {
17640Sstevel@tonic-gate kbdkeyreleased(kbdd, key);
17650Sstevel@tonic-gate }
17660Sstevel@tonic-gate return;
17670Sstevel@tonic-gate }
17680Sstevel@tonic-gate
17690Sstevel@tonic-gate shiftmask = k->k_shiftmask;
17700Sstevel@tonic-gate if (newstate == RELEASED)
17710Sstevel@tonic-gate shiftmask |= UPMASK;
17720Sstevel@tonic-gate
17730Sstevel@tonic-gate km = settable(kbdd, shiftmask);
17740Sstevel@tonic-gate if (km == NULL) { /* gross error */
17750Sstevel@tonic-gate kbdcancelrpt(kbdd);
17760Sstevel@tonic-gate return;
17770Sstevel@tonic-gate }
17780Sstevel@tonic-gate
17790Sstevel@tonic-gate if (key >= KEYMAP_SIZE)
17800Sstevel@tonic-gate return;
17810Sstevel@tonic-gate entry = km->keymap[key];
17820Sstevel@tonic-gate
17830Sstevel@tonic-gate if (entry == NONL) {
17840Sstevel@tonic-gate /*
17850Sstevel@tonic-gate * NONL appears only in the Num Lock table, and indicates that
17860Sstevel@tonic-gate * this key is not affected by Num Lock. This means we should
17870Sstevel@tonic-gate * ask for the table we would have gotten had Num Lock not been
17880Sstevel@tonic-gate * down, and translate using that table.
17890Sstevel@tonic-gate */
17900Sstevel@tonic-gate km = settable(kbdd, shiftmask & ~NUMLOCKMASK);
17910Sstevel@tonic-gate if (km == NULL) { /* gross error */
17920Sstevel@tonic-gate kbdcancelrpt(kbdd);
17930Sstevel@tonic-gate return;
17940Sstevel@tonic-gate }
17950Sstevel@tonic-gate entry = km->keymap[key];
17960Sstevel@tonic-gate }
17970Sstevel@tonic-gate entrytype = (ushort_t)(entry & 0xFF00) >> 8;
17980Sstevel@tonic-gate
17990Sstevel@tonic-gate if (entrytype == (SHIFTKEYS >> 8)) {
18000Sstevel@tonic-gate /*
18010Sstevel@tonic-gate * Handle the state of toggle shifts specially.
18020Sstevel@tonic-gate * Ups should be ignored, and downs should be mapped to ups if
18030Sstevel@tonic-gate * that shift is currently on.
18040Sstevel@tonic-gate */
18050Sstevel@tonic-gate if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) {
18060Sstevel@tonic-gate if ((1 << (entry & 0x0F)) & k->k_togglemask) {
18070Sstevel@tonic-gate newstate = RELEASED; /* toggling off */
18080Sstevel@tonic-gate } else {
18090Sstevel@tonic-gate newstate = PRESSED; /* toggling on */
18100Sstevel@tonic-gate }
18110Sstevel@tonic-gate }
18120Sstevel@tonic-gate } else {
18130Sstevel@tonic-gate /*
18140Sstevel@tonic-gate * Handle Compose and floating accent key sequences
18150Sstevel@tonic-gate */
18160Sstevel@tonic-gate if (k->k_state == COMPOSE1) {
18170Sstevel@tonic-gate if (newstate == RELEASED)
18180Sstevel@tonic-gate return;
18190Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) {
18200Sstevel@tonic-gate if (kb_compose_map[entry] >= 0) {
18210Sstevel@tonic-gate kbdd->compose_key = entry;
18220Sstevel@tonic-gate k->k_state = COMPOSE2;
18230Sstevel@tonic-gate return;
18240Sstevel@tonic-gate }
18250Sstevel@tonic-gate }
18260Sstevel@tonic-gate k->k_state = NORMAL;
18270Sstevel@tonic-gate kbdd->led_state &= ~LED_COMPOSE;
18280Sstevel@tonic-gate kbdsetled(kbdd);
18290Sstevel@tonic-gate return;
18300Sstevel@tonic-gate } else if (k->k_state == COMPOSE2) {
18310Sstevel@tonic-gate if (newstate == RELEASED)
18320Sstevel@tonic-gate return;
18330Sstevel@tonic-gate k->k_state = NORMAL; /* next state is "normal" */
18340Sstevel@tonic-gate kbdd->led_state &= ~LED_COMPOSE;
18350Sstevel@tonic-gate kbdsetled(kbdd);
18360Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) {
18370Sstevel@tonic-gate if (kb_compose_map[entry] >= 0) {
18380Sstevel@tonic-gate if (kbdd->compose_key <= entry) {
18390Sstevel@tonic-gate ret_val = kbd_do_compose(
1840*5129Smarx kbdd->compose_key,
1841*5129Smarx entry,
1842*5129Smarx &result_iso);
18430Sstevel@tonic-gate } else {
18440Sstevel@tonic-gate ret_val = kbd_do_compose(
1845*5129Smarx entry,
1846*5129Smarx kbdd->compose_key,
1847*5129Smarx &result_iso);
18480Sstevel@tonic-gate }
18490Sstevel@tonic-gate if (ret_val == 1) {
18500Sstevel@tonic-gate if (kbdd->kbdd_translate ==
1851*5129Smarx TR_EVENT) {
18520Sstevel@tonic-gate fe.id =
1853*5129Smarx (kbdd->kbdd_compat ?
1854*5129Smarx ISO_FIRST :
1855*5129Smarx EUC_FIRST)
1856*5129Smarx + result_iso;
18570Sstevel@tonic-gate fe.value = 1;
18580Sstevel@tonic-gate kbdqueueevent(
1859*5129Smarx kbdd,
1860*5129Smarx &fe);
18610Sstevel@tonic-gate } else if (
1862*5129Smarx kbdd->kbdd_translate ==
1863*5129Smarx TR_ASCII)
18640Sstevel@tonic-gate kbdputcode(
1865*5129Smarx result_iso,
1866*5129Smarx q);
18670Sstevel@tonic-gate }
18680Sstevel@tonic-gate }
18690Sstevel@tonic-gate }
18700Sstevel@tonic-gate return;
18710Sstevel@tonic-gate } else if (k->k_state == FLTACCENT) {
18720Sstevel@tonic-gate if (newstate == RELEASED)
18730Sstevel@tonic-gate return;
18740Sstevel@tonic-gate k->k_state = NORMAL; /* next state is "normal" */
18750Sstevel@tonic-gate for (i = 0;
18760Sstevel@tonic-gate (kb_fltaccent_table[i].fa_entry
1877*5129Smarx != kbdd->fltaccent_entry) ||
18780Sstevel@tonic-gate (kb_fltaccent_table[i].ascii != entry);
18790Sstevel@tonic-gate i++) {
18800Sstevel@tonic-gate if (kb_fltaccent_table[i].fa_entry == 0)
18810Sstevel@tonic-gate /* Invalid second key: ignore key */
18820Sstevel@tonic-gate return;
18830Sstevel@tonic-gate }
18840Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT) {
18850Sstevel@tonic-gate fe.id = (kbdd->kbdd_compat ?
1886*5129Smarx ISO_FIRST : EUC_FIRST)
1887*5129Smarx + kb_fltaccent_table[i].iso;
18880Sstevel@tonic-gate fe.value = 1;
18890Sstevel@tonic-gate kbdqueueevent(kbdd, &fe);
18900Sstevel@tonic-gate } else if (kbdd->kbdd_translate == TR_ASCII)
18910Sstevel@tonic-gate kbdputcode(kb_fltaccent_table[i].iso, q);
18920Sstevel@tonic-gate return;
18930Sstevel@tonic-gate }
18940Sstevel@tonic-gate }
18950Sstevel@tonic-gate
18960Sstevel@tonic-gate /*
18970Sstevel@tonic-gate * If the key is going down, and it's not one of the keys that doesn't
18980Sstevel@tonic-gate * auto-repeat, set up the auto-repeat timeout.
18990Sstevel@tonic-gate *
19000Sstevel@tonic-gate * The keys that don't auto-repeat are the Compose key,
19010Sstevel@tonic-gate * the shift keys, the "bucky bit" keys, the "floating accent" keys,
19020Sstevel@tonic-gate * and the function keys when in TR_EVENT mode.
19030Sstevel@tonic-gate */
19040Sstevel@tonic-gate if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) &&
19050Sstevel@tonic-gate entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) &&
19060Sstevel@tonic-gate entrytype != (FA_CLASS >> 8) &&
19070Sstevel@tonic-gate !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) &&
19080Sstevel@tonic-gate kbdd->kbdd_translate == TR_EVENT)) {
19090Sstevel@tonic-gate if (k->k_rptkey != keycode) {
19100Sstevel@tonic-gate kbdcancelrpt(kbdd);
19110Sstevel@tonic-gate kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd,
19120Sstevel@tonic-gate kbd_repeatdelay);
19130Sstevel@tonic-gate k->k_rptkey = keycode;
19140Sstevel@tonic-gate }
19150Sstevel@tonic-gate } else if (key == KEYOF(k->k_rptkey)) /* key going up */
19160Sstevel@tonic-gate kbdcancelrpt(kbdd);
19170Sstevel@tonic-gate if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT))
19180Sstevel@tonic-gate kbdkeyreleased(kbdd, key);
19190Sstevel@tonic-gate
19200Sstevel@tonic-gate /*
19210Sstevel@tonic-gate * We assume here that keys other than shift keys and bucky keys have
19220Sstevel@tonic-gate * entries in the "up" table that cause nothing to be done, and thus we
19230Sstevel@tonic-gate * don't have to check for newstate == RELEASED.
19240Sstevel@tonic-gate */
19250Sstevel@tonic-gate switch (entrytype) {
19260Sstevel@tonic-gate
19270Sstevel@tonic-gate case 0x0: /* regular key */
19280Sstevel@tonic-gate switch (kbdd->kbdd_translate) {
19290Sstevel@tonic-gate
19300Sstevel@tonic-gate case TR_EVENT:
19310Sstevel@tonic-gate fe.id = entry | k->k_buckybits;
19320Sstevel@tonic-gate fe.value = 1;
19330Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, entry);
19340Sstevel@tonic-gate break;
19350Sstevel@tonic-gate
19360Sstevel@tonic-gate case TR_ASCII:
19370Sstevel@tonic-gate kbdputcode(entry | k->k_buckybits, q);
19380Sstevel@tonic-gate break;
19390Sstevel@tonic-gate }
19400Sstevel@tonic-gate break;
19410Sstevel@tonic-gate
19420Sstevel@tonic-gate case SHIFTKEYS >> 8: {
19430Sstevel@tonic-gate uint_t shiftbit = 1 << (entry & 0x0F);
19440Sstevel@tonic-gate
19450Sstevel@tonic-gate /* Modify toggle state (see toggle processing above) */
19460Sstevel@tonic-gate if (shiftbit & k->k_curkeyboard->k_toggleshifts) {
19470Sstevel@tonic-gate if (newstate == RELEASED) {
19480Sstevel@tonic-gate if (shiftbit == CAPSMASK) {
19490Sstevel@tonic-gate kbdd->led_state &= ~LED_CAPS_LOCK;
19500Sstevel@tonic-gate kbdsetled(kbdd);
19510Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) {
19520Sstevel@tonic-gate kbdd->led_state &= ~LED_NUM_LOCK;
19530Sstevel@tonic-gate kbdsetled(kbdd);
19540Sstevel@tonic-gate }
19550Sstevel@tonic-gate k->k_togglemask &= ~shiftbit;
19560Sstevel@tonic-gate } else {
19570Sstevel@tonic-gate if (shiftbit == CAPSMASK) {
19580Sstevel@tonic-gate kbdd->led_state |= LED_CAPS_LOCK;
19590Sstevel@tonic-gate kbdsetled(kbdd);
19600Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) {
19610Sstevel@tonic-gate kbdd->led_state |= LED_NUM_LOCK;
19620Sstevel@tonic-gate kbdsetled(kbdd);
19630Sstevel@tonic-gate }
19640Sstevel@tonic-gate k->k_togglemask |= shiftbit;
19650Sstevel@tonic-gate }
19660Sstevel@tonic-gate }
19670Sstevel@tonic-gate
19680Sstevel@tonic-gate if (newstate == RELEASED)
19690Sstevel@tonic-gate k->k_shiftmask &= ~shiftbit;
19700Sstevel@tonic-gate else
19710Sstevel@tonic-gate k->k_shiftmask |= shiftbit;
19720Sstevel@tonic-gate
19730Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
19740Sstevel@tonic-gate /*
19750Sstevel@tonic-gate * Relying on ordinal correspondence between
19760Sstevel@tonic-gate * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
19770Sstevel@tonic-gate * kbd.h CAPSLOCK-RIGHTCTRL in order to
19780Sstevel@tonic-gate * correctly translate entry into fe.id.
19790Sstevel@tonic-gate */
19800Sstevel@tonic-gate fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
19810Sstevel@tonic-gate fe.value = 1;
19820Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id);
19830Sstevel@tonic-gate }
19840Sstevel@tonic-gate break;
19850Sstevel@tonic-gate }
19860Sstevel@tonic-gate
19870Sstevel@tonic-gate case BUCKYBITS >> 8:
19880Sstevel@tonic-gate k->k_buckybits ^= 1 << (7 + (entry & 0x0F));
19890Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
19900Sstevel@tonic-gate /*
19910Sstevel@tonic-gate * Relying on ordinal correspondence between
19920Sstevel@tonic-gate * vuid_event.h SHIFT_META-SHIFT_TOP &
19930Sstevel@tonic-gate * kbd.h METABIT-SYSTEMBIT in order to
19940Sstevel@tonic-gate * correctly translate entry into fe.id.
19950Sstevel@tonic-gate */
19960Sstevel@tonic-gate fe.id = SHIFT_META + (entry & 0x0F);
19970Sstevel@tonic-gate fe.value = 1;
19980Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id);
19990Sstevel@tonic-gate }
20000Sstevel@tonic-gate break;
20010Sstevel@tonic-gate
20020Sstevel@tonic-gate case FUNNY >> 8:
20030Sstevel@tonic-gate switch (entry) {
20040Sstevel@tonic-gate case NOP:
20050Sstevel@tonic-gate break;
20060Sstevel@tonic-gate
20070Sstevel@tonic-gate case IDLE:
20080Sstevel@tonic-gate /* Fall thru into RESET code */
20090Sstevel@tonic-gate /* FALLTHRU */
20100Sstevel@tonic-gate case RESET:
20110Sstevel@tonic-gate gotreset:
20120Sstevel@tonic-gate k->k_shiftmask &= k->k_curkeyboard->k_idleshifts;
20130Sstevel@tonic-gate k->k_shiftmask |= k->k_togglemask;
20140Sstevel@tonic-gate k->k_buckybits &= k->k_curkeyboard->k_idlebuckys;
20150Sstevel@tonic-gate kbdcancelrpt(kbdd);
20160Sstevel@tonic-gate kbdreleaseall(kbdd);
20170Sstevel@tonic-gate break;
20180Sstevel@tonic-gate
20190Sstevel@tonic-gate case ERROR:
20200Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Error detected");
20210Sstevel@tonic-gate goto gotreset;
20220Sstevel@tonic-gate
20230Sstevel@tonic-gate case COMPOSE:
20240Sstevel@tonic-gate k->k_state = COMPOSE1;
20250Sstevel@tonic-gate kbdd->led_state |= LED_COMPOSE;
20260Sstevel@tonic-gate kbdsetled(kbdd);
20270Sstevel@tonic-gate break;
20280Sstevel@tonic-gate /*
20290Sstevel@tonic-gate * Remember when adding new entries that,
20300Sstevel@tonic-gate * if they should NOT auto-repeat,
20310Sstevel@tonic-gate * they should be put into the IF statement
20320Sstevel@tonic-gate * just above this switch block.
20330Sstevel@tonic-gate */
20340Sstevel@tonic-gate default:
20350Sstevel@tonic-gate goto badentry;
20360Sstevel@tonic-gate }
20370Sstevel@tonic-gate break;
20380Sstevel@tonic-gate
20390Sstevel@tonic-gate case FA_CLASS >> 8:
20400Sstevel@tonic-gate if (k->k_state == NORMAL) {
20410Sstevel@tonic-gate kbdd->fltaccent_entry = entry;
20420Sstevel@tonic-gate k->k_state = FLTACCENT;
20430Sstevel@tonic-gate }
20440Sstevel@tonic-gate return;
20450Sstevel@tonic-gate
20460Sstevel@tonic-gate case STRING >> 8:
20470Sstevel@tonic-gate cp = &keystringtab[entry & 0x0F][0];
20480Sstevel@tonic-gate while (*cp != '\0') {
20490Sstevel@tonic-gate switch (kbdd->kbdd_translate) {
20500Sstevel@tonic-gate
20510Sstevel@tonic-gate case TR_EVENT:
20520Sstevel@tonic-gate kbd_send_esc_event(*cp, kbdd);
20530Sstevel@tonic-gate break;
20540Sstevel@tonic-gate
20550Sstevel@tonic-gate case TR_ASCII:
20560Sstevel@tonic-gate kbdputcode((uchar_t)*cp, q);
20570Sstevel@tonic-gate break;
20580Sstevel@tonic-gate }
20590Sstevel@tonic-gate cp++;
20600Sstevel@tonic-gate }
20610Sstevel@tonic-gate break;
20620Sstevel@tonic-gate
20630Sstevel@tonic-gate case FUNCKEYS >> 8:
20640Sstevel@tonic-gate switch (kbdd->kbdd_translate) {
20650Sstevel@tonic-gate
20660Sstevel@tonic-gate case TR_ASCII:
20670Sstevel@tonic-gate bufp = buf;
20680Sstevel@tonic-gate cp = strsetwithdecimal(bufp + 2,
2069*5129Smarx (uint_t)((entry & 0x003F) + 192),
2070*5129Smarx sizeof (buf) - 5);
20710Sstevel@tonic-gate *bufp++ = '\033'; /* Escape */
20720Sstevel@tonic-gate *bufp++ = '[';
20730Sstevel@tonic-gate while (*cp != '\0')
20740Sstevel@tonic-gate *bufp++ = *cp++;
20750Sstevel@tonic-gate *bufp++ = 'z';
20760Sstevel@tonic-gate *bufp = '\0';
20770Sstevel@tonic-gate kbdputbuf(buf, q);
20780Sstevel@tonic-gate break;
20790Sstevel@tonic-gate
20800Sstevel@tonic-gate case TR_EVENT:
20810Sstevel@tonic-gate /*
20820Sstevel@tonic-gate * Take advantage of the similar
20830Sstevel@tonic-gate * ordering of kbd.h function keys and
20840Sstevel@tonic-gate * vuid_event.h function keys to do a
20850Sstevel@tonic-gate * simple translation to achieve a
20860Sstevel@tonic-gate * mapping between the 2 different
20870Sstevel@tonic-gate * address spaces.
20880Sstevel@tonic-gate */
20890Sstevel@tonic-gate fe.id = (entry & 0x003F) + KEY_LEFTFIRST;
20900Sstevel@tonic-gate fe.value = 1;
20910Sstevel@tonic-gate /*
20920Sstevel@tonic-gate * Assume "up" table only generates
20930Sstevel@tonic-gate * shift changes.
20940Sstevel@tonic-gate */
20950Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id);
20960Sstevel@tonic-gate /*
20970Sstevel@tonic-gate * Function key events can be expanded
20980Sstevel@tonic-gate * by terminal emulator software to
20990Sstevel@tonic-gate * produce the standard escape sequence
21000Sstevel@tonic-gate * generated by the TR_ASCII case above
21010Sstevel@tonic-gate * if a function key event is not used
21020Sstevel@tonic-gate * by terminal emulator software
21030Sstevel@tonic-gate * directly.
21040Sstevel@tonic-gate */
21050Sstevel@tonic-gate break;
21060Sstevel@tonic-gate }
21070Sstevel@tonic-gate break;
21080Sstevel@tonic-gate
21090Sstevel@tonic-gate /*
21100Sstevel@tonic-gate * Remember when adding new entries that,
21110Sstevel@tonic-gate * if they should NOT auto-repeat,
21120Sstevel@tonic-gate * they should be put into the IF statement
21130Sstevel@tonic-gate * just above this switch block.
21140Sstevel@tonic-gate */
21150Sstevel@tonic-gate case PADKEYS >> 8:
21160Sstevel@tonic-gate switch (kbdd->kbdd_translate) {
21170Sstevel@tonic-gate
21180Sstevel@tonic-gate case TR_ASCII:
21190Sstevel@tonic-gate kbdputcode(kb_numlock_table[entry&0x1F], q);
21200Sstevel@tonic-gate break;
21210Sstevel@tonic-gate
21220Sstevel@tonic-gate case TR_EVENT:
21230Sstevel@tonic-gate /*
21240Sstevel@tonic-gate * Take advantage of the similar
21250Sstevel@tonic-gate * ordering of kbd.h keypad keys and
21260Sstevel@tonic-gate * vuid_event.h keypad keys to do a
21270Sstevel@tonic-gate * simple translation to achieve a
21280Sstevel@tonic-gate * mapping between the 2 different
21290Sstevel@tonic-gate * address spaces.
21300Sstevel@tonic-gate */
21310Sstevel@tonic-gate fe.id = (entry & 0x001F) + VKEY_FIRSTPAD;
21320Sstevel@tonic-gate fe.value = 1;
21330Sstevel@tonic-gate /*
21340Sstevel@tonic-gate * Assume "up" table only generates
21350Sstevel@tonic-gate * shift changes.
21360Sstevel@tonic-gate */
21370Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id);
21380Sstevel@tonic-gate /*
21390Sstevel@tonic-gate * Keypad key events can be expanded
21400Sstevel@tonic-gate * by terminal emulator software to
21410Sstevel@tonic-gate * produce the standard ascii character
21420Sstevel@tonic-gate * generated by the TR_ASCII case above
21430Sstevel@tonic-gate * if a keypad key event is not used
21440Sstevel@tonic-gate * by terminal emulator software
21450Sstevel@tonic-gate * directly.
21460Sstevel@tonic-gate */
21470Sstevel@tonic-gate break;
21480Sstevel@tonic-gate }
21490Sstevel@tonic-gate
21500Sstevel@tonic-gate badentry:
21510Sstevel@tonic-gate break;
21520Sstevel@tonic-gate }
21530Sstevel@tonic-gate }
21540Sstevel@tonic-gate
21550Sstevel@tonic-gate static int
kbd_do_compose(ushort_t first_entry,ushort_t second_entry,ushort_t * result_iso_ptr)21560Sstevel@tonic-gate kbd_do_compose(ushort_t first_entry, ushort_t second_entry,
21570Sstevel@tonic-gate ushort_t *result_iso_ptr)
21580Sstevel@tonic-gate {
21590Sstevel@tonic-gate struct compose_sequence_t *ptr;
21600Sstevel@tonic-gate
21610Sstevel@tonic-gate ptr = &kb_compose_table[kb_compose_map[first_entry]];
21620Sstevel@tonic-gate while (ptr->first == first_entry) {
21630Sstevel@tonic-gate if (ptr->second == second_entry) {
21640Sstevel@tonic-gate *result_iso_ptr = ptr->iso;
21650Sstevel@tonic-gate return (1);
21660Sstevel@tonic-gate }
21670Sstevel@tonic-gate ptr++;
21680Sstevel@tonic-gate }
21690Sstevel@tonic-gate return (0);
21700Sstevel@tonic-gate }
21710Sstevel@tonic-gate
21720Sstevel@tonic-gate static void
kbd_send_esc_event(char c,register struct kbddata * kbdd)21730Sstevel@tonic-gate kbd_send_esc_event(char c, register struct kbddata *kbdd)
21740Sstevel@tonic-gate {
21750Sstevel@tonic-gate Firm_event fe;
21760Sstevel@tonic-gate
21770Sstevel@tonic-gate fe.id = c;
21780Sstevel@tonic-gate fe.value = 1;
21790Sstevel@tonic-gate fe.pair_type = FE_PAIR_NONE;
21800Sstevel@tonic-gate fe.pair = 0;
21810Sstevel@tonic-gate /*
21820Sstevel@tonic-gate * Pretend as if each cp pushed and released
21830Sstevel@tonic-gate * Calling kbdqueueevent avoids addr translation
21840Sstevel@tonic-gate * and pair base determination of kbdkeypressed.
21850Sstevel@tonic-gate */
21860Sstevel@tonic-gate kbdqueueevent(kbdd, &fe);
21870Sstevel@tonic-gate fe.value = 0;
21880Sstevel@tonic-gate kbdqueueevent(kbdd, &fe);
21890Sstevel@tonic-gate }
21900Sstevel@tonic-gate
21910Sstevel@tonic-gate char *
strsetwithdecimal(char * buf,uint_t val,uint_t maxdigs)21920Sstevel@tonic-gate strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
21930Sstevel@tonic-gate {
21940Sstevel@tonic-gate int hradix = 5;
21950Sstevel@tonic-gate char *bp;
21960Sstevel@tonic-gate int lowbit;
21970Sstevel@tonic-gate char *tab = "0123456789abcdef";
21980Sstevel@tonic-gate
21990Sstevel@tonic-gate bp = buf + maxdigs;
22000Sstevel@tonic-gate *(--bp) = '\0';
22010Sstevel@tonic-gate while (val) {
22020Sstevel@tonic-gate lowbit = val & 1;
22030Sstevel@tonic-gate val = (val >> 1);
22040Sstevel@tonic-gate *(--bp) = tab[val % hradix * 2 + lowbit];
22050Sstevel@tonic-gate val /= hradix;
22060Sstevel@tonic-gate }
22070Sstevel@tonic-gate return (bp);
22080Sstevel@tonic-gate }
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate static void
kbdkeypressed(struct kbddata * kbdd,uchar_t key_station,Firm_event * fe,ushort_t base)22110Sstevel@tonic-gate kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe,
22120Sstevel@tonic-gate ushort_t base)
22130Sstevel@tonic-gate {
22140Sstevel@tonic-gate register struct keyboardstate *k;
22150Sstevel@tonic-gate register short id_addr;
22160Sstevel@tonic-gate
22170Sstevel@tonic-gate /* Set pair values */
22180Sstevel@tonic-gate if (fe->id < (ushort_t)VKEY_FIRST) {
22190Sstevel@tonic-gate /*
22200Sstevel@tonic-gate * If CTRLed, find the ID that would have been used had it
22210Sstevel@tonic-gate * not been CTRLed.
22220Sstevel@tonic-gate */
22230Sstevel@tonic-gate k = &kbdd->kbdd_state;
22240Sstevel@tonic-gate if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) {
22250Sstevel@tonic-gate struct keymap *km;
22260Sstevel@tonic-gate
22270Sstevel@tonic-gate km = settable(kbdd,
22280Sstevel@tonic-gate k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK));
22290Sstevel@tonic-gate if (km == NULL)
22300Sstevel@tonic-gate return;
22310Sstevel@tonic-gate base = km->keymap[key_station];
22320Sstevel@tonic-gate }
22330Sstevel@tonic-gate if (base != fe->id) {
22340Sstevel@tonic-gate fe->pair_type = FE_PAIR_SET;
22350Sstevel@tonic-gate fe->pair = base;
22360Sstevel@tonic-gate goto send;
22370Sstevel@tonic-gate }
22380Sstevel@tonic-gate }
22390Sstevel@tonic-gate fe->pair_type = FE_PAIR_NONE;
22400Sstevel@tonic-gate fe->pair = 0;
22410Sstevel@tonic-gate send:
22420Sstevel@tonic-gate /* Adjust event id address for multiple keyboard/workstation support */
22430Sstevel@tonic-gate switch (vuid_id_addr(fe->id)) {
22440Sstevel@tonic-gate case ASCII_FIRST:
22450Sstevel@tonic-gate id_addr = kbdd->kbdd_ascii_addr;
22460Sstevel@tonic-gate break;
22470Sstevel@tonic-gate case TOP_FIRST:
22480Sstevel@tonic-gate id_addr = kbdd->kbdd_top_addr;
22490Sstevel@tonic-gate break;
22500Sstevel@tonic-gate case VKEY_FIRST:
22510Sstevel@tonic-gate id_addr = kbdd->kbdd_vkey_addr;
22520Sstevel@tonic-gate break;
22530Sstevel@tonic-gate default:
22540Sstevel@tonic-gate id_addr = vuid_id_addr(fe->id);
22550Sstevel@tonic-gate }
22560Sstevel@tonic-gate fe->id = vuid_id_offset(fe->id) | id_addr;
22570Sstevel@tonic-gate kbdqueuepress(kbdd, key_station, fe);
22580Sstevel@tonic-gate }
22590Sstevel@tonic-gate
22600Sstevel@tonic-gate static void
kbdqueuepress(struct kbddata * kbdd,uchar_t key_station,Firm_event * fe)22610Sstevel@tonic-gate kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe)
22620Sstevel@tonic-gate {
22630Sstevel@tonic-gate register struct key_event *ke, *ke_free;
22640Sstevel@tonic-gate register int i;
22650Sstevel@tonic-gate
22660Sstevel@tonic-gate if (key_station == IDLEKEY)
22670Sstevel@tonic-gate return;
22680Sstevel@tonic-gate #ifdef KBD_DEBUG
22690Sstevel@tonic-gate if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station);
22700Sstevel@tonic-gate #endif
22710Sstevel@tonic-gate ke_free = 0;
22720Sstevel@tonic-gate /* Scan table of down key stations */
22730Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT ||
22740Sstevel@tonic-gate kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
22750Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs;
22760Sstevel@tonic-gate i < kbdd->kbdd_downs_entries;
22770Sstevel@tonic-gate i++, ke++) {
22780Sstevel@tonic-gate /* Keycode already down? */
22790Sstevel@tonic-gate if (ke->key_station == key_station) {
22800Sstevel@tonic-gate #ifdef KBD_DEBUG
22810Sstevel@tonic-gate printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i);
22820Sstevel@tonic-gate #endif
22830Sstevel@tonic-gate goto add_event;
22840Sstevel@tonic-gate }
22850Sstevel@tonic-gate if (ke->key_station == 0)
22860Sstevel@tonic-gate ke_free = ke;
22870Sstevel@tonic-gate }
22880Sstevel@tonic-gate if (ke_free) {
22890Sstevel@tonic-gate ke = ke_free;
22900Sstevel@tonic-gate goto add_event;
22910Sstevel@tonic-gate }
22920Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Too many keys down!");
22930Sstevel@tonic-gate ke = kbdd->kbdd_downs;
22940Sstevel@tonic-gate }
22950Sstevel@tonic-gate add_event:
22960Sstevel@tonic-gate ke->key_station = key_station;
22970Sstevel@tonic-gate ke->event = *fe;
22980Sstevel@tonic-gate kbdqueueevent(kbdd, fe);
22990Sstevel@tonic-gate }
23000Sstevel@tonic-gate
23010Sstevel@tonic-gate static void
kbdkeyreleased(register struct kbddata * kbdd,uchar_t key_station)23020Sstevel@tonic-gate kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station)
23030Sstevel@tonic-gate {
23040Sstevel@tonic-gate register struct key_event *ke;
23050Sstevel@tonic-gate register int i;
23060Sstevel@tonic-gate
23070Sstevel@tonic-gate if (key_station == IDLEKEY)
23080Sstevel@tonic-gate return;
23090Sstevel@tonic-gate #ifdef KBD_DEBUG
23100Sstevel@tonic-gate if (kbd_input_debug)
23110Sstevel@tonic-gate printf("KBD RELEASE key=%d\n", key_station);
23120Sstevel@tonic-gate #endif
23130Sstevel@tonic-gate if (kbdd->kbdd_translate != TR_EVENT &&
23140Sstevel@tonic-gate kbdd->kbdd_translate != TR_UNTRANS_EVENT)
23150Sstevel@tonic-gate return;
23160Sstevel@tonic-gate /* Scan table of down key stations */
23170Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs;
23180Sstevel@tonic-gate i < kbdd->kbdd_downs_entries;
23190Sstevel@tonic-gate i++, ke++) {
23200Sstevel@tonic-gate /* Found? */
23210Sstevel@tonic-gate if (ke->key_station == key_station) {
23220Sstevel@tonic-gate ke->key_station = 0;
23230Sstevel@tonic-gate ke->event.value = 0;
23240Sstevel@tonic-gate kbdqueueevent(kbdd, &ke->event);
23250Sstevel@tonic-gate }
23260Sstevel@tonic-gate }
23270Sstevel@tonic-gate
23280Sstevel@tonic-gate /*
23290Sstevel@tonic-gate * Ignore if couldn't find because may be called twice
23300Sstevel@tonic-gate * for the same key station in the case of the kbdrpt
23310Sstevel@tonic-gate * routine being called unnecessarily.
23320Sstevel@tonic-gate */
23330Sstevel@tonic-gate }
23340Sstevel@tonic-gate
23350Sstevel@tonic-gate static void
kbdreleaseall(struct kbddata * kbdd)23360Sstevel@tonic-gate kbdreleaseall(struct kbddata *kbdd)
23370Sstevel@tonic-gate {
23380Sstevel@tonic-gate register struct key_event *ke;
23390Sstevel@tonic-gate register int i;
23400Sstevel@tonic-gate
23410Sstevel@tonic-gate #ifdef KBD_DEBUG
23420Sstevel@tonic-gate if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n");
23430Sstevel@tonic-gate #endif
23440Sstevel@tonic-gate /* Scan table of down key stations */
23450Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs;
23460Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; i++, ke++) {
23470Sstevel@tonic-gate /* Key station not zero */
23480Sstevel@tonic-gate if (ke->key_station)
23490Sstevel@tonic-gate kbdkeyreleased(kbdd, ke->key_station);
23500Sstevel@tonic-gate /* kbdkeyreleased resets kbdd_downs entry */
23510Sstevel@tonic-gate }
23520Sstevel@tonic-gate }
23530Sstevel@tonic-gate
23540Sstevel@tonic-gate /*
23550Sstevel@tonic-gate * Pass a keycode up the stream, if you can, otherwise throw it away.
23560Sstevel@tonic-gate */
23570Sstevel@tonic-gate static void
kbdputcode(uint_t code,queue_t * q)23580Sstevel@tonic-gate kbdputcode(uint_t code, queue_t *q)
23590Sstevel@tonic-gate {
23600Sstevel@tonic-gate register mblk_t *bp;
23610Sstevel@tonic-gate
23620Sstevel@tonic-gate if (!canput(q))
23630Sstevel@tonic-gate cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode");
23640Sstevel@tonic-gate else {
23650Sstevel@tonic-gate if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL)
23660Sstevel@tonic-gate cmn_err(CE_WARN,
23670Sstevel@tonic-gate "kbdputcode: Can't allocate block for keycode");
23680Sstevel@tonic-gate else {
23690Sstevel@tonic-gate *bp->b_wptr++ = code;
23700Sstevel@tonic-gate putnext(q, bp);
23710Sstevel@tonic-gate }
23720Sstevel@tonic-gate }
23730Sstevel@tonic-gate }
23740Sstevel@tonic-gate
23750Sstevel@tonic-gate /*
23760Sstevel@tonic-gate * Pass generated keycode sequence to upstream, if possible.
23770Sstevel@tonic-gate */
23780Sstevel@tonic-gate static void
kbdputbuf(char * buf,queue_t * q)23790Sstevel@tonic-gate kbdputbuf(char *buf, queue_t *q)
23800Sstevel@tonic-gate {
23810Sstevel@tonic-gate register mblk_t *bp;
23820Sstevel@tonic-gate
23830Sstevel@tonic-gate if (!canput(q))
23840Sstevel@tonic-gate cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode");
23850Sstevel@tonic-gate else {
23860Sstevel@tonic-gate if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL)
23870Sstevel@tonic-gate cmn_err(CE_WARN,
2388*5129Smarx "kbdputbuf: Can't allocate block for keycode");
23890Sstevel@tonic-gate else {
23900Sstevel@tonic-gate while (*buf) {
23910Sstevel@tonic-gate *bp->b_wptr++ = *buf;
23920Sstevel@tonic-gate buf++;
23930Sstevel@tonic-gate }
23940Sstevel@tonic-gate putnext(q, bp);
23950Sstevel@tonic-gate }
23960Sstevel@tonic-gate }
23970Sstevel@tonic-gate }
23980Sstevel@tonic-gate
23990Sstevel@tonic-gate /*
24000Sstevel@tonic-gate * Pass a VUID "firm event" up the stream, if you can.
24010Sstevel@tonic-gate */
24020Sstevel@tonic-gate static void
kbdqueueevent(struct kbddata * kbdd,Firm_event * fe)24030Sstevel@tonic-gate kbdqueueevent(struct kbddata *kbdd, Firm_event *fe)
24040Sstevel@tonic-gate {
24050Sstevel@tonic-gate register queue_t *q;
24060Sstevel@tonic-gate register mblk_t *bp;
24070Sstevel@tonic-gate
24080Sstevel@tonic-gate if ((q = kbdd->kbdd_readq) == NULL)
24090Sstevel@tonic-gate return;
24100Sstevel@tonic-gate if (!canput(q)) {
24110Sstevel@tonic-gate if (kbd_overflow_msg)
24120Sstevel@tonic-gate cmn_err(CE_WARN,
2413*5129Smarx "kbd: Buffer flushed when overflowed");
24140Sstevel@tonic-gate kbdflush(kbdd);
24150Sstevel@tonic-gate kbd_overflow_cnt++;
24160Sstevel@tonic-gate } else {
24170Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL)
24180Sstevel@tonic-gate cmn_err(CE_WARN,
24190Sstevel@tonic-gate "kbdqueueevent: Can't allocate block for event");
24200Sstevel@tonic-gate else {
24210Sstevel@tonic-gate #if 1 /* XX64 */
24220Sstevel@tonic-gate struct timeval now;
24230Sstevel@tonic-gate
24240Sstevel@tonic-gate /*
24250Sstevel@tonic-gate * XX64: This is something of a compromise. It
24260Sstevel@tonic-gate * seems justifiable based on the usage of these
24270Sstevel@tonic-gate * timestamps as an ordering relation as opposed
24280Sstevel@tonic-gate * to a strict timing thing.
24290Sstevel@tonic-gate *
24300Sstevel@tonic-gate * But should we restore Firm_event's time stamp
24310Sstevel@tonic-gate * to be a timeval, and send 32-bit and 64-bit
24320Sstevel@tonic-gate * events up the pipe?
24330Sstevel@tonic-gate */
24340Sstevel@tonic-gate uniqtime(&now);
24350Sstevel@tonic-gate TIMEVAL_TO_TIMEVAL32(&fe->time, &now);
24360Sstevel@tonic-gate #else
24370Sstevel@tonic-gate uniqtime(&fe->time);
24380Sstevel@tonic-gate #endif
24390Sstevel@tonic-gate *(Firm_event *)bp->b_wptr = *fe;
24400Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event);
24410Sstevel@tonic-gate putnext(q, bp);
24420Sstevel@tonic-gate }
24430Sstevel@tonic-gate }
24440Sstevel@tonic-gate }
2445