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