17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5e4603304Sqz150045 * Common Development and Distribution License (the "License"). 6e4603304Sqz150045 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22e4603304Sqz150045 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate /* SunOS-4.0 1.60 */ 287c478bd9Sstevel@tonic-gate /* From: SunOS4.0 sundev/kbd.c */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Keyboard input streams module - handles conversion of up/down codes to 327c478bd9Sstevel@tonic-gate * ASCII or event format. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/param.h> 367c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 377c478bd9Sstevel@tonic-gate #include <sys/signal.h> 387c478bd9Sstevel@tonic-gate #include <sys/termios.h> 397c478bd9Sstevel@tonic-gate #include <sys/termio.h> 407c478bd9Sstevel@tonic-gate #include <sys/stream.h> 417c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 427c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 437c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 447c478bd9Sstevel@tonic-gate #include <sys/file.h> 457c478bd9Sstevel@tonic-gate #include <sys/uio.h> 467c478bd9Sstevel@tonic-gate #include <sys/errno.h> 477c478bd9Sstevel@tonic-gate #include <sys/time.h> 487c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 497c478bd9Sstevel@tonic-gate #include <sys/kbd.h> 507c478bd9Sstevel@tonic-gate #include <sys/kbio.h> 517c478bd9Sstevel@tonic-gate #include <sys/kbdreg.h> 527c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h> 537c478bd9Sstevel@tonic-gate #include <sys/debug.h> 547c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 557c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 567c478bd9Sstevel@tonic-gate #include <sys/policy.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static struct streamtab kbd_info; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate static struct fmodsw fsw = { 637c478bd9Sstevel@tonic-gate "kb", 647c478bd9Sstevel@tonic-gate &kbd_info, 657c478bd9Sstevel@tonic-gate D_MP | D_MTPERMOD 667c478bd9Sstevel@tonic-gate }; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 737c478bd9Sstevel@tonic-gate &mod_strmodops, "streams module for keyboard", &fsw 747c478bd9Sstevel@tonic-gate }; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 777c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlstrmod, NULL 787c478bd9Sstevel@tonic-gate }; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate int 817c478bd9Sstevel@tonic-gate _init(void) 827c478bd9Sstevel@tonic-gate { 837c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate int 877c478bd9Sstevel@tonic-gate _fini(void) 887c478bd9Sstevel@tonic-gate { 897c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate int 937c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * For now these are shared. 1007c478bd9Sstevel@tonic-gate * These data structures are static (defined in keytables.c) thus 1017c478bd9Sstevel@tonic-gate * there is no need to perform any locking. 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate extern struct keyboards keytables[]; 1047c478bd9Sstevel@tonic-gate extern char keystringtab[16][KTAB_STRLEN]; 1057c478bd9Sstevel@tonic-gate extern struct compose_sequence_t kb_compose_table[]; 1067c478bd9Sstevel@tonic-gate extern signed char kb_compose_map[]; 1077c478bd9Sstevel@tonic-gate extern struct fltaccent_sequence_t kb_fltaccent_table[]; 1087c478bd9Sstevel@tonic-gate extern uchar_t kb_numlock_table[]; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* 1117c478bd9Sstevel@tonic-gate * This value corresponds approximately to max 10 fingers 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate static int kbd_downs_size = 15; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate typedef struct key_event { 1167c478bd9Sstevel@tonic-gate uchar_t key_station; /* Physical key station associated with event */ 1177c478bd9Sstevel@tonic-gate Firm_event event; /* Event that sent out on down */ 1187c478bd9Sstevel@tonic-gate } Key_event; 1197c478bd9Sstevel@tonic-gate struct kbddata { 1207c478bd9Sstevel@tonic-gate queue_t *kbdd_readq; 1217c478bd9Sstevel@tonic-gate queue_t *kbdd_writeq; 1227c478bd9Sstevel@tonic-gate mblk_t *kbdd_iocpending; /* "ioctl" awaiting buffer */ 1237c478bd9Sstevel@tonic-gate mblk_t *kbdd_replypending; /* "ioctl" reply awaiting result */ 1247c478bd9Sstevel@tonic-gate int kbdd_flags; /* random flags */ 1257c478bd9Sstevel@tonic-gate bufcall_id_t kbdd_bufcallid; /* bufcall id */ 1267c478bd9Sstevel@tonic-gate timeout_id_t kbdd_rptid; /* timeout id for kbdrpt() */ 1277c478bd9Sstevel@tonic-gate timeout_id_t kbdd_layoutid; /* timeout id for kbdlayout() */ 1287c478bd9Sstevel@tonic-gate int kbdd_iocid; /* ID of "ioctl" being waited for */ 1297c478bd9Sstevel@tonic-gate int kbdd_iocerror; /* error return from "ioctl" */ 1307c478bd9Sstevel@tonic-gate struct keyboardstate kbdd_state; 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * State of keyboard & keyboard 1337c478bd9Sstevel@tonic-gate * specific settings, e.g., tables 1347c478bd9Sstevel@tonic-gate */ 1357c478bd9Sstevel@tonic-gate int kbdd_translate; /* Translate keycodes? */ 1367c478bd9Sstevel@tonic-gate int kbdd_translatable; /* Keyboard is translatable? */ 1377c478bd9Sstevel@tonic-gate int kbdd_compat; /* Generating pre-4.1 events? */ 1387c478bd9Sstevel@tonic-gate short kbdd_ascii_addr; /* Vuid_id_addr for ascii events */ 1397c478bd9Sstevel@tonic-gate short kbdd_top_addr; /* Vuid_id_addr for top events */ 1407c478bd9Sstevel@tonic-gate short kbdd_vkey_addr; /* Vuid_id_addr for vkey events */ 1417c478bd9Sstevel@tonic-gate struct key_event *kbdd_downs; 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Table of key stations currently down 1447c478bd9Sstevel@tonic-gate * that have firm events that need 1457c478bd9Sstevel@tonic-gate * to be matched with up transitions 1467c478bd9Sstevel@tonic-gate * when kbdd_translate is TR_*EVENT 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate int kbdd_downs_entries; /* # of possible entries in kbdd_downs */ 1497c478bd9Sstevel@tonic-gate uint_t kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */ 1507c478bd9Sstevel@tonic-gate ushort_t compose_key; /* first compose key */ 1517c478bd9Sstevel@tonic-gate ushort_t fltaccent_entry; /* floating accent keymap entry */ 1527c478bd9Sstevel@tonic-gate char led_state; /* current state of LEDs */ 153*b05bac8eSqz150045 unsigned char shiftkey; /* used for the new abort keys */ 1547c478bd9Sstevel@tonic-gate }; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate #define KBD_OPEN 0x00000001 /* keyboard is open for business */ 1577c478bd9Sstevel@tonic-gate #define KBD_IOCWAIT 0x00000002 /* "open" waiting for "ioctl" to finish */ 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate #define NO_HARD_RESET 0 /* don't do hard reset */ 1607c478bd9Sstevel@tonic-gate #define HARD_RESET 1 /* do hard reset */ 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate /* 1647c478bd9Sstevel@tonic-gate * Constants setup during the first open of a kbd (so that they can be patched 1657c478bd9Sstevel@tonic-gate * for debugging purposes). 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate static int kbd_repeatrate; 1687c478bd9Sstevel@tonic-gate static int kbd_repeatdelay; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate static int kbd_overflow_cnt; /* Number of times kbd overflowed input q */ 1717c478bd9Sstevel@tonic-gate static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */ 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 1747c478bd9Sstevel@tonic-gate int kbd_debug = 0; 1757c478bd9Sstevel@tonic-gate int kbd_ra_debug = 0; 1767c478bd9Sstevel@tonic-gate int kbd_raw_debug = 0; 1777c478bd9Sstevel@tonic-gate int kbd_rpt_debug = 0; 1787c478bd9Sstevel@tonic-gate int kbd_input_debug = 0; 1797c478bd9Sstevel@tonic-gate #endif /* KBD_DEBUG */ 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate static int kbdopen(queue_t *, dev_t *, int, int, cred_t *); 1827c478bd9Sstevel@tonic-gate static int kbdclose(queue_t *, int, cred_t *); 1837c478bd9Sstevel@tonic-gate static void kbdwput(queue_t *, mblk_t *); 1847c478bd9Sstevel@tonic-gate static void kbdrput(queue_t *, mblk_t *); 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate static struct module_info kbdmiinfo = { 1877c478bd9Sstevel@tonic-gate 0, 1887c478bd9Sstevel@tonic-gate "kb", 1897c478bd9Sstevel@tonic-gate 0, 1907c478bd9Sstevel@tonic-gate INFPSZ, 1917c478bd9Sstevel@tonic-gate 2048, 1927c478bd9Sstevel@tonic-gate 128 1937c478bd9Sstevel@tonic-gate }; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate static struct qinit kbdrinit = { 1967c478bd9Sstevel@tonic-gate (int (*)())kbdrput, 1977c478bd9Sstevel@tonic-gate (int (*)())NULL, 1987c478bd9Sstevel@tonic-gate kbdopen, 1997c478bd9Sstevel@tonic-gate kbdclose, 2007c478bd9Sstevel@tonic-gate (int (*)())NULL, 2017c478bd9Sstevel@tonic-gate &kbdmiinfo 2027c478bd9Sstevel@tonic-gate }; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate static struct module_info kbdmoinfo = { 2057c478bd9Sstevel@tonic-gate 0, 2067c478bd9Sstevel@tonic-gate "kb", 2077c478bd9Sstevel@tonic-gate 0, 2087c478bd9Sstevel@tonic-gate INFPSZ, 2097c478bd9Sstevel@tonic-gate 2048, 2107c478bd9Sstevel@tonic-gate 128 2117c478bd9Sstevel@tonic-gate }; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate static struct qinit kbdwinit = { 2147c478bd9Sstevel@tonic-gate (int (*)())kbdwput, 2157c478bd9Sstevel@tonic-gate (int (*)())NULL, 2167c478bd9Sstevel@tonic-gate kbdopen, 2177c478bd9Sstevel@tonic-gate kbdclose, 2187c478bd9Sstevel@tonic-gate (int (*)())NULL, 2197c478bd9Sstevel@tonic-gate &kbdmoinfo 2207c478bd9Sstevel@tonic-gate }; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate static struct streamtab kbd_info = { 2237c478bd9Sstevel@tonic-gate &kbdrinit, 2247c478bd9Sstevel@tonic-gate &kbdwinit, 2257c478bd9Sstevel@tonic-gate NULL, 2267c478bd9Sstevel@tonic-gate NULL, 2277c478bd9Sstevel@tonic-gate }; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate static void kbdreioctl(void *); 2307c478bd9Sstevel@tonic-gate static void kbdioctl(queue_t *, mblk_t *); 2317c478bd9Sstevel@tonic-gate static void kbdflush(struct kbddata *); 2327c478bd9Sstevel@tonic-gate static void kbduse(struct kbddata *, unsigned); 2337c478bd9Sstevel@tonic-gate static void kbdsetled(struct kbddata *); 2347c478bd9Sstevel@tonic-gate static void kbdcmd(queue_t *, char); 2357c478bd9Sstevel@tonic-gate static void kbdreset(struct kbddata *, uint_t); 2367c478bd9Sstevel@tonic-gate static int kbdsetkey(struct kbddata *, struct kiockey *, cred_t *); 2377c478bd9Sstevel@tonic-gate static int kbdgetkey(struct kbddata *, struct kiockey *); 2387c478bd9Sstevel@tonic-gate static int kbdskey(struct kbddata *, struct kiockeymap *, cred_t *); 2397c478bd9Sstevel@tonic-gate static int kbdgkey(struct kbddata *, struct kiockeymap *); 2407c478bd9Sstevel@tonic-gate static void kbdlayouttimeout(void *); 2417c478bd9Sstevel@tonic-gate static void kbdinput(struct kbddata *, unsigned); 2427c478bd9Sstevel@tonic-gate static void kbdid(struct kbddata *, int); 2437c478bd9Sstevel@tonic-gate static struct keymap *settable(struct kbddata *, uint_t); 2447c478bd9Sstevel@tonic-gate static void kbdrpt(void *); 2457c478bd9Sstevel@tonic-gate static void kbdcancelrpt(struct kbddata *); 2467c478bd9Sstevel@tonic-gate static void kbdtranslate(struct kbddata *, unsigned, queue_t *); 2477c478bd9Sstevel@tonic-gate static int kbd_do_compose(ushort_t, ushort_t, ushort_t *); 2487c478bd9Sstevel@tonic-gate static void kbd_send_esc_event(char, struct kbddata *); 2497c478bd9Sstevel@tonic-gate char *strsetwithdecimal(char *, uint_t, uint_t); 2507c478bd9Sstevel@tonic-gate static void kbdkeypressed(struct kbddata *, uchar_t, Firm_event *, 2517c478bd9Sstevel@tonic-gate ushort_t); 2527c478bd9Sstevel@tonic-gate static void kbdqueuepress(struct kbddata *, uchar_t, Firm_event *); 2537c478bd9Sstevel@tonic-gate static void kbdkeyreleased(struct kbddata *, uchar_t); 2547c478bd9Sstevel@tonic-gate static void kbdreleaseall(struct kbddata *); 2557c478bd9Sstevel@tonic-gate static void kbdputcode(uint_t, queue_t *); 2567c478bd9Sstevel@tonic-gate static void kbdputbuf(char *, queue_t *); 2577c478bd9Sstevel@tonic-gate static void kbdqueueevent(struct kbddata *, Firm_event *); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * Dummy qbufcall callback routine used by open and close. 2617c478bd9Sstevel@tonic-gate * The framework will wake up qwait_sig when we return from 2627c478bd9Sstevel@tonic-gate * this routine (as part of leaving the perimeters.) 2637c478bd9Sstevel@tonic-gate * (The framework enters the perimeters before calling the qbufcall() callback 2647c478bd9Sstevel@tonic-gate * and leaves the perimeters after the callback routine has executed. The 2657c478bd9Sstevel@tonic-gate * framework performs an implicit wakeup of any thread in qwait/qwait_sig 2667c478bd9Sstevel@tonic-gate * when it leaves the perimeter. See qwait(9E).) 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2697c478bd9Sstevel@tonic-gate static void dummy_callback(void *arg) 2707c478bd9Sstevel@tonic-gate {} 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * Open a keyboard. 2757c478bd9Sstevel@tonic-gate * Ttyopen sets line characteristics 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2787c478bd9Sstevel@tonic-gate static int 2797c478bd9Sstevel@tonic-gate kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate register int error; 2827c478bd9Sstevel@tonic-gate register struct kbddata *kbdd; 2837c478bd9Sstevel@tonic-gate mblk_t *mp; 2847c478bd9Sstevel@tonic-gate mblk_t *datap; 2857c478bd9Sstevel@tonic-gate register struct iocblk *iocb; 2867c478bd9Sstevel@tonic-gate register struct termios *cb; 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* Set these up only once so that they could be changed from adb */ 2897c478bd9Sstevel@tonic-gate if (!kbd_repeatrate) { 2907c478bd9Sstevel@tonic-gate kbd_repeatrate = (hz+29)/30; 2917c478bd9Sstevel@tonic-gate kbd_repeatdelay = hz/2; 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL) 2957c478bd9Sstevel@tonic-gate return (0); /* already attached */ 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /* 2987c478bd9Sstevel@tonic-gate * Only allow open requests to succeed for privileged users. This 2997c478bd9Sstevel@tonic-gate * necessary to prevent users from pushing the "kb" module again 3007c478bd9Sstevel@tonic-gate * on the stream associated with /dev/kbd. 3017c478bd9Sstevel@tonic-gate */ 3027c478bd9Sstevel@tonic-gate if (secpolicy_console(crp) != 0) { 3037c478bd9Sstevel@tonic-gate return (EPERM); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate switch (sflag) { 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate case MODOPEN: 3107c478bd9Sstevel@tonic-gate break; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate case CLONEOPEN: 3137c478bd9Sstevel@tonic-gate return (EINVAL); /* No Bozos! */ 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* allocate keyboard */ 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP); 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* 3227c478bd9Sstevel@tonic-gate * Set up queue pointers, so that the "put" procedure will accept 3237c478bd9Sstevel@tonic-gate * the reply to the "ioctl" message we send down. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate q->q_ptr = kbdd; 3267c478bd9Sstevel@tonic-gate WR(q)->q_ptr = kbdd; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate qprocson(q); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * Setup tty modes. 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate while ((mp = mkiocb(TCSETSF)) == NULL) { 3347c478bd9Sstevel@tonic-gate timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI, 3357c478bd9Sstevel@tonic-gate dummy_callback, NULL); 3367c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) { 3377c478bd9Sstevel@tonic-gate qunbufcall(q, id); 3387c478bd9Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 3397c478bd9Sstevel@tonic-gate qprocsoff(q); 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate return (EINTR); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate while ((datap = allocb(sizeof (struct termios), BPRI_HI)) == 3457c478bd9Sstevel@tonic-gate NULL) { 3467c478bd9Sstevel@tonic-gate timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI, 3477c478bd9Sstevel@tonic-gate dummy_callback, NULL); 3487c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) { 3497c478bd9Sstevel@tonic-gate qunbufcall(q, id); 3507c478bd9Sstevel@tonic-gate freemsg(mp); 3517c478bd9Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 3527c478bd9Sstevel@tonic-gate qprocsoff(q); 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate return (EINTR); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate iocb = (struct iocblk *)mp->b_rptr; 3597c478bd9Sstevel@tonic-gate iocb->ioc_count = sizeof (struct termios); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate cb = (struct termios *)datap->b_rptr; 3627c478bd9Sstevel@tonic-gate cb->c_iflag = 0; 3637c478bd9Sstevel@tonic-gate cb->c_oflag = 0; 3647c478bd9Sstevel@tonic-gate cb->c_cflag = CREAD|CS8|B1200; 3657c478bd9Sstevel@tonic-gate cb->c_lflag = 0; 3667c478bd9Sstevel@tonic-gate bzero(cb->c_cc, NCCS); 3677c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (struct termios); 3687c478bd9Sstevel@tonic-gate mp->b_cont = datap; 3697c478bd9Sstevel@tonic-gate kbdd->kbdd_flags |= KBD_IOCWAIT; /* indicate that we're */ 3707c478bd9Sstevel@tonic-gate kbdd->kbdd_iocid = iocb->ioc_id; /* waiting for this response */ 3717c478bd9Sstevel@tonic-gate putnext(WR(q), mp); 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* 3747c478bd9Sstevel@tonic-gate * Now wait for it. Let our read queue put routine wake us up 3757c478bd9Sstevel@tonic-gate * when it arrives. 3767c478bd9Sstevel@tonic-gate */ 3777c478bd9Sstevel@tonic-gate while (kbdd->kbdd_flags & KBD_IOCWAIT) { 3787c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) { 3797c478bd9Sstevel@tonic-gate error = EINTR; 3807c478bd9Sstevel@tonic-gate goto error; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate if ((error = kbdd->kbdd_iocerror) != 0) 3847c478bd9Sstevel@tonic-gate goto error; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * Set up private data. 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate kbdd->kbdd_readq = q; 3907c478bd9Sstevel@tonic-gate kbdd->kbdd_writeq = WR(q); 3917c478bd9Sstevel@tonic-gate kbdd->kbdd_iocpending = NULL; 3927c478bd9Sstevel@tonic-gate kbdd->kbdd_translatable = TR_CAN; 3937c478bd9Sstevel@tonic-gate kbdd->kbdd_translate = TR_ASCII; 3947c478bd9Sstevel@tonic-gate kbdd->kbdd_compat = 1; 3957c478bd9Sstevel@tonic-gate kbdd->kbdd_ascii_addr = ASCII_FIRST; 3967c478bd9Sstevel@tonic-gate kbdd->kbdd_top_addr = TOP_FIRST; 3977c478bd9Sstevel@tonic-gate kbdd->kbdd_vkey_addr = VKEY_FIRST; 3987c478bd9Sstevel@tonic-gate /* Allocate dynamic memory for downs table */ 3997c478bd9Sstevel@tonic-gate kbdd->kbdd_downs_entries = kbd_downs_size; 4007c478bd9Sstevel@tonic-gate kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event); 4017c478bd9Sstevel@tonic-gate kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP); 4027c478bd9Sstevel@tonic-gate kbdd->kbdd_flags = KBD_OPEN; 4037c478bd9Sstevel@tonic-gate kbdd->led_state = 0; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 4067c478bd9Sstevel@tonic-gate * Reset kbd. 4077c478bd9Sstevel@tonic-gate */ 4087c478bd9Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate return (0); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate error: 4137c478bd9Sstevel@tonic-gate qprocsoff(q); 4147c478bd9Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 4157c478bd9Sstevel@tonic-gate return (error); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * Close a keyboard. 4207c478bd9Sstevel@tonic-gate */ 4217c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 4227c478bd9Sstevel@tonic-gate static int 4237c478bd9Sstevel@tonic-gate kbdclose(register queue_t *q, int flag, cred_t *crp) 4247c478bd9Sstevel@tonic-gate { 4257c478bd9Sstevel@tonic-gate register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 4267c478bd9Sstevel@tonic-gate register mblk_t *mp; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate qprocsoff(q); 4297c478bd9Sstevel@tonic-gate /* 4307c478bd9Sstevel@tonic-gate * Since we're about to destroy our private data, turn off 4317c478bd9Sstevel@tonic-gate * our open flag first, so we don't accept any more input 4327c478bd9Sstevel@tonic-gate * and try to use that data. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate kbdd->kbdd_flags = 0; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * There was a KIOCLAYOUT pending; presumably, it timed out. 4397c478bd9Sstevel@tonic-gate * Throw the reply away. 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 4427c478bd9Sstevel@tonic-gate freemsg(mp); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* clear all timeouts */ 4467c478bd9Sstevel@tonic-gate if (kbdd->kbdd_bufcallid) 4477c478bd9Sstevel@tonic-gate qunbufcall(q, kbdd->kbdd_bufcallid); 4487c478bd9Sstevel@tonic-gate if (kbdd->kbdd_rptid) 4497c478bd9Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_rptid); 4507c478bd9Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 4517c478bd9Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_layoutid); 4527c478bd9Sstevel@tonic-gate kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 4537c478bd9Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 4547c478bd9Sstevel@tonic-gate return (0); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate /* 4587c478bd9Sstevel@tonic-gate * Line discipline output queue put procedure: handles M_IOCTL 4597c478bd9Sstevel@tonic-gate * messages. 4607c478bd9Sstevel@tonic-gate */ 4617c478bd9Sstevel@tonic-gate static void 4627c478bd9Sstevel@tonic-gate kbdwput(register queue_t *q, register mblk_t *mp) 4637c478bd9Sstevel@tonic-gate { 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * Process M_FLUSH, and some M_IOCTL, messages here; pass 4667c478bd9Sstevel@tonic-gate * everything else down. 4677c478bd9Sstevel@tonic-gate */ 4687c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate case M_FLUSH: 4717c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 4727c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 4737c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 4747c478bd9Sstevel@tonic-gate flushq(RD(q), FLUSHDATA); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate default: 4777c478bd9Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */ 4787c478bd9Sstevel@tonic-gate break; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate case M_IOCTL: 4817c478bd9Sstevel@tonic-gate kbdioctl(q, mp); 4827c478bd9Sstevel@tonic-gate break; 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate static void 4887c478bd9Sstevel@tonic-gate kbdreioctl(void *kbdd_addr) 4897c478bd9Sstevel@tonic-gate { 4907c478bd9Sstevel@tonic-gate struct kbddata *kbdd = kbdd_addr; 4917c478bd9Sstevel@tonic-gate queue_t *q; 4927c478bd9Sstevel@tonic-gate mblk_t *mp; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate kbdd->kbdd_bufcallid = 0; 4957c478bd9Sstevel@tonic-gate q = kbdd->kbdd_writeq; 4967c478bd9Sstevel@tonic-gate if ((mp = kbdd->kbdd_iocpending) != NULL) { 4977c478bd9Sstevel@tonic-gate kbdd->kbdd_iocpending = NULL; /* not pending any more */ 4987c478bd9Sstevel@tonic-gate kbdioctl(q, mp); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate static void 5037c478bd9Sstevel@tonic-gate kbdioctl(register queue_t *q, register mblk_t *mp) 5047c478bd9Sstevel@tonic-gate { 5057c478bd9Sstevel@tonic-gate register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 5067c478bd9Sstevel@tonic-gate register struct iocblk *iocp; 5077c478bd9Sstevel@tonic-gate register short new_translate; 5087c478bd9Sstevel@tonic-gate register Vuid_addr_probe *addr_probe; 5097c478bd9Sstevel@tonic-gate register short *addr_ptr; 5107c478bd9Sstevel@tonic-gate mblk_t *datap; 5117c478bd9Sstevel@tonic-gate size_t ioctlrespsize; 5127c478bd9Sstevel@tonic-gate int err = 0; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate case VUIDSFORMAT: 5197c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 5207c478bd9Sstevel@tonic-gate if (err != 0) 5217c478bd9Sstevel@tonic-gate break; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ? 5247c478bd9Sstevel@tonic-gate TR_ASCII : TR_EVENT; 5257c478bd9Sstevel@tonic-gate if (new_translate == kbdd->kbdd_translate) 5267c478bd9Sstevel@tonic-gate break; 5277c478bd9Sstevel@tonic-gate kbdd->kbdd_translate = new_translate; 5287c478bd9Sstevel@tonic-gate goto output_format_change; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate case KIOCTRANS: 5317c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 5327c478bd9Sstevel@tonic-gate if (err != 0) 5337c478bd9Sstevel@tonic-gate break; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate new_translate = *(int *)mp->b_cont->b_rptr; 5367c478bd9Sstevel@tonic-gate if (new_translate == kbdd->kbdd_translate) 5377c478bd9Sstevel@tonic-gate break; 5387c478bd9Sstevel@tonic-gate kbdd->kbdd_translate = new_translate; 5397c478bd9Sstevel@tonic-gate goto output_format_change; 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate case KIOCCMD: 5427c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 5437c478bd9Sstevel@tonic-gate if (err != 0) 5447c478bd9Sstevel@tonic-gate break; 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate kbdcmd(q, (char)(*(int *)mp->b_cont->b_rptr)); 5477c478bd9Sstevel@tonic-gate break; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate case KIOCSLED: 5507c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (uchar_t)); 5517c478bd9Sstevel@tonic-gate if (err != 0) 5527c478bd9Sstevel@tonic-gate break; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr; 5557c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 5567c478bd9Sstevel@tonic-gate break; 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate case KIOCGLED: 5597c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) { 5607c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 5617c478bd9Sstevel@tonic-gate goto allocfailure; 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate *(uchar_t *)datap->b_wptr = kbdd->led_state; 5647c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (uchar_t); 5657c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 5667c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 5677c478bd9Sstevel@tonic-gate mp->b_cont = datap; 5687c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (uchar_t); 5697c478bd9Sstevel@tonic-gate break; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate case VUIDGFORMAT: 5727c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 5737c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 5747c478bd9Sstevel@tonic-gate goto allocfailure; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = 5777c478bd9Sstevel@tonic-gate (kbdd->kbdd_translate == TR_EVENT || 5787c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == TR_UNTRANS_EVENT) ? 5797c478bd9Sstevel@tonic-gate VUID_FIRM_EVENT: VUID_NATIVE; 5807c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 5817c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 5827c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 5837c478bd9Sstevel@tonic-gate mp->b_cont = datap; 5847c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 5857c478bd9Sstevel@tonic-gate break; 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate case KIOCGTRANS: 5887c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 5897c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 5907c478bd9Sstevel@tonic-gate goto allocfailure; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_translate; 5937c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 5947c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 5957c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 5967c478bd9Sstevel@tonic-gate mp->b_cont = datap; 5977c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 5987c478bd9Sstevel@tonic-gate break; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate case VUIDSADDR: 6017c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe)); 6027c478bd9Sstevel@tonic-gate if (err != 0) 6037c478bd9Sstevel@tonic-gate break; 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 6067c478bd9Sstevel@tonic-gate switch (addr_probe->base) { 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate case ASCII_FIRST: 6097c478bd9Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_ascii_addr; 6107c478bd9Sstevel@tonic-gate break; 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate case TOP_FIRST: 6137c478bd9Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_top_addr; 6147c478bd9Sstevel@tonic-gate break; 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate case VKEY_FIRST: 6177c478bd9Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_vkey_addr; 6187c478bd9Sstevel@tonic-gate break; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate default: 6217c478bd9Sstevel@tonic-gate err = ENODEV; 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate if ((err == 0) && (*addr_ptr != addr_probe->data.next)) { 6247c478bd9Sstevel@tonic-gate *addr_ptr = addr_probe->data.next; 6257c478bd9Sstevel@tonic-gate goto output_format_change; 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate break; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate case VUIDGADDR: 6307c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe)); 6317c478bd9Sstevel@tonic-gate if (err != 0) 6327c478bd9Sstevel@tonic-gate break; 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 6357c478bd9Sstevel@tonic-gate switch (addr_probe->base) { 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate case ASCII_FIRST: 6387c478bd9Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_ascii_addr; 6397c478bd9Sstevel@tonic-gate break; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate case TOP_FIRST: 6427c478bd9Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_top_addr; 6437c478bd9Sstevel@tonic-gate break; 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate case VKEY_FIRST: 6467c478bd9Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_vkey_addr; 6477c478bd9Sstevel@tonic-gate break; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate default: 6507c478bd9Sstevel@tonic-gate err = ENODEV; 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate break; 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate case KIOCTRANSABLE: 6557c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 6567c478bd9Sstevel@tonic-gate if (err != 0) 6577c478bd9Sstevel@tonic-gate break; 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) { 6607c478bd9Sstevel@tonic-gate kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr; 6617c478bd9Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 6627c478bd9Sstevel@tonic-gate goto output_format_change; 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate break; 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate case KIOCGTRANSABLE: 6677c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 6687c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 6697c478bd9Sstevel@tonic-gate goto allocfailure; 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_translatable; 6727c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 6737c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 6747c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 6757c478bd9Sstevel@tonic-gate mp->b_cont = datap; 6767c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 6777c478bd9Sstevel@tonic-gate break; 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate case KIOCSCOMPAT: 6807c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 6817c478bd9Sstevel@tonic-gate if (err != 0) 6827c478bd9Sstevel@tonic-gate break; 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr; 6857c478bd9Sstevel@tonic-gate break; 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate case KIOCGCOMPAT: 6887c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 6897c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 6907c478bd9Sstevel@tonic-gate goto allocfailure; 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_compat; 6937c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 6947c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 6957c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 6967c478bd9Sstevel@tonic-gate mp->b_cont = datap; 6977c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 6987c478bd9Sstevel@tonic-gate break; 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate case KIOCSETKEY: 7017c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey)); 7027c478bd9Sstevel@tonic-gate if (err != 0) 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr, 7067c478bd9Sstevel@tonic-gate iocp->ioc_cr); 7077c478bd9Sstevel@tonic-gate /* 7087c478bd9Sstevel@tonic-gate * Since this only affects any subsequent key presses, 7097c478bd9Sstevel@tonic-gate * don't goto output_format_change. One might want to 7107c478bd9Sstevel@tonic-gate * toggle the keytable entries dynamically. 7117c478bd9Sstevel@tonic-gate */ 7127c478bd9Sstevel@tonic-gate break; 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate case KIOCGETKEY: 7157c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey)); 7167c478bd9Sstevel@tonic-gate if (err != 0) 7177c478bd9Sstevel@tonic-gate break; 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr); 7207c478bd9Sstevel@tonic-gate break; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate case KIOCSKEY: 7237c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap)); 7247c478bd9Sstevel@tonic-gate if (err != 0) 7257c478bd9Sstevel@tonic-gate break; 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr, 7287c478bd9Sstevel@tonic-gate iocp->ioc_cr); 7297c478bd9Sstevel@tonic-gate /* 7307c478bd9Sstevel@tonic-gate * Since this only affects any subsequent key presses, 7317c478bd9Sstevel@tonic-gate * don't goto output_format_change. One might want to 7327c478bd9Sstevel@tonic-gate * toggle the keytable entries dynamically. 7337c478bd9Sstevel@tonic-gate */ 7347c478bd9Sstevel@tonic-gate break; 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate case KIOCGKEY: 7377c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap)); 7387c478bd9Sstevel@tonic-gate if (err != 0) 7397c478bd9Sstevel@tonic-gate break; 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr); 7427c478bd9Sstevel@tonic-gate break; 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate case KIOCSDIRECT: 7457c478bd9Sstevel@tonic-gate goto output_format_change; 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate case KIOCGDIRECT: 7487c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 7497c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7507c478bd9Sstevel@tonic-gate goto allocfailure; 7517c478bd9Sstevel@tonic-gate } 7527c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = 1; /* always direct */ 7537c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 7547c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 7557c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 7567c478bd9Sstevel@tonic-gate mp->b_cont = datap; 7577c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 7587c478bd9Sstevel@tonic-gate break; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate case KIOCTYPE: 7617c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 7627c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7637c478bd9Sstevel@tonic-gate goto allocfailure; 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_state.k_id; 7667c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 7677c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 7687c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 7697c478bd9Sstevel@tonic-gate mp->b_cont = datap; 7707c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 7717c478bd9Sstevel@tonic-gate break; 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate case KIOCLAYOUT: 7747c478bd9Sstevel@tonic-gate if ((datap = kbdd->kbdd_replypending) != NULL) { 7757c478bd9Sstevel@tonic-gate /* 7767c478bd9Sstevel@tonic-gate * There was an earlier KIOCLAYOUT pending; presumably, 7777c478bd9Sstevel@tonic-gate * it timed out. Throw the reply away. 7787c478bd9Sstevel@tonic-gate */ 7797c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 7807c478bd9Sstevel@tonic-gate freemsg(datap); 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_id == KB_SUN4 || 7847c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_id == KB_PC) { 7857c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 7867c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7877c478bd9Sstevel@tonic-gate goto allocfailure; 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0; 7907c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */ 7917c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 7927c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 7937c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 7947c478bd9Sstevel@tonic-gate mp->b_cont = datap; 7957c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 7967c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = mp; 7977c478bd9Sstevel@tonic-gate kbdcmd(q, (char)KBD_CMD_GETLAYOUT); 7987c478bd9Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 7997c478bd9Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_layoutid); 8007c478bd9Sstevel@tonic-gate kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout, 8017c478bd9Sstevel@tonic-gate kbdd, hz / 5); 8027c478bd9Sstevel@tonic-gate return; /* wait for reply from keyboard */ 8037c478bd9Sstevel@tonic-gate } else { 8047c478bd9Sstevel@tonic-gate /* 8057c478bd9Sstevel@tonic-gate * Not a Type 4 keyboard; return an immediate error. 8067c478bd9Sstevel@tonic-gate */ 8077c478bd9Sstevel@tonic-gate err = EINVAL; 8087c478bd9Sstevel@tonic-gate break; 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate case KIOCGRPTDELAY: 8127c478bd9Sstevel@tonic-gate /* 8137c478bd9Sstevel@tonic-gate * Report the autorepeat delay, unit in millisecond 8147c478bd9Sstevel@tonic-gate */ 8157c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 8167c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 8177c478bd9Sstevel@tonic-gate goto allocfailure; 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay); 8207c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate /* free msg to prevent memory leak */ 8237c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) 8247c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 8257c478bd9Sstevel@tonic-gate mp->b_cont = datap; 8267c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 8277c478bd9Sstevel@tonic-gate break; 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate case KIOCSRPTDELAY: 8307c478bd9Sstevel@tonic-gate /* 8317c478bd9Sstevel@tonic-gate * Set the autorepeat delay 8327c478bd9Sstevel@tonic-gate */ 8337c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate if (err != 0) 8367c478bd9Sstevel@tonic-gate break; 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate /* validate the input */ 8397c478bd9Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) { 8407c478bd9Sstevel@tonic-gate err = EINVAL; 8417c478bd9Sstevel@tonic-gate break; 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 8447c478bd9Sstevel@tonic-gate if (kbd_repeatdelay <= 0) 8457c478bd9Sstevel@tonic-gate kbd_repeatdelay = 1; 8467c478bd9Sstevel@tonic-gate break; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate case KIOCGRPTRATE: 8497c478bd9Sstevel@tonic-gate /* 8507c478bd9Sstevel@tonic-gate * Report the autorepeat rate 8517c478bd9Sstevel@tonic-gate */ 8527c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 8537c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 8547c478bd9Sstevel@tonic-gate goto allocfailure; 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate); 8577c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate /* free msg to prevent memory leak */ 8607c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) 8617c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 8627c478bd9Sstevel@tonic-gate mp->b_cont = datap; 8637c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 8647c478bd9Sstevel@tonic-gate break; 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate case KIOCSRPTRATE: 8677c478bd9Sstevel@tonic-gate /* 8687c478bd9Sstevel@tonic-gate * Set the autorepeat rate 8697c478bd9Sstevel@tonic-gate */ 8707c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate if (err != 0) 8737c478bd9Sstevel@tonic-gate break; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate /* validate the input */ 8767c478bd9Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) { 8777c478bd9Sstevel@tonic-gate err = EINVAL; 8787c478bd9Sstevel@tonic-gate break; 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 8817c478bd9Sstevel@tonic-gate if (kbd_repeatrate <= 0) 8827c478bd9Sstevel@tonic-gate kbd_repeatrate = 1; 8837c478bd9Sstevel@tonic-gate break; 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate default: 8867c478bd9Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */ 8877c478bd9Sstevel@tonic-gate return; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate goto done; 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate output_format_change: 8927c478bd9Sstevel@tonic-gate kbdflush(kbdd); 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate done: 8957c478bd9Sstevel@tonic-gate if (err != 0) { 8967c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0; 8977c478bd9Sstevel@tonic-gate iocp->ioc_error = err; 8987c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK; 8997c478bd9Sstevel@tonic-gate } else { 9007c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0; 9017c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */ 9027c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate qreply(q, mp); 9057c478bd9Sstevel@tonic-gate return; 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate allocfailure: 9087c478bd9Sstevel@tonic-gate /* 9097c478bd9Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but 9107c478bd9Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when 9117c478bd9Sstevel@tonic-gate * it's more likely that we can get what we need. 9127c478bd9Sstevel@tonic-gate * If there's already one being saved, throw it out, since it 9137c478bd9Sstevel@tonic-gate * must have timed out. 9147c478bd9Sstevel@tonic-gate */ 9157c478bd9Sstevel@tonic-gate if (kbdd->kbdd_iocpending != NULL) 9167c478bd9Sstevel@tonic-gate freemsg(kbdd->kbdd_iocpending); 9177c478bd9Sstevel@tonic-gate kbdd->kbdd_iocpending = mp; 9187c478bd9Sstevel@tonic-gate if (kbdd->kbdd_bufcallid) 9197c478bd9Sstevel@tonic-gate qunbufcall(q, kbdd->kbdd_bufcallid); 9207c478bd9Sstevel@tonic-gate kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI, 9217c478bd9Sstevel@tonic-gate kbdreioctl, kbdd); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate static void 9257c478bd9Sstevel@tonic-gate kbdflush(register struct kbddata *kbdd) 9267c478bd9Sstevel@tonic-gate { 9277c478bd9Sstevel@tonic-gate register queue_t *q; 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate /* Flush pending data already sent upstream */ 9307c478bd9Sstevel@tonic-gate if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL) 9317c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHR); 9327c478bd9Sstevel@tonic-gate /* Flush pending ups */ 9337c478bd9Sstevel@tonic-gate bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 9347c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate /* 9387c478bd9Sstevel@tonic-gate * Pass keycode upstream, either translated or untranslated. 9397c478bd9Sstevel@tonic-gate */ 9407c478bd9Sstevel@tonic-gate static void 9417c478bd9Sstevel@tonic-gate kbduse(register struct kbddata *kbdd, unsigned keycode) 9427c478bd9Sstevel@tonic-gate { 9437c478bd9Sstevel@tonic-gate register queue_t *readq; 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 9467c478bd9Sstevel@tonic-gate if (kbd_input_debug) printf("KBD USE key=%d\n", keycode); 9477c478bd9Sstevel@tonic-gate #endif 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate if ((readq = kbdd->kbdd_readq) == NULL) 9507c478bd9Sstevel@tonic-gate return; 9517c478bd9Sstevel@tonic-gate if (!kbdd->kbdd_translatable || 9527c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == TR_NONE) 9537c478bd9Sstevel@tonic-gate kbdputcode(keycode, readq); 9547c478bd9Sstevel@tonic-gate else 9557c478bd9Sstevel@tonic-gate kbdtranslate(kbdd, keycode, readq); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* 9597c478bd9Sstevel@tonic-gate * kbdclick is used to remember the current click value of the 9607c478bd9Sstevel@tonic-gate * Sun-3 keyboard. This brain damaged keyboard will reset the 9617c478bd9Sstevel@tonic-gate * clicking to the "default" value after a reset command and 9627c478bd9Sstevel@tonic-gate * there is no way to read out the current click value. We 9637c478bd9Sstevel@tonic-gate * cannot send a click command immediately after the reset 9647c478bd9Sstevel@tonic-gate * command or the keyboard gets screwed up. So we wait until 9657c478bd9Sstevel@tonic-gate * we get the ID byte before we send back the click command. 9667c478bd9Sstevel@tonic-gate * Unfortunately, this means that there is a small window 9677c478bd9Sstevel@tonic-gate * where the keyboard can click when it really shouldn't be. 9687c478bd9Sstevel@tonic-gate * A value of -1 means that kbdclick has not been initialized yet. 9697c478bd9Sstevel@tonic-gate */ 9707c478bd9Sstevel@tonic-gate static int kbdclick = -1; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate /* 9737c478bd9Sstevel@tonic-gate * Send command byte to keyboard, if you can. 9747c478bd9Sstevel@tonic-gate */ 9757c478bd9Sstevel@tonic-gate static void 9767c478bd9Sstevel@tonic-gate kbdcmd(register queue_t *q, char cmd) 9777c478bd9Sstevel@tonic-gate { 9787c478bd9Sstevel@tonic-gate register mblk_t *bp; 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate if (canput(q)) { 9817c478bd9Sstevel@tonic-gate if ((bp = allocb(1, BPRI_MED)) == NULL) 9827c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 9837c478bd9Sstevel@tonic-gate "kbdcmd: Can't allocate block for command"); 9847c478bd9Sstevel@tonic-gate else { 9857c478bd9Sstevel@tonic-gate *bp->b_wptr++ = cmd; 9867c478bd9Sstevel@tonic-gate putnext(q, bp); 9877c478bd9Sstevel@tonic-gate if (cmd == KBD_CMD_NOCLICK) 9887c478bd9Sstevel@tonic-gate kbdclick = 0; 9897c478bd9Sstevel@tonic-gate else if (cmd == KBD_CMD_CLICK) 9907c478bd9Sstevel@tonic-gate kbdclick = 1; 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate /* 9967c478bd9Sstevel@tonic-gate * Update the keyboard LEDs to match the current keyboard state. 9977c478bd9Sstevel@tonic-gate * Do this only on Type 4 keyboards; other keyboards don't support the 9987c478bd9Sstevel@tonic-gate * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs). 9997c478bd9Sstevel@tonic-gate */ 10007c478bd9Sstevel@tonic-gate static void 10017c478bd9Sstevel@tonic-gate kbdsetled(register struct kbddata *kbdd) 10027c478bd9Sstevel@tonic-gate { 10037c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_id == KB_SUN4 || 10047c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_id == KB_PC) { 10057c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED); 10067c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, kbdd->led_state); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate /* 10117c478bd9Sstevel@tonic-gate * Reset the keyboard 10127c478bd9Sstevel@tonic-gate */ 10137c478bd9Sstevel@tonic-gate static void 10147c478bd9Sstevel@tonic-gate kbdreset(register struct kbddata *kbdd, uint_t hard_reset) 10157c478bd9Sstevel@tonic-gate { 10167c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 10197c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translatable) { 10207c478bd9Sstevel@tonic-gate k->k_idstate = KID_NONE; 10217c478bd9Sstevel@tonic-gate k->k_id = -1; 10227c478bd9Sstevel@tonic-gate k->k_state = NORMAL; 10237c478bd9Sstevel@tonic-gate if (hard_reset) 10247c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET); 10257c478bd9Sstevel@tonic-gate } else { 10267c478bd9Sstevel@tonic-gate bzero(k, sizeof (struct keyboardstate)); 10277c478bd9Sstevel@tonic-gate k->k_id = KB_ASCII; 10287c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* 10337c478bd9Sstevel@tonic-gate * Old special codes. 10347c478bd9Sstevel@tonic-gate */ 10357c478bd9Sstevel@tonic-gate #define OLD_SHIFTKEYS 0x80 10367c478bd9Sstevel@tonic-gate #define OLD_BUCKYBITS 0x90 10377c478bd9Sstevel@tonic-gate #define OLD_FUNNY 0xA0 10387c478bd9Sstevel@tonic-gate #define OLD_FA_UMLAUT 0xA9 10397c478bd9Sstevel@tonic-gate #define OLD_FA_CFLEX 0xAA 10407c478bd9Sstevel@tonic-gate #define OLD_FA_TILDE 0xAB 10417c478bd9Sstevel@tonic-gate #define OLD_FA_CEDILLA 0xAC 10427c478bd9Sstevel@tonic-gate #define OLD_FA_ACUTE 0xAD 10437c478bd9Sstevel@tonic-gate #define OLD_FA_GRAVE 0xAE 10447c478bd9Sstevel@tonic-gate #define OLD_ISOCHAR 0xAF 10457c478bd9Sstevel@tonic-gate #define OLD_STRING 0xB0 10467c478bd9Sstevel@tonic-gate #define OLD_LEFTFUNC 0xC0 10477c478bd9Sstevel@tonic-gate #define OLD_RIGHTFUNC 0xD0 10487c478bd9Sstevel@tonic-gate #define OLD_TOPFUNC 0xE0 10497c478bd9Sstevel@tonic-gate #define OLD_BOTTOMFUNC 0xF0 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate /* 10527c478bd9Sstevel@tonic-gate * Map old special codes to new ones. 10537c478bd9Sstevel@tonic-gate * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F. 10547c478bd9Sstevel@tonic-gate */ 10557c478bd9Sstevel@tonic-gate static ushort_t special_old_to_new[] = { 10567c478bd9Sstevel@tonic-gate SHIFTKEYS, 10577c478bd9Sstevel@tonic-gate BUCKYBITS, 10587c478bd9Sstevel@tonic-gate FUNNY, 10597c478bd9Sstevel@tonic-gate STRING, 10607c478bd9Sstevel@tonic-gate LEFTFUNC, 10617c478bd9Sstevel@tonic-gate RIGHTFUNC, 10627c478bd9Sstevel@tonic-gate TOPFUNC, 10637c478bd9Sstevel@tonic-gate BOTTOMFUNC, 10647c478bd9Sstevel@tonic-gate }; 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate /* 10677c478bd9Sstevel@tonic-gate * Set individual keystation translation from old-style entry. 10687c478bd9Sstevel@tonic-gate * TODO: Have each keyboard own own translation tables. 10697c478bd9Sstevel@tonic-gate */ 10707c478bd9Sstevel@tonic-gate static int 10717c478bd9Sstevel@tonic-gate kbdsetkey(register struct kbddata *kbdd, struct kiockey *key, cred_t *cr) 10727c478bd9Sstevel@tonic-gate { 10737c478bd9Sstevel@tonic-gate int strtabindex, i; 10747c478bd9Sstevel@tonic-gate struct keymap *km; 10757c478bd9Sstevel@tonic-gate register int tablemask; 10767c478bd9Sstevel@tonic-gate register ushort_t entry; 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 10797c478bd9Sstevel@tonic-gate return (EINVAL); 10807c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 10817c478bd9Sstevel@tonic-gate return (EINVAL); 10827c478bd9Sstevel@tonic-gate tablemask = key->kio_tablemask; 10837c478bd9Sstevel@tonic-gate if (tablemask == KIOCABORT1) { 10847c478bd9Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 10857c478bd9Sstevel@tonic-gate return (EPERM); 10867c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station; 10877c478bd9Sstevel@tonic-gate return (0); 10887c478bd9Sstevel@tonic-gate } 10897c478bd9Sstevel@tonic-gate if (tablemask == KIOCABORT2) { 10907c478bd9Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 10917c478bd9Sstevel@tonic-gate return (EPERM); 10927c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station; 10937c478bd9Sstevel@tonic-gate return (0); 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate if ((tablemask & ALTGRAPHMASK) || 10967c478bd9Sstevel@tonic-gate (km = settable(kbdd, (uint_t)tablemask)) == NULL) 10977c478bd9Sstevel@tonic-gate return (EINVAL); 10987c478bd9Sstevel@tonic-gate if (key->kio_entry >= (uchar_t)OLD_STRING && 10997c478bd9Sstevel@tonic-gate key->kio_entry <= (uchar_t)(OLD_STRING + 15)) { 11007c478bd9Sstevel@tonic-gate strtabindex = key->kio_entry - OLD_STRING; 11017c478bd9Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 11027c478bd9Sstevel@tonic-gate keystringtab[strtabindex][i] = key->kio_string[i]; 11037c478bd9Sstevel@tonic-gate keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate entry = key->kio_entry; 11067c478bd9Sstevel@tonic-gate /* 11077c478bd9Sstevel@tonic-gate * There's nothing we need do with OLD_ISOCHAR. 11087c478bd9Sstevel@tonic-gate */ 11097c478bd9Sstevel@tonic-gate if (entry != OLD_ISOCHAR) { 11107c478bd9Sstevel@tonic-gate if (entry & 0x80) { 11117c478bd9Sstevel@tonic-gate if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE) 11127c478bd9Sstevel@tonic-gate entry = FA_CLASS + (entry & 0x0F) - 9; 11137c478bd9Sstevel@tonic-gate else 11147c478bd9Sstevel@tonic-gate entry = 11157c478bd9Sstevel@tonic-gate special_old_to_new[entry >> 4 & 0x07] 11167c478bd9Sstevel@tonic-gate + (entry & 0x0F); 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate km->keymap[key->kio_station] = entry; 11207c478bd9Sstevel@tonic-gate return (0); 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate /* 11247c478bd9Sstevel@tonic-gate * Map new special codes to old ones. 11257c478bd9Sstevel@tonic-gate * Indexed by (new special code) >> 8; add (new special code) & 0xFF. 11267c478bd9Sstevel@tonic-gate */ 11277c478bd9Sstevel@tonic-gate static uchar_t special_new_to_old[] = { 11287c478bd9Sstevel@tonic-gate 0, /* normal */ 11297c478bd9Sstevel@tonic-gate OLD_SHIFTKEYS, /* SHIFTKEYS */ 11307c478bd9Sstevel@tonic-gate OLD_BUCKYBITS, /* BUCKYBITS */ 11317c478bd9Sstevel@tonic-gate OLD_FUNNY, /* FUNNY */ 11327c478bd9Sstevel@tonic-gate OLD_FA_UMLAUT, /* FA_CLASS */ 11337c478bd9Sstevel@tonic-gate OLD_STRING, /* STRING */ 11347c478bd9Sstevel@tonic-gate OLD_LEFTFUNC, /* FUNCKEYS */ 11357c478bd9Sstevel@tonic-gate }; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate /* 11387c478bd9Sstevel@tonic-gate * Get individual keystation translation as old-style entry. 11397c478bd9Sstevel@tonic-gate */ 11407c478bd9Sstevel@tonic-gate static int 11417c478bd9Sstevel@tonic-gate kbdgetkey(register struct kbddata *kbdd, struct kiockey *key) 11427c478bd9Sstevel@tonic-gate { 11437c478bd9Sstevel@tonic-gate int strtabindex, i; 11447c478bd9Sstevel@tonic-gate struct keymap *km; 11457c478bd9Sstevel@tonic-gate register ushort_t entry; 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 11487c478bd9Sstevel@tonic-gate return (EINVAL); 11497c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 11507c478bd9Sstevel@tonic-gate return (EINVAL); 11517c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 11527c478bd9Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1; 11537c478bd9Sstevel@tonic-gate return (0); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 11567c478bd9Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2; 11577c478bd9Sstevel@tonic-gate return (0); 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 11607c478bd9Sstevel@tonic-gate return (EINVAL); 11617c478bd9Sstevel@tonic-gate entry = km->keymap[key->kio_station]; 11627c478bd9Sstevel@tonic-gate if (entry & 0xFF00) 11637c478bd9Sstevel@tonic-gate key->kio_entry = 11647c478bd9Sstevel@tonic-gate special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8] 11657c478bd9Sstevel@tonic-gate + (entry & 0x00FF); 11667c478bd9Sstevel@tonic-gate else { 11677c478bd9Sstevel@tonic-gate if (entry & 0x80) 11687c478bd9Sstevel@tonic-gate key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */ 11697c478bd9Sstevel@tonic-gate else 11707c478bd9Sstevel@tonic-gate key->kio_entry = (ushort_t)entry; 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) { 11737c478bd9Sstevel@tonic-gate strtabindex = entry - STRING; 11747c478bd9Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 11757c478bd9Sstevel@tonic-gate key->kio_string[i] = keystringtab[strtabindex][i]; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate return (0); 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate /* 11817c478bd9Sstevel@tonic-gate * Set individual keystation translation from new-style entry. 11827c478bd9Sstevel@tonic-gate * TODO: Have each keyboard own own translation tables. 11837c478bd9Sstevel@tonic-gate */ 11847c478bd9Sstevel@tonic-gate static int 11857c478bd9Sstevel@tonic-gate kbdskey(register struct kbddata *kbdd, struct kiockeymap *key, cred_t *cr) 11867c478bd9Sstevel@tonic-gate { 11877c478bd9Sstevel@tonic-gate int strtabindex, i; 11887c478bd9Sstevel@tonic-gate struct keymap *km; 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 11917c478bd9Sstevel@tonic-gate return (EINVAL); 11927c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 11937c478bd9Sstevel@tonic-gate return (EINVAL); 11947c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 11957c478bd9Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 11967c478bd9Sstevel@tonic-gate return (EPERM); 11977c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station; 11987c478bd9Sstevel@tonic-gate return (0); 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 12017c478bd9Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 12027c478bd9Sstevel@tonic-gate return (EPERM); 12037c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station; 12047c478bd9Sstevel@tonic-gate return (0); 12057c478bd9Sstevel@tonic-gate } 12067c478bd9Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 12077c478bd9Sstevel@tonic-gate return (EINVAL); 12087c478bd9Sstevel@tonic-gate if (key->kio_entry >= STRING && 12097c478bd9Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) { 12107c478bd9Sstevel@tonic-gate strtabindex = key->kio_entry-STRING; 12117c478bd9Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 12127c478bd9Sstevel@tonic-gate keystringtab[strtabindex][i] = key->kio_string[i]; 12137c478bd9Sstevel@tonic-gate keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 12147c478bd9Sstevel@tonic-gate } 12157c478bd9Sstevel@tonic-gate km->keymap[key->kio_station] = key->kio_entry; 12167c478bd9Sstevel@tonic-gate return (0); 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate /* 12207c478bd9Sstevel@tonic-gate * Get individual keystation translation as new-style entry. 12217c478bd9Sstevel@tonic-gate */ 12227c478bd9Sstevel@tonic-gate static int 12237c478bd9Sstevel@tonic-gate kbdgkey(register struct kbddata *kbdd, struct kiockeymap *key) 12247c478bd9Sstevel@tonic-gate { 12257c478bd9Sstevel@tonic-gate int strtabindex, i; 12267c478bd9Sstevel@tonic-gate struct keymap *km; 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 12297c478bd9Sstevel@tonic-gate return (EINVAL); 12307c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 12317c478bd9Sstevel@tonic-gate return (EINVAL); 12327c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 12337c478bd9Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1; 12347c478bd9Sstevel@tonic-gate return (0); 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 12377c478bd9Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2; 12387c478bd9Sstevel@tonic-gate return (0); 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 12417c478bd9Sstevel@tonic-gate return (EINVAL); 12427c478bd9Sstevel@tonic-gate key->kio_entry = km->keymap[key->kio_station]; 12437c478bd9Sstevel@tonic-gate if (key->kio_entry >= STRING && 12447c478bd9Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) { 12457c478bd9Sstevel@tonic-gate strtabindex = key->kio_entry-STRING; 12467c478bd9Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 12477c478bd9Sstevel@tonic-gate key->kio_string[i] = keystringtab[strtabindex][i]; 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate return (0); 12507c478bd9Sstevel@tonic-gate } 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate static void 12537c478bd9Sstevel@tonic-gate kbdlayouttimeout(void *arg) 12547c478bd9Sstevel@tonic-gate { 12557c478bd9Sstevel@tonic-gate struct kbddata *kbdd = arg; 12567c478bd9Sstevel@tonic-gate mblk_t *mp; 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate kbdd->kbdd_layoutid = 0; 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate /* 12617c478bd9Sstevel@tonic-gate * Timed out waiting for reply to "get keyboard layout" command. 12627c478bd9Sstevel@tonic-gate * Return an ETIME error. 12637c478bd9Sstevel@tonic-gate */ 12647c478bd9Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 12657c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 12667c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK; 12677c478bd9Sstevel@tonic-gate ((struct iocblk *)mp->b_rptr)->ioc_error = ETIME; 12687c478bd9Sstevel@tonic-gate putnext(kbdd->kbdd_readq, mp); 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate } 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate /* 12737c478bd9Sstevel@tonic-gate * Put procedure for input from driver end of stream (read queue). 12747c478bd9Sstevel@tonic-gate */ 12757c478bd9Sstevel@tonic-gate static void 12767c478bd9Sstevel@tonic-gate kbdrput(register queue_t *q, register mblk_t *mp) 12777c478bd9Sstevel@tonic-gate { 12787c478bd9Sstevel@tonic-gate struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 12797c478bd9Sstevel@tonic-gate register mblk_t *bp; 12807c478bd9Sstevel@tonic-gate register uchar_t *readp; 12817c478bd9Sstevel@tonic-gate struct iocblk *iocp; 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate if (kbdd == 0) { 12847c478bd9Sstevel@tonic-gate freemsg(mp); /* nobody's listening */ 12857c478bd9Sstevel@tonic-gate return; 12867c478bd9Sstevel@tonic-gate } 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate case M_FLUSH: 12917c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 12927c478bd9Sstevel@tonic-gate flushq(WR(q), FLUSHDATA); 12937c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 12947c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate default: 12977c478bd9Sstevel@tonic-gate putnext(q, mp); 12987c478bd9Sstevel@tonic-gate return; 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate case M_BREAK: 13017c478bd9Sstevel@tonic-gate /* 13027c478bd9Sstevel@tonic-gate * Will get M_BREAK only if this is not the system 13037c478bd9Sstevel@tonic-gate * keyboard, otherwise serial port will eat break 13047c478bd9Sstevel@tonic-gate * and call kmdb/OBP, without passing anything up. 13057c478bd9Sstevel@tonic-gate */ 13067c478bd9Sstevel@tonic-gate freemsg(mp); 13077c478bd9Sstevel@tonic-gate return; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate case M_IOCACK: 13107c478bd9Sstevel@tonic-gate case M_IOCNAK: 13117c478bd9Sstevel@tonic-gate /* 13127c478bd9Sstevel@tonic-gate * If we are doing an "ioctl" ourselves, check if this 13137c478bd9Sstevel@tonic-gate * is the reply to that code. If so, wake up the 13147c478bd9Sstevel@tonic-gate * "open" routine, and toss the reply, otherwise just 13157c478bd9Sstevel@tonic-gate * pass it up. 13167c478bd9Sstevel@tonic-gate */ 13177c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 13187c478bd9Sstevel@tonic-gate if (!(kbdd->kbdd_flags & KBD_IOCWAIT) || 13197c478bd9Sstevel@tonic-gate iocp->ioc_id != kbdd->kbdd_iocid) { 13207c478bd9Sstevel@tonic-gate /* 13217c478bd9Sstevel@tonic-gate * This isn't the reply we're looking for. Move along. 13227c478bd9Sstevel@tonic-gate */ 13237c478bd9Sstevel@tonic-gate if (kbdd->kbdd_flags & KBD_OPEN) 13247c478bd9Sstevel@tonic-gate putnext(q, mp); 13257c478bd9Sstevel@tonic-gate else 13267c478bd9Sstevel@tonic-gate freemsg(mp); /* not ready to listen */ 13277c478bd9Sstevel@tonic-gate } else { 13287c478bd9Sstevel@tonic-gate kbdd->kbdd_flags &= ~KBD_IOCWAIT; 13297c478bd9Sstevel@tonic-gate kbdd->kbdd_iocerror = iocp->ioc_error; 13307c478bd9Sstevel@tonic-gate freemsg(mp); 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate return; 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate case M_DATA: 13357c478bd9Sstevel@tonic-gate if (!(kbdd->kbdd_flags & KBD_OPEN)) { 13367c478bd9Sstevel@tonic-gate freemsg(mp); /* not read to listen */ 13377c478bd9Sstevel@tonic-gate return; 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate break; 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate /* 13437c478bd9Sstevel@tonic-gate * A data message, consisting of bytes from the keyboard. 13447c478bd9Sstevel@tonic-gate * Ram them through our state machine. 13457c478bd9Sstevel@tonic-gate */ 13467c478bd9Sstevel@tonic-gate bp = mp; 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate do { 13497c478bd9Sstevel@tonic-gate readp = bp->b_rptr; 13507c478bd9Sstevel@tonic-gate while (readp < bp->b_wptr) 13517c478bd9Sstevel@tonic-gate kbdinput(kbdd, *readp++); 13527c478bd9Sstevel@tonic-gate bp->b_rptr = readp; 13537c478bd9Sstevel@tonic-gate } while ((bp = bp->b_cont) != NULL); /* next block, if any */ 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate freemsg(mp); 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate /* 13597c478bd9Sstevel@tonic-gate * A keypress was received. Process it through the state machine 13607c478bd9Sstevel@tonic-gate * to check for aborts. 13617c478bd9Sstevel@tonic-gate */ 13627c478bd9Sstevel@tonic-gate static void 13637c478bd9Sstevel@tonic-gate kbdinput(register struct kbddata *kbdd, register unsigned key) 13647c478bd9Sstevel@tonic-gate { 13657c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 13667c478bd9Sstevel@tonic-gate register mblk_t *mp; 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 13697c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 13707c478bd9Sstevel@tonic-gate if (kbd_input_debug) 13717c478bd9Sstevel@tonic-gate printf("kbdinput key %x\n", key); 13727c478bd9Sstevel@tonic-gate #endif 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate switch (k->k_idstate) { 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate case KID_NONE: 13777c478bd9Sstevel@tonic-gate if (key == RESETKEY) { 13787c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_PREFACE; 13797c478bd9Sstevel@tonic-gate } else { 13807c478bd9Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 13817c478bd9Sstevel@tonic-gate /* allows hot plug of kbd after booting without kbd */ 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate return; 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate case KID_GOT_PREFACE: 13867c478bd9Sstevel@tonic-gate kbdid(kbdd, (int)key); 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* 13897c478bd9Sstevel@tonic-gate * We just did a reset command to a Type 3 or Type 4 13907c478bd9Sstevel@tonic-gate * keyboard which sets the click back to the default 13917c478bd9Sstevel@tonic-gate * (which is currently ON!). We use the kbdclick 13927c478bd9Sstevel@tonic-gate * variable to see if the keyboard should be turned on 13937c478bd9Sstevel@tonic-gate * or off. If it has not been set, then we use the 13947c478bd9Sstevel@tonic-gate * keyboard-click? property. 13957c478bd9Sstevel@tonic-gate */ 13967c478bd9Sstevel@tonic-gate switch (kbdclick) { 13977c478bd9Sstevel@tonic-gate case 0: 13987c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK); 13997c478bd9Sstevel@tonic-gate break; 14007c478bd9Sstevel@tonic-gate case 1: 14017c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_CLICK); 14027c478bd9Sstevel@tonic-gate break; 14037c478bd9Sstevel@tonic-gate case -1: 14047c478bd9Sstevel@tonic-gate default: 14057c478bd9Sstevel@tonic-gate { 14067c478bd9Sstevel@tonic-gate char wrkbuf[8]; 14077c478bd9Sstevel@tonic-gate int len; 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK); 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate bzero(wrkbuf, 8); 14127c478bd9Sstevel@tonic-gate len = 7; 14137c478bd9Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY, 14147c478bd9Sstevel@tonic-gate ddi_root_node(), 0, "keyboard-click?", 14157c478bd9Sstevel@tonic-gate (caddr_t)wrkbuf, &len) == 14167c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS && 14177c478bd9Sstevel@tonic-gate len > 0 && len < 8) { 14187c478bd9Sstevel@tonic-gate if (strcmp(wrkbuf, "true") == 0) { 14197c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, 14207c478bd9Sstevel@tonic-gate KBD_CMD_CLICK); 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate break; 14257c478bd9Sstevel@tonic-gate } 14267c478bd9Sstevel@tonic-gate /* 14277c478bd9Sstevel@tonic-gate * A keyboard reset clears the LEDs. 14287c478bd9Sstevel@tonic-gate * Restore the LEDs from the last value we set 14297c478bd9Sstevel@tonic-gate * them to. 14307c478bd9Sstevel@tonic-gate */ 14317c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 14327c478bd9Sstevel@tonic-gate return; 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate case KID_OK: 14357c478bd9Sstevel@tonic-gate switch (key) { 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate #if defined(KBD_PRESSED_PREFIX) 14387c478bd9Sstevel@tonic-gate case KBD_PRESSED_PREFIX: 14397c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_PRESSED; 14407c478bd9Sstevel@tonic-gate return; 14417c478bd9Sstevel@tonic-gate #endif 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate #if defined(KBD_RELEASED_PREFIX) 14447c478bd9Sstevel@tonic-gate case KBD_RELEASED_PREFIX: 14457c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_RELEASED; 14467c478bd9Sstevel@tonic-gate return; 14477c478bd9Sstevel@tonic-gate #endif 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate case 0: 14507c478bd9Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 14517c478bd9Sstevel@tonic-gate return; 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* 14547c478bd9Sstevel@tonic-gate * we want to check for ID only if we are in 14557c478bd9Sstevel@tonic-gate * translatable mode. 14567c478bd9Sstevel@tonic-gate */ 14577c478bd9Sstevel@tonic-gate case RESETKEY: 14587c478bd9Sstevel@tonic-gate kbdreset(kbdd, NO_HARD_RESET); 14597c478bd9Sstevel@tonic-gate if (k->k_idstate == KID_NONE) { 14607c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_PREFACE; 14617c478bd9Sstevel@tonic-gate } 14627c478bd9Sstevel@tonic-gate return; 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate case LAYOUTKEY: 14657c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_LAYOUT; 14667c478bd9Sstevel@tonic-gate return; 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate break; 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate #if defined(KBD_PRESSED_PREFIX) 14717c478bd9Sstevel@tonic-gate case KID_GOT_PRESSED: 14727c478bd9Sstevel@tonic-gate key = BUILDKEY(key, PRESSED); 14737c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 14747c478bd9Sstevel@tonic-gate break; 14757c478bd9Sstevel@tonic-gate #endif 14767c478bd9Sstevel@tonic-gate #if defined(KBD_RELEASED_PREFIX) 14777c478bd9Sstevel@tonic-gate case KID_GOT_RELEASED: 14787c478bd9Sstevel@tonic-gate key = BUILDKEY(key, RELEASED); 14797c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 14807c478bd9Sstevel@tonic-gate break; 14817c478bd9Sstevel@tonic-gate #endif 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate case KID_GOT_LAYOUT: 14847c478bd9Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 14857c478bd9Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, 14867c478bd9Sstevel@tonic-gate kbdd->kbdd_layoutid); 14877c478bd9Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 14887c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 14897c478bd9Sstevel@tonic-gate *(int *)mp->b_cont->b_wptr = key; 14907c478bd9Sstevel@tonic-gate mp->b_cont->b_wptr += sizeof (int); 14917c478bd9Sstevel@tonic-gate putnext(kbdd->kbdd_readq, mp); 14927c478bd9Sstevel@tonic-gate } 14937c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 14947c478bd9Sstevel@tonic-gate return; 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate switch (k->k_state) { 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate #if defined(__sparc) 15007c478bd9Sstevel@tonic-gate normalstate: 15017c478bd9Sstevel@tonic-gate k->k_state = NORMAL; 15027c478bd9Sstevel@tonic-gate /* FALLTHRU */ 15037c478bd9Sstevel@tonic-gate #endif 15047c478bd9Sstevel@tonic-gate case NORMAL: 15057c478bd9Sstevel@tonic-gate #if defined(__sparc) 15067c478bd9Sstevel@tonic-gate if (k->k_curkeyboard) { 15077c478bd9Sstevel@tonic-gate if (key == k->k_curkeyboard->k_abort1) { 15087c478bd9Sstevel@tonic-gate k->k_state = ABORT1; 15097c478bd9Sstevel@tonic-gate break; 15107c478bd9Sstevel@tonic-gate } 1511e4603304Sqz150045 if ((key == k->k_curkeyboard->k_newabort1) || 1512e4603304Sqz150045 (key == k->k_curkeyboard->k_newabort1a)) { 1513e4603304Sqz150045 k->k_state = NEWABORT1; 1514*b05bac8eSqz150045 kbdd->shiftkey = key; 1515e4603304Sqz150045 } 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate #endif 15187c478bd9Sstevel@tonic-gate kbduse(kbdd, key); 15197c478bd9Sstevel@tonic-gate break; 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate #if defined(__sparc) 15227c478bd9Sstevel@tonic-gate case ABORT1: 15237c478bd9Sstevel@tonic-gate if (k->k_curkeyboard) { 15247c478bd9Sstevel@tonic-gate /* 15257c478bd9Sstevel@tonic-gate * Only recognize this as an abort sequence if 15267c478bd9Sstevel@tonic-gate * the "hardware" console is set to be this device. 15277c478bd9Sstevel@tonic-gate */ 15287c478bd9Sstevel@tonic-gate if (key == k->k_curkeyboard->k_abort2 && 15297c478bd9Sstevel@tonic-gate rconsvp == wsconsvp) { 15307c478bd9Sstevel@tonic-gate DELAY(100000); 15317c478bd9Sstevel@tonic-gate abort_sequence_enter((char *)NULL); 15327c478bd9Sstevel@tonic-gate k->k_state = NORMAL; 15337c478bd9Sstevel@tonic-gate kbduse(kbdd, IDLEKEY); /* fake */ 15347c478bd9Sstevel@tonic-gate return; 15357c478bd9Sstevel@tonic-gate } else { 15367c478bd9Sstevel@tonic-gate kbduse(kbdd, k->k_curkeyboard->k_abort1); 15377c478bd9Sstevel@tonic-gate goto normalstate; 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate break; 1541e4603304Sqz150045 case NEWABORT1: 1542e4603304Sqz150045 if (k->k_curkeyboard) { 1543e4603304Sqz150045 /* 1544e4603304Sqz150045 * Only recognize this as an abort sequence if 1545e4603304Sqz150045 * the "hardware" console is set to be this device. 1546e4603304Sqz150045 */ 1547e4603304Sqz150045 if (key == k->k_curkeyboard->k_newabort2 && 1548e4603304Sqz150045 rconsvp == wsconsvp) { 1549e4603304Sqz150045 DELAY(100000); 1550e4603304Sqz150045 abort_sequence_enter((char *)NULL); 1551e4603304Sqz150045 k->k_state = NORMAL; 1552*b05bac8eSqz150045 kbdd->shiftkey |= RELEASED; 1553*b05bac8eSqz150045 kbduse(kbdd, kbdd->shiftkey); 1554e4603304Sqz150045 kbduse(kbdd, IDLEKEY); /* fake */ 1555e4603304Sqz150045 return; 1556e4603304Sqz150045 } else { 1557e4603304Sqz150045 goto normalstate; 1558e4603304Sqz150045 } 1559e4603304Sqz150045 } 1560e4603304Sqz150045 break; 15617c478bd9Sstevel@tonic-gate #endif 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate case COMPOSE1: 15647c478bd9Sstevel@tonic-gate case COMPOSE2: 15657c478bd9Sstevel@tonic-gate case FLTACCENT: 15667c478bd9Sstevel@tonic-gate if (key != IDLEKEY) 15677c478bd9Sstevel@tonic-gate kbduse(kbdd, key); 15687c478bd9Sstevel@tonic-gate break; 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate static void 15737c478bd9Sstevel@tonic-gate kbdid(register struct kbddata *kbdd, int id) 15747c478bd9Sstevel@tonic-gate { 15757c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 15767c478bd9Sstevel@tonic-gate int i; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 15817c478bd9Sstevel@tonic-gate k->k_shiftmask = 0; 15827c478bd9Sstevel@tonic-gate k->k_buckybits = 0; 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate /* 15857c478bd9Sstevel@tonic-gate * Reset k_rptkey to IDLEKEY. We need to cancel 15867c478bd9Sstevel@tonic-gate * the autorepeat feature, if any. 15877c478bd9Sstevel@tonic-gate */ 15887c478bd9Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 15897c478bd9Sstevel@tonic-gate if (kbdd->kbdd_rptid) 15907c478bd9Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 15917c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 15927c478bd9Sstevel@tonic-gate k->k_rptkey = IDLEKEY; 15937c478bd9Sstevel@tonic-gate } 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate k->k_curkeyboard = NULL; 15967c478bd9Sstevel@tonic-gate for (i = 0; keytables[i].table; i++) { 15977c478bd9Sstevel@tonic-gate if (keytables[i].id == id) { 15987c478bd9Sstevel@tonic-gate k->k_id = id; 15997c478bd9Sstevel@tonic-gate k->k_curkeyboard = keytables[i].table; 16007c478bd9Sstevel@tonic-gate break; 16017c478bd9Sstevel@tonic-gate } 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate if (!k->k_curkeyboard) { 16047c478bd9Sstevel@tonic-gate k->k_id = keytables[0].id; 16057c478bd9Sstevel@tonic-gate k->k_curkeyboard = keytables[0].table; 16067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Unknown keyboard type, " 16077c478bd9Sstevel@tonic-gate "Type %d assumed", k->k_id); 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate /* 16127c478bd9Sstevel@tonic-gate * This routine determines which table we should look in to decode 16137c478bd9Sstevel@tonic-gate * the current keycode. 16147c478bd9Sstevel@tonic-gate */ 16157c478bd9Sstevel@tonic-gate static struct keymap * 16167c478bd9Sstevel@tonic-gate settable(register struct kbddata *kbdd, register uint_t mask) 16177c478bd9Sstevel@tonic-gate { 16187c478bd9Sstevel@tonic-gate register struct keyboard *kp; 16197c478bd9Sstevel@tonic-gate 16207c478bd9Sstevel@tonic-gate kp = kbdd->kbdd_state.k_curkeyboard; 16217c478bd9Sstevel@tonic-gate if (kp == NULL) 16227c478bd9Sstevel@tonic-gate return (NULL); 16237c478bd9Sstevel@tonic-gate if (mask & UPMASK) 16247c478bd9Sstevel@tonic-gate return (kp->k_up); 16257c478bd9Sstevel@tonic-gate if (mask & NUMLOCKMASK) 16267c478bd9Sstevel@tonic-gate return (kp->k_numlock); 16277c478bd9Sstevel@tonic-gate if (mask & CTRLMASK) 16287c478bd9Sstevel@tonic-gate return (kp->k_control); 16297c478bd9Sstevel@tonic-gate if (mask & ALTGRAPHMASK) 16307c478bd9Sstevel@tonic-gate return (kp->k_altgraph); 16317c478bd9Sstevel@tonic-gate if (mask & SHIFTMASK) 16327c478bd9Sstevel@tonic-gate return (kp->k_shifted); 16337c478bd9Sstevel@tonic-gate if (mask & CAPSMASK) 16347c478bd9Sstevel@tonic-gate return (kp->k_caps); 16357c478bd9Sstevel@tonic-gate return (kp->k_normal); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate static void 16397c478bd9Sstevel@tonic-gate kbdrpt(void *arg) 16407c478bd9Sstevel@tonic-gate { 16417c478bd9Sstevel@tonic-gate struct kbddata *kbdd = arg; 16427c478bd9Sstevel@tonic-gate struct keyboardstate *k; 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 16457c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 16467c478bd9Sstevel@tonic-gate if (kbd_rpt_debug) 16477c478bd9Sstevel@tonic-gate printf("kbdrpt key %x\n", k->k_rptkey); 16487c478bd9Sstevel@tonic-gate #endif 16497c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate kbdkeyreleased(kbdd, KEYOF(k->k_rptkey)); 16527c478bd9Sstevel@tonic-gate kbduse(kbdd, k->k_rptkey); 16537c478bd9Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 16547c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt, 16557c478bd9Sstevel@tonic-gate kbdd, kbd_repeatrate); 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate } 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate static void 16607c478bd9Sstevel@tonic-gate kbdcancelrpt(register struct kbddata *kbdd) 16617c478bd9Sstevel@tonic-gate { 16627c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 16657c478bd9Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 16667c478bd9Sstevel@tonic-gate if (kbdd->kbdd_rptid) 16677c478bd9Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 16687c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 16697c478bd9Sstevel@tonic-gate k->k_rptkey = IDLEKEY; 16707c478bd9Sstevel@tonic-gate } 16717c478bd9Sstevel@tonic-gate ASSERT(kbdd->kbdd_rptid == 0); 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate static void 16757c478bd9Sstevel@tonic-gate kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q) 16767c478bd9Sstevel@tonic-gate { 16777c478bd9Sstevel@tonic-gate register uchar_t key; 16787c478bd9Sstevel@tonic-gate register unsigned newstate; 16797c478bd9Sstevel@tonic-gate unsigned shiftmask; 16807c478bd9Sstevel@tonic-gate register ushort_t entry, entrytype; 16817c478bd9Sstevel@tonic-gate register char *cp, *bufp; 16827c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 16837c478bd9Sstevel@tonic-gate ushort_t result_iso; 16847c478bd9Sstevel@tonic-gate struct keymap *km; 16857c478bd9Sstevel@tonic-gate Firm_event fe; 16867c478bd9Sstevel@tonic-gate int i, ret_val; 16877c478bd9Sstevel@tonic-gate char buf[14]; 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 16907c478bd9Sstevel@tonic-gate newstate = STATEOF(keycode); 16917c478bd9Sstevel@tonic-gate key = KEYOF(keycode); 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 16947c478bd9Sstevel@tonic-gate if (kbd_input_debug) { 16957c478bd9Sstevel@tonic-gate printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n", 16967c478bd9Sstevel@tonic-gate keycode, newstate, key); 16977c478bd9Sstevel@tonic-gate } 16987c478bd9Sstevel@tonic-gate #endif 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 17017c478bd9Sstevel@tonic-gate if (newstate == PRESSED) { 17027c478bd9Sstevel@tonic-gate bzero(&fe, sizeof (fe)); 17037c478bd9Sstevel@tonic-gate fe.id = key; 17047c478bd9Sstevel@tonic-gate fe.value = 1; 17057c478bd9Sstevel@tonic-gate kbdqueuepress(kbdd, key, &fe); 17067c478bd9Sstevel@tonic-gate } else { 17077c478bd9Sstevel@tonic-gate kbdkeyreleased(kbdd, key); 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate return; 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate shiftmask = k->k_shiftmask; 17137c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 17147c478bd9Sstevel@tonic-gate shiftmask |= UPMASK; 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate km = settable(kbdd, shiftmask); 17177c478bd9Sstevel@tonic-gate if (km == NULL) { /* gross error */ 17187c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 17197c478bd9Sstevel@tonic-gate return; 17207c478bd9Sstevel@tonic-gate } 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate if (key >= KEYMAP_SIZE) 17237c478bd9Sstevel@tonic-gate return; 17247c478bd9Sstevel@tonic-gate entry = km->keymap[key]; 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate if (entry == NONL) { 17277c478bd9Sstevel@tonic-gate /* 17287c478bd9Sstevel@tonic-gate * NONL appears only in the Num Lock table, and indicates that 17297c478bd9Sstevel@tonic-gate * this key is not affected by Num Lock. This means we should 17307c478bd9Sstevel@tonic-gate * ask for the table we would have gotten had Num Lock not been 17317c478bd9Sstevel@tonic-gate * down, and translate using that table. 17327c478bd9Sstevel@tonic-gate */ 17337c478bd9Sstevel@tonic-gate km = settable(kbdd, shiftmask & ~NUMLOCKMASK); 17347c478bd9Sstevel@tonic-gate if (km == NULL) { /* gross error */ 17357c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 17367c478bd9Sstevel@tonic-gate return; 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate entry = km->keymap[key]; 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate entrytype = (ushort_t)(entry & 0xFF00) >> 8; 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate if (entrytype == (SHIFTKEYS >> 8)) { 17437c478bd9Sstevel@tonic-gate /* 17447c478bd9Sstevel@tonic-gate * Handle the state of toggle shifts specially. 17457c478bd9Sstevel@tonic-gate * Ups should be ignored, and downs should be mapped to ups if 17467c478bd9Sstevel@tonic-gate * that shift is currently on. 17477c478bd9Sstevel@tonic-gate */ 17487c478bd9Sstevel@tonic-gate if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) { 17497c478bd9Sstevel@tonic-gate if ((1 << (entry & 0x0F)) & k->k_togglemask) { 17507c478bd9Sstevel@tonic-gate newstate = RELEASED; /* toggling off */ 17517c478bd9Sstevel@tonic-gate } else { 17527c478bd9Sstevel@tonic-gate newstate = PRESSED; /* toggling on */ 17537c478bd9Sstevel@tonic-gate } 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate } else { 17567c478bd9Sstevel@tonic-gate /* 17577c478bd9Sstevel@tonic-gate * Handle Compose and floating accent key sequences 17587c478bd9Sstevel@tonic-gate */ 17597c478bd9Sstevel@tonic-gate if (k->k_state == COMPOSE1) { 17607c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 17617c478bd9Sstevel@tonic-gate return; 17627c478bd9Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) { 17637c478bd9Sstevel@tonic-gate if (kb_compose_map[entry] >= 0) { 17647c478bd9Sstevel@tonic-gate kbdd->compose_key = entry; 17657c478bd9Sstevel@tonic-gate k->k_state = COMPOSE2; 17667c478bd9Sstevel@tonic-gate return; 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate } 17697c478bd9Sstevel@tonic-gate k->k_state = NORMAL; 17707c478bd9Sstevel@tonic-gate kbdd->led_state &= ~LED_COMPOSE; 17717c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 17727c478bd9Sstevel@tonic-gate return; 17737c478bd9Sstevel@tonic-gate } else if (k->k_state == COMPOSE2) { 17747c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 17757c478bd9Sstevel@tonic-gate return; 17767c478bd9Sstevel@tonic-gate k->k_state = NORMAL; /* next state is "normal" */ 17777c478bd9Sstevel@tonic-gate kbdd->led_state &= ~LED_COMPOSE; 17787c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 17797c478bd9Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) { 17807c478bd9Sstevel@tonic-gate if (kb_compose_map[entry] >= 0) { 17817c478bd9Sstevel@tonic-gate if (kbdd->compose_key <= entry) { 17827c478bd9Sstevel@tonic-gate ret_val = kbd_do_compose( 17837c478bd9Sstevel@tonic-gate kbdd->compose_key, 17847c478bd9Sstevel@tonic-gate entry, 17857c478bd9Sstevel@tonic-gate &result_iso); 17867c478bd9Sstevel@tonic-gate } else { 17877c478bd9Sstevel@tonic-gate ret_val = kbd_do_compose( 17887c478bd9Sstevel@tonic-gate entry, 17897c478bd9Sstevel@tonic-gate kbdd->compose_key, 17907c478bd9Sstevel@tonic-gate &result_iso); 17917c478bd9Sstevel@tonic-gate } 17927c478bd9Sstevel@tonic-gate if (ret_val == 1) { 17937c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == 17947c478bd9Sstevel@tonic-gate TR_EVENT) { 17957c478bd9Sstevel@tonic-gate fe.id = 17967c478bd9Sstevel@tonic-gate (kbdd->kbdd_compat ? 17977c478bd9Sstevel@tonic-gate ISO_FIRST : EUC_FIRST) 17987c478bd9Sstevel@tonic-gate + result_iso; 17997c478bd9Sstevel@tonic-gate fe.value = 1; 18007c478bd9Sstevel@tonic-gate kbdqueueevent( 18017c478bd9Sstevel@tonic-gate kbdd, 18027c478bd9Sstevel@tonic-gate &fe); 18037c478bd9Sstevel@tonic-gate } else if ( 18047c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == 18057c478bd9Sstevel@tonic-gate TR_ASCII) 18067c478bd9Sstevel@tonic-gate kbdputcode( 18077c478bd9Sstevel@tonic-gate result_iso, 18087c478bd9Sstevel@tonic-gate q); 18097c478bd9Sstevel@tonic-gate } 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate } 18127c478bd9Sstevel@tonic-gate return; 18137c478bd9Sstevel@tonic-gate } else if (k->k_state == FLTACCENT) { 18147c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 18157c478bd9Sstevel@tonic-gate return; 18167c478bd9Sstevel@tonic-gate k->k_state = NORMAL; /* next state is "normal" */ 18177c478bd9Sstevel@tonic-gate for (i = 0; 18187c478bd9Sstevel@tonic-gate (kb_fltaccent_table[i].fa_entry 18197c478bd9Sstevel@tonic-gate != kbdd->fltaccent_entry) || 18207c478bd9Sstevel@tonic-gate (kb_fltaccent_table[i].ascii != entry); 18217c478bd9Sstevel@tonic-gate i++) { 18227c478bd9Sstevel@tonic-gate if (kb_fltaccent_table[i].fa_entry == 0) 18237c478bd9Sstevel@tonic-gate /* Invalid second key: ignore key */ 18247c478bd9Sstevel@tonic-gate return; 18257c478bd9Sstevel@tonic-gate } 18267c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT) { 18277c478bd9Sstevel@tonic-gate fe.id = (kbdd->kbdd_compat ? 18287c478bd9Sstevel@tonic-gate ISO_FIRST : EUC_FIRST) 18297c478bd9Sstevel@tonic-gate + kb_fltaccent_table[i].iso; 18307c478bd9Sstevel@tonic-gate fe.value = 1; 18317c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 18327c478bd9Sstevel@tonic-gate } else if (kbdd->kbdd_translate == TR_ASCII) 18337c478bd9Sstevel@tonic-gate kbdputcode(kb_fltaccent_table[i].iso, q); 18347c478bd9Sstevel@tonic-gate return; 18357c478bd9Sstevel@tonic-gate } 18367c478bd9Sstevel@tonic-gate } 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate /* 18397c478bd9Sstevel@tonic-gate * If the key is going down, and it's not one of the keys that doesn't 18407c478bd9Sstevel@tonic-gate * auto-repeat, set up the auto-repeat timeout. 18417c478bd9Sstevel@tonic-gate * 18427c478bd9Sstevel@tonic-gate * The keys that don't auto-repeat are the Compose key, 18437c478bd9Sstevel@tonic-gate * the shift keys, the "bucky bit" keys, the "floating accent" keys, 18447c478bd9Sstevel@tonic-gate * and the function keys when in TR_EVENT mode. 18457c478bd9Sstevel@tonic-gate */ 18467c478bd9Sstevel@tonic-gate if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) && 18477c478bd9Sstevel@tonic-gate entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) && 18487c478bd9Sstevel@tonic-gate entrytype != (FA_CLASS >> 8) && 18497c478bd9Sstevel@tonic-gate !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) && 18507c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == TR_EVENT)) { 18517c478bd9Sstevel@tonic-gate if (k->k_rptkey != keycode) { 18527c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 18537c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd, 18547c478bd9Sstevel@tonic-gate kbd_repeatdelay); 18557c478bd9Sstevel@tonic-gate k->k_rptkey = keycode; 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate } else if (key == KEYOF(k->k_rptkey)) /* key going up */ 18587c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 18597c478bd9Sstevel@tonic-gate if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT)) 18607c478bd9Sstevel@tonic-gate kbdkeyreleased(kbdd, key); 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate /* 18637c478bd9Sstevel@tonic-gate * We assume here that keys other than shift keys and bucky keys have 18647c478bd9Sstevel@tonic-gate * entries in the "up" table that cause nothing to be done, and thus we 18657c478bd9Sstevel@tonic-gate * don't have to check for newstate == RELEASED. 18667c478bd9Sstevel@tonic-gate */ 18677c478bd9Sstevel@tonic-gate switch (entrytype) { 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate case 0x0: /* regular key */ 18707c478bd9Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate case TR_EVENT: 18737c478bd9Sstevel@tonic-gate fe.id = entry | k->k_buckybits; 18747c478bd9Sstevel@tonic-gate fe.value = 1; 18757c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, entry); 18767c478bd9Sstevel@tonic-gate break; 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate case TR_ASCII: 18797c478bd9Sstevel@tonic-gate kbdputcode(entry | k->k_buckybits, q); 18807c478bd9Sstevel@tonic-gate break; 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate break; 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate case SHIFTKEYS >> 8: { 18857c478bd9Sstevel@tonic-gate uint_t shiftbit = 1 << (entry & 0x0F); 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate /* Modify toggle state (see toggle processing above) */ 18887c478bd9Sstevel@tonic-gate if (shiftbit & k->k_curkeyboard->k_toggleshifts) { 18897c478bd9Sstevel@tonic-gate if (newstate == RELEASED) { 18907c478bd9Sstevel@tonic-gate if (shiftbit == CAPSMASK) { 18917c478bd9Sstevel@tonic-gate kbdd->led_state &= ~LED_CAPS_LOCK; 18927c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 18937c478bd9Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) { 18947c478bd9Sstevel@tonic-gate kbdd->led_state &= ~LED_NUM_LOCK; 18957c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 18967c478bd9Sstevel@tonic-gate } 18977c478bd9Sstevel@tonic-gate k->k_togglemask &= ~shiftbit; 18987c478bd9Sstevel@tonic-gate } else { 18997c478bd9Sstevel@tonic-gate if (shiftbit == CAPSMASK) { 19007c478bd9Sstevel@tonic-gate kbdd->led_state |= LED_CAPS_LOCK; 19017c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 19027c478bd9Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) { 19037c478bd9Sstevel@tonic-gate kbdd->led_state |= LED_NUM_LOCK; 19047c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate k->k_togglemask |= shiftbit; 19077c478bd9Sstevel@tonic-gate } 19087c478bd9Sstevel@tonic-gate } 19097c478bd9Sstevel@tonic-gate 19107c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 19117c478bd9Sstevel@tonic-gate k->k_shiftmask &= ~shiftbit; 19127c478bd9Sstevel@tonic-gate else 19137c478bd9Sstevel@tonic-gate k->k_shiftmask |= shiftbit; 19147c478bd9Sstevel@tonic-gate 19157c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 19167c478bd9Sstevel@tonic-gate /* 19177c478bd9Sstevel@tonic-gate * Relying on ordinal correspondence between 19187c478bd9Sstevel@tonic-gate * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL & 19197c478bd9Sstevel@tonic-gate * kbd.h CAPSLOCK-RIGHTCTRL in order to 19207c478bd9Sstevel@tonic-gate * correctly translate entry into fe.id. 19217c478bd9Sstevel@tonic-gate */ 19227c478bd9Sstevel@tonic-gate fe.id = SHIFT_CAPSLOCK + (entry & 0x0F); 19237c478bd9Sstevel@tonic-gate fe.value = 1; 19247c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate break; 19277c478bd9Sstevel@tonic-gate } 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate case BUCKYBITS >> 8: 19307c478bd9Sstevel@tonic-gate k->k_buckybits ^= 1 << (7 + (entry & 0x0F)); 19317c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 19327c478bd9Sstevel@tonic-gate /* 19337c478bd9Sstevel@tonic-gate * Relying on ordinal correspondence between 19347c478bd9Sstevel@tonic-gate * vuid_event.h SHIFT_META-SHIFT_TOP & 19357c478bd9Sstevel@tonic-gate * kbd.h METABIT-SYSTEMBIT in order to 19367c478bd9Sstevel@tonic-gate * correctly translate entry into fe.id. 19377c478bd9Sstevel@tonic-gate */ 19387c478bd9Sstevel@tonic-gate fe.id = SHIFT_META + (entry & 0x0F); 19397c478bd9Sstevel@tonic-gate fe.value = 1; 19407c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 19417c478bd9Sstevel@tonic-gate } 19427c478bd9Sstevel@tonic-gate break; 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate case FUNNY >> 8: 19457c478bd9Sstevel@tonic-gate switch (entry) { 19467c478bd9Sstevel@tonic-gate case NOP: 19477c478bd9Sstevel@tonic-gate break; 19487c478bd9Sstevel@tonic-gate 19497c478bd9Sstevel@tonic-gate case IDLE: 19507c478bd9Sstevel@tonic-gate /* Fall thru into RESET code */ 19517c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19527c478bd9Sstevel@tonic-gate case RESET: 19537c478bd9Sstevel@tonic-gate gotreset: 19547c478bd9Sstevel@tonic-gate k->k_shiftmask &= k->k_curkeyboard->k_idleshifts; 19557c478bd9Sstevel@tonic-gate k->k_shiftmask |= k->k_togglemask; 19567c478bd9Sstevel@tonic-gate k->k_buckybits &= k->k_curkeyboard->k_idlebuckys; 19577c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 19587c478bd9Sstevel@tonic-gate kbdreleaseall(kbdd); 19597c478bd9Sstevel@tonic-gate break; 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate case ERROR: 19627c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Error detected"); 19637c478bd9Sstevel@tonic-gate goto gotreset; 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate case COMPOSE: 19667c478bd9Sstevel@tonic-gate k->k_state = COMPOSE1; 19677c478bd9Sstevel@tonic-gate kbdd->led_state |= LED_COMPOSE; 19687c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 19697c478bd9Sstevel@tonic-gate break; 19707c478bd9Sstevel@tonic-gate /* 19717c478bd9Sstevel@tonic-gate * Remember when adding new entries that, 19727c478bd9Sstevel@tonic-gate * if they should NOT auto-repeat, 19737c478bd9Sstevel@tonic-gate * they should be put into the IF statement 19747c478bd9Sstevel@tonic-gate * just above this switch block. 19757c478bd9Sstevel@tonic-gate */ 19767c478bd9Sstevel@tonic-gate default: 19777c478bd9Sstevel@tonic-gate goto badentry; 19787c478bd9Sstevel@tonic-gate } 19797c478bd9Sstevel@tonic-gate break; 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate case FA_CLASS >> 8: 19827c478bd9Sstevel@tonic-gate if (k->k_state == NORMAL) { 19837c478bd9Sstevel@tonic-gate kbdd->fltaccent_entry = entry; 19847c478bd9Sstevel@tonic-gate k->k_state = FLTACCENT; 19857c478bd9Sstevel@tonic-gate } 19867c478bd9Sstevel@tonic-gate return; 19877c478bd9Sstevel@tonic-gate 19887c478bd9Sstevel@tonic-gate case STRING >> 8: 19897c478bd9Sstevel@tonic-gate cp = &keystringtab[entry & 0x0F][0]; 19907c478bd9Sstevel@tonic-gate while (*cp != '\0') { 19917c478bd9Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 19927c478bd9Sstevel@tonic-gate 19937c478bd9Sstevel@tonic-gate case TR_EVENT: 19947c478bd9Sstevel@tonic-gate kbd_send_esc_event(*cp, kbdd); 19957c478bd9Sstevel@tonic-gate break; 19967c478bd9Sstevel@tonic-gate 19977c478bd9Sstevel@tonic-gate case TR_ASCII: 19987c478bd9Sstevel@tonic-gate kbdputcode((uchar_t)*cp, q); 19997c478bd9Sstevel@tonic-gate break; 20007c478bd9Sstevel@tonic-gate } 20017c478bd9Sstevel@tonic-gate cp++; 20027c478bd9Sstevel@tonic-gate } 20037c478bd9Sstevel@tonic-gate break; 20047c478bd9Sstevel@tonic-gate 20057c478bd9Sstevel@tonic-gate case FUNCKEYS >> 8: 20067c478bd9Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 20077c478bd9Sstevel@tonic-gate 20087c478bd9Sstevel@tonic-gate case TR_ASCII: 20097c478bd9Sstevel@tonic-gate bufp = buf; 20107c478bd9Sstevel@tonic-gate cp = strsetwithdecimal(bufp + 2, 20117c478bd9Sstevel@tonic-gate (uint_t)((entry & 0x003F) + 192), 20127c478bd9Sstevel@tonic-gate sizeof (buf) - 5); 20137c478bd9Sstevel@tonic-gate *bufp++ = '\033'; /* Escape */ 20147c478bd9Sstevel@tonic-gate *bufp++ = '['; 20157c478bd9Sstevel@tonic-gate while (*cp != '\0') 20167c478bd9Sstevel@tonic-gate *bufp++ = *cp++; 20177c478bd9Sstevel@tonic-gate *bufp++ = 'z'; 20187c478bd9Sstevel@tonic-gate *bufp = '\0'; 20197c478bd9Sstevel@tonic-gate kbdputbuf(buf, q); 20207c478bd9Sstevel@tonic-gate break; 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate case TR_EVENT: 20237c478bd9Sstevel@tonic-gate /* 20247c478bd9Sstevel@tonic-gate * Take advantage of the similar 20257c478bd9Sstevel@tonic-gate * ordering of kbd.h function keys and 20267c478bd9Sstevel@tonic-gate * vuid_event.h function keys to do a 20277c478bd9Sstevel@tonic-gate * simple translation to achieve a 20287c478bd9Sstevel@tonic-gate * mapping between the 2 different 20297c478bd9Sstevel@tonic-gate * address spaces. 20307c478bd9Sstevel@tonic-gate */ 20317c478bd9Sstevel@tonic-gate fe.id = (entry & 0x003F) + KEY_LEFTFIRST; 20327c478bd9Sstevel@tonic-gate fe.value = 1; 20337c478bd9Sstevel@tonic-gate /* 20347c478bd9Sstevel@tonic-gate * Assume "up" table only generates 20357c478bd9Sstevel@tonic-gate * shift changes. 20367c478bd9Sstevel@tonic-gate */ 20377c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 20387c478bd9Sstevel@tonic-gate /* 20397c478bd9Sstevel@tonic-gate * Function key events can be expanded 20407c478bd9Sstevel@tonic-gate * by terminal emulator software to 20417c478bd9Sstevel@tonic-gate * produce the standard escape sequence 20427c478bd9Sstevel@tonic-gate * generated by the TR_ASCII case above 20437c478bd9Sstevel@tonic-gate * if a function key event is not used 20447c478bd9Sstevel@tonic-gate * by terminal emulator software 20457c478bd9Sstevel@tonic-gate * directly. 20467c478bd9Sstevel@tonic-gate */ 20477c478bd9Sstevel@tonic-gate break; 20487c478bd9Sstevel@tonic-gate } 20497c478bd9Sstevel@tonic-gate break; 20507c478bd9Sstevel@tonic-gate 20517c478bd9Sstevel@tonic-gate /* 20527c478bd9Sstevel@tonic-gate * Remember when adding new entries that, 20537c478bd9Sstevel@tonic-gate * if they should NOT auto-repeat, 20547c478bd9Sstevel@tonic-gate * they should be put into the IF statement 20557c478bd9Sstevel@tonic-gate * just above this switch block. 20567c478bd9Sstevel@tonic-gate */ 20577c478bd9Sstevel@tonic-gate case PADKEYS >> 8: 20587c478bd9Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate case TR_ASCII: 20617c478bd9Sstevel@tonic-gate kbdputcode(kb_numlock_table[entry&0x1F], q); 20627c478bd9Sstevel@tonic-gate break; 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate case TR_EVENT: 20657c478bd9Sstevel@tonic-gate /* 20667c478bd9Sstevel@tonic-gate * Take advantage of the similar 20677c478bd9Sstevel@tonic-gate * ordering of kbd.h keypad keys and 20687c478bd9Sstevel@tonic-gate * vuid_event.h keypad keys to do a 20697c478bd9Sstevel@tonic-gate * simple translation to achieve a 20707c478bd9Sstevel@tonic-gate * mapping between the 2 different 20717c478bd9Sstevel@tonic-gate * address spaces. 20727c478bd9Sstevel@tonic-gate */ 20737c478bd9Sstevel@tonic-gate fe.id = (entry & 0x001F) + VKEY_FIRSTPAD; 20747c478bd9Sstevel@tonic-gate fe.value = 1; 20757c478bd9Sstevel@tonic-gate /* 20767c478bd9Sstevel@tonic-gate * Assume "up" table only generates 20777c478bd9Sstevel@tonic-gate * shift changes. 20787c478bd9Sstevel@tonic-gate */ 20797c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 20807c478bd9Sstevel@tonic-gate /* 20817c478bd9Sstevel@tonic-gate * Keypad key events can be expanded 20827c478bd9Sstevel@tonic-gate * by terminal emulator software to 20837c478bd9Sstevel@tonic-gate * produce the standard ascii character 20847c478bd9Sstevel@tonic-gate * generated by the TR_ASCII case above 20857c478bd9Sstevel@tonic-gate * if a keypad key event is not used 20867c478bd9Sstevel@tonic-gate * by terminal emulator software 20877c478bd9Sstevel@tonic-gate * directly. 20887c478bd9Sstevel@tonic-gate */ 20897c478bd9Sstevel@tonic-gate break; 20907c478bd9Sstevel@tonic-gate } 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate badentry: 20937c478bd9Sstevel@tonic-gate break; 20947c478bd9Sstevel@tonic-gate } 20957c478bd9Sstevel@tonic-gate } 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate static int 20987c478bd9Sstevel@tonic-gate kbd_do_compose(ushort_t first_entry, ushort_t second_entry, 20997c478bd9Sstevel@tonic-gate ushort_t *result_iso_ptr) 21007c478bd9Sstevel@tonic-gate { 21017c478bd9Sstevel@tonic-gate struct compose_sequence_t *ptr; 21027c478bd9Sstevel@tonic-gate 21037c478bd9Sstevel@tonic-gate ptr = &kb_compose_table[kb_compose_map[first_entry]]; 21047c478bd9Sstevel@tonic-gate while (ptr->first == first_entry) { 21057c478bd9Sstevel@tonic-gate if (ptr->second == second_entry) { 21067c478bd9Sstevel@tonic-gate *result_iso_ptr = ptr->iso; 21077c478bd9Sstevel@tonic-gate return (1); 21087c478bd9Sstevel@tonic-gate } 21097c478bd9Sstevel@tonic-gate ptr++; 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate return (0); 21127c478bd9Sstevel@tonic-gate } 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate static void 21157c478bd9Sstevel@tonic-gate kbd_send_esc_event(char c, register struct kbddata *kbdd) 21167c478bd9Sstevel@tonic-gate { 21177c478bd9Sstevel@tonic-gate Firm_event fe; 21187c478bd9Sstevel@tonic-gate 21197c478bd9Sstevel@tonic-gate fe.id = c; 21207c478bd9Sstevel@tonic-gate fe.value = 1; 21217c478bd9Sstevel@tonic-gate fe.pair_type = FE_PAIR_NONE; 21227c478bd9Sstevel@tonic-gate fe.pair = 0; 21237c478bd9Sstevel@tonic-gate /* 21247c478bd9Sstevel@tonic-gate * Pretend as if each cp pushed and released 21257c478bd9Sstevel@tonic-gate * Calling kbdqueueevent avoids addr translation 21267c478bd9Sstevel@tonic-gate * and pair base determination of kbdkeypressed. 21277c478bd9Sstevel@tonic-gate */ 21287c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 21297c478bd9Sstevel@tonic-gate fe.value = 0; 21307c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 21317c478bd9Sstevel@tonic-gate } 21327c478bd9Sstevel@tonic-gate 21337c478bd9Sstevel@tonic-gate char * 21347c478bd9Sstevel@tonic-gate strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs) 21357c478bd9Sstevel@tonic-gate { 21367c478bd9Sstevel@tonic-gate int hradix = 5; 21377c478bd9Sstevel@tonic-gate char *bp; 21387c478bd9Sstevel@tonic-gate int lowbit; 21397c478bd9Sstevel@tonic-gate char *tab = "0123456789abcdef"; 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate bp = buf + maxdigs; 21427c478bd9Sstevel@tonic-gate *(--bp) = '\0'; 21437c478bd9Sstevel@tonic-gate while (val) { 21447c478bd9Sstevel@tonic-gate lowbit = val & 1; 21457c478bd9Sstevel@tonic-gate val = (val >> 1); 21467c478bd9Sstevel@tonic-gate *(--bp) = tab[val % hradix * 2 + lowbit]; 21477c478bd9Sstevel@tonic-gate val /= hradix; 21487c478bd9Sstevel@tonic-gate } 21497c478bd9Sstevel@tonic-gate return (bp); 21507c478bd9Sstevel@tonic-gate } 21517c478bd9Sstevel@tonic-gate 21527c478bd9Sstevel@tonic-gate static void 21537c478bd9Sstevel@tonic-gate kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe, 21547c478bd9Sstevel@tonic-gate ushort_t base) 21557c478bd9Sstevel@tonic-gate { 21567c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 21577c478bd9Sstevel@tonic-gate register short id_addr; 21587c478bd9Sstevel@tonic-gate 21597c478bd9Sstevel@tonic-gate /* Set pair values */ 21607c478bd9Sstevel@tonic-gate if (fe->id < (ushort_t)VKEY_FIRST) { 21617c478bd9Sstevel@tonic-gate /* 21627c478bd9Sstevel@tonic-gate * If CTRLed, find the ID that would have been used had it 21637c478bd9Sstevel@tonic-gate * not been CTRLed. 21647c478bd9Sstevel@tonic-gate */ 21657c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 21667c478bd9Sstevel@tonic-gate if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) { 21677c478bd9Sstevel@tonic-gate struct keymap *km; 21687c478bd9Sstevel@tonic-gate 21697c478bd9Sstevel@tonic-gate km = settable(kbdd, 21707c478bd9Sstevel@tonic-gate k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK)); 21717c478bd9Sstevel@tonic-gate if (km == NULL) 21727c478bd9Sstevel@tonic-gate return; 21737c478bd9Sstevel@tonic-gate base = km->keymap[key_station]; 21747c478bd9Sstevel@tonic-gate } 21757c478bd9Sstevel@tonic-gate if (base != fe->id) { 21767c478bd9Sstevel@tonic-gate fe->pair_type = FE_PAIR_SET; 21777c478bd9Sstevel@tonic-gate fe->pair = base; 21787c478bd9Sstevel@tonic-gate goto send; 21797c478bd9Sstevel@tonic-gate } 21807c478bd9Sstevel@tonic-gate } 21817c478bd9Sstevel@tonic-gate fe->pair_type = FE_PAIR_NONE; 21827c478bd9Sstevel@tonic-gate fe->pair = 0; 21837c478bd9Sstevel@tonic-gate send: 21847c478bd9Sstevel@tonic-gate /* Adjust event id address for multiple keyboard/workstation support */ 21857c478bd9Sstevel@tonic-gate switch (vuid_id_addr(fe->id)) { 21867c478bd9Sstevel@tonic-gate case ASCII_FIRST: 21877c478bd9Sstevel@tonic-gate id_addr = kbdd->kbdd_ascii_addr; 21887c478bd9Sstevel@tonic-gate break; 21897c478bd9Sstevel@tonic-gate case TOP_FIRST: 21907c478bd9Sstevel@tonic-gate id_addr = kbdd->kbdd_top_addr; 21917c478bd9Sstevel@tonic-gate break; 21927c478bd9Sstevel@tonic-gate case VKEY_FIRST: 21937c478bd9Sstevel@tonic-gate id_addr = kbdd->kbdd_vkey_addr; 21947c478bd9Sstevel@tonic-gate break; 21957c478bd9Sstevel@tonic-gate default: 21967c478bd9Sstevel@tonic-gate id_addr = vuid_id_addr(fe->id); 21977c478bd9Sstevel@tonic-gate } 21987c478bd9Sstevel@tonic-gate fe->id = vuid_id_offset(fe->id) | id_addr; 21997c478bd9Sstevel@tonic-gate kbdqueuepress(kbdd, key_station, fe); 22007c478bd9Sstevel@tonic-gate } 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate static void 22037c478bd9Sstevel@tonic-gate kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe) 22047c478bd9Sstevel@tonic-gate { 22057c478bd9Sstevel@tonic-gate register struct key_event *ke, *ke_free; 22067c478bd9Sstevel@tonic-gate register int i; 22077c478bd9Sstevel@tonic-gate 22087c478bd9Sstevel@tonic-gate if (key_station == IDLEKEY) 22097c478bd9Sstevel@tonic-gate return; 22107c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 22117c478bd9Sstevel@tonic-gate if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station); 22127c478bd9Sstevel@tonic-gate #endif 22137c478bd9Sstevel@tonic-gate ke_free = 0; 22147c478bd9Sstevel@tonic-gate /* Scan table of down key stations */ 22157c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT || 22167c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 22177c478bd9Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 22187c478bd9Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; 22197c478bd9Sstevel@tonic-gate i++, ke++) { 22207c478bd9Sstevel@tonic-gate /* Keycode already down? */ 22217c478bd9Sstevel@tonic-gate if (ke->key_station == key_station) { 22227c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 22237c478bd9Sstevel@tonic-gate printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i); 22247c478bd9Sstevel@tonic-gate #endif 22257c478bd9Sstevel@tonic-gate goto add_event; 22267c478bd9Sstevel@tonic-gate } 22277c478bd9Sstevel@tonic-gate if (ke->key_station == 0) 22287c478bd9Sstevel@tonic-gate ke_free = ke; 22297c478bd9Sstevel@tonic-gate } 22307c478bd9Sstevel@tonic-gate if (ke_free) { 22317c478bd9Sstevel@tonic-gate ke = ke_free; 22327c478bd9Sstevel@tonic-gate goto add_event; 22337c478bd9Sstevel@tonic-gate } 22347c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Too many keys down!"); 22357c478bd9Sstevel@tonic-gate ke = kbdd->kbdd_downs; 22367c478bd9Sstevel@tonic-gate } 22377c478bd9Sstevel@tonic-gate add_event: 22387c478bd9Sstevel@tonic-gate ke->key_station = key_station; 22397c478bd9Sstevel@tonic-gate ke->event = *fe; 22407c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, fe); 22417c478bd9Sstevel@tonic-gate } 22427c478bd9Sstevel@tonic-gate 22437c478bd9Sstevel@tonic-gate static void 22447c478bd9Sstevel@tonic-gate kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station) 22457c478bd9Sstevel@tonic-gate { 22467c478bd9Sstevel@tonic-gate register struct key_event *ke; 22477c478bd9Sstevel@tonic-gate register int i; 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate if (key_station == IDLEKEY) 22507c478bd9Sstevel@tonic-gate return; 22517c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 22527c478bd9Sstevel@tonic-gate if (kbd_input_debug) 22537c478bd9Sstevel@tonic-gate printf("KBD RELEASE key=%d\n", key_station); 22547c478bd9Sstevel@tonic-gate #endif 22557c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate != TR_EVENT && 22567c478bd9Sstevel@tonic-gate kbdd->kbdd_translate != TR_UNTRANS_EVENT) 22577c478bd9Sstevel@tonic-gate return; 22587c478bd9Sstevel@tonic-gate /* Scan table of down key stations */ 22597c478bd9Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 22607c478bd9Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; 22617c478bd9Sstevel@tonic-gate i++, ke++) { 22627c478bd9Sstevel@tonic-gate /* Found? */ 22637c478bd9Sstevel@tonic-gate if (ke->key_station == key_station) { 22647c478bd9Sstevel@tonic-gate ke->key_station = 0; 22657c478bd9Sstevel@tonic-gate ke->event.value = 0; 22667c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, &ke->event); 22677c478bd9Sstevel@tonic-gate } 22687c478bd9Sstevel@tonic-gate } 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate /* 22717c478bd9Sstevel@tonic-gate * Ignore if couldn't find because may be called twice 22727c478bd9Sstevel@tonic-gate * for the same key station in the case of the kbdrpt 22737c478bd9Sstevel@tonic-gate * routine being called unnecessarily. 22747c478bd9Sstevel@tonic-gate */ 22757c478bd9Sstevel@tonic-gate } 22767c478bd9Sstevel@tonic-gate 22777c478bd9Sstevel@tonic-gate static void 22787c478bd9Sstevel@tonic-gate kbdreleaseall(struct kbddata *kbdd) 22797c478bd9Sstevel@tonic-gate { 22807c478bd9Sstevel@tonic-gate register struct key_event *ke; 22817c478bd9Sstevel@tonic-gate register int i; 22827c478bd9Sstevel@tonic-gate 22837c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 22847c478bd9Sstevel@tonic-gate if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n"); 22857c478bd9Sstevel@tonic-gate #endif 22867c478bd9Sstevel@tonic-gate /* Scan table of down key stations */ 22877c478bd9Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 22887c478bd9Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; i++, ke++) { 22897c478bd9Sstevel@tonic-gate /* Key station not zero */ 22907c478bd9Sstevel@tonic-gate if (ke->key_station) 22917c478bd9Sstevel@tonic-gate kbdkeyreleased(kbdd, ke->key_station); 22927c478bd9Sstevel@tonic-gate /* kbdkeyreleased resets kbdd_downs entry */ 22937c478bd9Sstevel@tonic-gate } 22947c478bd9Sstevel@tonic-gate } 22957c478bd9Sstevel@tonic-gate 22967c478bd9Sstevel@tonic-gate /* 22977c478bd9Sstevel@tonic-gate * Pass a keycode up the stream, if you can, otherwise throw it away. 22987c478bd9Sstevel@tonic-gate */ 22997c478bd9Sstevel@tonic-gate static void 23007c478bd9Sstevel@tonic-gate kbdputcode(uint_t code, queue_t *q) 23017c478bd9Sstevel@tonic-gate { 23027c478bd9Sstevel@tonic-gate register mblk_t *bp; 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate if (!canput(q)) 23057c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode"); 23067c478bd9Sstevel@tonic-gate else { 23077c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) 23087c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 23097c478bd9Sstevel@tonic-gate "kbdputcode: Can't allocate block for keycode"); 23107c478bd9Sstevel@tonic-gate else { 23117c478bd9Sstevel@tonic-gate *bp->b_wptr++ = code; 23127c478bd9Sstevel@tonic-gate putnext(q, bp); 23137c478bd9Sstevel@tonic-gate } 23147c478bd9Sstevel@tonic-gate } 23157c478bd9Sstevel@tonic-gate } 23167c478bd9Sstevel@tonic-gate 23177c478bd9Sstevel@tonic-gate /* 23187c478bd9Sstevel@tonic-gate * Pass generated keycode sequence to upstream, if possible. 23197c478bd9Sstevel@tonic-gate */ 23207c478bd9Sstevel@tonic-gate static void 23217c478bd9Sstevel@tonic-gate kbdputbuf(char *buf, queue_t *q) 23227c478bd9Sstevel@tonic-gate { 23237c478bd9Sstevel@tonic-gate register mblk_t *bp; 23247c478bd9Sstevel@tonic-gate 23257c478bd9Sstevel@tonic-gate if (!canput(q)) 23267c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode"); 23277c478bd9Sstevel@tonic-gate else { 23287c478bd9Sstevel@tonic-gate if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) 23297c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 23307c478bd9Sstevel@tonic-gate "kbdputbuf: Can't allocate block for keycode"); 23317c478bd9Sstevel@tonic-gate else { 23327c478bd9Sstevel@tonic-gate while (*buf) { 23337c478bd9Sstevel@tonic-gate *bp->b_wptr++ = *buf; 23347c478bd9Sstevel@tonic-gate buf++; 23357c478bd9Sstevel@tonic-gate } 23367c478bd9Sstevel@tonic-gate putnext(q, bp); 23377c478bd9Sstevel@tonic-gate } 23387c478bd9Sstevel@tonic-gate } 23397c478bd9Sstevel@tonic-gate } 23407c478bd9Sstevel@tonic-gate 23417c478bd9Sstevel@tonic-gate /* 23427c478bd9Sstevel@tonic-gate * Pass a VUID "firm event" up the stream, if you can. 23437c478bd9Sstevel@tonic-gate */ 23447c478bd9Sstevel@tonic-gate static void 23457c478bd9Sstevel@tonic-gate kbdqueueevent(struct kbddata *kbdd, Firm_event *fe) 23467c478bd9Sstevel@tonic-gate { 23477c478bd9Sstevel@tonic-gate register queue_t *q; 23487c478bd9Sstevel@tonic-gate register mblk_t *bp; 23497c478bd9Sstevel@tonic-gate 23507c478bd9Sstevel@tonic-gate if ((q = kbdd->kbdd_readq) == NULL) 23517c478bd9Sstevel@tonic-gate return; 23527c478bd9Sstevel@tonic-gate if (!canput(q)) { 23537c478bd9Sstevel@tonic-gate if (kbd_overflow_msg) 23547c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 23557c478bd9Sstevel@tonic-gate "kbd: Buffer flushed when overflowed"); 23567c478bd9Sstevel@tonic-gate kbdflush(kbdd); 23577c478bd9Sstevel@tonic-gate kbd_overflow_cnt++; 23587c478bd9Sstevel@tonic-gate } else { 23597c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) 23607c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 23617c478bd9Sstevel@tonic-gate "kbdqueueevent: Can't allocate block for event"); 23627c478bd9Sstevel@tonic-gate else { 23637c478bd9Sstevel@tonic-gate #if 1 /* XX64 */ 23647c478bd9Sstevel@tonic-gate struct timeval now; 23657c478bd9Sstevel@tonic-gate 23667c478bd9Sstevel@tonic-gate /* 23677c478bd9Sstevel@tonic-gate * XX64: This is something of a compromise. It 23687c478bd9Sstevel@tonic-gate * seems justifiable based on the usage of these 23697c478bd9Sstevel@tonic-gate * timestamps as an ordering relation as opposed 23707c478bd9Sstevel@tonic-gate * to a strict timing thing. 23717c478bd9Sstevel@tonic-gate * 23727c478bd9Sstevel@tonic-gate * But should we restore Firm_event's time stamp 23737c478bd9Sstevel@tonic-gate * to be a timeval, and send 32-bit and 64-bit 23747c478bd9Sstevel@tonic-gate * events up the pipe? 23757c478bd9Sstevel@tonic-gate */ 23767c478bd9Sstevel@tonic-gate uniqtime(&now); 23777c478bd9Sstevel@tonic-gate TIMEVAL_TO_TIMEVAL32(&fe->time, &now); 23787c478bd9Sstevel@tonic-gate #else 23797c478bd9Sstevel@tonic-gate uniqtime(&fe->time); 23807c478bd9Sstevel@tonic-gate #endif 23817c478bd9Sstevel@tonic-gate *(Firm_event *)bp->b_wptr = *fe; 23827c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event); 23837c478bd9Sstevel@tonic-gate putnext(q, bp); 23847c478bd9Sstevel@tonic-gate } 23857c478bd9Sstevel@tonic-gate } 23867c478bd9Sstevel@tonic-gate } 2387