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, NULL }
 227 };
 228 
 229 int
 230 _init(void)
 231 {
 232         int     error;
 233 
 234         mutex_init(&consmslock, NULL, MUTEX_DRIVER, NULL);
 235         mutex_init(&consms_msg_lock, NULL, MUTEX_DRIVER, NULL);
 236         error = mod_install(&modlinkage);
 237         if (error != 0) {
 238                 mutex_destroy(&consmslock);
 239                 mutex_destroy(&consms_msg_lock);
 240         }
 241         return (error);
 242 }
 243 
 244 int
 245 _fini(void)
 246 {
 247         int     error;
 248 
 249         error = mod_remove(&modlinkage);
 250         if (error != 0)
 251                 return (error);
 252         mutex_destroy(&consmslock);
 253         mutex_destroy(&consms_msg_lock);
 254         return (0);
 255 }
 256 
 257 int
 258 _info(struct modinfo *modinfop)
 259 {
 260         return (mod_info(&modlinkage, modinfop));
 261 }
 262 
 263 static int
 264 consms_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
 265 {
 266         kstat_t *ksp;
 267 
 268         switch (cmd) {
 269         case DDI_ATTACH:
 270                 break;
 271         default:
 272                 return (DDI_FAILURE);
 273         }
 274 
 275         if (ddi_create_minor_node(devi, "mouse", S_IFCHR,
 276             0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
 277                 ddi_remove_minor_node(devi, NULL);
 278                 return (-1);
 279         }
 280         consms_dip = devi;
 281         (void) ddi_prop_update_int(DDI_DEV_T_NONE, devi, DDI_NO_AUTODETACH, 1);
 282 
 283         ksp = kstat_create("consms", 0, "activity", "misc", KSTAT_TYPE_NAMED,
 284             sizeof (consms_kstat) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
 285         if (ksp) {
 286                 ksp->ks_data = (void *)&consms_kstat;
 287                 ksp->ks_update = consms_kstat_update;
 288                 kstat_install(ksp);
 289                 consms_idle_stamp = gethrestime_sec();  /* initial value */
 290         }
 291 
 292         consms_state.consms_lqs = NULL;
 293         consms_state.consms_num_lqs = 0;
 294 
 295         /* default consms state values */
 296         consms_state.consms_vuid_format = VUID_FIRM_EVENT;
 297         consms_state.consms_num_buttons = 0;
 298         consms_state.consms_num_wheels = 0;
 299         consms_state.consms_wheel_state_bf |= VUID_WHEEL_STATE_ENABLED;
 300         consms_state.consms_ms_parms.jitter_thresh =
 301             CONSMS_PARMS_DEFAULT_JITTER;
 302         consms_state.consms_ms_parms.speed_limit =
 303             CONSMS_PARMS_DEFAULT_SPEED_LIMIT;
 304         consms_state.consms_ms_parms.speed_law =
 305             CONSMS_PARMS_DEFAULT_SPEED_LAW;
 306         consms_state.consms_ms_sr.height = CONSMS_SR_DEFAULT_HEIGHT;
 307         consms_state.consms_ms_sr.width = CONSMS_SR_DEFAULT_WIDTH;
 308 
 309         return (DDI_SUCCESS);
 310 }
 311 
 312 /*ARGSUSED*/
 313 static int
 314 consms_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
 315 {
 316         switch (cmd) {
 317         case DDI_DETACH:
 318         default:
 319                 return (DDI_FAILURE);
 320         }
 321 }
 322 
 323 /*ARGSUSED*/
 324 static int
 325 consms_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
 326         void **result)
 327 {
 328         register int error;
 329 
 330         switch (infocmd) {
 331         case DDI_INFO_DEVT2DEVINFO:
 332                 if (consms_dip == NULL) {
 333                         error = DDI_FAILURE;
 334                 } else {
 335                         *result = (void *) consms_dip;
 336                         error = DDI_SUCCESS;
 337                 }
 338                 break;
 339         case DDI_INFO_DEVT2INSTANCE:
 340                 *result = (void *)0;
 341                 error = DDI_SUCCESS;
 342                 break;
 343         default:
 344                 error = DDI_FAILURE;
 345         }
 346         return (error);
 347 }
 348 
 349 
 350 /*ARGSUSED*/
 351 static int
 352 consmsopen(q, devp, flag, sflag, crp)
 353         queue_t *q;
 354         dev_t   *devp;
 355         int     flag, sflag;
 356         cred_t  *crp;
 357 {
 358         upperqueue = q;
 359         qprocson(q);
 360         return (0);
 361 }
 362 
 363 /*ARGSUSED*/
 364 static int
 365 consmsclose(q, flag, crp)
 366         queue_t *q;
 367         int     flag;
 368         cred_t  *crp;
 369 {
 370         qprocsoff(q);
 371         upperqueue = NULL;
 372         return (0);
 373 }
 374 
 375 /*
 376  * Put procedure for upper write queue.
 377  */
 378 static void
 379 consmsuwput(q, mp)
 380         register queue_t *q;
 381         register mblk_t *mp;
 382 {
 383         struct iocblk           *iocbp = (struct iocblk *)mp->b_rptr;
 384         consms_msg_t            *msg;
 385         int                     error = 0;
 386 
 387         switch (mp->b_datap->db_type) {
 388 
 389         case M_IOCTL:
 390                 consmsioctl(q, mp);
 391                 break;
 392 
 393         case M_FLUSH:
 394                 if (*mp->b_rptr & FLUSHW)
 395                         flushq(q, FLUSHDATA);
 396                 if (*mp->b_rptr & FLUSHR)
 397                         flushq(RD(q), FLUSHDATA);
 398                 if (consms_state.consms_num_lqs > 0) {
 399                         consms_mux_disp_data(mp);
 400                 } else {
 401                         /*
 402                          * No lower queue; just reflect this back upstream.
 403                          */
 404                         *mp->b_rptr &= ~FLUSHW;
 405                         if (*mp->b_rptr & FLUSHR)
 406                                 qreply(q, mp);
 407                         else
 408                                 freemsg(mp);
 409                 }
 410                 break;
 411 
 412         case M_DATA:
 413                 if (consms_state.consms_num_lqs > 0) {
 414                         consms_mux_disp_data(mp);
 415                 } else {
 416                         freemsg(mp);
 417                 }
 418                 break;
 419 
 420         case M_IOCDATA:
 421                 if ((msg = consms_mux_find_msg(iocbp->ioc_id)) != NULL) {
 422                         consms_mux_iocdata(msg, mp);
 423                 } else {
 424                         error = EINVAL;
 425                 }
 426                 break;
 427 
 428         default:
 429                 error = EINVAL;
 430                 break;
 431         }
 432 
 433         if (error) {
 434                 /*
 435                  * Pass an error message up.
 436                  */
 437                 mp->b_datap->db_type = M_ERROR;
 438                 if (mp->b_cont) {
 439                         freemsg(mp->b_cont);
 440                         mp->b_cont = NULL;
 441                 }
 442                 mp->b_rptr = mp->b_datap->db_base;
 443                 mp->b_wptr = mp->b_rptr + sizeof (char);
 444                 *mp->b_rptr = (char)error;
 445                 qreply(q, mp);
 446         }
 447 }
 448 
 449 static void
 450 consmsioctl(q, mp)
 451         register queue_t *q;
 452         register mblk_t *mp;
 453 {
 454         register struct iocblk *iocp;
 455         int             error;
 456         mblk_t          *datap;
 457 
 458         iocp = (struct iocblk *)mp->b_rptr;
 459 
 460         switch (iocp->ioc_cmd) {
 461 
 462         case I_LINK:
 463         case I_PLINK:
 464                 mutex_enter(&consmslock);
 465                 consms_plink(q, mp);
 466                 mutex_exit(&consmslock);
 467                 return;
 468 
 469         case I_UNLINK:
 470         case I_PUNLINK:
 471                 mutex_enter(&consmslock);
 472                 if ((error = consms_punlink(q, mp)) != 0) {
 473                         mutex_exit(&consmslock);
 474                         miocnak(q, mp, 0, error);
 475                         return;
 476                 }
 477                 mutex_exit(&consmslock);
 478                 iocp->ioc_count = 0;
 479                 break;
 480 
 481         case MSIOBUTTONS:       /* query the number of buttons */
 482                 if ((consms_state.consms_num_lqs <= 0) ||
 483                     ((datap = allocb(sizeof (int), BPRI_HI)) == NULL)) {
 484                         miocnak(q, mp, 0, ENOMEM);
 485                         return;
 486                 }
 487                 *(int *)datap->b_wptr = consms_state.consms_num_buttons;
 488                 datap->b_wptr += sizeof (int);
 489                 if (mp->b_cont) {
 490                         freemsg(mp->b_cont);
 491                 }
 492                 mp->b_cont = datap;
 493                 iocp->ioc_count = sizeof (int);
 494                 break;
 495 
 496         default:
 497                 /*
 498                  * Pass this through, if there's something to pass it
 499                  * through to; otherwise, reject it.
 500                  */
 501                 if (consms_state.consms_num_lqs <= 0) {
 502                         miocnak(q, mp, 0, EINVAL);
 503                         return;
 504                 }
 505                 if ((error = consms_mux_disp_ioctl(q, mp)) != 0)
 506                         miocnak(q, mp, 0, error);
 507 
 508                 return;
 509         }
 510 
 511         /*
 512          * Common exit path for calls that return a positive
 513          * acknowledgment with a return value of 0.
 514          */
 515         miocack(q, mp, iocp->ioc_count, 0);
 516 }
 517 
 518 /*
 519  * Service procedure for lower write queue.
 520  * Puts things on the queue below us, if it lets us.
 521  */
 522 static void
 523 consmslwserv(q)
 524         register queue_t *q;
 525 {
 526         register mblk_t *mp;
 527 
 528         while (canput(q->q_next) && (mp = getq(q)) != NULL)
 529                 putnext(q, mp);
 530 }
 531 
 532 /*
 533  * Put procedure for lower read queue.
 534  */
 535 static void
 536 consmslrput(q, mp)
 537         register queue_t *q;
 538         register mblk_t *mp;
 539 {
 540         struct iocblk           *iocbp = (struct iocblk *)mp->b_rptr;
 541         struct copyreq          *copyreq = (struct copyreq *)mp->b_rptr;
 542         consms_msg_t            *msg;
 543         consms_lq_t             *lq = (consms_lq_t *)q->q_ptr;
 544 
 545         ASSERT(lq != NULL);
 546 
 547         switch (mp->b_datap->db_type) {
 548         case M_FLUSH:
 549                 if (*mp->b_rptr & FLUSHW)
 550                         flushq(WR(q), FLUSHDATA);
 551                 if (*mp->b_rptr & FLUSHR)
 552                         flushq(q, FLUSHDATA);
 553                 if (upperqueue != NULL)
 554                         putnext(upperqueue, mp);        /* pass it through */
 555                 else {
 556                         /*
 557                          * No upper queue; just reflect this back downstream.
 558                          */
 559                         *mp->b_rptr &= ~FLUSHR;
 560                         if (*mp->b_rptr & FLUSHW)
 561                                 qreply(q, mp);
 562                         else
 563                                 freemsg(mp);
 564                 }
 565                 break;
 566 
 567         case M_DATA:
 568                 if (upperqueue != NULL)
 569                         putnext(upperqueue, mp);
 570                 else
 571                         freemsg(mp);
 572                 consms_idle_stamp = gethrestime_sec();
 573                 break;
 574 
 575         case M_IOCACK:
 576         case M_IOCNAK:
 577                 /*
 578                  * First, check to see if this device
 579                  * is still being initialized.
 580                  */
 581                 if (lq->lq_ioc_reply_func != NULL) {
 582                         mutex_enter(&consmslock);
 583                         lq->lq_ioc_reply_func(lq, mp);
 584                         mutex_exit(&consmslock);
 585                         freemsg(mp);
 586                         break;
 587                 }
 588 
 589                 /*
 590                  * This is normal ioctl ack for upper layer.
 591                  */
 592                 if ((msg = consms_mux_find_msg(iocbp->ioc_id)) != NULL) {
 593                         consms_mux_ack(msg, mp);
 594                 } else {
 595                         freemsg(mp);
 596                 }
 597                 consms_idle_stamp = gethrestime_sec();
 598                 break;
 599 
 600         case M_COPYIN:
 601         case M_COPYOUT:
 602                 if ((msg = consms_mux_find_msg(copyreq->cq_id)) != NULL) {
 603                         consms_mux_copyreq(q, msg, mp);
 604                 } else
 605                         freemsg(mp);
 606                 consms_idle_stamp = gethrestime_sec();
 607                 break;
 608 
 609         case M_ERROR:
 610         case M_HANGUP:
 611         default:
 612                 freemsg(mp);    /* anything useful here? */
 613                 break;
 614         }
 615 }
 616 
 617 /* ARGSUSED */
 618 static int
 619 consms_kstat_update(kstat_t *ksp, int rw)
 620 {
 621         if (rw == KSTAT_WRITE)
 622                 return (EACCES);
 623 
 624         consms_kstat.idle_sec.value.l = gethrestime_sec() - consms_idle_stamp;
 625         return (0);
 626 }
 627 
 628 /*ARGSUSED*/
 629 static int
 630 consms_punlink(queue_t *q, mblk_t *mp)
 631 {
 632         struct linkblk  *linkp;
 633         consms_lq_t     *lq;
 634         consms_lq_t     *prev_lq;
 635 
 636         ASSERT(MUTEX_HELD(&consmslock));
 637 
 638         linkp = (struct linkblk *)mp->b_cont->b_rptr;
 639 
 640         prev_lq = NULL;
 641         for (lq = consms_state.consms_lqs; lq != NULL; lq = lq->lq_next) {
 642                 if (lq->lq_queue == linkp->l_qbot) {
 643                         if (prev_lq)
 644                                 prev_lq->lq_next = lq->lq_next;
 645                         else
 646                                 consms_state.consms_lqs = lq->lq_next;
 647                         kmem_free(lq, sizeof (*lq));
 648                         consms_state.consms_num_lqs--;
 649 
 650                         /*
 651                          * Check to see if mouse capabilities
 652                          * have changed.
 653                          */
 654                         consms_check_caps();
 655 
 656                         return (0);
 657                 }
 658                 prev_lq = lq;
 659         }
 660 
 661         return (EINVAL);
 662 }
 663 
 664 /*
 665  * Link a specific mouse into our mouse list.
 666  */
 667 static void
 668 consms_plink(queue_t *q, mblk_t *mp)
 669 {
 670         struct  linkblk *linkp;
 671         consms_lq_t     *lq;
 672         queue_t         *lowq;
 673 
 674         ASSERT(MUTEX_HELD(&consmslock));
 675 
 676         linkp = (struct linkblk *)mp->b_cont->b_rptr;
 677         lowq = linkp->l_qbot;
 678 
 679         lq = kmem_zalloc(sizeof (*lq), KM_SLEEP);
 680 
 681         lowq->q_ptr = (void *)lq;
 682         OTHERQ(lowq)->q_ptr = (void *)lq;
 683         lq->lq_queue = lowq;
 684         lq->lq_pending_plink = mp;
 685         lq->lq_pending_queue = q;
 686 
 687         /*
 688          * Set the number of buttons to 3 by default
 689          * in case the following MSIOBUTTONS ioctl fails.
 690          */
 691         lq->lq_num_buttons = 3;
 692 
 693         /*
 694          * Begin to initialize this mouse.
 695          */
 696         lq->lq_state = LQS_START;
 697         consms_lqs_ack_complete(lq, NULL);
 698 }
 699 
 700 /*
 701  * Initialize the newly hotplugged-in mouse,
 702  * e.g. get the number of buttons, set event
 703  * format. Then we add it into our list.
 704  */
 705 static void
 706 consms_lqs_ack_complete(consms_lq_t *lq, mblk_t *mp)
 707 {
 708         mblk_t                  *req = NULL;
 709         boolean_t               skipped = B_FALSE;
 710         wheel_state             *ws;
 711         Ms_screen_resolution    *sr;
 712         Ms_parms                *params;
 713 
 714         ASSERT(MUTEX_HELD(&consmslock));
 715 
 716         /*
 717          * We try each ioctl even if the previous one fails
 718          * until we reach LQS_DONE, and then add this lq
 719          * into our lq list.
 720          *
 721          * If the message allocation fails, we skip this ioctl,
 722          * set skipped flag to B_TRUE in order to skip the ioctl
 723          * result, then we try next ioctl, go to next state.
 724          */
 725         while ((lq->lq_state < LQS_DONE) && (req == NULL)) {
 726                 switch (lq->lq_state) {
 727                 case LQS_START:
 728                         /*
 729                          * First, issue MSIOBUTTONS ioctl
 730                          * to get the number of buttons.
 731                          */
 732                         req = mkiocb(MSIOBUTTONS);
 733                         if (req && ((req->b_cont = allocb(sizeof (int),
 734                             BPRI_MED)) == NULL)) {
 735                                 freemsg(req);
 736                                 req = NULL;
 737                         }
 738                         if (req == NULL)
 739                                 skipped = B_TRUE;
 740                         lq->lq_state++;
 741                         break;
 742 
 743                 case LQS_BUTTON_COUNT_PENDING:
 744                         if (!skipped && mp && mp->b_cont &&
 745                             (mp->b_datap->db_type == M_IOCACK))
 746                                 lq->lq_num_buttons =
 747                                     *(int *)mp->b_cont->b_rptr;
 748 
 749                         /*
 750                          * Second, issue VUIDGWHEELCOUNT ioctl
 751                          * to get the count of wheels.
 752                          */
 753                         req = mkiocb(VUIDGWHEELCOUNT);
 754                         if (req && ((req->b_cont = allocb(sizeof (int),
 755                             BPRI_MED)) == NULL)) {
 756                                 freemsg(req);
 757                                 req = NULL;
 758                         }
 759                         if (req == NULL)
 760                                 skipped = B_TRUE;
 761                         lq->lq_state++;
 762                         break;
 763 
 764                 case LQS_WHEEL_COUNT_PENDING:
 765                         if (!skipped && mp && mp->b_cont &&
 766                             (mp->b_datap->db_type == M_IOCACK))
 767                                 lq->lq_num_wheels =
 768                                     *(int *)mp->b_cont->b_rptr;
 769 
 770                         /*
 771                          * Third, issue VUIDSFORMAT ioctl
 772                          * to set the event format.
 773                          */
 774                         req = mkiocb(VUIDSFORMAT);
 775                         if (req && ((req->b_cont = allocb(sizeof (int),
 776                             BPRI_MED)) == NULL)) {
 777                                 freemsg(req);
 778                                 req = NULL;
 779                         }
 780                         if (req) {
 781                                 *(int *)req->b_cont->b_wptr =
 782                                     consms_state.consms_vuid_format;
 783                                 req->b_cont->b_wptr += sizeof (int);
 784                         }
 785                         lq->lq_state++;
 786                         break;
 787 
 788                 case LQS_SET_VUID_FORMAT_PENDING:
 789                         /*
 790                          * Fourth, issue VUIDSWHEELSTATE ioctl
 791                          * to set the wheel state (enable or disable).
 792                          */
 793                         req = mkiocb(VUIDSWHEELSTATE);
 794                         if (req && ((req->b_cont = allocb(sizeof (wheel_state),
 795                             BPRI_MED)) == NULL)) {
 796                                 freemsg(req);
 797                                 req = NULL;
 798                         }
 799                         if (req) {
 800                                 ws = (wheel_state *)req->b_cont->b_wptr;
 801                                 ws->vers = VUID_WHEEL_STATE_VERS;
 802                                 ws->id = 0;  /* the first wheel */
 803                                 ws->stateflags =
 804                                     consms_state.consms_wheel_state_bf & 1;
 805                                 req->b_cont->b_wptr += sizeof (wheel_state);
 806                         }
 807                         lq->lq_state++;
 808                         break;
 809 
 810                 case LQS_SET_WHEEL_STATE_PENDING:
 811                         /*
 812                          * Fifth,  issue MSIOSETPARMS ioctl
 813                          * to set the parameters for USB mouse.
 814                          */
 815                         req = mkiocb(MSIOSETPARMS);
 816                         if (req && ((req->b_cont = allocb(sizeof (Ms_parms),
 817                             BPRI_MED)) == NULL)) {
 818                                 freemsg(req);
 819                                 req = NULL;
 820                         }
 821                         if (req) {
 822                                 params = (Ms_parms *)req->b_cont->b_wptr;
 823                                 *params = consms_state.consms_ms_parms;
 824                                 req->b_cont->b_wptr += sizeof (Ms_parms);
 825                         }
 826                         lq->lq_state++;
 827                         break;
 828 
 829                 case LQS_SET_PARMS_PENDING:
 830                         /*
 831                          * Sixth, issue MSIOSRESOLUTION ioctl
 832                          * to set the screen resolution for absolute mouse.
 833                          */
 834                         req = mkiocb(MSIOSRESOLUTION);
 835                         if (req && ((req->b_cont =
 836                             allocb(sizeof (Ms_screen_resolution),
 837                             BPRI_MED)) == NULL)) {
 838                                 freemsg(req);
 839                                 req = NULL;
 840                         }
 841                         if (req) {
 842                                 sr =
 843                                     (Ms_screen_resolution *)req->b_cont->b_wptr;
 844                                 *sr = consms_state.consms_ms_sr;
 845                                 req->b_cont->b_wptr +=
 846                                     sizeof (Ms_screen_resolution);
 847                         }
 848                         lq->lq_state++;
 849                         break;
 850 
 851                 case LQS_SET_RESOLUTION_PENDING:
 852                         /*
 853                          * All jobs are done, lq->lq_state is turned into
 854                          * LQS_DONE, and this lq is added into our list.
 855                          */
 856                         lq->lq_state++;
 857                         consms_add_lq(lq);
 858                         break;
 859                 }
 860         }
 861 
 862         if (lq->lq_state < LQS_DONE) {
 863                 lq->lq_ioc_reply_func = consms_lqs_ack_complete;
 864                 (void) putq(lq->lq_queue, req);
 865         }
 866 }
 867 
 868 /*
 869  * Add this specific lq into our list, finally reply
 870  * the previous pending I_PLINK ioctl. Also check to
 871  * see if mouse capabilities have changed, and send
 872  * a dynamical notification event to upper layer if
 873  * necessary.
 874  */
 875 static void
 876 consms_add_lq(consms_lq_t *lq)
 877 {
 878         struct  iocblk          *iocp;
 879 
 880         ASSERT(MUTEX_HELD(&consmslock));
 881 
 882         lq->lq_ioc_reply_func = NULL;
 883         iocp = (struct iocblk *)lq->lq_pending_plink->b_rptr;
 884         iocp->ioc_error = 0;
 885         iocp->ioc_count = 0;
 886         iocp->ioc_rval = 0;
 887         lq->lq_pending_plink->b_datap->db_type = M_IOCACK;
 888 
 889         /* Reply to the I_PLINK ioctl. */
 890         qreply(lq->lq_pending_queue, lq->lq_pending_plink);
 891 
 892         lq->lq_pending_plink = NULL;
 893         lq->lq_pending_queue = NULL;
 894 
 895         /*
 896          * Add this lq into list.
 897          */
 898         consms_state.consms_num_lqs++;
 899 
 900         lq->lq_next = consms_state.consms_lqs;
 901         consms_state.consms_lqs = lq;
 902 
 903         /*
 904          * Check to see if mouse capabilities
 905          * have changed.
 906          */
 907         consms_check_caps();
 908 
 909 }
 910 
 911 
 912 static void
 913 consms_check_caps(void)
 914 {
 915         consms_lq_t *lq;
 916         int     max_buttons = 0;
 917         int     max_wheels = 0;
 918         mblk_t  *mp;
 919 
 920         /*
 921          * Check to see if the number of buttons
 922          * and the number of wheels have changed.
 923          */
 924         for (lq = consms_state.consms_lqs; lq != NULL; lq = lq->lq_next) {
 925                 max_buttons = CONSMS_MAX(max_buttons, lq->lq_num_buttons);
 926                 max_wheels = CONSMS_MAX(max_wheels, lq->lq_num_wheels);
 927         }
 928 
 929         if (max_buttons != consms_state.consms_num_buttons) {
 930                 /*
 931                  * Since the number of buttons have changed,
 932                  * send a MOUSE_CAP_CHANGE_NUM_BUT dynamical
 933                  * notification event to upper layer.
 934                  */
 935                 consms_state.consms_num_buttons = max_buttons;
 936                 if (upperqueue != NULL) {
 937                         if ((mp = consms_new_firm_event(
 938                             MOUSE_CAP_CHANGE_NUM_BUT,
 939                             consms_state.consms_num_buttons)) != NULL) {
 940                                 putnext(upperqueue, mp);
 941                         }
 942                 }
 943         }
 944 
 945         if (max_wheels != consms_state.consms_num_wheels) {
 946                 /*
 947                  * Since the number of wheels have changed,
 948                  * send a MOUSE_CAP_CHANGE_NUM_WHEEL dynamical
 949                  * notification event to upper layer.
 950                  */
 951                 consms_state.consms_num_wheels = max_wheels;
 952                 if (upperqueue != NULL) {
 953                         if ((mp = consms_new_firm_event(
 954                             MOUSE_CAP_CHANGE_NUM_WHEEL,
 955                             consms_state.consms_num_wheels)) != NULL) {
 956                                 putnext(upperqueue, mp);
 957                         }
 958                 }
 959         }
 960 }
 961 
 962 /*
 963  * Allocate a dynamical notification event.
 964  */
 965 static mblk_t *
 966 consms_new_firm_event(ushort_t id, int value)
 967 {
 968         Firm_event *fep;
 969         mblk_t  *tmp;
 970 
 971         if ((tmp = allocb(sizeof (Firm_event), BPRI_HI)) != NULL) {
 972                 fep = (Firm_event *)tmp->b_wptr;
 973                 fep->id = id;
 974                 fep->pair_type = FE_PAIR_NONE;
 975                 fep->pair = NULL;
 976                 fep->value = value;
 977                 tmp->b_wptr += sizeof (Firm_event);
 978         }
 979 
 980         return (tmp);
 981 }
 982 
 983 /*
 984  * Start of dispatching interfaces as a multiplexor
 985  */
 986 
 987 /*
 988  * There is a global msg list (consms_mux_msg),
 989  * which is used to link all ioctl messages from
 990  * upper layer, which are currently being processed.
 991  *
 992  * consms_mux_link_msg links a msg into the list,
 993  * consms_mux_unlink_msg unlinks a msg from the list,
 994  * consms_mux_find_msg finds a msg from the list
 995  * according to its unique id.
 996  *
 997  * The id of each msg is taken from stream's mp,
 998  * so the id is supposed to be unique.
 999  */
1000 static void
1001 consms_mux_link_msg(consms_msg_t *msg)
1002 {
1003         mutex_enter(&consms_msg_lock);
1004         msg->msg_next = consms_mux_msg;
1005         consms_mux_msg = msg;
1006         mutex_exit(&consms_msg_lock);
1007 }
1008 
1009 static consms_msg_t *
1010 consms_mux_unlink_msg(uint_t msg_id)
1011 {
1012         consms_msg_t    *msg;
1013         consms_msg_t    *prev_msg;
1014 
1015         mutex_enter(&consms_msg_lock);
1016         prev_msg = NULL;
1017         for (msg = consms_mux_msg; msg != NULL;
1018             prev_msg = msg, msg = msg->msg_next) {
1019                 if (msg->msg_id == msg_id)
1020                         break;
1021         }
1022 
1023         if (msg != NULL) {
1024                 if (prev_msg != NULL) {
1025                         prev_msg->msg_next = msg->msg_next;
1026                 } else {
1027                         consms_mux_msg = consms_mux_msg->msg_next;
1028                 }
1029                 msg->msg_next = NULL;
1030         }
1031         mutex_exit(&consms_msg_lock);
1032 
1033         return (msg);
1034 }
1035 
1036 static consms_msg_t *
1037 consms_mux_find_msg(uint_t msg_id)
1038 {
1039         consms_msg_t    *msg;
1040 
1041         mutex_enter(&consms_msg_lock);
1042         for (msg = consms_mux_msg; msg != NULL; msg = msg->msg_next) {
1043                 if (msg->msg_id == msg_id)
1044                         break;
1045         }
1046         mutex_exit(&consms_msg_lock);
1047 
1048         return (msg);
1049 }
1050 
1051 /*
1052  * Received ACK or NAK from lower mice
1053  *
1054  * For non-transparent ioctl, the msg->msg_rsp_list
1055  * is always NULL; for transparent ioctl, it
1056  * remembers the M_COPYIN/M_COPYOUT request
1057  * messages from lower mice. So here if msg->msg_rsp_list
1058  * is NULL (after receiving all ACK/NAKs), we
1059  * are done with this specific ioctl.
1060  *
1061  * As long as one of lower mice responds success,
1062  * we treat it success for a ioctl.
1063  */
1064 static void
1065 consms_mux_ack(consms_msg_t *msg, mblk_t *mp)
1066 {
1067         mblk_t  *ack_mp;
1068 
1069         /* increment response_nums */
1070         msg->msg_num_responses++;
1071 
1072         if (mp->b_datap->db_type == M_IOCACK) {
1073                 /*
1074                  * Received ACK from lower, then
1075                  * this is the last step for both
1076                  * non-transparent and transparent
1077                  * ioctl. We only need to remember
1078                  * one of the ACKs, finally reply
1079                  * this ACK to upper layer for this
1080                  * specific ioctl.
1081                  */
1082                 ASSERT(msg->msg_rsp_list == NULL);
1083                 if (msg->msg_ack_mp == NULL) {
1084                         msg->msg_ack_mp = mp;
1085                         mp = NULL;
1086                 }
1087         }
1088 
1089         /*
1090          * Check to see if all lower mice have responded
1091          * to our dispatching ioctl.
1092          */
1093         if (msg->msg_num_responses == msg->msg_num_requests) {
1094                 if ((msg->msg_ack_mp == NULL) &&
1095                     (msg->msg_rsp_list == NULL)) {
1096                         /*
1097                          * All are NAKed.
1098                          */
1099                         ack_mp = mp;
1100                         mp = NULL;
1101                 } else if (msg->msg_rsp_list == NULL) {
1102                         /*
1103                          * The last step and at least one ACKed.
1104                          */
1105                         ack_mp = msg->msg_ack_mp;
1106                         consms_mux_cache_states(msg->msg_request);
1107                         consms_mux_max_wheel_report(ack_mp);
1108                 } else {
1109                         /*
1110                          * This is a NAK, but we have
1111                          * already received M_COPYIN
1112                          * or M_COPYOUT request from
1113                          * at least one of lower mice.
1114                          * (msg->msg_rsp_list != NULL)
1115                          *
1116                          * Still copyin or copyout.
1117                          */
1118                         ack_mp = msg->msg_rsp_list->rsp_mp;
1119                         consms_mux_max_wheel_report(ack_mp);
1120                 }
1121 
1122                 qreply(msg->msg_queue, ack_mp);
1123 
1124                 if (msg->msg_rsp_list == NULL) {
1125                         /*
1126                          * We are done with this ioctl.
1127                          */
1128                         if (msg->msg_request)
1129                                 freemsg(msg->msg_request);
1130                         (void) consms_mux_unlink_msg(msg->msg_id);
1131                         kmem_free(msg, sizeof (*msg));
1132                 }
1133         }
1134 
1135         if (mp) {
1136                 freemsg(mp);
1137         }
1138 }
1139 
1140 /*
1141  * Received M_COPYIN or M_COPYOUT request from
1142  * lower mice for transparent ioctl
1143  *
1144  * We remember each M_COPYIN/M_COPYOUT into the
1145  * msg->msg_rsp_list, reply upper layer using the first
1146  * M_COPYIN/M_COPYOUT in the list after receiving
1147  * all responses from lower mice, even if some of
1148  * them return NAKs.
1149  */
1150 static void
1151 consms_mux_copyreq(queue_t *q, consms_msg_t *msg, mblk_t *mp)
1152 {
1153         consms_response_t       *rsp;
1154 
1155         rsp = (consms_response_t *)kmem_zalloc(sizeof (*rsp), KM_SLEEP);
1156         rsp->rsp_mp = mp;
1157         rsp->rsp_queue = q;
1158         if (msg->msg_rsp_list) {
1159                 rsp->rsp_next = msg->msg_rsp_list;
1160         }
1161         msg->msg_rsp_list = rsp;
1162         msg->msg_num_responses++;
1163 
1164         if (msg->msg_num_responses == msg->msg_num_requests) {
1165                 consms_mux_max_wheel_report(msg->msg_rsp_list->rsp_mp);
1166                 qreply(msg->msg_queue, msg->msg_rsp_list->rsp_mp);
1167         }
1168 }
1169 
1170 /*
1171  * Do the real job for updating M_COPYIN/M_COPYOUT
1172  * request with the mp of M_IOCDATA, then put it
1173  * down to lower mice.
1174  */
1175 static void
1176 consms_mux_disp_iocdata(consms_response_t *rsp, mblk_t *mp)
1177 {
1178         mblk_t  *down_mp = rsp->rsp_mp;
1179         struct copyresp *copyresp = (struct copyresp *)mp->b_rptr;
1180         struct copyresp *newresp = (struct copyresp *)down_mp->b_rptr;
1181 
1182         /*
1183          * Update the rval.
1184          */
1185         newresp->cp_rval = copyresp->cp_rval;
1186 
1187         /*
1188          * Update the db_type to M_IOCDATA.
1189          */
1190         down_mp->b_datap->db_type = mp->b_datap->db_type;
1191 
1192         /*
1193          * Update the b_cont.
1194          */
1195         if (down_mp->b_cont != NULL) {
1196                 freemsg(down_mp->b_cont);
1197                 down_mp->b_cont = NULL;
1198         }
1199         if (mp->b_cont != NULL) {
1200                 down_mp->b_cont = copymsg(mp->b_cont);
1201         }
1202 
1203         /*
1204          * Put it down.
1205          */
1206         (void) putq(WR(rsp->rsp_queue), down_mp);
1207 }
1208 
1209 /*
1210  * Dispatch M_IOCDATA down to all lower mice
1211  * for transparent ioctl.
1212  *
1213  * We update each M_COPYIN/M_COPYOUT in the
1214  * msg->msg_rsp_list with the M_IOCDATA.
1215  */
1216 static void
1217 consms_mux_iocdata(consms_msg_t *msg, mblk_t *mp)
1218 {
1219         consms_response_t       *rsp;
1220         consms_response_t       *tmp;
1221         consms_response_t       *first;
1222         struct copyresp         *copyresp;
1223         int                     request_nums;
1224 
1225         ASSERT(msg->msg_rsp_list != NULL);
1226 
1227         /*
1228          * We should remember the ioc data for
1229          * VUIDSWHEELSTATE, and MSIOSRESOLUTION,
1230          * for we will cache the wheel state and
1231          * the screen resolution later if ACKed.
1232          */
1233         copyresp = (struct copyresp *)mp->b_rptr;
1234         if ((copyresp->cp_cmd == VUIDSWHEELSTATE) ||
1235             (copyresp->cp_cmd == MSIOSRESOLUTION)) {
1236                 freemsg(msg->msg_request);
1237                 msg->msg_request = copymsg(mp);
1238         }
1239 
1240         /*
1241          * Update request numbers and response numbers.
1242          */
1243         msg->msg_num_requests = msg->msg_num_responses;
1244         msg->msg_num_responses = 0;
1245         request_nums = 1;
1246 
1247         /*
1248          * Since we have use the first M_COPYIN/M_COPYOUT
1249          * in the msg_rsp_list to reply upper layer, the mp
1250          * of M_IOCDATA can be directly used for that.
1251          */
1252         first = msg->msg_rsp_list;
1253         rsp = first->rsp_next;
1254         msg->msg_rsp_list = NULL;
1255 
1256         for (rsp = first->rsp_next; rsp != NULL; ) {
1257                 tmp = rsp;
1258                 rsp = rsp->rsp_next;
1259                 consms_mux_disp_iocdata(tmp, mp);
1260                 kmem_free(tmp, sizeof (*tmp));
1261                 request_nums++;
1262         }
1263 
1264         /* Must set the request number before the last q. */
1265         msg->msg_num_requests = request_nums;
1266 
1267         /* the first one */
1268         (void) putq(WR(first->rsp_queue), mp);
1269         kmem_free(first, sizeof (*first));
1270 }
1271 
1272 
1273 /*
1274  * Here we update the number of wheels with
1275  * the virtual mouse for VUIDGWHEELCOUNT ioctl.
1276  */
1277 static void
1278 consms_mux_max_wheel_report(mblk_t *mp)
1279 {
1280         struct iocblk           *iocp;
1281         int                     num_wheels;
1282 
1283         if (mp == NULL || mp->b_cont == NULL)
1284                 return;
1285 
1286         iocp = (struct iocblk *)mp->b_rptr;
1287 
1288         if ((iocp->ioc_cmd == VUIDGWHEELCOUNT) &&
1289             (mp->b_datap->db_type == M_COPYOUT)) {
1290                 num_wheels = *(int *)mp->b_cont->b_rptr;
1291                 if (num_wheels < consms_state.consms_num_wheels) {
1292                         *(int *)mp->b_cont->b_rptr =
1293                             consms_state.consms_num_wheels;
1294                 }
1295         }
1296 }
1297 
1298 /*
1299  * Update the virtual mouse state variables with
1300  * the latest value from upper layer when these
1301  * set ioctls return success. Thus we can update
1302  * low mice with the latest state values during
1303  * hotplug.
1304  */
1305 static void
1306 consms_mux_cache_states(mblk_t *mp)
1307 {
1308         struct iocblk           *iocp;
1309         Ms_parms                *parms;
1310         Ms_screen_resolution    *sr;
1311         wheel_state             *ws;
1312 
1313         if (mp == NULL || mp->b_cont == NULL)
1314                 return;
1315 
1316         iocp = (struct iocblk *)mp->b_rptr;
1317         switch (iocp->ioc_cmd) {
1318         case VUIDSFORMAT:
1319                 consms_state.consms_vuid_format = *(int *)mp->b_cont->b_rptr;
1320                 break;
1321 
1322         case MSIOSETPARMS:
1323                 parms = (Ms_parms *)mp->b_cont->b_rptr;
1324                 consms_state.consms_ms_parms = *parms;
1325                 break;
1326 
1327         case MSIOSRESOLUTION:
1328                 sr = (Ms_screen_resolution *)mp->b_cont->b_rptr;
1329                 consms_state.consms_ms_sr = *sr;
1330                 break;
1331 
1332         case VUIDSWHEELSTATE:
1333                 ws = (wheel_state *)mp->b_cont->b_rptr;
1334                 consms_state.consms_wheel_state_bf =
1335                     (ws->stateflags << ws->id) |
1336                     (consms_state.consms_wheel_state_bf & ~(1 << ws->id));
1337                 break;
1338         }
1339 }
1340 
1341 /*
1342  * Dispatch ioctl mp (non-transparent and transparent)
1343  * down to all lower mice.
1344  *
1345  * First, create a pending message for this mp, link it into
1346  * the global messages list. Then wait for ACK/NAK for
1347  * non-transparent ioctl, COPYIN/COPYOUT for transparent
1348  * ioctl.
1349  */
1350 static int
1351 consms_mux_disp_ioctl(queue_t *q, mblk_t *mp)
1352 {
1353         struct iocblk   *iocp;
1354         consms_msg_t    *msg;
1355         consms_lq_t     *lq;
1356         mblk_t          *copy_mp;
1357         int             error = 0;
1358 
1359         iocp = (struct iocblk *)mp->b_rptr;
1360         msg = (consms_msg_t *)kmem_zalloc(sizeof (*msg), KM_SLEEP);
1361         msg->msg_id = iocp->ioc_id;
1362         msg->msg_request = mp;
1363         msg->msg_queue = q;
1364         msg->msg_num_requests = consms_state.consms_num_lqs;
1365         consms_mux_link_msg(msg);
1366 
1367         for (lq = consms_state.consms_lqs; lq != NULL; lq = lq->lq_next) {
1368                 if ((copy_mp = copymsg(mp)) != NULL) {
1369                         (void) putq(lq->lq_queue, copy_mp);
1370                 } else {
1371                         /*
1372                          * If copymsg fails, we ignore this lq and
1373                          * try next one. As long as one of them succeeds,
1374                          * we dispatch this ioctl down. And later as long
1375                          * as one of the lower drivers return success, we
1376                          * reply to this ioctl with success.
1377                          */
1378                         msg->msg_num_requests--;
1379                 }
1380         }
1381 
1382         if (msg->msg_num_requests <= 0) {
1383                 /*
1384                  * Since copymsg fails for all lqs, we NAK this ioctl.
1385                  */
1386                 (void) consms_mux_unlink_msg(msg->msg_id);
1387                 kmem_free(msg, sizeof (*msg));
1388                 error = ENOMEM;
1389         }
1390 
1391         return (error);
1392 }
1393 
1394 /*
1395  * Dispatch M_DATA and M_FLUSH message down to all
1396  * lower mice, and there are no acknowledgements
1397  * for them. Here we just copy the mp and then
1398  * put it into the lower queues.
1399  */
1400 static void
1401 consms_mux_disp_data(mblk_t *mp)
1402 {
1403         consms_lq_t     *lq;
1404         mblk_t          *copy_mp;
1405 
1406         for (lq = consms_state.consms_lqs; lq != NULL; lq = lq->lq_next) {
1407                 if ((copy_mp = copymsg(mp)) != NULL) {
1408                         (void) putq(lq->lq_queue, copy_mp);
1409                 }
1410         }
1411 
1412         freemsg(mp);
1413 }