1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Console mouse driver for Sun. 31*7c478bd9Sstevel@tonic-gate * The console "zs" port is linked under us, with the "ms" module pushed 32*7c478bd9Sstevel@tonic-gate * on top of it. 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * This device merely provides a way to have "/dev/mouse" automatically 35*7c478bd9Sstevel@tonic-gate * have the "ms" module present. Due to problems with the way the "specfs" 36*7c478bd9Sstevel@tonic-gate * file system works, you can't use an indirect device (a "stat" on 37*7c478bd9Sstevel@tonic-gate * "/dev/mouse" won't get the right snode, so you won't get the right time 38*7c478bd9Sstevel@tonic-gate * of last access), and due to problems with the kernel window system code, 39*7c478bd9Sstevel@tonic-gate * you can't use a "cons"-like driver ("/dev/mouse" won't be a streams device, 40*7c478bd9Sstevel@tonic-gate * even though operations on it get turned into operations on the real stream). 41*7c478bd9Sstevel@tonic-gate * 42*7c478bd9Sstevel@tonic-gate * This module supports multiple mice connected to the system at the same time. 43*7c478bd9Sstevel@tonic-gate * All the mice are linked under consms, and act as a mouse with replicated 44*7c478bd9Sstevel@tonic-gate * clicks. Only USB and PS/2 mouse are supported to be virtual mouse now. 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/vuid_wheel.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/msio.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/consms.h> 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static void consms_plink(queue_t *, mblk_t *); 65*7c478bd9Sstevel@tonic-gate static int consms_punlink(queue_t *, mblk_t *); 66*7c478bd9Sstevel@tonic-gate static void 67*7c478bd9Sstevel@tonic-gate consms_lqs_ack_complete(consms_lq_t *, mblk_t *); 68*7c478bd9Sstevel@tonic-gate static void consms_add_lq(consms_lq_t *); 69*7c478bd9Sstevel@tonic-gate static void consms_check_caps(void); 70*7c478bd9Sstevel@tonic-gate static mblk_t *consms_new_firm_event(int, int); 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate static void consms_mux_max_wheel_report(mblk_t *); 73*7c478bd9Sstevel@tonic-gate static void consms_mux_cache_states(mblk_t *); 74*7c478bd9Sstevel@tonic-gate static void consms_mux_link_msg(consms_msg_t *); 75*7c478bd9Sstevel@tonic-gate static consms_msg_t *consms_mux_unlink_msg(uint_t); 76*7c478bd9Sstevel@tonic-gate static consms_msg_t *consms_mux_find_msg(uint_t); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate static void consms_mux_iocdata(consms_msg_t *, mblk_t *); 79*7c478bd9Sstevel@tonic-gate static void consms_mux_disp_iocdata(consms_response_t *, mblk_t *); 80*7c478bd9Sstevel@tonic-gate static int consms_mux_disp_ioctl(queue_t *, mblk_t *); 81*7c478bd9Sstevel@tonic-gate static void consms_mux_copyreq(queue_t *, consms_msg_t *, mblk_t *); 82*7c478bd9Sstevel@tonic-gate static void consms_mux_ack(consms_msg_t *, mblk_t *); 83*7c478bd9Sstevel@tonic-gate static void consms_mux_disp_data(mblk_t *); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate static int consmsopen(); 87*7c478bd9Sstevel@tonic-gate static int consmsclose(); 88*7c478bd9Sstevel@tonic-gate static void consmsuwput(); 89*7c478bd9Sstevel@tonic-gate static void consmslrput(); 90*7c478bd9Sstevel@tonic-gate static void consmslwserv(); 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static struct module_info consmsm_info = { 93*7c478bd9Sstevel@tonic-gate 0, 94*7c478bd9Sstevel@tonic-gate "consms", 95*7c478bd9Sstevel@tonic-gate 0, 96*7c478bd9Sstevel@tonic-gate 1024, 97*7c478bd9Sstevel@tonic-gate 2048, 98*7c478bd9Sstevel@tonic-gate 128 99*7c478bd9Sstevel@tonic-gate }; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate static struct qinit consmsurinit = { 102*7c478bd9Sstevel@tonic-gate putq, 103*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 104*7c478bd9Sstevel@tonic-gate consmsopen, 105*7c478bd9Sstevel@tonic-gate consmsclose, 106*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 107*7c478bd9Sstevel@tonic-gate &consmsm_info, 108*7c478bd9Sstevel@tonic-gate NULL 109*7c478bd9Sstevel@tonic-gate }; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate static struct qinit consmsuwinit = { 112*7c478bd9Sstevel@tonic-gate (int (*)())consmsuwput, 113*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 114*7c478bd9Sstevel@tonic-gate consmsopen, 115*7c478bd9Sstevel@tonic-gate consmsclose, 116*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 117*7c478bd9Sstevel@tonic-gate &consmsm_info, 118*7c478bd9Sstevel@tonic-gate NULL 119*7c478bd9Sstevel@tonic-gate }; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate static struct qinit consmslrinit = { 122*7c478bd9Sstevel@tonic-gate (int (*)())consmslrput, 123*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 124*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 125*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 126*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 127*7c478bd9Sstevel@tonic-gate &consmsm_info, 128*7c478bd9Sstevel@tonic-gate NULL 129*7c478bd9Sstevel@tonic-gate }; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate static struct qinit consmslwinit = { 132*7c478bd9Sstevel@tonic-gate putq, 133*7c478bd9Sstevel@tonic-gate (int (*)())consmslwserv, 134*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 135*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 136*7c478bd9Sstevel@tonic-gate (int (*)())NULL, 137*7c478bd9Sstevel@tonic-gate &consmsm_info, 138*7c478bd9Sstevel@tonic-gate NULL 139*7c478bd9Sstevel@tonic-gate }; 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate static struct streamtab consms_str_info = { 142*7c478bd9Sstevel@tonic-gate &consmsurinit, 143*7c478bd9Sstevel@tonic-gate &consmsuwinit, 144*7c478bd9Sstevel@tonic-gate &consmslrinit, 145*7c478bd9Sstevel@tonic-gate &consmslwinit, 146*7c478bd9Sstevel@tonic-gate }; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate static void consmsioctl(queue_t *q, mblk_t *mp); 149*7c478bd9Sstevel@tonic-gate static int consms_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 150*7c478bd9Sstevel@tonic-gate void **result); 151*7c478bd9Sstevel@tonic-gate static int consms_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 152*7c478bd9Sstevel@tonic-gate static int consms_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 153*7c478bd9Sstevel@tonic-gate static int consms_kstat_update(kstat_t *, int); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* 156*7c478bd9Sstevel@tonic-gate * Module global data are protected by the per-module inner perimeter. 157*7c478bd9Sstevel@tonic-gate */ 158*7c478bd9Sstevel@tonic-gate static queue_t *upperqueue; /* regular mouse queue above us */ 159*7c478bd9Sstevel@tonic-gate static dev_info_t *consms_dip; /* private copy of devinfo pointer */ 160*7c478bd9Sstevel@tonic-gate static long consms_idle_stamp; /* seconds tstamp of latest mouse op */ 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate static consms_msg_t *consms_mux_msg; /* ioctl messages being processed */ 163*7c478bd9Sstevel@tonic-gate static kmutex_t consms_msg_lock; /* protect ioctl messages list */ 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate static consms_state_t consms_state; /* the global virtual mouse state */ 166*7c478bd9Sstevel@tonic-gate static kmutex_t consmslock; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * Normally, kstats of type KSTAT_TYPE_NAMED have multiple elements. In 171*7c478bd9Sstevel@tonic-gate * this case we use this type for a single element because the ioctl code 172*7c478bd9Sstevel@tonic-gate * for it knows how to handle mixed kernel/user data models. Also, it 173*7c478bd9Sstevel@tonic-gate * will be easier to add new statistics later. 174*7c478bd9Sstevel@tonic-gate */ 175*7c478bd9Sstevel@tonic-gate static struct { 176*7c478bd9Sstevel@tonic-gate kstat_named_t idle_sec; /* seconds since last user op */ 177*7c478bd9Sstevel@tonic-gate } consms_kstat = { 178*7c478bd9Sstevel@tonic-gate { "idle_sec", KSTAT_DATA_LONG, } 179*7c478bd9Sstevel@tonic-gate }; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate static struct cb_ops cb_consms_ops = { 183*7c478bd9Sstevel@tonic-gate nulldev, /* cb_open */ 184*7c478bd9Sstevel@tonic-gate nulldev, /* cb_close */ 185*7c478bd9Sstevel@tonic-gate nodev, /* cb_strategy */ 186*7c478bd9Sstevel@tonic-gate nodev, /* cb_print */ 187*7c478bd9Sstevel@tonic-gate nodev, /* cb_dump */ 188*7c478bd9Sstevel@tonic-gate nodev, /* cb_read */ 189*7c478bd9Sstevel@tonic-gate nodev, /* cb_write */ 190*7c478bd9Sstevel@tonic-gate nodev, /* cb_ioctl */ 191*7c478bd9Sstevel@tonic-gate nodev, /* cb_devmap */ 192*7c478bd9Sstevel@tonic-gate nodev, /* cb_mmap */ 193*7c478bd9Sstevel@tonic-gate nodev, /* cb_segmap */ 194*7c478bd9Sstevel@tonic-gate nochpoll, /* cb_chpoll */ 195*7c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 196*7c478bd9Sstevel@tonic-gate &consms_str_info, /* cb_stream */ 197*7c478bd9Sstevel@tonic-gate D_MP | D_MTPERMOD /* cb_flag */ 198*7c478bd9Sstevel@tonic-gate }; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate static struct dev_ops consms_ops = { 201*7c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev */ 202*7c478bd9Sstevel@tonic-gate 0, /* devo_refcnt */ 203*7c478bd9Sstevel@tonic-gate consms_info, /* devo_getinfo */ 204*7c478bd9Sstevel@tonic-gate nulldev, /* devo_identify */ 205*7c478bd9Sstevel@tonic-gate nulldev, /* devo_probe */ 206*7c478bd9Sstevel@tonic-gate consms_attach, /* devo_attach */ 207*7c478bd9Sstevel@tonic-gate consms_detach, /* devo_detach */ 208*7c478bd9Sstevel@tonic-gate nodev, /* devo_reset */ 209*7c478bd9Sstevel@tonic-gate &(cb_consms_ops), /* devo_cb_ops */ 210*7c478bd9Sstevel@tonic-gate (struct bus_ops *)NULL, /* devo_bus_ops */ 211*7c478bd9Sstevel@tonic-gate NULL /* devo_power */ 212*7c478bd9Sstevel@tonic-gate }; 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 220*7c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a pseudo driver */ 221*7c478bd9Sstevel@tonic-gate "Mouse Driver for Sun 'consms' %I%", 222*7c478bd9Sstevel@tonic-gate &consms_ops, /* driver ops */ 223*7c478bd9Sstevel@tonic-gate }; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 226*7c478bd9Sstevel@tonic-gate MODREV_1, 227*7c478bd9Sstevel@tonic-gate (void *)&modldrv, 228*7c478bd9Sstevel@tonic-gate NULL 229*7c478bd9Sstevel@tonic-gate }; 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate int 232*7c478bd9Sstevel@tonic-gate _init(void) 233*7c478bd9Sstevel@tonic-gate { 234*7c478bd9Sstevel@tonic-gate int error; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate mutex_init(&consmslock, NULL, MUTEX_DRIVER, NULL); 237*7c478bd9Sstevel@tonic-gate mutex_init(&consms_msg_lock, NULL, MUTEX_DRIVER, NULL); 238*7c478bd9Sstevel@tonic-gate error = mod_install(&modlinkage); 239*7c478bd9Sstevel@tonic-gate if (error != 0) { 240*7c478bd9Sstevel@tonic-gate mutex_destroy(&consmslock); 241*7c478bd9Sstevel@tonic-gate mutex_destroy(&consms_msg_lock); 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate return (error); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate int 247*7c478bd9Sstevel@tonic-gate _fini(void) 248*7c478bd9Sstevel@tonic-gate { 249*7c478bd9Sstevel@tonic-gate int error; 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate error = mod_remove(&modlinkage); 252*7c478bd9Sstevel@tonic-gate if (error != 0) 253*7c478bd9Sstevel@tonic-gate return (error); 254*7c478bd9Sstevel@tonic-gate mutex_destroy(&consmslock); 255*7c478bd9Sstevel@tonic-gate mutex_destroy(&consms_msg_lock); 256*7c478bd9Sstevel@tonic-gate return (0); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate int 260*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 261*7c478bd9Sstevel@tonic-gate { 262*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate static int 266*7c478bd9Sstevel@tonic-gate consms_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 267*7c478bd9Sstevel@tonic-gate { 268*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate switch (cmd) { 271*7c478bd9Sstevel@tonic-gate case DDI_ATTACH: 272*7c478bd9Sstevel@tonic-gate break; 273*7c478bd9Sstevel@tonic-gate default: 274*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(devi, "mouse", S_IFCHR, 278*7c478bd9Sstevel@tonic-gate 0, DDI_PSEUDO, NULL) == DDI_FAILURE) { 279*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 280*7c478bd9Sstevel@tonic-gate return (-1); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate consms_dip = devi; 283*7c478bd9Sstevel@tonic-gate (void) ddi_prop_update_int(DDI_DEV_T_NONE, devi, DDI_NO_AUTODETACH, 1); 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate ksp = kstat_create("consms", 0, "activity", "misc", KSTAT_TYPE_NAMED, 286*7c478bd9Sstevel@tonic-gate sizeof (consms_kstat) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 287*7c478bd9Sstevel@tonic-gate if (ksp) { 288*7c478bd9Sstevel@tonic-gate ksp->ks_data = (void *)&consms_kstat; 289*7c478bd9Sstevel@tonic-gate ksp->ks_update = consms_kstat_update; 290*7c478bd9Sstevel@tonic-gate kstat_install(ksp); 291*7c478bd9Sstevel@tonic-gate consms_idle_stamp = gethrestime_sec(); /* initial value */ 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate consms_state.consms_lqs = NULL; 295*7c478bd9Sstevel@tonic-gate consms_state.consms_num_lqs = 0; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate /* default consms state values */ 298*7c478bd9Sstevel@tonic-gate consms_state.consms_vuid_format = VUID_FIRM_EVENT; 299*7c478bd9Sstevel@tonic-gate consms_state.consms_num_buttons = 0; 300*7c478bd9Sstevel@tonic-gate consms_state.consms_num_wheels = 0; 301*7c478bd9Sstevel@tonic-gate consms_state.consms_wheel_state_bf |= VUID_WHEEL_STATE_ENABLED; 302*7c478bd9Sstevel@tonic-gate consms_state.consms_ms_parms.jitter_thresh = 303*7c478bd9Sstevel@tonic-gate CONSMS_PARMS_DEFAULT_JITTER; 304*7c478bd9Sstevel@tonic-gate consms_state.consms_ms_parms.speed_limit = 305*7c478bd9Sstevel@tonic-gate CONSMS_PARMS_DEFAULT_SPEED_LIMIT; 306*7c478bd9Sstevel@tonic-gate consms_state.consms_ms_parms.speed_law = 307*7c478bd9Sstevel@tonic-gate CONSMS_PARMS_DEFAULT_SPEED_LAW; 308*7c478bd9Sstevel@tonic-gate consms_state.consms_ms_sr.height = CONSMS_SR_DEFAULT_HEIGHT; 309*7c478bd9Sstevel@tonic-gate consms_state.consms_ms_sr.width = CONSMS_SR_DEFAULT_WIDTH; 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 315*7c478bd9Sstevel@tonic-gate static int 316*7c478bd9Sstevel@tonic-gate consms_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate switch (cmd) { 319*7c478bd9Sstevel@tonic-gate case DDI_DETACH: 320*7c478bd9Sstevel@tonic-gate default: 321*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 326*7c478bd9Sstevel@tonic-gate static int 327*7c478bd9Sstevel@tonic-gate consms_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 328*7c478bd9Sstevel@tonic-gate void **result) 329*7c478bd9Sstevel@tonic-gate { 330*7c478bd9Sstevel@tonic-gate register int error; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate switch (infocmd) { 333*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 334*7c478bd9Sstevel@tonic-gate if (consms_dip == NULL) { 335*7c478bd9Sstevel@tonic-gate error = DDI_FAILURE; 336*7c478bd9Sstevel@tonic-gate } else { 337*7c478bd9Sstevel@tonic-gate *result = (void *) consms_dip; 338*7c478bd9Sstevel@tonic-gate error = DDI_SUCCESS; 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate break; 341*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 342*7c478bd9Sstevel@tonic-gate *result = (void *)0; 343*7c478bd9Sstevel@tonic-gate error = DDI_SUCCESS; 344*7c478bd9Sstevel@tonic-gate break; 345*7c478bd9Sstevel@tonic-gate default: 346*7c478bd9Sstevel@tonic-gate error = DDI_FAILURE; 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate return (error); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 353*7c478bd9Sstevel@tonic-gate static int 354*7c478bd9Sstevel@tonic-gate consmsopen(q, devp, flag, sflag, crp) 355*7c478bd9Sstevel@tonic-gate queue_t *q; 356*7c478bd9Sstevel@tonic-gate dev_t *devp; 357*7c478bd9Sstevel@tonic-gate int flag, sflag; 358*7c478bd9Sstevel@tonic-gate cred_t *crp; 359*7c478bd9Sstevel@tonic-gate { 360*7c478bd9Sstevel@tonic-gate upperqueue = q; 361*7c478bd9Sstevel@tonic-gate qprocson(q); 362*7c478bd9Sstevel@tonic-gate return (0); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 366*7c478bd9Sstevel@tonic-gate static int 367*7c478bd9Sstevel@tonic-gate consmsclose(q, flag, crp) 368*7c478bd9Sstevel@tonic-gate queue_t *q; 369*7c478bd9Sstevel@tonic-gate int flag; 370*7c478bd9Sstevel@tonic-gate cred_t *crp; 371*7c478bd9Sstevel@tonic-gate { 372*7c478bd9Sstevel@tonic-gate qprocsoff(q); 373*7c478bd9Sstevel@tonic-gate upperqueue = NULL; 374*7c478bd9Sstevel@tonic-gate return (0); 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate /* 378*7c478bd9Sstevel@tonic-gate * Put procedure for upper write queue. 379*7c478bd9Sstevel@tonic-gate */ 380*7c478bd9Sstevel@tonic-gate static void 381*7c478bd9Sstevel@tonic-gate consmsuwput(q, mp) 382*7c478bd9Sstevel@tonic-gate register queue_t *q; 383*7c478bd9Sstevel@tonic-gate register mblk_t *mp; 384*7c478bd9Sstevel@tonic-gate { 385*7c478bd9Sstevel@tonic-gate struct iocblk *iocbp = (struct iocblk *)mp->b_rptr; 386*7c478bd9Sstevel@tonic-gate consms_msg_t *msg; 387*7c478bd9Sstevel@tonic-gate int error = 0; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate case M_IOCTL: 392*7c478bd9Sstevel@tonic-gate consmsioctl(q, mp); 393*7c478bd9Sstevel@tonic-gate break; 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate case M_FLUSH: 396*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 397*7c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 398*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 399*7c478bd9Sstevel@tonic-gate flushq(RD(q), FLUSHDATA); 400*7c478bd9Sstevel@tonic-gate if (consms_state.consms_num_lqs > 0) { 401*7c478bd9Sstevel@tonic-gate consms_mux_disp_data(mp); 402*7c478bd9Sstevel@tonic-gate } else { 403*7c478bd9Sstevel@tonic-gate /* 404*7c478bd9Sstevel@tonic-gate * No lower queue; just reflect this back upstream. 405*7c478bd9Sstevel@tonic-gate */ 406*7c478bd9Sstevel@tonic-gate *mp->b_rptr &= ~FLUSHW; 407*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 408*7c478bd9Sstevel@tonic-gate qreply(q, mp); 409*7c478bd9Sstevel@tonic-gate else 410*7c478bd9Sstevel@tonic-gate freemsg(mp); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate break; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate case M_DATA: 415*7c478bd9Sstevel@tonic-gate if (consms_state.consms_num_lqs > 0) { 416*7c478bd9Sstevel@tonic-gate consms_mux_disp_data(mp); 417*7c478bd9Sstevel@tonic-gate } else { 418*7c478bd9Sstevel@tonic-gate error = EINVAL; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate break; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate case M_IOCDATA: 423*7c478bd9Sstevel@tonic-gate if ((msg = consms_mux_find_msg(iocbp->ioc_id)) != NULL) { 424*7c478bd9Sstevel@tonic-gate consms_mux_iocdata(msg, mp); 425*7c478bd9Sstevel@tonic-gate } else { 426*7c478bd9Sstevel@tonic-gate error = EINVAL; 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate break; 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate default: 431*7c478bd9Sstevel@tonic-gate error = EINVAL; 432*7c478bd9Sstevel@tonic-gate break; 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate if (error) { 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate * Pass an error message up. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 440*7c478bd9Sstevel@tonic-gate if (mp->b_cont) { 441*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 442*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 445*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 446*7c478bd9Sstevel@tonic-gate *mp->b_rptr = (char)error; 447*7c478bd9Sstevel@tonic-gate qreply(q, mp); 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate static void 452*7c478bd9Sstevel@tonic-gate consmsioctl(q, mp) 453*7c478bd9Sstevel@tonic-gate register queue_t *q; 454*7c478bd9Sstevel@tonic-gate register mblk_t *mp; 455*7c478bd9Sstevel@tonic-gate { 456*7c478bd9Sstevel@tonic-gate register struct iocblk *iocp; 457*7c478bd9Sstevel@tonic-gate int error; 458*7c478bd9Sstevel@tonic-gate mblk_t *datap; 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate case I_LINK: 465*7c478bd9Sstevel@tonic-gate case I_PLINK: 466*7c478bd9Sstevel@tonic-gate mutex_enter(&consmslock); 467*7c478bd9Sstevel@tonic-gate consms_plink(q, mp); 468*7c478bd9Sstevel@tonic-gate mutex_exit(&consmslock); 469*7c478bd9Sstevel@tonic-gate return; 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate case I_UNLINK: 472*7c478bd9Sstevel@tonic-gate case I_PUNLINK: 473*7c478bd9Sstevel@tonic-gate mutex_enter(&consmslock); 474*7c478bd9Sstevel@tonic-gate if ((error = consms_punlink(q, mp)) != 0) { 475*7c478bd9Sstevel@tonic-gate mutex_exit(&consmslock); 476*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 477*7c478bd9Sstevel@tonic-gate return; 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate mutex_exit(&consmslock); 480*7c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 481*7c478bd9Sstevel@tonic-gate break; 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate case MSIOBUTTONS: /* query the number of buttons */ 484*7c478bd9Sstevel@tonic-gate if ((consms_state.consms_num_lqs <= 0) || 485*7c478bd9Sstevel@tonic-gate ((datap = allocb(sizeof (int), BPRI_HI)) == NULL)) { 486*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 487*7c478bd9Sstevel@tonic-gate return; 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = consms_state.consms_num_buttons; 490*7c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 491*7c478bd9Sstevel@tonic-gate if (mp->b_cont) { 492*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate mp->b_cont = datap; 495*7c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 496*7c478bd9Sstevel@tonic-gate break; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate default: 499*7c478bd9Sstevel@tonic-gate /* 500*7c478bd9Sstevel@tonic-gate * Pass this through, if there's something to pass it 501*7c478bd9Sstevel@tonic-gate * through to; otherwise, reject it. 502*7c478bd9Sstevel@tonic-gate */ 503*7c478bd9Sstevel@tonic-gate if (consms_state.consms_num_lqs <= 0) { 504*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 505*7c478bd9Sstevel@tonic-gate return; 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate if ((error = consms_mux_disp_ioctl(q, mp)) != 0) 508*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate return; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate /* 514*7c478bd9Sstevel@tonic-gate * Common exit path for calls that return a positive 515*7c478bd9Sstevel@tonic-gate * acknowledgment with a return value of 0. 516*7c478bd9Sstevel@tonic-gate */ 517*7c478bd9Sstevel@tonic-gate miocack(q, mp, iocp->ioc_count, 0); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate /* 521*7c478bd9Sstevel@tonic-gate * Service procedure for lower write queue. 522*7c478bd9Sstevel@tonic-gate * Puts things on the queue below us, if it lets us. 523*7c478bd9Sstevel@tonic-gate */ 524*7c478bd9Sstevel@tonic-gate static void 525*7c478bd9Sstevel@tonic-gate consmslwserv(q) 526*7c478bd9Sstevel@tonic-gate register queue_t *q; 527*7c478bd9Sstevel@tonic-gate { 528*7c478bd9Sstevel@tonic-gate register mblk_t *mp; 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate while (canput(q->q_next) && (mp = getq(q)) != NULL) 531*7c478bd9Sstevel@tonic-gate putnext(q, mp); 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate /* 535*7c478bd9Sstevel@tonic-gate * Put procedure for lower read queue. 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate static void 538*7c478bd9Sstevel@tonic-gate consmslrput(q, mp) 539*7c478bd9Sstevel@tonic-gate register queue_t *q; 540*7c478bd9Sstevel@tonic-gate register mblk_t *mp; 541*7c478bd9Sstevel@tonic-gate { 542*7c478bd9Sstevel@tonic-gate struct iocblk *iocbp = (struct iocblk *)mp->b_rptr; 543*7c478bd9Sstevel@tonic-gate struct copyreq *copyreq = (struct copyreq *)mp->b_rptr; 544*7c478bd9Sstevel@tonic-gate consms_msg_t *msg; 545*7c478bd9Sstevel@tonic-gate consms_lq_t *lq = (consms_lq_t *)q->q_ptr; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate ASSERT(lq != NULL); 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 550*7c478bd9Sstevel@tonic-gate case M_FLUSH: 551*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 552*7c478bd9Sstevel@tonic-gate flushq(WR(q), FLUSHDATA); 553*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 554*7c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 555*7c478bd9Sstevel@tonic-gate if (upperqueue != NULL) 556*7c478bd9Sstevel@tonic-gate putnext(upperqueue, mp); /* pass it through */ 557*7c478bd9Sstevel@tonic-gate else { 558*7c478bd9Sstevel@tonic-gate /* 559*7c478bd9Sstevel@tonic-gate * No upper queue; just reflect this back downstream. 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate *mp->b_rptr &= ~FLUSHR; 562*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 563*7c478bd9Sstevel@tonic-gate qreply(q, mp); 564*7c478bd9Sstevel@tonic-gate else 565*7c478bd9Sstevel@tonic-gate freemsg(mp); 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate break; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate case M_DATA: 570*7c478bd9Sstevel@tonic-gate if (upperqueue != NULL) 571*7c478bd9Sstevel@tonic-gate putnext(upperqueue, mp); 572*7c478bd9Sstevel@tonic-gate else 573*7c478bd9Sstevel@tonic-gate freemsg(mp); 574*7c478bd9Sstevel@tonic-gate consms_idle_stamp = gethrestime_sec(); 575*7c478bd9Sstevel@tonic-gate break; 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate case M_IOCACK: 578*7c478bd9Sstevel@tonic-gate case M_IOCNAK: 579*7c478bd9Sstevel@tonic-gate /* 580*7c478bd9Sstevel@tonic-gate * First, check to see if this device 581*7c478bd9Sstevel@tonic-gate * is still being initialized. 582*7c478bd9Sstevel@tonic-gate */ 583*7c478bd9Sstevel@tonic-gate if (lq->lq_ioc_reply_func != NULL) { 584*7c478bd9Sstevel@tonic-gate mutex_enter(&consmslock); 585*7c478bd9Sstevel@tonic-gate lq->lq_ioc_reply_func(lq, mp); 586*7c478bd9Sstevel@tonic-gate mutex_exit(&consmslock); 587*7c478bd9Sstevel@tonic-gate freemsg(mp); 588*7c478bd9Sstevel@tonic-gate break; 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate /* 592*7c478bd9Sstevel@tonic-gate * This is normal ioctl ack for upper layer. 593*7c478bd9Sstevel@tonic-gate */ 594*7c478bd9Sstevel@tonic-gate if ((msg = consms_mux_find_msg(iocbp->ioc_id)) != NULL) { 595*7c478bd9Sstevel@tonic-gate consms_mux_ack(msg, mp); 596*7c478bd9Sstevel@tonic-gate } else { 597*7c478bd9Sstevel@tonic-gate freemsg(mp); 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate consms_idle_stamp = gethrestime_sec(); 600*7c478bd9Sstevel@tonic-gate break; 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate case M_COPYIN: 603*7c478bd9Sstevel@tonic-gate case M_COPYOUT: 604*7c478bd9Sstevel@tonic-gate if ((msg = consms_mux_find_msg(copyreq->cq_id)) != NULL) { 605*7c478bd9Sstevel@tonic-gate consms_mux_copyreq(q, msg, mp); 606*7c478bd9Sstevel@tonic-gate } else 607*7c478bd9Sstevel@tonic-gate freemsg(mp); 608*7c478bd9Sstevel@tonic-gate consms_idle_stamp = gethrestime_sec(); 609*7c478bd9Sstevel@tonic-gate break; 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate case M_ERROR: 612*7c478bd9Sstevel@tonic-gate case M_HANGUP: 613*7c478bd9Sstevel@tonic-gate default: 614*7c478bd9Sstevel@tonic-gate freemsg(mp); /* anything useful here? */ 615*7c478bd9Sstevel@tonic-gate break; 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 620*7c478bd9Sstevel@tonic-gate static int 621*7c478bd9Sstevel@tonic-gate consms_kstat_update(kstat_t *ksp, int rw) 622*7c478bd9Sstevel@tonic-gate { 623*7c478bd9Sstevel@tonic-gate if (rw == KSTAT_WRITE) 624*7c478bd9Sstevel@tonic-gate return (EACCES); 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate consms_kstat.idle_sec.value.l = gethrestime_sec() - consms_idle_stamp; 627*7c478bd9Sstevel@tonic-gate return (0); 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 631*7c478bd9Sstevel@tonic-gate static int 632*7c478bd9Sstevel@tonic-gate consms_punlink(queue_t *q, mblk_t *mp) 633*7c478bd9Sstevel@tonic-gate { 634*7c478bd9Sstevel@tonic-gate struct linkblk *linkp; 635*7c478bd9Sstevel@tonic-gate consms_lq_t *lq; 636*7c478bd9Sstevel@tonic-gate consms_lq_t *prev_lq; 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&consmslock)); 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate linkp = (struct linkblk *)mp->b_cont->b_rptr; 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate prev_lq = NULL; 643*7c478bd9Sstevel@tonic-gate for (lq = consms_state.consms_lqs; lq != NULL; lq = lq->lq_next) { 644*7c478bd9Sstevel@tonic-gate if (lq->lq_queue == linkp->l_qbot) { 645*7c478bd9Sstevel@tonic-gate if (prev_lq) 646*7c478bd9Sstevel@tonic-gate prev_lq->lq_next = lq->lq_next; 647*7c478bd9Sstevel@tonic-gate else 648*7c478bd9Sstevel@tonic-gate consms_state.consms_lqs = lq->lq_next; 649*7c478bd9Sstevel@tonic-gate kmem_free(lq, sizeof (*lq)); 650*7c478bd9Sstevel@tonic-gate consms_state.consms_num_lqs--; 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate /* 653*7c478bd9Sstevel@tonic-gate * Check to see if mouse capabilities 654*7c478bd9Sstevel@tonic-gate * have changed. 655*7c478bd9Sstevel@tonic-gate */ 656*7c478bd9Sstevel@tonic-gate consms_check_caps(); 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate return (0); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate prev_lq = lq; 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate return (EINVAL); 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate /* 667*7c478bd9Sstevel@tonic-gate * Link a specific mouse into our mouse list. 668*7c478bd9Sstevel@tonic-gate */ 669*7c478bd9Sstevel@tonic-gate static void 670*7c478bd9Sstevel@tonic-gate consms_plink(queue_t *q, mblk_t *mp) 671*7c478bd9Sstevel@tonic-gate { 672*7c478bd9Sstevel@tonic-gate struct linkblk *linkp; 673*7c478bd9Sstevel@tonic-gate consms_lq_t *lq; 674*7c478bd9Sstevel@tonic-gate queue_t *lowq; 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&consmslock)); 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate linkp = (struct linkblk *)mp->b_cont->b_rptr; 679*7c478bd9Sstevel@tonic-gate lowq = linkp->l_qbot; 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate lq = kmem_zalloc(sizeof (*lq), KM_SLEEP); 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate lowq->q_ptr = (void *)lq; 684*7c478bd9Sstevel@tonic-gate OTHERQ(lowq)->q_ptr = (void *)lq; 685*7c478bd9Sstevel@tonic-gate lq->lq_queue = lowq; 686*7c478bd9Sstevel@tonic-gate lq->lq_pending_plink = mp; 687*7c478bd9Sstevel@tonic-gate lq->lq_pending_queue = q; 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* 690*7c478bd9Sstevel@tonic-gate * Set the number of buttons to 3 by default 691*7c478bd9Sstevel@tonic-gate * in case the following MSIOBUTTONS ioctl fails. 692*7c478bd9Sstevel@tonic-gate */ 693*7c478bd9Sstevel@tonic-gate lq->lq_num_buttons = 3; 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate /* 696*7c478bd9Sstevel@tonic-gate * Begin to initialize this mouse. 697*7c478bd9Sstevel@tonic-gate */ 698*7c478bd9Sstevel@tonic-gate lq->lq_state = LQS_START; 699*7c478bd9Sstevel@tonic-gate consms_lqs_ack_complete(lq, NULL); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate /* 703*7c478bd9Sstevel@tonic-gate * Initialize the newly hotplugged-in mouse, 704*7c478bd9Sstevel@tonic-gate * e.g. get the number of buttons, set event 705*7c478bd9Sstevel@tonic-gate * format. Then we add it into our list. 706*7c478bd9Sstevel@tonic-gate */ 707*7c478bd9Sstevel@tonic-gate static void 708*7c478bd9Sstevel@tonic-gate consms_lqs_ack_complete(consms_lq_t *lq, mblk_t *mp) 709*7c478bd9Sstevel@tonic-gate { 710*7c478bd9Sstevel@tonic-gate mblk_t *req = NULL; 711*7c478bd9Sstevel@tonic-gate boolean_t skipped = B_FALSE; 712*7c478bd9Sstevel@tonic-gate wheel_state *ws; 713*7c478bd9Sstevel@tonic-gate Ms_screen_resolution *sr; 714*7c478bd9Sstevel@tonic-gate Ms_parms *params; 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&consmslock)); 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate /* 719*7c478bd9Sstevel@tonic-gate * We try each ioctl even if the previous one fails 720*7c478bd9Sstevel@tonic-gate * until we reach LQS_DONE, and then add this lq 721*7c478bd9Sstevel@tonic-gate * into our lq list. 722*7c478bd9Sstevel@tonic-gate * 723*7c478bd9Sstevel@tonic-gate * If the message allocation fails, we skip this ioctl, 724*7c478bd9Sstevel@tonic-gate * set skipped flag to B_TRUE in order to skip the ioctl 725*7c478bd9Sstevel@tonic-gate * result, then we try next ioctl, go to next state. 726*7c478bd9Sstevel@tonic-gate */ 727*7c478bd9Sstevel@tonic-gate while ((lq->lq_state < LQS_DONE) && (req == NULL)) { 728*7c478bd9Sstevel@tonic-gate switch (lq->lq_state) { 729*7c478bd9Sstevel@tonic-gate case LQS_START: 730*7c478bd9Sstevel@tonic-gate /* 731*7c478bd9Sstevel@tonic-gate * First, issue MSIOBUTTONS ioctl 732*7c478bd9Sstevel@tonic-gate * to get the number of buttons. 733*7c478bd9Sstevel@tonic-gate */ 734*7c478bd9Sstevel@tonic-gate req = mkiocb(MSIOBUTTONS); 735*7c478bd9Sstevel@tonic-gate if (req && ((req->b_cont = allocb(sizeof (int), 736*7c478bd9Sstevel@tonic-gate BPRI_MED)) == NULL)) { 737*7c478bd9Sstevel@tonic-gate freemsg(req); 738*7c478bd9Sstevel@tonic-gate req = NULL; 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate if (req == NULL) 741*7c478bd9Sstevel@tonic-gate skipped = B_TRUE; 742*7c478bd9Sstevel@tonic-gate lq->lq_state++; 743*7c478bd9Sstevel@tonic-gate break; 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate case LQS_BUTTON_COUNT_PENDING: 746*7c478bd9Sstevel@tonic-gate if (!skipped && mp && mp->b_cont && 747*7c478bd9Sstevel@tonic-gate (mp->b_datap->db_type == M_IOCACK)) 748*7c478bd9Sstevel@tonic-gate lq->lq_num_buttons = 749*7c478bd9Sstevel@tonic-gate *(int *)mp->b_cont->b_rptr; 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate /* 752*7c478bd9Sstevel@tonic-gate * Second, issue VUIDGWHEELCOUNT ioctl 753*7c478bd9Sstevel@tonic-gate * to get the count of wheels. 754*7c478bd9Sstevel@tonic-gate */ 755*7c478bd9Sstevel@tonic-gate req = mkiocb(VUIDGWHEELCOUNT); 756*7c478bd9Sstevel@tonic-gate if (req && ((req->b_cont = allocb(sizeof (int), 757*7c478bd9Sstevel@tonic-gate BPRI_MED)) == NULL)) { 758*7c478bd9Sstevel@tonic-gate freemsg(req); 759*7c478bd9Sstevel@tonic-gate req = NULL; 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate if (req == NULL) 762*7c478bd9Sstevel@tonic-gate skipped = B_TRUE; 763*7c478bd9Sstevel@tonic-gate lq->lq_state++; 764*7c478bd9Sstevel@tonic-gate break; 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate case LQS_WHEEL_COUNT_PENDING: 767*7c478bd9Sstevel@tonic-gate if (!skipped && mp && mp->b_cont && 768*7c478bd9Sstevel@tonic-gate (mp->b_datap->db_type == M_IOCACK)) 769*7c478bd9Sstevel@tonic-gate lq->lq_num_wheels = 770*7c478bd9Sstevel@tonic-gate *(int *)mp->b_cont->b_rptr; 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate /* 773*7c478bd9Sstevel@tonic-gate * Third, issue VUIDSFORMAT ioctl 774*7c478bd9Sstevel@tonic-gate * to set the event format. 775*7c478bd9Sstevel@tonic-gate */ 776*7c478bd9Sstevel@tonic-gate req = mkiocb(VUIDSFORMAT); 777*7c478bd9Sstevel@tonic-gate if (req && ((req->b_cont = allocb(sizeof (int), 778*7c478bd9Sstevel@tonic-gate BPRI_MED)) == NULL)) { 779*7c478bd9Sstevel@tonic-gate freemsg(req); 780*7c478bd9Sstevel@tonic-gate req = NULL; 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate if (req) { 783*7c478bd9Sstevel@tonic-gate *(int *)req->b_cont->b_wptr = 784*7c478bd9Sstevel@tonic-gate consms_state.consms_vuid_format; 785*7c478bd9Sstevel@tonic-gate req->b_cont->b_wptr += sizeof (int); 786*7c478bd9Sstevel@tonic-gate } 787*7c478bd9Sstevel@tonic-gate lq->lq_state++; 788*7c478bd9Sstevel@tonic-gate break; 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate case LQS_SET_VUID_FORMAT_PENDING: 791*7c478bd9Sstevel@tonic-gate /* 792*7c478bd9Sstevel@tonic-gate * Fourth, issue VUIDSWHEELSTATE ioctl 793*7c478bd9Sstevel@tonic-gate * to set the wheel state (enable or disable). 794*7c478bd9Sstevel@tonic-gate */ 795*7c478bd9Sstevel@tonic-gate req = mkiocb(VUIDSWHEELSTATE); 796*7c478bd9Sstevel@tonic-gate if (req && ((req->b_cont = allocb(sizeof (wheel_state), 797*7c478bd9Sstevel@tonic-gate BPRI_MED)) == NULL)) { 798*7c478bd9Sstevel@tonic-gate freemsg(req); 799*7c478bd9Sstevel@tonic-gate req = NULL; 800*7c478bd9Sstevel@tonic-gate } 801*7c478bd9Sstevel@tonic-gate if (req) { 802*7c478bd9Sstevel@tonic-gate ws = (wheel_state *)req->b_cont->b_wptr; 803*7c478bd9Sstevel@tonic-gate ws->vers = VUID_WHEEL_STATE_VERS; 804*7c478bd9Sstevel@tonic-gate ws->id = 0; /* the first wheel */ 805*7c478bd9Sstevel@tonic-gate ws->stateflags = 806*7c478bd9Sstevel@tonic-gate consms_state.consms_wheel_state_bf & 1; 807*7c478bd9Sstevel@tonic-gate req->b_cont->b_wptr += sizeof (wheel_state); 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate lq->lq_state++; 810*7c478bd9Sstevel@tonic-gate break; 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate case LQS_SET_WHEEL_STATE_PENDING: 813*7c478bd9Sstevel@tonic-gate /* 814*7c478bd9Sstevel@tonic-gate * Fifth, issue MSIOSRESOLUTION ioctl 815*7c478bd9Sstevel@tonic-gate * to set the screen resolution for absolute mouse. 816*7c478bd9Sstevel@tonic-gate */ 817*7c478bd9Sstevel@tonic-gate req = mkiocb(MSIOSRESOLUTION); 818*7c478bd9Sstevel@tonic-gate if (req && ((req->b_cont = 819*7c478bd9Sstevel@tonic-gate allocb(sizeof (Ms_screen_resolution), 820*7c478bd9Sstevel@tonic-gate BPRI_MED)) == NULL)) { 821*7c478bd9Sstevel@tonic-gate freemsg(req); 822*7c478bd9Sstevel@tonic-gate req = NULL; 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate if (req) { 825*7c478bd9Sstevel@tonic-gate sr = 826*7c478bd9Sstevel@tonic-gate (Ms_screen_resolution *)req->b_cont->b_wptr; 827*7c478bd9Sstevel@tonic-gate *sr = consms_state.consms_ms_sr; 828*7c478bd9Sstevel@tonic-gate req->b_cont->b_wptr += 829*7c478bd9Sstevel@tonic-gate sizeof (Ms_screen_resolution); 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate lq->lq_state++; 832*7c478bd9Sstevel@tonic-gate break; 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate case LQS_SET_RESOLUTION_PENDING: 835*7c478bd9Sstevel@tonic-gate /* 836*7c478bd9Sstevel@tonic-gate * Sixth, issue MSIOSETPARMS ioctl 837*7c478bd9Sstevel@tonic-gate * to set the parameters for USB mouse. 838*7c478bd9Sstevel@tonic-gate */ 839*7c478bd9Sstevel@tonic-gate req = mkiocb(MSIOSETPARMS); 840*7c478bd9Sstevel@tonic-gate if (req && ((req->b_cont = allocb(sizeof (Ms_parms), 841*7c478bd9Sstevel@tonic-gate BPRI_MED)) == NULL)) { 842*7c478bd9Sstevel@tonic-gate freemsg(req); 843*7c478bd9Sstevel@tonic-gate req = NULL; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate if (req) { 846*7c478bd9Sstevel@tonic-gate params = (Ms_parms *)req->b_cont->b_wptr; 847*7c478bd9Sstevel@tonic-gate *params = consms_state.consms_ms_parms; 848*7c478bd9Sstevel@tonic-gate req->b_cont->b_wptr += sizeof (Ms_parms); 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate lq->lq_state++; 851*7c478bd9Sstevel@tonic-gate break; 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate case LQS_SET_PARMS_PENDING: 854*7c478bd9Sstevel@tonic-gate /* 855*7c478bd9Sstevel@tonic-gate * All jobs are done, lq->lq_state is turned into 856*7c478bd9Sstevel@tonic-gate * LQS_DONE, and this lq is added into our list. 857*7c478bd9Sstevel@tonic-gate */ 858*7c478bd9Sstevel@tonic-gate lq->lq_state++; 859*7c478bd9Sstevel@tonic-gate consms_add_lq(lq); 860*7c478bd9Sstevel@tonic-gate break; 861*7c478bd9Sstevel@tonic-gate } 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate if (lq->lq_state < LQS_DONE) { 865*7c478bd9Sstevel@tonic-gate lq->lq_ioc_reply_func = consms_lqs_ack_complete; 866*7c478bd9Sstevel@tonic-gate (void) putq(lq->lq_queue, req); 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate /* 871*7c478bd9Sstevel@tonic-gate * Add this specific lq into our list, finally reply 872*7c478bd9Sstevel@tonic-gate * the previous pending I_PLINK ioctl. Also check to 873*7c478bd9Sstevel@tonic-gate * see if mouse capabilities have changed, and send 874*7c478bd9Sstevel@tonic-gate * a dynamical notification event to upper layer if 875*7c478bd9Sstevel@tonic-gate * necessary. 876*7c478bd9Sstevel@tonic-gate */ 877*7c478bd9Sstevel@tonic-gate static void 878*7c478bd9Sstevel@tonic-gate consms_add_lq(consms_lq_t *lq) 879*7c478bd9Sstevel@tonic-gate { 880*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&consmslock)); 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate lq->lq_ioc_reply_func = NULL; 885*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)lq->lq_pending_plink->b_rptr; 886*7c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; 887*7c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 888*7c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0; 889*7c478bd9Sstevel@tonic-gate lq->lq_pending_plink->b_datap->db_type = M_IOCACK; 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate /* Reply to the I_PLINK ioctl. */ 892*7c478bd9Sstevel@tonic-gate qreply(lq->lq_pending_queue, lq->lq_pending_plink); 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate lq->lq_pending_plink = NULL; 895*7c478bd9Sstevel@tonic-gate lq->lq_pending_queue = NULL; 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate /* 898*7c478bd9Sstevel@tonic-gate * Add this lq into list. 899*7c478bd9Sstevel@tonic-gate */ 900*7c478bd9Sstevel@tonic-gate consms_state.consms_num_lqs++; 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate lq->lq_next = consms_state.consms_lqs; 903*7c478bd9Sstevel@tonic-gate consms_state.consms_lqs = lq; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate /* 906*7c478bd9Sstevel@tonic-gate * Check to see if mouse capabilities 907*7c478bd9Sstevel@tonic-gate * have changed. 908*7c478bd9Sstevel@tonic-gate */ 909*7c478bd9Sstevel@tonic-gate consms_check_caps(); 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate static void 915*7c478bd9Sstevel@tonic-gate consms_check_caps(void) 916*7c478bd9Sstevel@tonic-gate { 917*7c478bd9Sstevel@tonic-gate consms_lq_t *lq; 918*7c478bd9Sstevel@tonic-gate int max_buttons = 0; 919*7c478bd9Sstevel@tonic-gate int max_wheels = 0; 920*7c478bd9Sstevel@tonic-gate mblk_t *mp; 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate /* 923*7c478bd9Sstevel@tonic-gate * Check to see if the number of buttons 924*7c478bd9Sstevel@tonic-gate * and the number of wheels have changed. 925*7c478bd9Sstevel@tonic-gate */ 926*7c478bd9Sstevel@tonic-gate for (lq = consms_state.consms_lqs; lq != NULL; lq = lq->lq_next) { 927*7c478bd9Sstevel@tonic-gate max_buttons = CONSMS_MAX(max_buttons, lq->lq_num_buttons); 928*7c478bd9Sstevel@tonic-gate max_wheels = CONSMS_MAX(max_wheels, lq->lq_num_wheels); 929*7c478bd9Sstevel@tonic-gate } 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate if (max_buttons != consms_state.consms_num_buttons) { 932*7c478bd9Sstevel@tonic-gate /* 933*7c478bd9Sstevel@tonic-gate * Since the number of buttons have changed, 934*7c478bd9Sstevel@tonic-gate * send a MOUSE_CAP_CHANGE_NUM_BUT dynamical 935*7c478bd9Sstevel@tonic-gate * notification event to upper layer. 936*7c478bd9Sstevel@tonic-gate */ 937*7c478bd9Sstevel@tonic-gate consms_state.consms_num_buttons = max_buttons; 938*7c478bd9Sstevel@tonic-gate if (upperqueue != NULL) { 939*7c478bd9Sstevel@tonic-gate if ((mp = consms_new_firm_event( 940*7c478bd9Sstevel@tonic-gate MOUSE_CAP_CHANGE_NUM_BUT, 941*7c478bd9Sstevel@tonic-gate consms_state.consms_num_buttons)) != NULL) { 942*7c478bd9Sstevel@tonic-gate putnext(upperqueue, mp); 943*7c478bd9Sstevel@tonic-gate } 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate if (max_wheels != consms_state.consms_num_wheels) { 948*7c478bd9Sstevel@tonic-gate /* 949*7c478bd9Sstevel@tonic-gate * Since the number of wheels have changed, 950*7c478bd9Sstevel@tonic-gate * send a MOUSE_CAP_CHANGE_NUM_WHEEL dynamical 951*7c478bd9Sstevel@tonic-gate * notification event to upper layer. 952*7c478bd9Sstevel@tonic-gate */ 953*7c478bd9Sstevel@tonic-gate consms_state.consms_num_wheels = max_wheels; 954*7c478bd9Sstevel@tonic-gate if (upperqueue != NULL) { 955*7c478bd9Sstevel@tonic-gate if ((mp = consms_new_firm_event( 956*7c478bd9Sstevel@tonic-gate MOUSE_CAP_CHANGE_NUM_WHEEL, 957*7c478bd9Sstevel@tonic-gate consms_state.consms_num_wheels)) != NULL) { 958*7c478bd9Sstevel@tonic-gate putnext(upperqueue, mp); 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate /* 965*7c478bd9Sstevel@tonic-gate * Allocate a dynamical notification event. 966*7c478bd9Sstevel@tonic-gate */ 967*7c478bd9Sstevel@tonic-gate static mblk_t * 968*7c478bd9Sstevel@tonic-gate consms_new_firm_event(int id, int value) 969*7c478bd9Sstevel@tonic-gate { 970*7c478bd9Sstevel@tonic-gate Firm_event *fep; 971*7c478bd9Sstevel@tonic-gate mblk_t *tmp; 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if ((tmp = allocb(sizeof (Firm_event), BPRI_HI)) != NULL) { 974*7c478bd9Sstevel@tonic-gate fep = (Firm_event *)tmp->b_wptr; 975*7c478bd9Sstevel@tonic-gate fep->id = id; 976*7c478bd9Sstevel@tonic-gate fep->pair_type = FE_PAIR_NONE; 977*7c478bd9Sstevel@tonic-gate fep->pair = NULL; 978*7c478bd9Sstevel@tonic-gate fep->value = value; 979*7c478bd9Sstevel@tonic-gate tmp->b_wptr += sizeof (Firm_event); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate return (tmp); 983*7c478bd9Sstevel@tonic-gate } 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate /* 986*7c478bd9Sstevel@tonic-gate * Start of dispatching interfaces as a multiplexor 987*7c478bd9Sstevel@tonic-gate */ 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate /* 990*7c478bd9Sstevel@tonic-gate * There is a global msg list (consms_mux_msg), 991*7c478bd9Sstevel@tonic-gate * which is used to link all ioctl messages from 992*7c478bd9Sstevel@tonic-gate * upper layer, which are currently being processed. 993*7c478bd9Sstevel@tonic-gate * 994*7c478bd9Sstevel@tonic-gate * consms_mux_link_msg links a msg into the list, 995*7c478bd9Sstevel@tonic-gate * consms_mux_unlink_msg unlinks a msg from the list, 996*7c478bd9Sstevel@tonic-gate * consms_mux_find_msg finds a msg from the list 997*7c478bd9Sstevel@tonic-gate * according to its unique id. 998*7c478bd9Sstevel@tonic-gate * 999*7c478bd9Sstevel@tonic-gate * The id of each msg is taken from stream's mp, 1000*7c478bd9Sstevel@tonic-gate * so the id is supposed to be unique. 1001*7c478bd9Sstevel@tonic-gate */ 1002*7c478bd9Sstevel@tonic-gate static void 1003*7c478bd9Sstevel@tonic-gate consms_mux_link_msg(consms_msg_t *msg) 1004*7c478bd9Sstevel@tonic-gate { 1005*7c478bd9Sstevel@tonic-gate mutex_enter(&consms_msg_lock); 1006*7c478bd9Sstevel@tonic-gate msg->msg_next = consms_mux_msg; 1007*7c478bd9Sstevel@tonic-gate consms_mux_msg = msg; 1008*7c478bd9Sstevel@tonic-gate mutex_exit(&consms_msg_lock); 1009*7c478bd9Sstevel@tonic-gate } 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate static consms_msg_t * 1012*7c478bd9Sstevel@tonic-gate consms_mux_unlink_msg(uint_t msg_id) 1013*7c478bd9Sstevel@tonic-gate { 1014*7c478bd9Sstevel@tonic-gate consms_msg_t *msg; 1015*7c478bd9Sstevel@tonic-gate consms_msg_t *prev_msg; 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate mutex_enter(&consms_msg_lock); 1018*7c478bd9Sstevel@tonic-gate prev_msg = NULL; 1019*7c478bd9Sstevel@tonic-gate for (msg = consms_mux_msg; msg != NULL; 1020*7c478bd9Sstevel@tonic-gate prev_msg = msg, msg = msg->msg_next) { 1021*7c478bd9Sstevel@tonic-gate if (msg->msg_id == msg_id) 1022*7c478bd9Sstevel@tonic-gate break; 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate if (msg != NULL) { 1026*7c478bd9Sstevel@tonic-gate if (prev_msg != NULL) { 1027*7c478bd9Sstevel@tonic-gate prev_msg->msg_next = msg->msg_next; 1028*7c478bd9Sstevel@tonic-gate } else { 1029*7c478bd9Sstevel@tonic-gate consms_mux_msg = consms_mux_msg->msg_next; 1030*7c478bd9Sstevel@tonic-gate } 1031*7c478bd9Sstevel@tonic-gate msg->msg_next = NULL; 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate mutex_exit(&consms_msg_lock); 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate return (msg); 1036*7c478bd9Sstevel@tonic-gate } 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate static consms_msg_t * 1039*7c478bd9Sstevel@tonic-gate consms_mux_find_msg(uint_t msg_id) 1040*7c478bd9Sstevel@tonic-gate { 1041*7c478bd9Sstevel@tonic-gate consms_msg_t *msg; 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate mutex_enter(&consms_msg_lock); 1044*7c478bd9Sstevel@tonic-gate for (msg = consms_mux_msg; msg != NULL; msg = msg->msg_next) { 1045*7c478bd9Sstevel@tonic-gate if (msg->msg_id == msg_id) 1046*7c478bd9Sstevel@tonic-gate break; 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate mutex_exit(&consms_msg_lock); 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate return (msg); 1051*7c478bd9Sstevel@tonic-gate } 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate /* 1054*7c478bd9Sstevel@tonic-gate * Received ACK or NAK from lower mice 1055*7c478bd9Sstevel@tonic-gate * 1056*7c478bd9Sstevel@tonic-gate * For non-transparent ioctl, the msg->msg_rsp_list 1057*7c478bd9Sstevel@tonic-gate * is always NULL; for transparent ioctl, it 1058*7c478bd9Sstevel@tonic-gate * remembers the M_COPYIN/M_COPYOUT request 1059*7c478bd9Sstevel@tonic-gate * messages from lower mice. So here if msg->msg_rsp_list 1060*7c478bd9Sstevel@tonic-gate * is NULL (after receiving all ACK/NAKs), we 1061*7c478bd9Sstevel@tonic-gate * are done with this specific ioctl. 1062*7c478bd9Sstevel@tonic-gate * 1063*7c478bd9Sstevel@tonic-gate * As long as one of lower mice responds success, 1064*7c478bd9Sstevel@tonic-gate * we treat it success for a ioctl. 1065*7c478bd9Sstevel@tonic-gate */ 1066*7c478bd9Sstevel@tonic-gate static void 1067*7c478bd9Sstevel@tonic-gate consms_mux_ack(consms_msg_t *msg, mblk_t *mp) 1068*7c478bd9Sstevel@tonic-gate { 1069*7c478bd9Sstevel@tonic-gate mblk_t *ack_mp; 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate /* increment response_nums */ 1072*7c478bd9Sstevel@tonic-gate msg->msg_num_responses++; 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_IOCACK) { 1075*7c478bd9Sstevel@tonic-gate /* 1076*7c478bd9Sstevel@tonic-gate * Received ACK from lower, then 1077*7c478bd9Sstevel@tonic-gate * this is the last step for both 1078*7c478bd9Sstevel@tonic-gate * non-transparent and transparent 1079*7c478bd9Sstevel@tonic-gate * ioctl. We only need to remember 1080*7c478bd9Sstevel@tonic-gate * one of the ACKs, finally reply 1081*7c478bd9Sstevel@tonic-gate * this ACK to upper layer for this 1082*7c478bd9Sstevel@tonic-gate * specific ioctl. 1083*7c478bd9Sstevel@tonic-gate */ 1084*7c478bd9Sstevel@tonic-gate ASSERT(msg->msg_rsp_list == NULL); 1085*7c478bd9Sstevel@tonic-gate if (msg->msg_ack_mp == NULL) { 1086*7c478bd9Sstevel@tonic-gate msg->msg_ack_mp = mp; 1087*7c478bd9Sstevel@tonic-gate mp = NULL; 1088*7c478bd9Sstevel@tonic-gate } 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate /* 1092*7c478bd9Sstevel@tonic-gate * Check to see if all lower mice have responded 1093*7c478bd9Sstevel@tonic-gate * to our dispatching ioctl. 1094*7c478bd9Sstevel@tonic-gate */ 1095*7c478bd9Sstevel@tonic-gate if (msg->msg_num_responses == msg->msg_num_requests) { 1096*7c478bd9Sstevel@tonic-gate if ((msg->msg_ack_mp == NULL) && 1097*7c478bd9Sstevel@tonic-gate (msg->msg_rsp_list == NULL)) { 1098*7c478bd9Sstevel@tonic-gate /* 1099*7c478bd9Sstevel@tonic-gate * All are NAKed. 1100*7c478bd9Sstevel@tonic-gate */ 1101*7c478bd9Sstevel@tonic-gate ack_mp = mp; 1102*7c478bd9Sstevel@tonic-gate mp = NULL; 1103*7c478bd9Sstevel@tonic-gate } else if (msg->msg_rsp_list == NULL) { 1104*7c478bd9Sstevel@tonic-gate /* 1105*7c478bd9Sstevel@tonic-gate * The last step and at least one ACKed. 1106*7c478bd9Sstevel@tonic-gate */ 1107*7c478bd9Sstevel@tonic-gate ack_mp = msg->msg_ack_mp; 1108*7c478bd9Sstevel@tonic-gate consms_mux_cache_states(msg->msg_request); 1109*7c478bd9Sstevel@tonic-gate consms_mux_max_wheel_report(ack_mp); 1110*7c478bd9Sstevel@tonic-gate } else { 1111*7c478bd9Sstevel@tonic-gate /* 1112*7c478bd9Sstevel@tonic-gate * This is a NAK, but we have 1113*7c478bd9Sstevel@tonic-gate * already received M_COPYIN 1114*7c478bd9Sstevel@tonic-gate * or M_COPYOUT request from 1115*7c478bd9Sstevel@tonic-gate * at least one of lower mice. 1116*7c478bd9Sstevel@tonic-gate * (msg->msg_rsp_list != NULL) 1117*7c478bd9Sstevel@tonic-gate * 1118*7c478bd9Sstevel@tonic-gate * Still copyin or copyout. 1119*7c478bd9Sstevel@tonic-gate */ 1120*7c478bd9Sstevel@tonic-gate ack_mp = msg->msg_rsp_list->rsp_mp; 1121*7c478bd9Sstevel@tonic-gate consms_mux_max_wheel_report(ack_mp); 1122*7c478bd9Sstevel@tonic-gate } 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate qreply(msg->msg_queue, ack_mp); 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate if (msg->msg_rsp_list == NULL) { 1127*7c478bd9Sstevel@tonic-gate /* 1128*7c478bd9Sstevel@tonic-gate * We are done with this ioctl. 1129*7c478bd9Sstevel@tonic-gate */ 1130*7c478bd9Sstevel@tonic-gate if (msg->msg_request) 1131*7c478bd9Sstevel@tonic-gate freemsg(msg->msg_request); 1132*7c478bd9Sstevel@tonic-gate (void) consms_mux_unlink_msg(msg->msg_id); 1133*7c478bd9Sstevel@tonic-gate kmem_free(msg, sizeof (*msg)); 1134*7c478bd9Sstevel@tonic-gate } 1135*7c478bd9Sstevel@tonic-gate } 1136*7c478bd9Sstevel@tonic-gate 1137*7c478bd9Sstevel@tonic-gate if (mp) { 1138*7c478bd9Sstevel@tonic-gate freemsg(mp); 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate /* 1143*7c478bd9Sstevel@tonic-gate * Received M_COPYIN or M_COPYOUT request from 1144*7c478bd9Sstevel@tonic-gate * lower mice for transparent ioctl 1145*7c478bd9Sstevel@tonic-gate * 1146*7c478bd9Sstevel@tonic-gate * We remember each M_COPYIN/M_COPYOUT into the 1147*7c478bd9Sstevel@tonic-gate * msg->msg_rsp_list, reply upper layer using the first 1148*7c478bd9Sstevel@tonic-gate * M_COPYIN/M_COPYOUT in the list after receiving 1149*7c478bd9Sstevel@tonic-gate * all responses from lower mice, even if some of 1150*7c478bd9Sstevel@tonic-gate * them return NAKs. 1151*7c478bd9Sstevel@tonic-gate */ 1152*7c478bd9Sstevel@tonic-gate static void 1153*7c478bd9Sstevel@tonic-gate consms_mux_copyreq(queue_t *q, consms_msg_t *msg, mblk_t *mp) 1154*7c478bd9Sstevel@tonic-gate { 1155*7c478bd9Sstevel@tonic-gate consms_response_t *rsp; 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate rsp = (consms_response_t *)kmem_zalloc(sizeof (*rsp), KM_SLEEP); 1158*7c478bd9Sstevel@tonic-gate rsp->rsp_mp = mp; 1159*7c478bd9Sstevel@tonic-gate rsp->rsp_queue = q; 1160*7c478bd9Sstevel@tonic-gate if (msg->msg_rsp_list) { 1161*7c478bd9Sstevel@tonic-gate rsp->rsp_next = msg->msg_rsp_list; 1162*7c478bd9Sstevel@tonic-gate } 1163*7c478bd9Sstevel@tonic-gate msg->msg_rsp_list = rsp; 1164*7c478bd9Sstevel@tonic-gate msg->msg_num_responses++; 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate if (msg->msg_num_responses == msg->msg_num_requests) { 1167*7c478bd9Sstevel@tonic-gate consms_mux_max_wheel_report(msg->msg_rsp_list->rsp_mp); 1168*7c478bd9Sstevel@tonic-gate qreply(msg->msg_queue, msg->msg_rsp_list->rsp_mp); 1169*7c478bd9Sstevel@tonic-gate } 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate 1172*7c478bd9Sstevel@tonic-gate /* 1173*7c478bd9Sstevel@tonic-gate * Do the real job for updating M_COPYIN/M_COPYOUT 1174*7c478bd9Sstevel@tonic-gate * request with the mp of M_IOCDATA, then put it 1175*7c478bd9Sstevel@tonic-gate * down to lower mice. 1176*7c478bd9Sstevel@tonic-gate */ 1177*7c478bd9Sstevel@tonic-gate static void 1178*7c478bd9Sstevel@tonic-gate consms_mux_disp_iocdata(consms_response_t *rsp, mblk_t *mp) 1179*7c478bd9Sstevel@tonic-gate { 1180*7c478bd9Sstevel@tonic-gate mblk_t *down_mp = rsp->rsp_mp; 1181*7c478bd9Sstevel@tonic-gate struct copyresp *copyresp = (struct copyresp *)mp->b_rptr; 1182*7c478bd9Sstevel@tonic-gate struct copyresp *newresp = (struct copyresp *)down_mp->b_rptr; 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate /* 1185*7c478bd9Sstevel@tonic-gate * Update the rval. 1186*7c478bd9Sstevel@tonic-gate */ 1187*7c478bd9Sstevel@tonic-gate newresp->cp_rval = copyresp->cp_rval; 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate /* 1190*7c478bd9Sstevel@tonic-gate * Update the db_type to M_IOCDATA. 1191*7c478bd9Sstevel@tonic-gate */ 1192*7c478bd9Sstevel@tonic-gate down_mp->b_datap->db_type = mp->b_datap->db_type; 1193*7c478bd9Sstevel@tonic-gate 1194*7c478bd9Sstevel@tonic-gate /* 1195*7c478bd9Sstevel@tonic-gate * Update the b_cont. 1196*7c478bd9Sstevel@tonic-gate */ 1197*7c478bd9Sstevel@tonic-gate if (down_mp->b_cont != NULL) { 1198*7c478bd9Sstevel@tonic-gate freemsg(down_mp->b_cont); 1199*7c478bd9Sstevel@tonic-gate down_mp->b_cont = NULL; 1200*7c478bd9Sstevel@tonic-gate } 1201*7c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) { 1202*7c478bd9Sstevel@tonic-gate down_mp->b_cont = copymsg(mp->b_cont); 1203*7c478bd9Sstevel@tonic-gate } 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate /* 1206*7c478bd9Sstevel@tonic-gate * Put it down. 1207*7c478bd9Sstevel@tonic-gate */ 1208*7c478bd9Sstevel@tonic-gate (void) putq(WR(rsp->rsp_queue), down_mp); 1209*7c478bd9Sstevel@tonic-gate } 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate /* 1212*7c478bd9Sstevel@tonic-gate * Dispatch M_IOCDATA down to all lower mice 1213*7c478bd9Sstevel@tonic-gate * for transparent ioctl. 1214*7c478bd9Sstevel@tonic-gate * 1215*7c478bd9Sstevel@tonic-gate * We update each M_COPYIN/M_COPYOUT in the 1216*7c478bd9Sstevel@tonic-gate * msg->msg_rsp_list with the M_IOCDATA. 1217*7c478bd9Sstevel@tonic-gate */ 1218*7c478bd9Sstevel@tonic-gate static void 1219*7c478bd9Sstevel@tonic-gate consms_mux_iocdata(consms_msg_t *msg, mblk_t *mp) 1220*7c478bd9Sstevel@tonic-gate { 1221*7c478bd9Sstevel@tonic-gate consms_response_t *rsp; 1222*7c478bd9Sstevel@tonic-gate consms_response_t *tmp; 1223*7c478bd9Sstevel@tonic-gate consms_response_t *first; 1224*7c478bd9Sstevel@tonic-gate struct copyresp *copyresp; 1225*7c478bd9Sstevel@tonic-gate int request_nums; 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate ASSERT(msg->msg_rsp_list != NULL); 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate /* 1230*7c478bd9Sstevel@tonic-gate * We should remember the ioc data for 1231*7c478bd9Sstevel@tonic-gate * VUIDSWHEELSTATE, and MSIOSRESOLUTION, 1232*7c478bd9Sstevel@tonic-gate * for we will cache the wheel state and 1233*7c478bd9Sstevel@tonic-gate * the screen resolution later if ACKed. 1234*7c478bd9Sstevel@tonic-gate */ 1235*7c478bd9Sstevel@tonic-gate copyresp = (struct copyresp *)mp->b_rptr; 1236*7c478bd9Sstevel@tonic-gate if ((copyresp->cp_cmd == VUIDSWHEELSTATE) || 1237*7c478bd9Sstevel@tonic-gate (copyresp->cp_cmd == MSIOSRESOLUTION)) { 1238*7c478bd9Sstevel@tonic-gate freemsg(msg->msg_request); 1239*7c478bd9Sstevel@tonic-gate msg->msg_request = copymsg(mp); 1240*7c478bd9Sstevel@tonic-gate } 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate /* 1243*7c478bd9Sstevel@tonic-gate * Update request numbers and response numbers. 1244*7c478bd9Sstevel@tonic-gate */ 1245*7c478bd9Sstevel@tonic-gate msg->msg_num_requests = msg->msg_num_responses; 1246*7c478bd9Sstevel@tonic-gate msg->msg_num_responses = 0; 1247*7c478bd9Sstevel@tonic-gate request_nums = 1; 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate /* 1250*7c478bd9Sstevel@tonic-gate * Since we have use the first M_COPYIN/M_COPYOUT 1251*7c478bd9Sstevel@tonic-gate * in the msg_rsp_list to reply upper layer, the mp 1252*7c478bd9Sstevel@tonic-gate * of M_IOCDATA can be directly used for that. 1253*7c478bd9Sstevel@tonic-gate */ 1254*7c478bd9Sstevel@tonic-gate first = msg->msg_rsp_list; 1255*7c478bd9Sstevel@tonic-gate rsp = first->rsp_next; 1256*7c478bd9Sstevel@tonic-gate msg->msg_rsp_list = NULL; 1257*7c478bd9Sstevel@tonic-gate 1258*7c478bd9Sstevel@tonic-gate for (rsp = first->rsp_next; rsp != NULL; ) { 1259*7c478bd9Sstevel@tonic-gate tmp = rsp; 1260*7c478bd9Sstevel@tonic-gate rsp = rsp->rsp_next; 1261*7c478bd9Sstevel@tonic-gate consms_mux_disp_iocdata(tmp, mp); 1262*7c478bd9Sstevel@tonic-gate kmem_free(tmp, sizeof (*tmp)); 1263*7c478bd9Sstevel@tonic-gate request_nums++; 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate /* Must set the request number before the last q. */ 1267*7c478bd9Sstevel@tonic-gate msg->msg_num_requests = request_nums; 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate /* the first one */ 1270*7c478bd9Sstevel@tonic-gate (void) putq(WR(first->rsp_queue), mp); 1271*7c478bd9Sstevel@tonic-gate kmem_free(first, sizeof (*first)); 1272*7c478bd9Sstevel@tonic-gate } 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate /* 1276*7c478bd9Sstevel@tonic-gate * Here we update the number of wheels with 1277*7c478bd9Sstevel@tonic-gate * the virtual mouse for VUIDGWHEELCOUNT ioctl. 1278*7c478bd9Sstevel@tonic-gate */ 1279*7c478bd9Sstevel@tonic-gate static void 1280*7c478bd9Sstevel@tonic-gate consms_mux_max_wheel_report(mblk_t *mp) 1281*7c478bd9Sstevel@tonic-gate { 1282*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 1283*7c478bd9Sstevel@tonic-gate int num_wheels; 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate if (mp == NULL || mp->b_cont == NULL) 1286*7c478bd9Sstevel@tonic-gate return; 1287*7c478bd9Sstevel@tonic-gate 1288*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate if ((iocp->ioc_cmd == VUIDGWHEELCOUNT) && 1291*7c478bd9Sstevel@tonic-gate (mp->b_datap->db_type == M_COPYOUT)) { 1292*7c478bd9Sstevel@tonic-gate num_wheels = *(int *)mp->b_cont->b_rptr; 1293*7c478bd9Sstevel@tonic-gate if (num_wheels < consms_state.consms_num_wheels) { 1294*7c478bd9Sstevel@tonic-gate *(int *)mp->b_cont->b_rptr = 1295*7c478bd9Sstevel@tonic-gate consms_state.consms_num_wheels; 1296*7c478bd9Sstevel@tonic-gate } 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate /* 1301*7c478bd9Sstevel@tonic-gate * Update the virtual mouse state variables with 1302*7c478bd9Sstevel@tonic-gate * the latest value from upper layer when these 1303*7c478bd9Sstevel@tonic-gate * set ioctls return success. Thus we can update 1304*7c478bd9Sstevel@tonic-gate * low mice with the latest state values during 1305*7c478bd9Sstevel@tonic-gate * hotplug. 1306*7c478bd9Sstevel@tonic-gate */ 1307*7c478bd9Sstevel@tonic-gate static void 1308*7c478bd9Sstevel@tonic-gate consms_mux_cache_states(mblk_t *mp) 1309*7c478bd9Sstevel@tonic-gate { 1310*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 1311*7c478bd9Sstevel@tonic-gate Ms_parms *parms; 1312*7c478bd9Sstevel@tonic-gate Ms_screen_resolution *sr; 1313*7c478bd9Sstevel@tonic-gate wheel_state *ws; 1314*7c478bd9Sstevel@tonic-gate 1315*7c478bd9Sstevel@tonic-gate if (mp == NULL || mp->b_cont == NULL) 1316*7c478bd9Sstevel@tonic-gate return; 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 1319*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 1320*7c478bd9Sstevel@tonic-gate case VUIDSFORMAT: 1321*7c478bd9Sstevel@tonic-gate consms_state.consms_vuid_format = *(int *)mp->b_cont->b_rptr; 1322*7c478bd9Sstevel@tonic-gate break; 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate case MSIOSETPARMS: 1325*7c478bd9Sstevel@tonic-gate parms = (Ms_parms *)mp->b_cont->b_rptr; 1326*7c478bd9Sstevel@tonic-gate consms_state.consms_ms_parms = *parms; 1327*7c478bd9Sstevel@tonic-gate break; 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate case MSIOSRESOLUTION: 1330*7c478bd9Sstevel@tonic-gate sr = (Ms_screen_resolution *)mp->b_cont->b_rptr; 1331*7c478bd9Sstevel@tonic-gate consms_state.consms_ms_sr = *sr; 1332*7c478bd9Sstevel@tonic-gate break; 1333*7c478bd9Sstevel@tonic-gate 1334*7c478bd9Sstevel@tonic-gate case VUIDSWHEELSTATE: 1335*7c478bd9Sstevel@tonic-gate ws = (wheel_state *)mp->b_cont->b_rptr; 1336*7c478bd9Sstevel@tonic-gate consms_state.consms_wheel_state_bf = 1337*7c478bd9Sstevel@tonic-gate (ws->stateflags << ws->id) | 1338*7c478bd9Sstevel@tonic-gate (consms_state.consms_wheel_state_bf & ~(1 << ws->id)); 1339*7c478bd9Sstevel@tonic-gate break; 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate } 1342*7c478bd9Sstevel@tonic-gate 1343*7c478bd9Sstevel@tonic-gate /* 1344*7c478bd9Sstevel@tonic-gate * Dispatch ioctl mp (non-transparent and transparent) 1345*7c478bd9Sstevel@tonic-gate * down to all lower mice. 1346*7c478bd9Sstevel@tonic-gate * 1347*7c478bd9Sstevel@tonic-gate * First, create a pending message for this mp, link it into 1348*7c478bd9Sstevel@tonic-gate * the global messages list. Then wait for ACK/NAK for 1349*7c478bd9Sstevel@tonic-gate * non-transparent ioctl, COPYIN/COPYOUT for transparent 1350*7c478bd9Sstevel@tonic-gate * ioctl. 1351*7c478bd9Sstevel@tonic-gate */ 1352*7c478bd9Sstevel@tonic-gate static int 1353*7c478bd9Sstevel@tonic-gate consms_mux_disp_ioctl(queue_t *q, mblk_t *mp) 1354*7c478bd9Sstevel@tonic-gate { 1355*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 1356*7c478bd9Sstevel@tonic-gate consms_msg_t *msg; 1357*7c478bd9Sstevel@tonic-gate consms_lq_t *lq; 1358*7c478bd9Sstevel@tonic-gate mblk_t *copy_mp; 1359*7c478bd9Sstevel@tonic-gate int error = 0; 1360*7c478bd9Sstevel@tonic-gate 1361*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 1362*7c478bd9Sstevel@tonic-gate msg = (consms_msg_t *)kmem_zalloc(sizeof (*msg), KM_SLEEP); 1363*7c478bd9Sstevel@tonic-gate msg->msg_id = iocp->ioc_id; 1364*7c478bd9Sstevel@tonic-gate msg->msg_request = mp; 1365*7c478bd9Sstevel@tonic-gate msg->msg_queue = q; 1366*7c478bd9Sstevel@tonic-gate msg->msg_num_requests = consms_state.consms_num_lqs; 1367*7c478bd9Sstevel@tonic-gate consms_mux_link_msg(msg); 1368*7c478bd9Sstevel@tonic-gate 1369*7c478bd9Sstevel@tonic-gate for (lq = consms_state.consms_lqs; lq != NULL; lq = lq->lq_next) { 1370*7c478bd9Sstevel@tonic-gate if ((copy_mp = copymsg(mp)) != NULL) { 1371*7c478bd9Sstevel@tonic-gate (void) putq(lq->lq_queue, copy_mp); 1372*7c478bd9Sstevel@tonic-gate } else { 1373*7c478bd9Sstevel@tonic-gate /* 1374*7c478bd9Sstevel@tonic-gate * If copymsg fails, we ignore this lq and 1375*7c478bd9Sstevel@tonic-gate * try next one. As long as one of them succeeds, 1376*7c478bd9Sstevel@tonic-gate * we dispatch this ioctl down. And later as long 1377*7c478bd9Sstevel@tonic-gate * as one of the lower drivers return success, we 1378*7c478bd9Sstevel@tonic-gate * reply to this ioctl with success. 1379*7c478bd9Sstevel@tonic-gate */ 1380*7c478bd9Sstevel@tonic-gate msg->msg_num_requests--; 1381*7c478bd9Sstevel@tonic-gate } 1382*7c478bd9Sstevel@tonic-gate } 1383*7c478bd9Sstevel@tonic-gate 1384*7c478bd9Sstevel@tonic-gate if (msg->msg_num_requests <= 0) { 1385*7c478bd9Sstevel@tonic-gate /* 1386*7c478bd9Sstevel@tonic-gate * Since copymsg fails for all lqs, we NAK this ioctl. 1387*7c478bd9Sstevel@tonic-gate */ 1388*7c478bd9Sstevel@tonic-gate (void) consms_mux_unlink_msg(msg->msg_id); 1389*7c478bd9Sstevel@tonic-gate kmem_free(msg, sizeof (*msg)); 1390*7c478bd9Sstevel@tonic-gate error = ENOMEM; 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate 1393*7c478bd9Sstevel@tonic-gate return (error); 1394*7c478bd9Sstevel@tonic-gate } 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate /* 1397*7c478bd9Sstevel@tonic-gate * Dispatch M_DATA and M_FLUSH message down to all 1398*7c478bd9Sstevel@tonic-gate * lower mice, and there are no acknowledgements 1399*7c478bd9Sstevel@tonic-gate * for them. Here we just copy the mp and then 1400*7c478bd9Sstevel@tonic-gate * put it into the lower queues. 1401*7c478bd9Sstevel@tonic-gate */ 1402*7c478bd9Sstevel@tonic-gate static void 1403*7c478bd9Sstevel@tonic-gate consms_mux_disp_data(mblk_t *mp) 1404*7c478bd9Sstevel@tonic-gate { 1405*7c478bd9Sstevel@tonic-gate consms_lq_t *lq; 1406*7c478bd9Sstevel@tonic-gate mblk_t *copy_mp; 1407*7c478bd9Sstevel@tonic-gate 1408*7c478bd9Sstevel@tonic-gate for (lq = consms_state.consms_lqs; lq != NULL; lq = lq->lq_next) { 1409*7c478bd9Sstevel@tonic-gate if ((copy_mp = copymsg(mp)) != NULL) { 1410*7c478bd9Sstevel@tonic-gate (void) putq(lq->lq_queue, copy_mp); 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate } 1413*7c478bd9Sstevel@tonic-gate 1414*7c478bd9Sstevel@tonic-gate freemsg(mp); 1415*7c478bd9Sstevel@tonic-gate } 1416