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