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  * DESCRIPTION
  29  *
  30  * ttymux - Multiplexer driver for multiplexing termio compliant streams onto
  31  * a single upper stream.
  32  *
  33  * ADD2FRONT macro can be used to specify the order in which a console
  34  * device is put in the queue of multiplexed physical serial devices,
  35  * during the association and disassociation of a console interface.
  36  * When this macro is defined, the device is placed in front of the queue,
  37  * otherwise by default it is placed at the end.
  38  * Console I/O happens to each of the physical devices in the order of
  39  * their position in this queue.
  40  */
  41 
  42 #include <sys/types.h>
  43 #include <sys/file.h>
  44 #include <sys/stream.h>
  45 #include <sys/strsubr.h>
  46 #include <sys/strlog.h>
  47 #include <sys/strsun.h>
  48 #include <sys/modctl.h>
  49 #include <sys/debug.h>
  50 #include <sys/kbio.h>
  51 #include <sys/devops.h>
  52 #include <sys/errno.h>
  53 #include <sys/stat.h>
  54 #include <sys/kmem.h>
  55 #include <sys/ddi.h>
  56 #include <sys/consdev.h>
  57 #include <sys/tty.h>
  58 #include <sys/ptyvar.h>
  59 #include <sys/termio.h>
  60 #include <sys/fcntl.h>
  61 #include <sys/mkdev.h>
  62 #include <sys/ser_sync.h>
  63 #include <sys/esunddi.h>
  64 #include <sys/policy.h>
  65 
  66 #include <sys/ttymux.h>
  67 #include "ttymux_impl.h"
  68 
  69 /*
  70  * Extern declarations
  71  */
  72 extern mblk_t *mkiocb(uint_t);
  73 extern int nulldev();
  74 extern uintptr_t space_fetch(char *key);
  75 
  76 extern int sm_ioctl_cmd(sm_uqi_t *, mblk_t *);
  77 extern int ttymux_abort_ioctl(mblk_t *);
  78 extern int ttymux_device_fini(sm_lqi_t *);
  79 extern int ttymux_device_init(sm_lqi_t *);
  80 
  81 /*
  82  * Exported interfaces
  83  */
  84 int sm_disassociate(int, sm_lqi_t *, ulong_t);
  85 int sm_associate(int, sm_lqi_t *, ulong_t, uint_t, char *);
  86 
  87 /*
  88  * Variables defined here and visible only internally
  89  */
  90 sm_ss_t         *sm_ssp = 0;
  91 static int      sm_instance = 0;
  92 static int      smctlunit;
  93 
  94 static uint_t   sm_default_trflag = 0;
  95 uint_t          sm_max_units = 6;
  96 uint_t          sm_minor_cnt = 0;
  97 static uint_t   sm_refuse_opens = 0;
  98 
  99 /*
 100  * Local definitions.
 101  */
 102 
 103 /* force these flags to be unset on console devices */
 104 static ulong_t  sm_cmask = (ulong_t)(CRTSXOFF|CRTSCTS);
 105 
 106 /*
 107  * SECTION
 108  * Implementation Section:
 109  */
 110 void
 111 sm_debug(char *msg, ...)
 112 {
 113         va_list args;
 114         char    buf[256];
 115         int     sz;
 116 
 117         va_start(args, msg);
 118         sz = vsnprintf(buf, sizeof (buf), msg, args);
 119         va_end(args);
 120 
 121         if (sz < 0)
 122                 (void) strlog(ddi_driver_major(sm_ssp->sm_dip), sm_instance, 1,
 123                     SL_TRACE, "vsnprintf parse error\n");
 124         else if (sz > sizeof (buf)) {
 125                 char *b;
 126                 size_t  len = sz + 1;
 127 
 128                 b = kmem_alloc(len, KM_SLEEP);
 129                 va_start(args, msg);
 130                 sz = vsnprintf(b, len, msg, args);
 131                 va_end(args);
 132                 if (sz > 0)
 133                         (void) strlog(ddi_driver_major(sm_ssp->sm_dip),
 134                             sm_instance, 1, SL_TRACE, b);
 135                 kmem_free(b, len);
 136         } else {
 137 
 138                 (void) strlog(ddi_driver_major(sm_ssp->sm_dip), sm_instance,
 139                     1, SL_TRACE, buf);
 140         }
 141 }
 142 
 143 void
 144 sm_log(char *msg, ...)
 145 {
 146         va_list args;
 147         char    buf[128];
 148         int     sz;
 149 
 150         va_start(args, msg);
 151         sz = vsnprintf(buf, sizeof (buf), msg, args);
 152         va_end(args);
 153 
 154         if (sz < 0)
 155                 (void) strlog(ddi_driver_major(sm_ssp->sm_dip), sm_instance, 1,
 156                     SL_TRACE, "vsnprintf parse error\n");
 157         else if (sz > sizeof (buf)) {
 158                 char *b;
 159                 size_t  len = sz + 1;
 160 
 161                 b = kmem_alloc(len, KM_SLEEP);
 162                 va_start(args, msg);
 163                 sz = vsnprintf(b, len, msg, args);
 164                 va_end(args);
 165                 if (sz > 0)
 166                         (void) strlog(ddi_driver_major(sm_ssp->sm_dip),
 167                             sm_instance, 1, SL_NOTE, b);
 168                 kmem_free(b, len);
 169         } else {
 170 
 171                 (void) strlog(ddi_driver_major(sm_ssp->sm_dip), sm_instance,
 172                     1, SL_NOTE, buf);
 173         }
 174 }
 175 
 176 /*
 177  * Should only be called if the caller can guarantee that the vnode
 178  * and/or the stream won't disappear while finding the dip.
 179  * This routine is only called during an I_PLINK request so it's safe.
 180  * The routine obtains the dev_t for a linked se stream.
 181  */
 182 static void
 183 sm_setdip(queue_t *q, sm_lqi_t *lqi)
 184 {
 185         lqi->sm_dev = q && STREAM(q) ? STREAM(q)->sd_vnode->v_rdev : NODEV;
 186 }
 187 
 188 /*
 189  * Called from driver close, state change reports and I_PUNLINK ioctl.
 190  * A lower stream has been unlinked - clean up the state associated with it.
 191  */
 192 void
 193 sm_lqifree(sm_lqi_t *lqi)
 194 {
 195         int mu_owned;
 196         sm_lqi_t **pplqi;
 197 
 198         ASSERT(mutex_owned(lqi->sm_umutex));
 199         ASSERT(SM_RQ(lqi) != 0);
 200 
 201         /*
 202          * Clear all state associated with this lower queue except
 203          * the identity of the queues themselves and the link id which
 204          * can only be cleared by issuing a streams I_PUNLINK ioctl.
 205          *
 206          * The association of a lower queue is a two step process:
 207          * 1. initialise the lower q data structure on I_PLINK
 208          * 2. associate an upper q with the lower q on SM_CMD_ASSOCIATE.
 209          *
 210          * If step 2 has ocurred then
 211          * remove this lower queue info from the logical unit.
 212          */
 213         if (lqi->sm_uqi) {
 214                 sm_dbg('Y', ("lqifree unit %d, ", lqi->sm_uqi->sm_lunit));
 215                 if ((mu_owned = mutex_owned(lqi->sm_uqi->sm_umutex)) == 0)
 216                         LOCK_UNIT(lqi->sm_uqi);
 217 
 218                 pplqi = &lqi->sm_uqi->sm_lqs;
 219                 while (*pplqi != lqi) {
 220                         ASSERT(*pplqi);
 221                         pplqi = &((*pplqi)->sm_nlqi);
 222                 }
 223                 *pplqi = lqi->sm_nlqi;
 224                 lqi->sm_uqi->sm_nlqs--;
 225 
 226                 if (mu_owned == 0)
 227                         UNLOCK_UNIT(lqi->sm_uqi);
 228 
 229                 lqi->sm_uqi = 0;
 230         }
 231 }
 232 
 233 /*
 234  * Given a q return the associated lower queue data structure or NULL.
 235  * Return the data locked.
 236  */
 237 static sm_lqi_t *
 238 get_lqi_byq(queue_t *q)
 239 {
 240         int i;
 241         sm_lqi_t *lqi, *flqi = 0;
 242 
 243         for (i = 0; i < MAX_LQS; i++) {
 244                 lqi = &sm_ssp->sm_lqs[i];
 245                 LOCK_UNIT(lqi);
 246                 if (flqi == 0 && lqi->sm_linkid == 0) /* assumes muxids != 0 */
 247                         flqi = lqi;
 248                 else if (SM_RQ(lqi) == q || SM_WQ(lqi) == q) {
 249                         if (flqi)
 250                                 UNLOCK_UNIT(flqi);
 251                         return (lqi);
 252                 }
 253                 else
 254                         UNLOCK_UNIT(lqi);
 255         }
 256         return (flqi);
 257 }
 258 
 259 /*
 260  * Given a streams link identifier return the associated lower queue data
 261  * structure or NULL.
 262  */
 263 sm_lqi_t *
 264 get_lqi_byid(int linkid)
 265 {
 266         int i;
 267         sm_lqi_t *lqi;
 268 
 269         if (linkid == 0)
 270                 return (NULL);
 271         for (i = 0; i < MAX_LQS; i++) {
 272                 lqi = &sm_ssp->sm_lqs[i];
 273                 if (lqi->sm_linkid == linkid)
 274                         return (lqi);
 275         }
 276         return (NULL);
 277 }
 278 
 279 /*
 280  * Given a dev_t for a lower stream return the associated lower queue data
 281  * structure or NULL.
 282  */
 283 sm_lqi_t *
 284 get_lqi_bydevt(dev_t dev)
 285 {
 286         int i;
 287         sm_lqi_t *lqi;
 288 
 289         if (dev == NODEV)
 290                 return (NULL);
 291 
 292         for (i = 0; i < MAX_LQS; i++) {
 293                 lqi = &sm_ssp->sm_lqs[i];
 294                 if (lqi->sm_dev == dev)
 295                         return (lqi);
 296         }
 297         return (NULL);
 298 }
 299 
 300 /*
 301  * Determine whether the input flag is set on at least
 302  * howmany queues.
 303  */
 304 static int
 305 sm_is_flag_set(sm_uqi_t *uqi, uint_t flag, uint_t howmany)
 306 {
 307         sm_lqi_t *lqi;
 308 
 309         if (howmany == 0)
 310                 return (0);
 311 
 312         for (lqi = uqi->sm_lqs; lqi; lqi = lqi->sm_nlqi) {
 313                 if (lqi->sm_flags & flag)
 314                         if (--howmany == 0)
 315                                 return (1);
 316         }
 317         return (0);
 318 }
 319 
 320 /*
 321  * How many usable queues are associated with a given upper stream
 322  */
 323 static int
 324 sm_uwq_error(sm_uqi_t *uqi)
 325 {
 326         return (sm_is_flag_set(uqi, (WERROR_MODE|HANGUP_MODE), uqi->sm_nlqs));
 327 }
 328 
 329 /*
 330  * How many of the queues associated with a given upper stream
 331  * - do not - have the given flags set.
 332  */
 333 static int
 334 sm_q_count(sm_uqi_t *uqi, uint_t flag)
 335 {
 336         sm_lqi_t *lqi;
 337         int count = 0;
 338 
 339         for (lqi = uqi->sm_lqs; lqi; lqi = lqi->sm_nlqi) {
 340                 if ((lqi->sm_flags & flag) == 0)
 341                         count++;
 342         }
 343         return (count);
 344 }
 345 
 346 /*
 347  * How many of the queues associated with a given upper stream
 348  * - do not - have the given flags set.
 349  */
 350 static int
 351 sm_qs_without(sm_uqi_t *uqi, uint_t flag, uint_t ioflag)
 352 {
 353         sm_lqi_t *lqi;
 354         int count = 0;
 355 
 356         for (lqi = uqi->sm_lqs; lqi; lqi = lqi->sm_nlqi) {
 357                 if ((lqi->sm_flags & flag) == 0 &&
 358                     (lqi->sm_ioflag & ioflag) == 0)
 359                         count++;
 360         }
 361         return (count);
 362 }
 363 
 364 /*
 365  * How many usable queues are associated with a given upper stream
 366  */
 367 static int
 368 sm_good_qs(sm_uqi_t *uqi)
 369 {
 370         return (sm_q_count(uqi, (WERROR_MODE|HANGUP_MODE)));
 371 }
 372 
 373 static int
 374 sm_cnt_oqs(sm_uqi_t *uqi)
 375 {
 376         return (sm_qs_without(uqi, (WERROR_MODE|HANGUP_MODE),
 377             (uint_t)FOROUTPUT));
 378 }
 379 
 380 /*
 381  * Send an ioctl downstream and remember that it was sent so that
 382  * its response can be caught on the way back up.
 383  */
 384 static void
 385 sm_issue_ioctl(void *arg)
 386 {
 387         sm_lqi_t *lqi = arg;
 388         uint_t cmdflag = 0;
 389         queue_t *q = SM_WQ(lqi);
 390         int iocmd, size;
 391 
 392         LOCK_UNIT(lqi);
 393 
 394         lqi->sm_bid = 0;
 395         if ((lqi->sm_flags & (WERROR_MODE|HANGUP_MODE)) == 0 &&
 396             (lqi->sm_flags & (WANT_CDSTAT|WANT_TCSET))) {
 397                 mblk_t *pioc;
 398 
 399                 if (lqi->sm_flags & WANT_TCSET) {
 400                         lqi->sm_flags &= ~WANT_TCSET;
 401                         iocmd = TCSETS;
 402                         cmdflag = WANT_TCSET;
 403                 } else if (lqi->sm_flags & WANT_SC) {
 404                         lqi->sm_flags &= ~WANT_SC;
 405                         iocmd = TIOCGSOFTCAR;
 406                         cmdflag = WANT_SC;
 407                 } else if (lqi->sm_flags & WANT_CD) {
 408                         lqi->sm_flags &= ~WANT_CD;
 409                         iocmd = TIOCMGET;
 410                 } else if (lqi->sm_flags & WANT_CL) {
 411                         lqi->sm_flags &= ~WANT_CL;
 412                         iocmd = TCGETS;
 413                         cmdflag = WANT_CL;
 414                 } else {
 415                         UNLOCK_UNIT(lqi);
 416                         return;
 417                 }
 418 
 419                 if (pioc = mkiocb(iocmd)) {
 420                         if (cmdflag == WANT_TCSET) {
 421                                 pioc->b_cont =
 422                                     sm_allocb(sizeof (struct termios),
 423                                     BPRI_MED);
 424                                 if (pioc->b_cont == 0) {
 425                                         freemsg(pioc);
 426                                         pioc = 0;
 427                                 } else {
 428                                         struct termios *tc = (struct termios *)
 429                                             pioc->b_cont->b_wptr;
 430 
 431                                         bzero((caddr_t)tc,
 432                                             sizeof (struct termios));
 433                                         tc->c_cflag = lqi->sm_ttycommon->
 434                                             t_cflag;
 435                                         pioc->b_cont->b_rptr =
 436                                             pioc->b_cont->b_wptr;
 437                                         pioc->b_cont->b_wptr +=
 438                                             sizeof (struct termios);
 439                                 }
 440                                 size = sizeof (struct iocblk) +
 441                                     sizeof (struct termios);
 442                         }
 443                         else
 444                                 size = sizeof (struct iocblk);
 445                 }
 446                 else
 447                         size = sizeof (struct iocblk);
 448 
 449                 if (pioc != 0) {
 450 
 451                         lqi->sm_piocid = ((struct iocblk *)pioc->b_rptr)->
 452                             ioc_id;
 453                         lqi->sm_flags |= SM_IOCPENDING;
 454 
 455                         /* lqi->sm_flags |= cmdflag; */
 456                         UNLOCK_UNIT(lqi);
 457                         (void) putq(q, pioc);
 458                 } else {
 459                         UNLOCK_UNIT(lqi);
 460                         lqi->sm_bid = qbufcall(WR(q), size, BPRI_MED,
 461                             sm_issue_ioctl, lqi);
 462                 }
 463         }
 464         else
 465                 UNLOCK_UNIT(lqi);
 466 }
 467 
 468 /*
 469  * Associate one of the drivers minor nodes with a serial device.
 470  */
 471 int
 472 sm_associate(int unit, sm_lqi_t *plqi, ulong_t tag, uint_t ioflag, char *dp)
 473 {
 474         sm_uqi_t *uqi;
 475         int rval = 0;
 476 
 477         sm_dbg('Y', ("sm_associate(%d, %d, %d): ",
 478             (plqi) ? plqi->sm_linkid : 0, unit, ioflag));
 479         /*
 480          * Check the data is valid.
 481          * Associate a lower queue with a logical unit.
 482          */
 483 
 484         if (unit < 0 || unit >= NLUNITS || plqi == 0 ||
 485             (uqi = get_uqi(sm_ssp, unit)) == 0) {
 486                 sm_dbg('@', (" invalid: lqi=0x%p lui=0x%p:", plqi, uqi));
 487                 rval = EINVAL;
 488         } else {
 489                 if ((ioflag & FORIO) == 0)
 490                         ioflag = FORIO;
 491 
 492                 LOCK_UNIT(plqi);
 493 
 494                 if (plqi->sm_uqi) {
 495                         if (plqi->sm_uqi->sm_lunit == unit) {
 496                                 if ((ioflag & (uint_t)FORIO) != 0)
 497                                         plqi->sm_ioflag =
 498                                             (ioflag & (uint_t)FORIO);
 499                                 rval = 0;
 500                         } else {
 501                                 sm_dbg('@', ("already associated with unit %d:",
 502                                     plqi->sm_uqi->sm_lunit));
 503                                 rval = EINVAL;
 504                         }
 505                 } else {
 506 
 507                         LOCK_UNIT(uqi);
 508 
 509                         if ((ioflag & (uint_t)FORIO) != 0)
 510                                 plqi->sm_ioflag = (ioflag & (uint_t)FORIO);
 511 
 512                         plqi->sm_ttycommon->t_cflag = uqi->sm_ttycommon->
 513                             t_cflag;
 514                         plqi->sm_ttycommon->t_flags = uqi->sm_ttycommon->
 515                             t_flags;
 516                         plqi->sm_uqi = uqi;
 517                         plqi->sm_mbits = 0;
 518                         plqi->sm_tag = tag;
 519 
 520                         if (*dp == '/')
 521                                 (void) strncpy(plqi->sm_path, dp, MAXPATHLEN);
 522                         else
 523                                 *(plqi->sm_path) = '\0';
 524 
 525                         plqi->sm_flags |= WANT_TCSET;
 526 #ifdef ADD2FRONT
 527                         plqi->sm_nlqi = uqi->sm_lqs;
 528                         uqi->sm_lqs = plqi;
 529 #else
 530                         plqi->sm_nlqi = 0;
 531                         if (uqi->sm_lqs) {
 532                                 sm_lqi_t *lq;
 533                                 for (lq = uqi->sm_lqs; lq->sm_nlqi;
 534                                     lq = lq->sm_nlqi) {
 535                                 }
 536                                 lq->sm_nlqi = plqi;
 537                         } else
 538                                 uqi->sm_lqs = plqi;
 539 #endif
 540                         uqi->sm_nlqs++;
 541 
 542                         (void) ttymux_device_init(plqi);
 543 
 544                         UNLOCK_UNIT(uqi);
 545                         rval = 0;
 546                         /*
 547                          * Everything looks good so it's now ok to enable lower
 548                          * queue processing.
 549                          * Note the lower queue should be enabled as soon as
 550                          * I_PLINK returns (used in sm_get_ttymodes etc).
 551                          * Schedule ioctls to obtain the terminal settings.
 552                          */
 553 
 554                         if ((uqi->sm_flags & FULLY_OPEN) || uqi->sm_waitq)
 555                                 plqi->sm_uqflags |= SM_UQVALID;
 556 
 557                         qenable(SM_RQ(plqi));
 558                         if (plqi->sm_flags & (WANT_CDSTAT|WANT_TCSET)) {
 559                                 /*
 560                                  * Bypass the lower half of the driver (hence
 561                                  * no qwriter) and apply the current termio
 562                                  * settings on the lower stream.
 563                                  */
 564                                 UNLOCK_UNIT(plqi);
 565                                 if (plqi->sm_bid) {
 566                                         qunbufcall(SM_WQ(plqi), plqi->sm_bid);
 567                                         plqi->sm_bid = 0;
 568                                 }
 569                                 /*
 570                                  * Only set cflags on the lower q if we know
 571                                  * the settings on any other lower queue.
 572                                  */
 573                                 sm_issue_ioctl(plqi);
 574                                 LOCK_UNIT(plqi);
 575 
 576                         }
 577                 }
 578 
 579                 UNLOCK_UNIT(plqi);
 580         }
 581         sm_dbg('Y', ("sm_associate: rval=%d.\n", rval));
 582         return (rval);
 583 }
 584 
 585 /*
 586  * Break an association between one of the driver's minor nodes and
 587  * a serial device.
 588  */
 589 int
 590 sm_disassociate(int unit, sm_lqi_t *plqi, ulong_t tag)
 591 {
 592         sm_uqi_t *uqi;
 593         int rval = 0;
 594 
 595         sm_dbg('Y', ("sm_disassociate: link %d, unit %d: ",
 596             (plqi) ? plqi->sm_linkid : 0, unit));
 597         /*
 598          * Check the data is valid.
 599          * Disassociate a lower queue with a logical unit.
 600          */
 601         if (unit < 0 || unit >= NLUNITS || plqi == 0 ||
 602             (uqi = get_uqi(sm_ssp, unit)) == 0) {
 603                 sm_dbg('@', ("invalid: lqi=0x%p lui=0x%p", plqi, uqi));
 604                 rval = EINVAL;
 605         } else {
 606                 LOCK_UNIT(plqi);
 607 
 608                 if (plqi->sm_uqi == NULL) {
 609                         sm_dbg('@', ("unit not associated"));
 610                         rval = EINVAL;
 611                 } else if (plqi->sm_uqi->sm_lunit != unit) {
 612                         sm_dbg('@', ("unit and linkid not related",
 613                             plqi->sm_uqi->sm_lunit));
 614                         rval = EINVAL;
 615                 } else if (plqi->sm_tag != tag) {
 616                         sm_dbg('@',
 617                             ("Invalid tag for TTYMUX_DISASSOC ioctl\n"));
 618                         rval = EPERM;
 619                 } else {
 620                         sm_dbg('Y', ("disassociating "));
 621 
 622                         (void) ttymux_device_fini(plqi);
 623 
 624                         /*
 625                          * Indicate that carrier status is no
 626                          * longer required and that the upper
 627                          * queue should not be used by plqi
 628                          */
 629                         plqi->sm_flags &= ~(WANT_CDSTAT|WANT_TCSET);
 630                         plqi->sm_uqflags &= ~(SM_UQVALID|SM_OBPCNDEV);
 631                         plqi->sm_ioflag = 0u;
 632 
 633                         sm_lqifree(plqi);
 634                         rval = 0;
 635                 }
 636                 UNLOCK_UNIT(plqi);
 637         }
 638         sm_dbg('Y', (" rval=%d.\n", rval));
 639         return (rval);
 640 
 641 }
 642 
 643 /*
 644  * Streams helper routines;
 645  */
 646 
 647 /*
 648  * Schedule a qbufcall for an upper queue.
 649  * Must be called within the perimiter of the parameter q.
 650  * fn must reenable the q.
 651  * Called:
 652  *       whenever a message must be placed on multiple queues and allocb fails;
 653  */
 654 static void
 655 sm_sched_uqcb(queue_t *q, int memreq, int pri, void (*fn)())
 656 {
 657         sm_uqi_t        *uqi = q->q_ptr;
 658 
 659         if (uqi->sm_ttybid != 0)
 660                 qunbufcall(q, uqi->sm_ttybid);
 661 
 662         noenable(q);
 663 
 664         uqi->sm_ttybid = qbufcall(q, memreq, pri, fn, uqi);
 665 }
 666 
 667 /*
 668  * qbufcall routine to restart the queues when memory is available.
 669  */
 670 static void
 671 sm_reenable_q(sm_uqi_t *uqi)
 672 {
 673         queue_t *wq = SM_WQ(uqi);
 674 
 675         if ((uqi->sm_flags & SM_STOPPED) == 0) {
 676                 enableok(wq);
 677                 qenable(wq);
 678         }
 679 }
 680 
 681 /*
 682  * Place a message on the write queue of each stream associated with
 683  * the given upper stream.
 684  */
 685 static void
 686 sm_senddown(sm_uqi_t *uqi)
 687 {
 688         sm_lqi_t *lqi;
 689 
 690         for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) {
 691                 if (lqi->sm_mp != 0) {
 692                         putnext(SM_WQ(lqi), lqi->sm_mp);
 693                         lqi->sm_mp = 0;
 694                 }
 695         }
 696 }
 697 
 698 /*
 699  * For each lower device that should receive a write message duplicate
 700  * the message block.
 701  */
 702 static int
 703 sm_dupmsg(sm_uqi_t *uqi, mblk_t *mp)
 704 {
 705         sm_lqi_t        *lqi;
 706         mblk_t  *origmp = mp;
 707 
 708         for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) {
 709                 lqi->sm_mp = 0;
 710                 if (lqi->sm_flags & WERROR_MODE) {
 711                         continue;
 712                 }
 713                 if ((lqi->sm_ioflag & (uint_t)FOROUTPUT) == 0) {
 714                         if (DB_TYPE(mp) == M_DATA)
 715                                 continue;
 716                 }
 717                 if (lqi->sm_nlqi == 0) {
 718                         lqi->sm_mp = mp;
 719                         origmp = NULL;
 720                 } else if ((lqi->sm_mp = sm_copymsg(mp)) == 0) {
 721                         sm_lqi_t *flqi;
 722 
 723                         for (flqi = uqi->sm_lqs; flqi != lqi;
 724                             flqi = flqi->sm_nlqi) {
 725                                 if (lqi->sm_mp) {
 726                                 /* must have been sm_copymsg */
 727                                         sm_freemsg(lqi->sm_mp);
 728                                         lqi->sm_mp = 0;
 729                                 }
 730                         }
 731                         return (sm_cnt_oqs(uqi) * msgdsize(mp));
 732                 }
 733         }
 734         if (origmp != NULL)
 735                 freemsg(origmp);
 736         return (0);
 737 }
 738 
 739 /*
 740  * Return 1 if all associated lower devices have room for another message
 741  * otherwise return 0.
 742  */
 743 static int
 744 sm_cansenddown(sm_uqi_t *uqi)
 745 {
 746 
 747         register sm_lqi_t       *lqi;
 748 
 749         if (uqi->sm_lqs == 0)
 750                 return (0);
 751 
 752         for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) {
 753                 if ((lqi->sm_flags & WERROR_MODE) == 0 &&
 754                     canputnext(SM_WQ(lqi)) == 0)
 755                         return (0);
 756         }
 757         return (1);
 758 }
 759 
 760 /*
 761  * Put a message down all associated lower queues.
 762  * Return 1 if the q function was called.
 763  */
 764 static int
 765 sm_putqs(queue_t *q, mblk_t *mp, int (*qfn)())
 766 {
 767         register sm_uqi_t *uqi = (sm_uqi_t *)q->q_ptr;
 768         register int memreq;
 769         int pri = (DB_TYPE(mp) < QPCTL) ? BPRI_MED : BPRI_HI;
 770         int rval = 0;
 771 
 772         if (uqi->sm_lqs == 0 || (uqi->sm_flags & WERROR_MODE)) {
 773 
 774                 sm_dbg('Q', ("sm_putqs: freeing (0x%p 0x%p).\n", uqi->sm_lqs,
 775                     uqi->sm_flags));
 776                 freemsg(mp);
 777         } else if (pri != BPRI_HI && sm_cansenddown(uqi) == 0) {
 778                 /* a lower q is flow controlled */
 779                 (void) qfn(q, mp);
 780                 rval = 1;
 781         } else if ((memreq = sm_dupmsg(uqi, mp)) == 0) {
 782 
 783                 sm_senddown(uqi);
 784 
 785         } else {
 786                 sm_log("sm_putqs: msg 0x%x - can't alloc %d bytes (pri %d).\n",
 787                     DB_TYPE(mp), memreq, pri);
 788                 sm_sched_uqcb(q, memreq, pri, sm_reenable_q);
 789 
 790                 (void) qfn(q, mp);
 791                 rval = 1;
 792 
 793         }
 794 
 795         return (rval);
 796 }
 797 
 798 /*
 799  * Service a streams link and unlink requests.
 800  */
 801 static void
 802 sm_link_req(queue_t *wq, mblk_t *mp)
 803 {
 804         struct linkblk *linkp;
 805         int rval;
 806         int cmd;
 807         sm_lqi_t *plqi;
 808 
 809         ASSERT(DB_TYPE(mp) == M_IOCTL);
 810 
 811         cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd;
 812         switch (cmd) {
 813 
 814         case I_LINK:
 815         case I_PLINK:
 816                 sm_dbg('G', ("sm_link_req: M_IOCTL %x (I_PLINK).\n", cmd));
 817 
 818                 linkp = (struct linkblk *)mp->b_cont->b_rptr;
 819 
 820                 /*
 821                  * 1.   Sanity check the link block.
 822                  * 2.   Validate that the queue is not already linked
 823                  *              (and resources available).
 824                  * 3.   Validate that the lower queue is not associated with
 825                  *              a logical unit.
 826                  * 4.   Remember that this lower queue is linked to the driver.
 827                  */
 828                 if ((linkp == NULL) || (MBLKL(mp) < sizeof (*linkp)) ||
 829                     linkp->l_qbot == NULL) {
 830                         sm_dbg('I', ("sm_link_req: invalid link block.\n"));
 831                         rval = EINVAL;
 832                 } else if ((plqi = get_lqi_byq(linkp->l_qbot)) == 0) {
 833                         sm_dbg('I', ("sm_link_req: out of resources.\n"));
 834                         rval = EBUSY; /* out of resources */
 835                 } else if (plqi->sm_uqi) {
 836                         UNLOCK_UNIT(plqi); /* was aquired by get_lqi_byq */
 837                         sm_dbg('I', ("sm_link_req: already associated.\n"));
 838                         rval = EBUSY; /* already linked */
 839                 } else {
 840                         SM_WQ(plqi) = linkp->l_qbot;
 841                         SM_RQ(plqi)     = OTHERQ(linkp->l_qbot);
 842 
 843                         linkp->l_qbot->q_ptr =
 844                             OTHERQ(linkp->l_qbot)->q_ptr = plqi;
 845                         plqi->sm_linkid = linkp->l_index;
 846                         UNLOCK_UNIT(plqi); /* was aquired by get_lqi_byq */
 847 
 848                         sm_dbg('H', ("sm_link_req: linkid = %d.\n",
 849                             linkp->l_index));
 850 
 851                         sm_setdip(linkp->l_qbot, plqi);
 852                         plqi->sm_ttycommon->t_flags = 0;
 853                         plqi->sm_ttycommon->t_cflag = 0;
 854                         plqi->sm_mbits = 0;
 855                         (void) ttymux_device_init(plqi);
 856                         rval = 0;
 857                 }
 858 
 859                 break;
 860 
 861         case I_UNLINK:
 862         case I_PUNLINK:
 863                 sm_dbg('G', ("sm_link_req: M_IOCTL (I_PUNLINK).\n"));
 864 
 865                 linkp = (struct linkblk *)mp->b_cont->b_rptr;
 866 
 867                 if ((linkp == NULL) ||
 868                     (MBLKL(mp) < sizeof (*linkp)) ||
 869                     linkp->l_qbot == NULL) {
 870                         rval = EINVAL;
 871                 } else if ((plqi = get_lqi_byid(linkp->l_index)) == 0) {
 872                         rval = EINVAL;
 873                 } else {
 874                         sm_uqi_t *uqi;
 875                         int werrmode;
 876 
 877                         /*
 878                          * Mark the lower q as invalid.
 879                          */
 880                         sm_dbg('G', ("I_PUNLINK: freeing link %d\n",
 881                             linkp->l_index));
 882 
 883                         if (plqi->sm_bid) {
 884                                 qunbufcall(SM_RQ(plqi), plqi->sm_bid);
 885                                 plqi->sm_bid = 0;
 886                         }
 887                         if (plqi->sm_ttybid) {
 888                                 qunbufcall(SM_RQ(plqi), plqi->sm_ttybid);
 889                                 plqi->sm_ttybid = 0;
 890                         }
 891 
 892                         uqi = plqi->sm_uqi;
 893 
 894 
 895                         (void) ttymux_device_fini(plqi);
 896 
 897                         if (uqi)
 898                                 (void) sm_disassociate(uqi->sm_lunit,
 899                                     plqi, plqi->sm_tag);
 900 
 901                         LOCK_UNIT(plqi);
 902 
 903                         plqi->sm_piocid = 0;
 904 
 905                         werrmode = (plqi->sm_flags & (WERROR_MODE|HANGUP_MODE))
 906                             ? 1 : 0;
 907 
 908                         plqi->sm_mbits = 0;
 909                         plqi->sm_flags = 0;
 910 
 911                         ttycommon_close(plqi->sm_ttycommon);
 912                         /* SM_RQ(plqi) = SM_WQ(plqi) = 0; */
 913                         plqi->sm_ttycommon->t_flags = 0;
 914                         plqi->sm_ttycommon->t_cflag = 0;
 915                         plqi->sm_ttycommon->t_iflag = 0;
 916                         plqi->sm_linkid = 0;
 917                         plqi->sm_dev = NODEV;
 918                         plqi->sm_hadkadbchar = 0;
 919                         plqi->sm_nachar = sm_ssp->sm_abs;
 920 
 921                         UNLOCK_UNIT(plqi);
 922                         if (uqi &&
 923                             werrmode &&
 924                             (uqi->sm_flags & FULLY_OPEN) &&
 925                             sm_uwq_error(uqi) &&
 926                             putnextctl(SM_RQ(uqi), M_HANGUP) == 0) {
 927                                 sm_log("sm_link_req: putnextctl(M_HANGUP)"
 928                                     " failed.\n");
 929                         }
 930 
 931                         rval = 0;
 932                 }
 933 
 934                 break;
 935         default:
 936                 rval = EINVAL;
 937         }
 938         if (rval != 0)
 939                 miocnak(wq, mp, 0, rval);
 940         else
 941                 miocack(wq, mp, 0, 0);
 942 }
 943 
 944 static int
 945 sm_getiocinfo(mblk_t *mp, struct sm_iocinfo *info)
 946 {
 947         switch (DB_TYPE(mp)) {
 948         case M_COPYOUT:
 949                 info->sm_id = ((struct copyreq *)mp->b_rptr)->cq_id;
 950                 info->sm_cmd = ((struct copyreq *)mp->b_rptr)->cq_cmd;
 951                 info->sm_data = (((struct copyreq *)mp->b_rptr)->cq_size &&
 952                     mp->b_cont) ? (void *)mp->b_cont->b_rptr : 0;
 953                 break;
 954         case M_COPYIN:
 955                 info->sm_id = ((struct copyresp *)mp->b_rptr)->cp_id;
 956                 info->sm_cmd = ((struct copyresp *)mp->b_rptr)->cp_cmd;
 957                 info->sm_data = 0;
 958                 break;
 959         case M_IOCACK:
 960                 info->sm_id = ((struct iocblk *)mp->b_rptr)->ioc_id;
 961                 info->sm_cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd;
 962                 /* the se driver has bug so we cannot use ioc_count */
 963                 info->sm_data = (((struct iocblk *)mp->b_rptr)->
 964                     ioc_error == 0 && mp->b_cont) ?
 965                     (void *)mp->b_cont->b_rptr : 0;
 966                 break;
 967         case M_IOCNAK:
 968                 info->sm_id = ((struct iocblk *)mp->b_rptr)->ioc_id;
 969                 info->sm_cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd;
 970                 info->sm_data = 0;
 971                 break;
 972         case M_IOCDATA:
 973                 info->sm_id = ((struct copyresp *)mp->b_rptr)->cp_id;
 974                 info->sm_cmd = ((struct copyresp *)mp->b_rptr)->cp_cmd;
 975                 info->sm_data = (((struct copyresp *)mp->b_rptr)->
 976                     cp_rval == 0 && mp->b_cont) ?
 977                     (void *)mp->b_cont->b_rptr : 0;
 978                 break;
 979         case M_IOCTL:
 980                 info->sm_id = ((struct iocblk *)mp->b_rptr)->ioc_id;
 981                 info->sm_cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd;
 982                 info->sm_data = 0;
 983                 break;
 984         default:
 985                 return (EINVAL);
 986         }
 987         return (0);
 988 }
 989 
 990 /*
 991  * Record the termio settings that have been set on the upper stream
 992  */
 993 static int
 994 sm_update_ttyinfo(mblk_t *mp, sm_uqi_t *uqi)
 995 {
 996         int err;
 997         struct sm_iocinfo info;
 998 
 999         if ((err = sm_getiocinfo(mp, &info)) != 0)
1000                 return (err);
1001 
1002         switch (info.sm_cmd) {
1003         case TIOCSPPS:
1004         case TIOCGPPS:
1005         case TIOCGPPSEV:
1006                 return (ENOTSUP);
1007         case TIOCGWINSZ:
1008         case TIOCSWINSZ:
1009                 break;
1010         case TCSBRK:
1011         case TIOCSBRK:
1012         case TIOCCBRK:
1013                 break;
1014         case TCSETSF:
1015                 uqi->sm_flags |= FLUSHR_PEND;
1016                 sm_dbg('I', ("TCSETSF: FLUSH is pending\n"));
1017                 /*FALLTHROUGH*/
1018         case TCSETSW:
1019         case TCSETS:
1020         case TCGETS:
1021                 if (info.sm_data != 0) {
1022                         ((struct termios *)info.sm_data)->c_cflag &=
1023                             (tcflag_t)(~uqi->sm_cmask);
1024                         uqi->sm_ttycommon->t_cflag =
1025                             ((struct termios *)info.sm_data)->c_cflag;
1026                 }
1027                 break;
1028         case TCSETAF:
1029                 sm_dbg('I', ("TCSETAF: FLUSH is pending\n"));
1030                 uqi->sm_flags |= FLUSHR_PEND;
1031                 /*FALLTHROUGH*/
1032         case TCSETAW:
1033         case TCSETA:
1034         case TCGETA:
1035                 if (info.sm_data != 0) {
1036                         ((struct termio *)info.sm_data)->c_cflag &=
1037                             (tcflag_t)(~uqi->sm_cmask);
1038                         uqi->sm_ttycommon->t_cflag =
1039                             (tcflag_t)((struct termio *)info.sm_data)->c_cflag;
1040                 }
1041                 break;
1042         case TIOCSSOFTCAR:
1043         case TIOCGSOFTCAR:
1044                 if (info.sm_data != 0) {
1045                         if (*(int *)info.sm_data == 1)
1046                                 uqi->sm_ttycommon->t_flags |= TS_SOFTCAR;
1047                         else
1048                                 uqi->sm_ttycommon->t_flags &= ~TS_SOFTCAR;
1049                 }
1050                 break;
1051         case TIOCMSET:
1052         case TIOCMGET:
1053                 if (info.sm_data != 0)
1054                         uqi->sm_mbits = *(int *)info.sm_data;
1055                 break;
1056         case TIOCMBIS:
1057                 if (info.sm_data != 0)
1058                         uqi->sm_mbits |= *(int *)info.sm_data;
1059                 break;
1060         case TIOCMBIC:
1061                 if (info.sm_data != 0)
1062                         uqi->sm_mbits &= ~(*(int *)info.sm_data);
1063                 break;
1064         default:
1065                 return (EINVAL);
1066                 /* NOTREACHED */
1067         } /* end switch cmd */
1068 
1069         if ((uqi->sm_mbits & TIOCM_CD) ||
1070             (uqi->sm_ttycommon->t_flags & TS_SOFTCAR) ||
1071             (uqi->sm_ttycommon->t_cflag & CLOCAL))
1072                 uqi->sm_flags |= SM_CARON;
1073         else
1074                 uqi->sm_flags &= ~SM_CARON;
1075 
1076         return (0);
1077 }
1078 
1079 /*
1080  * SECTION
1081  * STREAM's interface to the OS.
1082  * Routines directly callable from the OS.
1083  */
1084 
1085 /*
1086  * Processes high priority messages comming from modules above the
1087  * multiplexor.
1088  * Return 1 if the queue was disabled.
1089  */
1090 static int
1091 sm_hp_uwput(queue_t *wq, mblk_t *mp)
1092 {
1093         sm_uqi_t        *uqi = (sm_uqi_t *)(wq->q_ptr);
1094         int     rval = 0;
1095         sm_lqi_t        *plqi;
1096         int     msgtype = DB_TYPE(mp);
1097 
1098         switch (msgtype) {
1099 
1100         case M_FLUSH:
1101                 /*
1102                  * How to flush the bottom half:
1103                  * putctl1(SM_WQ(plqi), *mp->b_rptr)
1104                  * will work on the bottom half but if FLUSHR is set
1105                  * when is the right time to flush the upper read queue.
1106                  *
1107                  * Could set uqi->sm_flags & WANT_FLUSH but then what happens
1108                  * if FLUSHR is set and the driver sends up a FLUSHR
1109                  * before it handles the current FLUSHR request
1110                  * (if only there was an id for the message that could
1111                  * be matched when it returns back from the drivers.
1112                  *
1113                  * Thus I'm going by the book - the bottom half acts like
1114                  * a stream head and turns around FLUSHW back down to
1115                  * the driver (see lrput). The upper half acts like a
1116                  * driver and turns around FLUSHR:
1117                  */
1118 
1119                 sm_dbg('I', ("sm_hp_uwput: FLUSH request 0x%x\n", *mp->b_rptr));
1120                 /* flush the upper write queue */
1121                 if (*mp->b_rptr & FLUSHW)
1122                         flushq(wq, FLUSHDATA);
1123 
1124                 /*
1125                  * flush each associated lower write queue
1126                  * and pass down the driver (ignore the FLUSHR and deal with
1127                  * it when it comes back up the read side.
1128                  */
1129                 for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi) {
1130                         if ((plqi->sm_flags & WERROR_MODE) == 0 &&
1131                             SM_WQ(plqi)) {
1132                                 sm_dbg('I', ("flush lq 0x%p\n", SM_WQ(plqi)));
1133                                 if (*mp->b_rptr & FLUSHW)
1134                                         flushq(SM_WQ(plqi), FLUSHDATA);
1135                                 (void) putnextctl1(SM_WQ(plqi), M_FLUSH,
1136                                     *mp->b_rptr);
1137                         }
1138                 }
1139                 break;
1140 
1141         case M_STARTI:
1142                 for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi) {
1143                         plqi->sm_flags &= ~SM_ISTOPPED;
1144                         if ((plqi->sm_flags & WERROR_MODE) == 0)
1145                                 (void) putnextctl(SM_WQ(plqi), msgtype);
1146                 }
1147                 break;
1148 
1149         case M_STOPI:
1150                 for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi) {
1151                         plqi->sm_flags |= SM_ISTOPPED;
1152                         if ((plqi->sm_flags & WERROR_MODE) == 0)
1153                                 (void) putnextctl(SM_WQ(plqi), msgtype);
1154                 }
1155                 break;
1156 
1157         case M_STOP:    /* must never be queued */
1158                 uqi->sm_flags |= SM_STOPPED;
1159                 noenable(wq);
1160                 for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi)
1161                         if ((plqi->sm_flags & WERROR_MODE) == 0)
1162                                 (void) putnextctl(SM_WQ(plqi), msgtype);
1163 
1164                 rval = 1;
1165                 break;
1166 
1167         case M_START:   /* never be queued */
1168                 uqi->sm_flags &= ~SM_STOPPED;
1169                 enableok(wq);
1170                 qenable(wq);
1171                 for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi)
1172                         if ((plqi->sm_flags & WERROR_MODE) == 0)
1173                                 (void) putnextctl(SM_WQ(plqi), msgtype);
1174 
1175                 break;
1176 
1177         case M_PCSIG:
1178         case M_COPYOUT:
1179         case M_COPYIN:
1180         case M_IOCACK:
1181         case M_IOCNAK:
1182                 /* Wrong direction for message */
1183                 break;
1184         case M_READ:
1185                 break;
1186         case M_PCPROTO:
1187         case M_PCRSE:
1188         default:
1189                 sm_dbg('I', ("sm_hp_uwput: default case %d.\n", msgtype));
1190                 break;
1191         } /* end switch on high pri message type */
1192 
1193         freemsg(mp);
1194         return (rval);
1195 }
1196 
1197 static int
1198 sm_default_uwioctl(queue_t *wq, mblk_t *mp, int (*qfn)())
1199 {
1200         int     err;
1201         struct iocblk   *iobp;
1202         sm_uqi_t        *uqi;
1203 
1204         uqi = (sm_uqi_t *)(wq->q_ptr);
1205         iobp = (struct iocblk *)mp->b_rptr;
1206 
1207         switch (iobp->ioc_cmd) {
1208         case TIOCEXCL:
1209         case TIOCNXCL:
1210         case TIOCSTI:
1211                 /*
1212                  * The three ioctl types we support do not require any
1213                  * additional allocation and should not return a pending
1214                  * ioctl state. For this reason it is safe for us to ignore
1215                  * the return value from ttycommon_ioctl().
1216                  * Additionally, we translate any error response from
1217                  * ttycommon_ioctl() into EINVAL.
1218                  */
1219                 (void) ttycommon_ioctl(uqi->sm_ttycommon, wq, mp, &err);
1220                 if (err < 0)
1221                         miocnak(wq, mp, 0, EINVAL);
1222                 else
1223                         miocack(wq, mp, 0, 0);
1224                 return (0);
1225         default:
1226                 break;
1227         }
1228         if ((err = sm_update_ttyinfo(mp, uqi)) != 0) {
1229                 miocnak(wq, mp, 0, err);
1230                 return (0);
1231         }
1232 
1233         /*
1234          * If uqi->sm_siocdata.sm_iocid just overwrite it since the stream
1235          * head will have timed it out
1236          */
1237         uqi->sm_siocdata.sm_iocid = iobp->ioc_id;
1238         uqi->sm_siocdata.sm_acked = 0;
1239         uqi->sm_siocdata.sm_nacks = sm_good_qs(uqi);
1240         uqi->sm_siocdata.sm_acnt = 0;
1241         uqi->sm_siocdata.sm_policy = uqi->sm_policy;
1242         uqi->sm_siocdata.sm_flags = 0;
1243         sm_dbg('Z', (" want %d acks for id %d.\n",
1244             uqi->sm_siocdata.sm_nacks, iobp->ioc_id));
1245 
1246         return (sm_putqs(wq, mp, qfn));
1247 }
1248 
1249 /*
1250  *
1251  * sm_uwput - put function for an upper STREAM write.
1252  */
1253 static int
1254 sm_uwput(queue_t *wq, mblk_t *mp)
1255 {
1256         sm_uqi_t                *uqi;
1257         uchar_t         msgtype;
1258         int             cmd;
1259         struct iocblk   *iobp;
1260 
1261         uqi = (sm_uqi_t *)(wq->q_ptr);
1262         msgtype = DB_TYPE(mp);
1263 
1264         ASSERT(uqi != 0 && sm_ssp != 0);
1265 
1266         if (msgtype >= QPCTL && msgtype != M_IOCDATA) {
1267                 (void) sm_hp_uwput(wq, mp);
1268                 return (0);
1269         }
1270 
1271         switch (DB_TYPE(mp)) {
1272         case M_DATA:
1273         case M_DELAY:
1274         case M_BREAK:
1275         default:
1276                 (void) sm_putqs(wq, mp, putq);
1277                 break;
1278 
1279         case M_CTL:
1280                 if (((struct iocblk *)mp->b_rptr)->ioc_cmd == MC_CANONQUERY) {
1281                         (void) putnextctl1(OTHERQ(wq), M_CTL, MC_NOCANON);
1282                 }
1283                 freemsg(mp);
1284                 break;
1285         case M_IOCDATA: /* not handled as high pri because may need to putbq */
1286                 sm_dbg('M', ("sm_uwput(M_IOCDATA)\n"));
1287                 /*FALLTHROUGH*/
1288         case M_IOCTL:
1289                 cmd = (msgtype == M_IOCDATA) ?
1290                     ((struct copyresp *)mp->b_rptr)->cp_cmd :
1291                     ((struct iocblk *)mp->b_rptr)->ioc_cmd;
1292 
1293                 iobp = (struct iocblk *)mp->b_rptr;
1294                 iobp->ioc_rval = 0;
1295 
1296                 sm_dbg('M', ("sm_uwput(M_IOCTL:%d)\n", cmd));
1297 
1298                 switch (cmd) {
1299 
1300                 case CONSGETABORTENABLE:
1301                         iobp->ioc_error = ttymux_abort_ioctl(mp);
1302                         DB_TYPE(mp) = iobp->ioc_error ? M_IOCNAK : M_IOCACK;
1303                         qreply(wq, mp);
1304                         break;
1305                 case CONSSETABORTENABLE:
1306                         iobp->ioc_error =
1307                             secpolicy_sys_config(iobp->ioc_cr, B_FALSE) != 0 ?
1308                             EPERM : ttymux_abort_ioctl(mp);
1309                         DB_TYPE(mp) = iobp->ioc_error ? M_IOCNAK : M_IOCACK;
1310                         qreply(wq, mp);
1311                         break;
1312                 case TTYMUX_SETABORT:
1313                         if (secpolicy_sys_config(iobp->ioc_cr, B_FALSE) != 0) {
1314                                 iobp->ioc_error = EPERM;
1315                                 DB_TYPE(mp) = M_IOCNAK;
1316                                 qreply(wq, mp);
1317                                 break;
1318                         }
1319                         /*FALLTHROUGH*/
1320                 case TTYMUX_GETABORT:
1321                 case TTYMUX_GETABORTSTR:
1322                 case TTYMUX_ASSOC:
1323                 case TTYMUX_DISASSOC:
1324                 case TTYMUX_SETCTL:
1325                 case TTYMUX_GETLINK:
1326                 case TTYMUX_CONSDEV:
1327                 case TTYMUX_GETCTL:
1328                 case TTYMUX_LIST:
1329                         (void) sm_ioctl_cmd(uqi, mp);
1330                         qreply(wq, mp);
1331                         break;
1332                 case I_LINK:
1333                 case I_PLINK:
1334                 case I_UNLINK:
1335                 case I_PUNLINK:
1336                         qwriter(wq, mp, sm_link_req, PERIM_OUTER);
1337                         break;
1338                 case TCSETSW:
1339                 case TCSETSF:
1340                 case TCSETAW:
1341                 case TCSETAF:
1342                 case TCSBRK:
1343                         if (wq->q_first) {
1344                                 sm_dbg('A', ("sm_uwput: TCSET-> on srv q.\n"));
1345                                 /* keep message order intact */
1346                                 (void) putq(wq, mp);
1347                                 break;
1348                         }
1349                         /*FALLTHROUGH*/
1350                 default:
1351                         (void) sm_default_uwioctl(wq, mp, putq);
1352                         break;
1353                 }
1354 
1355                 break; /* M_IOCTL */
1356 
1357         } /* end switch on message type */
1358 
1359         return (0);
1360 }
1361 
1362 /*
1363  * sm_uwsrv - service function for an upper STREAM write.
1364  * 'sm_uwsrv' takes a q parameter.      The q parameter specifies the queue
1365  * which is to be serviced.     This function reads the messages which are on
1366  * this service queue and passes them to the appropriate lower driver queue.
1367  */
1368 static int
1369 sm_uwsrv(queue_t *q)
1370 {
1371         mblk_t  *mp;
1372         sm_uqi_t        *uqi = (sm_uqi_t *)(q->q_ptr);
1373         int             msgtype;
1374 
1375         ASSERT(q == SM_WQ(uqi));
1376 
1377         /*
1378          * Empty the queue unless explicitly stopped.
1379          */
1380         while (mp = getq(q)) {
1381                 msgtype = DB_TYPE(mp);
1382 
1383                 if (msgtype >= QPCTL && msgtype != M_IOCDATA)
1384                         if (sm_hp_uwput(q, mp)) {
1385                                 sm_dbg('T', ("sm_uwsrv: flowcontrolled.\n"));
1386                                 break; /* indicates that the is disabled */
1387                         }
1388                         else
1389                                 continue;
1390 
1391                 if (uqi->sm_flags & SM_STOPPED) {
1392                         (void) putbq(q, mp);
1393                         sm_dbg('T', ("sm_uwsrv: SM_STOPPED.\n"));
1394                         break;
1395                 }
1396 
1397                 /*
1398                  * Read any ttycommon data that may
1399                  * change (TS_SOFTCAR, CREAD, etc.).
1400                  */
1401                 switch (DB_TYPE(mp)) {
1402                 case M_IOCTL:
1403                 case M_IOCDATA:
1404                         if (sm_default_uwioctl(q, mp, putbq))
1405                                 return (0);
1406                         break;
1407 
1408                 default:
1409                         if (sm_putqs(q, mp, putbq))
1410                                 return (0);
1411                 }
1412         }
1413         return (0);
1414 }
1415 
1416 /*
1417  * Lower write side service routine used for backenabling upstream
1418  * flow control.
1419  */
1420 static int
1421 sm_lwsrv(queue_t *q)
1422 {
1423         sm_lqi_t *lqi = (sm_lqi_t *)q->q_ptr;
1424         queue_t *uwq;
1425 
1426         LOCK_UNIT(lqi);
1427         if (lqi->sm_uqflags & SM_UQVALID) {
1428                 /*
1429                  * It's safe to lock uqi since lwsrv runs asynchronously
1430                  * with the upper write routines so this cannot be an
1431                  * upper half thread. While holding the lqi lock and
1432                  * if SM_UQVALID is set we are guaranteed that
1433                  * lqi->sm_uqi will be valid.
1434                  */
1435                 sm_dbg('I', ("sm_lwsrv: re-enabling upper queue.\n"));
1436 
1437                 uwq = SM_WQ(lqi->sm_uqi);
1438                 UNLOCK_UNIT(lqi);
1439                 qenable(uwq);
1440         } else  {
1441                 UNLOCK_UNIT(lqi);
1442         }
1443         return (0);
1444 }
1445 
1446 /*
1447  * Upper read queue ioctl response handler for messages
1448  * passed from the lower half of the driver.
1449  */
1450 static int
1451 sm_uriocack(queue_t *rq, mblk_t *mp)
1452 {
1453         sm_uqi_t                *uqi = (sm_uqi_t *)rq->q_ptr;
1454         int             err, flag;
1455         sm_iocdata_t    *iodp;
1456         struct sm_iocinfo       info;
1457 
1458         if ((err = sm_getiocinfo(mp, &info)) != 0) {
1459                 sm_dbg('I', ("Unknown ioctl response\n"));
1460                 return (err);
1461         }
1462 
1463         if (info.sm_id == uqi->sm_piocdata.sm_iocid) {
1464                 iodp = &uqi->sm_piocdata;
1465         } else if (info.sm_id == uqi->sm_siocdata.sm_iocid) {
1466                 iodp = &uqi->sm_siocdata;
1467         } else {
1468                 sm_log("Unexpected ioctl response\n");
1469                 sm_dbg('I', ("Unexpected ioctl response (id %d)\n",
1470                     info.sm_id));
1471 
1472                 /*
1473                  * If the response is sent up it will result in
1474                  * duplicate ioctl responses. The ioctl has probably been
1475                  * timed out by the stream head so dispose of the response
1476                  * (since it has arrived too late.
1477                  */
1478                 goto out;
1479         }
1480 
1481         flag = SM_COPYIN;
1482 
1483         switch (DB_TYPE(mp)) {
1484         case M_COPYOUT:
1485                 flag = SM_COPYOUT;
1486                 /*FALLTHRU*/
1487         case M_COPYIN:
1488                 if (iodp->sm_flags & flag)
1489                         goto out;
1490                 iodp->sm_flags |= flag;
1491 
1492                 break;
1493         case M_IOCACK:
1494                 iodp->sm_ackcnt += 1;
1495                 iodp->sm_acnt += 1;
1496                 if (iodp->sm_policy == FIRSTACK) {
1497                         if (iodp->sm_acnt == iodp->sm_nacks)
1498                                 iodp->sm_iocid = 0;
1499                         if (iodp->sm_acnt == 1)
1500                                 iodp->sm_acked = 1;
1501                         else
1502                                 goto out;
1503                 } else {
1504                         if (iodp->sm_acnt == iodp->sm_nacks) {
1505                                 iodp->sm_iocid = 0;
1506                                 iodp->sm_acked = 1;
1507                         } else
1508                                 goto out;
1509                 }
1510                 break;
1511         case M_IOCNAK:
1512                 iodp->sm_nakcnt += 1;
1513                 iodp->sm_acnt += 1;
1514                 if (iodp->sm_acnt == iodp->sm_nacks) {
1515                         iodp->sm_iocid = 0;
1516                         if (iodp->sm_acked == 0) {
1517                                 iodp->sm_acked = 1;
1518                                 break;
1519                         }
1520                 }
1521                 goto out;
1522         default:
1523                 goto out;
1524         }
1525 
1526         /*
1527          * Merge the tty settings each of the associated lower streams.
1528          */
1529         if (info.sm_data)
1530                 (void) sm_update_ttyinfo(mp, uqi);
1531 
1532         if (iodp == &uqi->sm_piocdata) {
1533                 if (iodp->sm_iocid == 0) {
1534                         uqi->sm_flags &= ~SM_IOCPENDING;
1535                 }
1536         } else {
1537                 sm_dbg('I', ("sm_uriocack: forwarding response for %d.\n",
1538                     info.sm_id));
1539                 putnext(rq, mp);
1540                 return (0);
1541         }
1542 out:
1543         sm_dbg('I', ("sm_uriocack: freeing response for %d.\n", info.sm_id));
1544         freemsg(mp);
1545         return (0);
1546 }
1547 
1548 /*
1549  * Transfer a message from the lower read side of the multiplexer onto
1550  * the associated upper stream.
1551  */
1552 static int
1553 sm_ursendup(queue_t *q, mblk_t *mp)
1554 {
1555         sm_uqi_t        *uqi = (sm_uqi_t *)q->q_ptr;
1556 
1557         if (!canputnext(q) && DB_TYPE(mp) < QPCTL) {
1558                 sm_dbg('I', ("sm_ursendup: flow controlled.\n"));
1559                 return (1);
1560         }
1561 
1562         switch (DB_TYPE(mp)) {
1563         case M_COPYIN:
1564         case M_COPYOUT:
1565         case M_IOCACK:
1566         case M_IOCNAK:
1567                 (void) sm_uriocack(q, mp);
1568                 break;
1569         case M_HANGUP:
1570                 if (sm_uwq_error(uqi)) {
1571                         /* there are no usable lower q's */
1572                         uqi->sm_flags &= ~SM_CARON;
1573                         putnext(q, mp);
1574                 } else {
1575                         /* there are still usable q's - don't send up */
1576                         freemsg(mp);
1577                 }
1578                 break;
1579         case M_ERROR:
1580                 if (sm_uwq_error(uqi)) {
1581                         /* there are no usable lower q's */
1582                         uqi->sm_flags &= ~SM_CARON;
1583                         putnext(q, mp);
1584                 } else if (*mp->b_rptr == NOERROR) {
1585                         /* the error has cleared */
1586                         uqi->sm_flags &= ~ERROR_MODE;
1587                         putnext(q, mp);
1588                 } else {
1589                         /* there are still usable q's - don't send up */
1590                         freemsg(mp);
1591                 }
1592                 break;
1593         case M_FLUSH:
1594                 flushq(q, FLUSHDATA);
1595                 putnext(q, mp); /* time to use FLUSHR_PEND flag */
1596                 break;
1597         case M_CTL:
1598                 /* wrong direction - must have come from sm_close */
1599                 uqi->sm_flags |= SM_CLOSE;
1600                 sm_dbg('I', ("sm_ursrv: had SM_CLOSE.\n"));
1601                 freemsg(mp);
1602                 break;
1603         case M_UNHANGUP:
1604                 /* just pass them all up - they're harmless */
1605                 uqi->sm_flags |= SM_CARON;
1606                 /* FALLTHROUGH */
1607         default:
1608                 putnext(q, mp);
1609                 break;
1610         }
1611 
1612         return (0);
1613 }
1614 
1615 /*
1616  * sm_urput - put function for a lower STREAM read.
1617  */
1618 static int
1619 sm_urput(queue_t *q, mblk_t *mp)
1620 {
1621         if (sm_ursendup(q, mp) != 0)
1622                 (void) putq(q, mp);
1623 
1624         return (0);
1625 }
1626 
1627 /*
1628  * Upper read side service routine.
1629  * Read side needs to be fast so only check for duplicate M_IOCTL acks.
1630  */
1631 static int
1632 sm_ursrv(queue_t *q)
1633 {
1634         sm_uqi_t        *uqi = (sm_uqi_t *)q->q_ptr;
1635         mblk_t  *mp;
1636         int     flags = uqi->sm_flags;
1637 
1638         while ((mp = getq(q))) {
1639                 if (sm_ursendup(q, mp) != 0) {
1640                         sm_dbg('I', ("sm_ursrv: flow controlled.\n"));
1641                         (void) putbq(q, mp);
1642                         uqi->sm_flags |= WANT_RENB;
1643                         break;
1644                 }
1645         }
1646 
1647         /*
1648          * If the q service was called because it was no longer
1649          * flow controled then enable each of the driver queues.
1650          */
1651         if ((flags & WANT_RENB) && !(uqi->sm_flags & WANT_RENB)) {
1652                 sm_lqi_t *lqi;
1653                 queue_t *drq; /* read q of linked driver */
1654 
1655                 uqi->sm_flags &= ~WANT_RENB;
1656                 for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) {
1657                         drq = SM_RQ(lqi)->q_next;
1658                         if (drq && drq->q_first != 0)
1659                                 qenable(drq);
1660                 }
1661         }
1662 
1663         return (0);
1664 }
1665 
1666 /*
1667  * Check a message sent from a linked device for abort requests and
1668  * for flow control.
1669  */
1670 static int
1671 sm_lrmsg_check(queue_t *q, mblk_t *mp)
1672 {
1673         sm_lqi_t        *lqi    = (sm_lqi_t *)q->q_ptr;
1674 
1675         switch (DB_TYPE(mp)) {
1676         case M_DATA:
1677                 LOCK_UNIT(lqi);
1678                 /*
1679                  * check for abort - only allow abort on I/O consoles
1680                  * known to OBP -
1681                  * fix it when we do polled io
1682                  */
1683                 if ((lqi->sm_ioflag & (uint_t)FORINPUT) == 0) {
1684                         freemsg(mp);
1685                         UNLOCK_UNIT(lqi);
1686                         return (1);
1687                 }
1688                 if ((lqi->sm_uqflags & SM_OBPCNDEV) &&
1689                     lqi->sm_ctrla_abort_on &&
1690                     abort_enable == KIOCABORTALTERNATE) {
1691 
1692                         uchar_t         *rxc;
1693                         boolean_t       aborted = B_FALSE;
1694 
1695                         for (rxc = mp->b_rptr;
1696                             rxc != mp->b_wptr;
1697                             rxc++)
1698 
1699                                 if (*rxc == *lqi->sm_nachar) {
1700                                         lqi->sm_nachar++;
1701                                         if (*lqi->sm_nachar == '\0') {
1702                                                 abort_sequence_enter(
1703                                                     (char *)NULL);
1704                                                 lqi->sm_nachar = sm_ssp->sm_abs;
1705                                                 aborted = B_TRUE;
1706                                         }
1707                                 } else
1708                                         lqi->sm_nachar = (*rxc == *sm_ssp->
1709                                             sm_abs) ?
1710                                             sm_ssp->
1711                                             sm_abs + 1 :
1712                                             sm_ssp->sm_abs;
1713 
1714                         if (aborted) {
1715                                 freemsg(mp);
1716                                 UNLOCK_UNIT(lqi);
1717                                 return (1);
1718                         }
1719                 }
1720                 UNLOCK_UNIT(lqi);
1721                 break;
1722         case M_BREAK:   /* we'll eventually see this as a flush */
1723                 LOCK_UNIT(lqi);
1724                 /*
1725                  * Only allow abort on OBP devices. When polled I/O is
1726                  * supported allow abort on any console device.
1727                  * Parity errors are reported upstream as breaks so
1728                  * ensure that there is no data in the message before
1729                  * deciding whether to abort.
1730                  */
1731                 if ((lqi->sm_uqflags & SM_OBPCNDEV) && /* console stream */
1732                     (mp->b_wptr - mp->b_rptr == 0 &&
1733                     msgdsize(mp) == 0)) {       /* not due to parity */
1734 
1735                         if (lqi->sm_break_abort_on &&
1736                             abort_enable != KIOCABORTALTERNATE)
1737                                 abort_sequence_enter((char *)NULL);
1738 
1739                         freemsg(mp);
1740                         UNLOCK_UNIT(lqi);
1741                         return (1);
1742                 } else {
1743                         UNLOCK_UNIT(lqi);
1744                 }
1745                 break;
1746         default:
1747                 break;
1748         }
1749 
1750         if (DB_TYPE(mp) >= QPCTL)
1751                 return (0);
1752 
1753         LOCK_UNIT(lqi); /* lock out the upper half */
1754         if ((lqi->sm_uqflags & SM_UQVALID) && SM_RQ(lqi->sm_uqi)) {
1755                 UNLOCK_UNIT(lqi);
1756                 if (!canput(SM_RQ(lqi->sm_uqi))) {
1757                         sm_dbg('I', ("sm_lrmsg_check: flow controlled.\n"));
1758                         (void) putq(q, mp);
1759                         return (1);
1760                 }
1761         } else {
1762                 UNLOCK_UNIT(lqi);
1763         }
1764 
1765         return (0);
1766 }
1767 
1768 /*
1769  * sm_sendup - deliver a message to the upper read side of the multiplexer
1770  */
1771 static int
1772 sm_sendup(queue_t *q, mblk_t *mp)
1773 {
1774         sm_lqi_t        *lqi    = (sm_lqi_t *)q->q_ptr;
1775 
1776         if (sm_ssp == NULL) {
1777                 freemsg(mp);
1778                 return (0);
1779         }
1780 
1781         /*
1782          * Check for CD status change messages from driver.
1783          * (Remark: this is an se driver thread running at soft interupt
1784          * priority and the waiters are in user context).
1785          */
1786         switch (DB_TYPE(mp)) {
1787         case M_DATA:
1788         case M_BREAK:   /* we'll eventually see this as a flush */
1789                 break;
1790 
1791         /* high priority messages */
1792         case M_IOCACK:
1793         case M_IOCNAK:
1794                 if ((lqi->sm_flags & SM_IOCPENDING) && lqi->sm_piocid ==
1795                     ((struct iocblk *)mp->b_rptr)->ioc_id) {
1796                         freemsg(mp);
1797                         lqi->sm_flags &= ~SM_IOCPENDING;
1798                         sm_issue_ioctl(lqi);
1799                         return (0);
1800                 }
1801                 break;
1802         case M_UNHANGUP:
1803                 /*
1804                  * If the driver can send an M_UNHANGUP it must be able to
1805                  * accept messages from above (ie clear WERROR_MODE if set).
1806                  */
1807                 sm_dbg('E', ("lrput: M_UNHANGUP\n"));
1808                 lqi->sm_mbits |= TIOCM_CD;
1809                 lqi->sm_flags &= ~(WERROR_MODE|HANGUP_MODE);
1810 
1811                 break;
1812 
1813         case M_HANGUP:
1814                 sm_dbg('E', ("lrput: MHANGUP\n"));
1815                 lqi->sm_mbits &= ~TIOCM_CD;
1816                 lqi->sm_flags |= (WERROR_MODE|HANGUP_MODE);
1817                 break;
1818 
1819         case M_ERROR:
1820 
1821                 sm_dbg('E', ("lrput: MERROR\n"));
1822                 /*
1823                  * Tell the driver to flush rd/wr queue if its read/write error.
1824                  * if its a read/write error flush rq/wq (type in first bytes).
1825                  */
1826                 if ((mp->b_wptr - mp->b_rptr) == 2) {
1827                         uchar_t rw = 0;
1828 
1829                         if (*mp->b_rptr == NOERROR) {
1830                                 /* not in error anymore */
1831                                 lqi->sm_flags &= ~ERROR_MODE;
1832                                 lqi->sm_flags |= WANT_CD;
1833                         } else {
1834                                 if (*mp->b_rptr != 0) {
1835                                         /* read error */
1836                                         rw |= FLUSHR;
1837                                         lqi->sm_flags |= RERROR_MODE;
1838                                 }
1839                                 mp->b_rptr++;
1840                                 if (*mp->b_rptr != 0) {
1841                                         /* write error */
1842                                         rw |= FLUSHW;
1843                                         lqi->sm_flags |= WERROR_MODE;
1844                                 }
1845 
1846                                 mp->b_rptr--;
1847                                 /* has next driver done qprocsoff */
1848                                 if (rw && OTHERQ(q)->q_next != NULL) {
1849                                         (void) putnextctl1(OTHERQ(q), M_FLUSH,
1850                                             rw);
1851                                 }
1852                         }
1853                 } else if (*mp->b_rptr != 0 && OTHERQ(q)->q_next != NULL) {
1854                         sm_dbg('E', ("lrput: old style MERROR (?)\n"));
1855 
1856                         lqi->sm_flags |= (RERROR_MODE | WERROR_MODE);
1857                         (void) putnextctl1(OTHERQ(q), M_FLUSH, FLUSHRW);
1858                 }
1859                 break;
1860 
1861         case M_PCSIG:
1862         case M_SIG:
1863                 break;
1864         case M_COPYOUT:
1865         case M_COPYIN:
1866                 break;
1867         case M_FLUSH:
1868                 /* flush the read queue and pass on up */
1869                 flushq(q, FLUSHDATA);
1870                 break;
1871         default:
1872                 break;
1873         }
1874 
1875         LOCK_UNIT(lqi); /* lock out the upper half */
1876         if (lqi->sm_uqflags & SM_UQVALID && SM_RQ(lqi->sm_uqi)) {
1877                 UNLOCK_UNIT(lqi);
1878                 (void) putq(SM_RQ(lqi->sm_uqi), mp);
1879                 return (0);
1880         } else {
1881                 sm_dbg('I', ("sm_sendup: uq not valid\n"));
1882                 freemsg(mp);
1883         }
1884         UNLOCK_UNIT(lqi);
1885 
1886         return (0);
1887 }
1888 
1889 /*
1890  * sm_lrput - put function for a lower STREAM read.
1891  */
1892 static int
1893 sm_lrput(queue_t *q, mblk_t *mp)
1894 {
1895         if (sm_lrmsg_check(q, mp) == 0)
1896                 (void) sm_sendup(q, mp);
1897         return (0);
1898 }
1899 
1900 /*
1901  * sm_lrsrv - service function for the lower read STREAM.
1902  */
1903 static int
1904 sm_lrsrv(queue_t *q)
1905 {
1906         mblk_t  *mp;
1907 
1908         sm_dbg('I', ("sm_lrsrv: not controlled.\n"));
1909         while (mp = getq(q))
1910                 (void) sm_sendup(q, mp);
1911 
1912         return (0);
1913 }
1914 
1915 /*
1916  * Check whether a thread is allowed to open the requested device.
1917  */
1918 static int
1919 sm_ok_to_open(sm_uqi_t *uqi, int protocol, cred_t *credp, int *abort_waiters)
1920 {
1921         int rval = 0;
1922         int proto;
1923 
1924         *abort_waiters = 0;
1925 
1926         switch (protocol) {
1927                 case ASYNC_DEVICE: /* Standard async protocol */
1928                 if ((uqi->sm_protocol == NULL_PROTOCOL) ||
1929                     (uqi->sm_protocol == ASYN_PROTOCOL)) {
1930                         /*
1931                          * Lock out other incompatible protocol requests.
1932                          */
1933                         proto = ASYN_PROTOCOL;
1934                         rval = 0;
1935                 } else
1936                         rval = EBUSY;
1937                 break;
1938 
1939                 case OUTLINE:   /* Outdial protocol */
1940                 if ((uqi->sm_protocol == NULL_PROTOCOL) ||
1941                     (uqi->sm_protocol == OUTD_PROTOCOL)) {
1942                         proto = OUTD_PROTOCOL;
1943                         rval = 0;
1944                 } else if (uqi->sm_protocol == ASYN_PROTOCOL) {
1945                         /*
1946                          * check for dialout request on a line that is already
1947                          * open for dial in:
1948                          * kick off any thread that is waiting to fully open
1949                          */
1950                         if (uqi->sm_flags & FULLY_OPEN)
1951                                 rval = EBUSY;
1952                         else {
1953                                 proto = OUTD_PROTOCOL;
1954                                 *abort_waiters = 1;
1955                         }
1956                 } else
1957                         rval = EBUSY;
1958                 break;
1959                 default:
1960                         rval = ENOTSUP;
1961         }
1962 
1963         if (rval == 0 &&
1964             (uqi->sm_ttycommon->t_flags & TS_XCLUDE) &&
1965             secpolicy_excl_open(credp) != 0) {
1966 
1967                 if (uqi->sm_flags & FULLY_OPEN) {
1968                         rval = EBUSY; /* exclusive device already open */
1969                 } else {
1970                         /* NB TS_XCLUDE cant be set during open so NOTREACHED */
1971                         /* force any waiters to yield TS_XCLUDE */
1972                         *abort_waiters = 1;
1973                 }
1974         }
1975 
1976         if (rval == 0)
1977                 uqi->sm_protocol = proto;
1978 
1979         sm_dbg('A', ("ok_to_open (0x%p, %d) proto=%d rval %d (wabort=%d)",
1980             uqi, protocol, uqi->sm_protocol, rval, *abort_waiters));
1981 
1982         return (rval);
1983 }
1984 
1985 /* wait for memory to become available whilst performing a qwait */
1986 /*ARGSUSED*/
1987 static void dummy_callback(void *arg)
1988 {}
1989 
1990 /* ARGSUSED */
1991 static int
1992 sm_dump_msg(queue_t *q, mblk_t *mp)
1993 {
1994         freemsg(mp);
1995         return (0);
1996 }
1997 
1998 /*
1999  * Wait for a message to arrive - must be called with exclusive
2000  * access at the outer perimiter.
2001  */
2002 static int
2003 sm_qwait_sig(sm_uqi_t *uqi, queue_t *q)
2004 {
2005         int err;
2006 
2007         sm_dbg('C', ("sm_qwait_sig: waiting.\n"));
2008 
2009         uqi->sm_waitq = q;
2010         uqi->sm_nwaiters++;  /* required by the close routine */
2011         err = qwait_sig(q);
2012         if (--uqi->sm_nwaiters == 0)
2013                 uqi->sm_waitq = 0;
2014 
2015         if (err == 0)
2016                 err = EINTR;
2017         else if (q->q_ptr == 0) /* can happen if there are multiple waiters */
2018                 err = -1;
2019         else if (uqi->sm_flags & SM_CLOSE) {
2020                 uqi->sm_flags &= ~SM_CLOSE;
2021                 err = 1;        /* a different protocol has closed its stream */
2022         }
2023         else
2024                 err = 0;        /* was worth waiting for */
2025 
2026         sm_dbg('C', ("sm_qwait_sig: rval %d\n", err));
2027         return (err);
2028 }
2029 
2030 /*
2031  * Defer the opening of one the drivers devices until the state of each
2032  * associated lower stream is known.
2033  */
2034 static int
2035 sm_defer_open(sm_uqi_t *uqi, queue_t *q)
2036 {
2037         uint_t cmdflags = WANT_CDSTAT;
2038         int err, nqs;
2039 
2040         while ((nqs = sm_good_qs(uqi)) == 0) {
2041                 sm_dbg('C', ("sm_defer_open: no good qs\n"));
2042                 if (err = sm_qwait_sig(uqi, q))
2043                         return (err);
2044         }
2045 
2046         while ((uqi->sm_flags & SM_CARON) == 0) {
2047                 int iocmd;
2048                 mblk_t *pioc;
2049 
2050                 sm_dbg('C', ("sm_defer_open: flags 0x%x cmdflags 0x%x\n",
2051                     uqi->sm_flags, cmdflags));
2052                 if (cmdflags == 0) {
2053                         if (err = sm_qwait_sig(uqi, q))
2054                                 return (err);
2055                         continue;       /* waiting for an M_UNHANGUP */
2056                 } else if (cmdflags & WANT_SC) {
2057                         cmdflags &= ~WANT_SC;
2058                         iocmd = TIOCGSOFTCAR;
2059                 } else if (cmdflags & WANT_CD) {
2060                         cmdflags &= ~WANT_CD;
2061                         iocmd = TIOCMGET;
2062                 } else if (cmdflags & WANT_CL) {
2063                         cmdflags &= ~WANT_CL;
2064                         iocmd = TCGETS;
2065                 }
2066 
2067                 if (uqi->sm_piocdata.sm_iocid == 0) {
2068                         while ((pioc = mkiocb(iocmd)) == 0) {
2069                                 bufcall_id_t id =
2070                                     qbufcall(q, sizeof (struct iocblk),
2071                                     BPRI_MED, dummy_callback, 0);
2072                                 if (err = sm_qwait_sig(uqi, q)) {
2073                                         /* wait for the bufcall */
2074                                         qunbufcall(q, id);
2075                                         return (err);
2076                                 }
2077                                 qunbufcall(q, id);
2078                         }
2079 
2080                         uqi->sm_flags |= SM_IOCPENDING;
2081 
2082                         uqi->sm_piocdata.sm_iocid =
2083                             ((struct iocblk *)pioc->b_rptr)->ioc_id;
2084                         uqi->sm_piocdata.sm_acked = 0;
2085                         uqi->sm_piocdata.sm_nacks = nqs;
2086                         uqi->sm_piocdata.sm_acnt = 0;
2087                         uqi->sm_piocdata.sm_ackcnt = uqi->
2088                             sm_piocdata.sm_nakcnt = 0;
2089                         uqi->sm_piocdata.sm_policy = uqi->sm_policy;
2090                         uqi->sm_piocdata.sm_flags = SM_INTERNALIOC;
2091                         if (sm_putqs(WR(q), pioc, sm_dump_msg) != 0) {
2092                                 uqi->sm_piocdata.sm_iocid = 0;
2093                                 sm_log("sm_defer_open: bad putqs\n");
2094                                 return (-1);
2095                         }
2096                 }
2097 
2098                 sm_dbg('C', ("sm_defer_open: flags 0x%x\n", uqi->sm_flags));
2099                 while ((uqi->sm_flags & SM_CARON) == 0 &&
2100                     (uqi->sm_flags & SM_IOCPENDING) != 0)
2101                         if (err = sm_qwait_sig(uqi, q))
2102                                 return (err);
2103 
2104                 sm_dbg('C', ("defer_open: uq flags 0x%x.\n", uqi->sm_flags));
2105         }
2106         sm_dbg('C', ("defer_open: return 0.\n"));
2107         return (0);
2108 }
2109 
2110 static int
2111 sm_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
2112 {
2113         int             ftstat;
2114         int             unit;
2115         int             protocol;
2116         sm_uqi_t                *uqi;
2117         int             abort_waiters;
2118 
2119         if (sm_ssp == NULL)
2120                 return (ENXIO);
2121         /*
2122          * sflag = 0 => streams device.
2123          */
2124         if (sflag != 0 || DEV_TO_UNIT(*devp) >= NLUNITS) {
2125                 sm_dbg('C', ("open: sflag=%d or bad dev_t.\n", sflag));
2126                 return (ENXIO);
2127         }
2128 
2129         unit = DEV_TO_UNIT(*devp);
2130         protocol = DEV_TO_PROTOBITS(*devp);
2131 
2132         uqi = get_uqi(sm_ssp, unit);
2133 
2134         sm_dbg('C', ("open(0x%p, %d, 0x%x) :- unit=%d, proto=%d, uqi=0x%p\n",
2135             rq, *devp, flag, unit, protocol, uqi));
2136 
2137         if (uqi == 0)
2138                 return (ENXIO);
2139 
2140         if (sm_refuse_opens && unit > smctlunit && uqi->sm_nlqs == 0)
2141                 return (ENXIO);
2142 
2143         if (uqi->sm_flags & EXCL_OPEN && (flag & FEXCL)) {
2144                 return (EBUSY); /* device in use */
2145         }
2146 
2147         if ((flag & FEXCL)) {
2148                 if (secpolicy_excl_open(credp) != 0)
2149                         return (EPERM);
2150 
2151                 if ((uqi->sm_flags & FULLY_OPEN) || uqi->sm_nwaiters > 0)
2152                         return (EBUSY); /* device in use */
2153 
2154                 uqi->sm_flags |= EXCL_OPEN;
2155         }
2156 
2157         if (uqi->sm_protocol == NULL_PROTOCOL) {
2158                 struct termios *termiosp;
2159                 int len;
2160 
2161                 if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(),
2162                     DDI_PROP_NOTPROM, "ttymodes", (caddr_t)&termiosp, &len)
2163                     == DDI_PROP_SUCCESS &&
2164                     (len == sizeof (struct termios))) {
2165 
2166                         sm_dbg('C', ("open: c_cflag=0x%x\n",
2167                                 termiosp->c_cflag));
2168 
2169                         uqi->sm_ttycommon->t_iflag = termiosp->c_iflag;
2170                         uqi->sm_ttycommon->t_cflag = termiosp->c_cflag;
2171                         uqi->sm_ttycommon->t_stopc = termiosp->c_cc[VSTOP];
2172                         uqi->sm_ttycommon->t_startc = termiosp->c_cc[VSTART];
2173 
2174                         /*
2175                          * IGNBRK,BRKINT,INPCK,IXON,IXANY,IXOFF - drivers
2176                          * PARMRK,IGNPAR,ISTRIP - how to report parity
2177                          * INLCR,IGNCR,ICRNL,IUCLC - ldterm (sophisticated I/O)
2178                          * IXON, IXANY, IXOFF - flow control input
2179                          * CBAUD,CSIZE,CS5-8,CSTOPB,PARENB,PARODD,HUPCL,
2180                          * RCV1EN,XMT1EN,LOBLK,XCLUDE,CRTSXOFF,CRTSCTS,
2181                          * CIBAUD,PAREXT,CBAUDEXT,CIBAUDEXT,CREAD,CLOCAL
2182                          */
2183 
2184                         kmem_free(termiosp, len);
2185                 }
2186                 else
2187                         bzero((caddr_t)uqi->sm_ttycommon,
2188                             sizeof (uqi->sm_ttycommon));
2189 
2190                 if (*devp == rconsdev) {
2191                         uqi->sm_cmask = sm_cmask;
2192                         uqi->sm_ttycommon->t_flags |= TS_SOFTCAR;
2193                 } else {
2194                         uqi->sm_ttycommon->t_flags &= ~TS_SOFTCAR;
2195                 }
2196 
2197                 /*
2198                  * Clear the default CLOCAL and TS_SOFTCAR flags since
2199                  * they must correspond to the settings on the real devices.
2200                  */
2201 
2202                 uqi->sm_ttycommon->t_cflag &= ~(uqi->sm_cmask|CLOCAL);
2203                 uqi->sm_mbits = 0;
2204                 uqi->sm_policy = FIRSTACK;
2205                 if (unit == 0 && sm_ssp->sm_ms == 0)
2206                         sm_ssp->sm_ms = (sm_mux_state_t *)
2207                             space_fetch(TTYMUXPTR);
2208                 if (sm_ssp->sm_ms) {
2209                         if (sm_ssp->sm_ms->sm_cons_stdin.sm_dev == *devp ||
2210                             sm_ssp->sm_ms->sm_cons_stdout.sm_dev == *devp)
2211                                 sm_ssp->sm_lconsole = uqi;
2212                 }
2213         }
2214 
2215         /*
2216          * Does this thread need to wait?
2217          */
2218 
2219         sm_dbg('C', ("sm_open: %d %d 0x%p 0x%x\n",
2220             !(flag & (FNDELAY|FNONBLOCK)), !(protocol == OUTLINE), uqi->sm_lqs,
2221             uqi->sm_flags));
2222 
2223 tryopen:
2224 
2225         abort_waiters = 0;
2226         if (ftstat = sm_ok_to_open(uqi, protocol, credp, &abort_waiters)) {
2227                 sm_dbg('C', ("open failed stat=%d.\n", ftstat));
2228 
2229                 if ((uqi->sm_flags & FULLY_OPEN) == 0 && uqi->sm_nwaiters == 0)
2230                         uqi->sm_protocol = NULL_PROTOCOL;
2231                 if (flag & FEXCL)
2232                         uqi->sm_flags &= ~EXCL_OPEN;
2233                 return (ftstat);
2234         }
2235 
2236         if (abort_waiters) {
2237                 uqi->sm_dev = *devp;
2238                 /* different device wants to use the unit */
2239                 SM_RQ(uqi) = rq;
2240                 SM_WQ(uqi) = WR(rq);
2241         }
2242         if (rq->q_ptr == 0) {
2243                 sm_lqi_t *lqi;
2244 
2245                 uqi->sm_dev = *devp;
2246                 rq->q_ptr = WR(rq)->q_ptr = uqi;
2247                 SM_RQ(uqi) = rq;
2248                 SM_WQ(uqi) = WR(rq);
2249                 qprocson(rq);
2250                 for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) {
2251                         LOCK_UNIT(lqi);
2252                         lqi->sm_uqflags |= SM_UQVALID;
2253                         UNLOCK_UNIT(lqi);
2254                 }
2255 
2256                 sm_dbg('C', ("sm_open: SM_UQVALID set on lqs.\n"));
2257         }
2258 
2259         if (*devp != rconsdev && BLOCKING(uqi, protocol, flag)) {
2260 
2261                 uqi->sm_flags |= WANT_CDSTAT;
2262 
2263                 do {
2264                         /*
2265                          * Wait for notifications of changes in the CLOCAL
2266                          * and TS_SOFTCAR flags and a TIOCM_CD flag of a
2267                          * TIOCMGET request (come in on the write side queue).
2268                          */
2269 
2270                         if ((ftstat = sm_defer_open(uqi, rq)) != EINTR) {
2271                                 if (ftstat) {
2272                                         goto tryopen;
2273                                 } else {
2274                                         continue;
2275                                 }
2276                         }
2277 
2278                         if (uqi->sm_nwaiters == 0) { /* clean up */
2279                                 /*
2280                                  * only opens on an asynchronous
2281                                  * protocols reach here so checking
2282                                  * nwaiters == 0 is sufficient to
2283                                  * ensure that no other thread
2284                                  * is waiting on this logical unit
2285                                  */
2286                                 if ((uqi->sm_flags & FULLY_OPEN) == 0) {
2287 
2288                                         sm_lqi_t *lqi;
2289 
2290                                         uqi->sm_dev = NODEV;
2291                                         sm_dbg('C', ("sm_open FULLY_OPEN=0\n"));
2292                                         for (lqi = uqi->sm_lqs; lqi != 0;
2293                                             lqi = lqi->sm_nlqi) {
2294                                                 LOCK_UNIT(lqi);
2295                                                 lqi->sm_uqflags &= ~SM_UQVALID;
2296                                                 UNLOCK_UNIT(lqi);
2297                                         }
2298 
2299                                         qprocsoff(rq);
2300                                         rq->q_ptr = WR(rq)->q_ptr = 0;
2301                                         SM_RQ(uqi) = 0;
2302                                         SM_WQ(uqi) = 0;
2303                                 }
2304                         }
2305                         if ((uqi->sm_flags & FULLY_OPEN) == 0 &&
2306                             uqi->sm_nwaiters == 0)
2307                                 uqi->sm_protocol = NULL_PROTOCOL;
2308                         if (flag & FEXCL)
2309                                 uqi->sm_flags &= ~EXCL_OPEN;
2310                         sm_dbg('C', ("sm_open: done (ret %d).\n", ftstat));
2311                         return (ftstat);
2312                 } while (BLOCKING(uqi, protocol, flag));
2313         }
2314 
2315         uqi->sm_flags |= FULLY_OPEN;
2316 
2317         sm_dbg('C', ("sm_open done (ret %d).\n", ftstat));
2318         return (ftstat);
2319 }
2320 
2321 /*
2322  * Multiplexer device close routine.
2323  */
2324 /*ARGSUSED*/
2325 static int
2326 sm_close(queue_t *rq, int flag, cred_t *credp)
2327 {
2328         sm_uqi_t *uqi = (sm_uqi_t *)rq->q_ptr;
2329         sm_lqi_t *lqi;
2330 
2331         if (sm_ssp == NULL)
2332                 return (ENXIO);
2333 
2334         if (uqi == NULL) {
2335                 sm_dbg('C', ("close: WARN:- q 0x%p already closed.\n", rq));
2336                 return (ENXIO);
2337         }
2338 
2339         sm_dbg('C', ("close: uqi=0x%p unit=%d q=0x%p)\n", uqi, uqi->sm_lunit,
2340             rq));
2341 
2342         if (SM_RQ(uqi) != rq)
2343                 sm_dbg('C', ("sm_close: rq != current uqi queue\n"));
2344 
2345         if (uqi->sm_ttybid) {
2346                 qunbufcall(SM_RQ(uqi), uqi->sm_ttybid);
2347                 uqi->sm_ttybid = 0;
2348         }
2349 
2350         /*
2351          * Tell all the linked queues that the upper queue has gone
2352          * Note close will never get called on a stream while there is a
2353          * thread blocked trying to open the same stream.
2354          * If there is a blocked open on a different stream but on
2355          * the same logical unit it will reset the lower queue flags.
2356          */
2357         for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) {
2358                 LOCK_UNIT(lqi);
2359                 lqi->sm_uqflags &= ~SM_UQVALID;
2360                 UNLOCK_UNIT(lqi);
2361         }
2362 
2363         /*
2364          * Turn off the STREAMs queue processing for this queue.
2365          */
2366         qprocsoff(rq);
2367 
2368         /*
2369          * Similarly we will never get here if there is thread trying to
2370          * open ths stream.
2371          */
2372         LOCK_UNIT(uqi);
2373         if (uqi->sm_waitq == 0)
2374                 uqi->sm_flags = (uqi->sm_flags & SM_OBPCNDEV) ? SM_OBPCNDEV :
2375                     0U;
2376 
2377         uqi->sm_dev = NODEV;
2378         uqi->sm_protocol = NULL_PROTOCOL;
2379         ttycommon_close(uqi->sm_ttycommon);
2380         /* it just frees any pending ioctl */
2381 
2382         uqi->sm_ttycommon->t_cflag = 0;
2383         uqi->sm_ttycommon->t_flags = 0;
2384 
2385         /*
2386          * Reset the queue pointers to NULL.
2387          * If a thread is qwaiting in the open routine it will recheck
2388          * the q_ptr.
2389          */
2390         rq->q_ptr = NULL;
2391         WR(rq)->q_ptr = NULL;
2392         UNLOCK_UNIT(uqi);
2393 
2394         if (sm_ssp->sm_lconsole == uqi) {
2395                 /* this will never be the outdial device closing */
2396                 sm_ssp->sm_lconsole = 0;
2397         }
2398         /*
2399          * If there is another thread waiting for this close then unblock
2400          * the thread by putting a message on its read queue.
2401          */
2402         if (uqi->sm_waitq) {
2403                 sm_dbg('C', ("close(0x%p): doing putctl on 0x%p\n",
2404                     rq, uqi->sm_waitq));
2405                 if (rq == uqi->sm_waitq)
2406                         sm_log("close: waitq and closeq are same q\n");
2407                 (void) putctl(uqi->sm_waitq, M_CTL);
2408         }
2409 
2410         uqi->sm_flags &= ~(EXCL_OPEN | FULLY_OPEN);
2411         sm_dbg('C', ("close: returning ok.\n"));
2412         return (0);
2413 }
2414 
2415 /*
2416  * Initialise the software abort sequence for use when one of the
2417  * driver's nodes provides the system console.
2418  */
2419 static void
2420 sm_set_abort()
2421 {
2422         char ds[3] = { '\r', '~', CNTRL('b') };
2423         char as[SM_MAX_ABSLEN];
2424         int len = SM_MAX_ABSLEN;
2425 
2426         if (ddi_prop_op(DDI_DEV_T_ANY, sm_ssp->sm_dip, PROP_LEN_AND_VAL_BUF, 0,
2427             "abort-str", as, &len) != DDI_PROP_SUCCESS ||
2428             (len = strlen(as)) < SM_MIN_ABSLEN) {
2429                 (void) strcpy(as, ds);
2430                 len = strlen(as);
2431         } else {
2432                 char *s;
2433                 int i;
2434 
2435                 for (s = as, i = 0; i < len-1; i++, s++) {
2436                         if (as[i] == '^' && as[i+1] >= 'a' && as[i+1] <= 'z') {
2437                                 *s = as[i+1] - 'a' + 1;
2438                                 i++;
2439                         } else {
2440                                 *s = as[i];
2441                         }
2442                 }
2443                 *s++ = as[i];
2444                 *s = '\0';
2445                 len = strlen(as);
2446         }
2447 
2448         if (len < SM_MIN_ABSLEN)
2449                 (void) strcpy(sm_ssp->sm_abs, ds);
2450         else
2451                 (void) strcpy(sm_ssp->sm_abs, as);
2452 }
2453 
2454 /*
2455  *
2456  * sm_attach - initialisation routine per driver instance.
2457  */
2458 static int
2459 sm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2460 {
2461         int unit;
2462         char name[32];
2463         sm_uqi_t *uqi;
2464         sm_lqi_t *lqip;
2465 
2466         /*
2467          * Is this an attach?
2468          */
2469         if (cmd != DDI_ATTACH) {
2470                 return (DDI_FAILURE);
2471         }
2472 
2473         /*
2474          * Validate the instance number (sm is a single instance driver).
2475          */
2476         if (sm_ssp) {   /* only one instance allowed */
2477                 return (DDI_FAILURE);
2478         }
2479 
2480         sm_instance = ddi_get_instance(dip);
2481 
2482         /*
2483          * Create the default minor node which will become the console.
2484          * (create it with three different names).:
2485          *      con which appears in the /dev filesystem;
2486          *      input which matches the prom /multiplexer:input node;
2487          *      output which matches the prom /multiplexer:input node
2488          * Create a minor node for control operations.
2489          */
2490         if (ddi_create_minor_node(dip, "con", S_IFCHR, 0,
2491             DDI_PSEUDO, 0) != DDI_SUCCESS ||
2492             ddi_create_minor_node(dip, "input", S_IFCHR, 0,
2493             DDI_PSEUDO, 0) != DDI_SUCCESS ||
2494             ddi_create_minor_node(dip, "output", S_IFCHR, 0,
2495             DDI_PSEUDO, 0) != DDI_SUCCESS ||
2496             ddi_create_minor_node(dip, "ctl", S_IFCHR, 1,
2497             DDI_PSEUDO, 0) != DDI_SUCCESS) {
2498 
2499                 cmn_err(CE_WARN, "sm_attach: create minors failed.\n");
2500                 ddi_remove_minor_node(dip, NULL);
2501                 return (DDI_FAILURE);
2502         }
2503 
2504         smctlunit = 1;
2505 
2506         /*
2507          * Allocate private state for this instance.
2508          */
2509         sm_ssp = (sm_ss_t *)kmem_zalloc(sizeof (sm_ss_t), KM_SLEEP);
2510 
2511         /*
2512          * Initialise per instance data.
2513          */
2514         sm_ssp->sm_dip = dip;
2515 
2516         /*
2517          * Get required debug level.
2518          */
2519         sm_ssp->sm_trflag = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2520             DDI_PROP_DONTPASS, "sm-trlv", sm_default_trflag);
2521 
2522         sm_max_units = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2523             DDI_PROP_DONTPASS, "sm-max-units", sm_max_units);
2524         sm_minor_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2525             DDI_PROP_DONTPASS, "sm-minor-cnt", 0);
2526 
2527         sm_refuse_opens = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2528             DDI_PROP_DONTPASS, "sm-refuse-opens", sm_refuse_opens);
2529 
2530         sm_ssp->sm_ctrla_abort_on = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2531             DDI_PROP_DONTPASS, "sm-ctrla-abort-on", 1);
2532         sm_ssp->sm_break_abort_on = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2533             DDI_PROP_DONTPASS, "sm-break-abort-on", 0);
2534 
2535         sm_set_abort();
2536 
2537         sm_ssp->sm_lqs = (sm_lqi_t *)kmem_zalloc(sizeof (sm_lqi_t) * MAX_LQS,
2538             KM_SLEEP);
2539         sm_ssp->sm_uqs = (sm_uqi_t *)kmem_zalloc(sizeof (sm_uqi_t) * NLUNITS,
2540             KM_SLEEP);
2541 
2542         for (unit = 2; unit < NLUNITS && unit < sm_minor_cnt + 2; unit++) {
2543 
2544                 if (snprintf(name, sizeof (name), "sm%c", 'a' + unit-2) >
2545                     sizeof (name)) {
2546                         cmn_err(CE_WARN,
2547                             "sm_attach: create device for unit %d failed.\n",
2548                             unit);
2549                 } else if (ddi_create_minor_node(dip, name, S_IFCHR,
2550                     unit, DDI_NT_SERIAL, NULL) != DDI_SUCCESS) {
2551                         ddi_remove_minor_node(dip, NULL);
2552                         return (DDI_FAILURE);
2553                 }
2554 
2555                 if (snprintf(name, sizeof (name), "sm%c,cu", 'a' + unit-2) >
2556                     sizeof (name)) {
2557                         cmn_err(CE_WARN,
2558                             "sm_attach: create cu device for unit %d failed.\n",
2559                             unit);
2560                         continue;
2561                 } else if (ddi_create_minor_node(dip, name, S_IFCHR,
2562                     unit|OUTLINE, DDI_NT_SERIAL_DO, NULL) != DDI_SUCCESS) {
2563                         ddi_remove_minor_node(dip, NULL);
2564                         return (DDI_FAILURE);
2565                 }
2566         }
2567 
2568         for (unit = 0; unit < NLUNITS; unit++) {
2569 
2570                 uqi = get_uqi(sm_ssp, unit);
2571                 uqi->sm_lqs = 0;
2572                 uqi->sm_dev = NODEV;
2573                 uqi->sm_nlqs = 0;
2574                 uqi->sm_lunit = unit;
2575                 uqi->sm_protocol = NULL_PROTOCOL;
2576                 mutex_init(uqi->sm_umutex, NULL, MUTEX_DRIVER, NULL);
2577                 cv_init(uqi->sm_ucv, NULL, CV_DRIVER, NULL);
2578                 mutex_init(&uqi->sm_ttycommon->t_excl, NULL,
2579                     MUTEX_DRIVER, NULL);
2580         }
2581 
2582         for (unit = 0; unit < MAX_LQS; unit++) {
2583                 lqip = get_lqi(sm_ssp, unit);
2584                 lqip->sm_unit = unit;
2585                 lqip->sm_hadkadbchar = 0;
2586                 lqip->sm_nachar = sm_ssp->sm_abs;
2587                 lqip->sm_ioflag = FORIO;
2588                 lqip->sm_ctrla_abort_on = sm_ssp->sm_ctrla_abort_on;
2589                 lqip->sm_break_abort_on = sm_ssp->sm_break_abort_on;
2590                 mutex_init(lqip->sm_umutex, NULL, MUTEX_DRIVER, NULL);
2591                 cv_init(lqip->sm_ucv, NULL, CV_DRIVER, NULL);
2592                 mutex_init(&lqip->sm_ttycommon->t_excl, NULL,
2593                     MUTEX_DRIVER, NULL);
2594         }
2595 
2596         return (DDI_SUCCESS);
2597 }
2598 
2599 /*
2600  *
2601  * sm_detach - detach routine per driver instance.
2602  */
2603 static int
2604 sm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2605 {
2606         sm_uqi_t                *lu;
2607         sm_lqi_t                *pu;
2608         int             unit;
2609 
2610         /*
2611          * Is this a detach request for instance 0 (single instance driver).
2612          */
2613         if (cmd != DDI_DETACH)
2614                 return (DDI_FAILURE);
2615 
2616         if (sm_ssp == NULL)
2617                 return (DDI_FAILURE);
2618 
2619         sm_dbg('V', ("detach ..."));
2620 
2621 
2622         /*
2623          * Check that all the upper and lower queues are closed.
2624          */
2625 
2626         for (unit = 0; unit < NLUNITS; unit++) {
2627                 lu = &sm_ssp->sm_uqs[unit];
2628                 if (lu && lu->sm_protocol != NULL_PROTOCOL) {
2629                         sm_dbg('V', ("detach: upper unit still open.\n"));
2630                         return (DDI_FAILURE);
2631                 }
2632         }
2633         for (unit = 0; unit < MAX_LQS; unit++) {
2634                 pu = &sm_ssp->sm_lqs[unit];
2635                 if (pu && pu->sm_linkid != 0) {
2636                         sm_dbg('V', ("detach: lower unit still linked (%d)\n",
2637                             pu->sm_linkid));
2638                         return (DDI_FAILURE);
2639                 }
2640         }
2641 
2642         for (unit = 0; unit < NLUNITS; unit++) {
2643                 lu = &sm_ssp->sm_uqs[unit];
2644                 mutex_destroy(lu->sm_umutex);
2645                 cv_destroy(lu->sm_ucv);
2646                 mutex_destroy(&lu->sm_ttycommon->t_excl);
2647         }
2648         for (unit = 0; unit < MAX_LQS; unit++) {
2649                 pu = &sm_ssp->sm_lqs[unit];
2650                 mutex_destroy(pu->sm_umutex);
2651                 cv_destroy(pu->sm_ucv);
2652                 mutex_destroy(&pu->sm_ttycommon->t_excl);
2653         }
2654 
2655         /*
2656          * Tidy up per instance state.
2657          */
2658         kmem_free(sm_ssp->sm_lqs, sizeof (sm_lqi_t) * MAX_LQS);
2659         kmem_free(sm_ssp->sm_uqs, sizeof (sm_uqi_t) * NLUNITS);
2660         kmem_free(sm_ssp, sizeof (sm_ss_t));
2661 
2662         sm_ssp = 0;
2663 
2664         /*
2665          * Remove all of the devices created in attach.
2666          */
2667         ddi_remove_minor_node(dip, NULL);
2668 
2669         return (DDI_SUCCESS);
2670 }
2671 
2672 /*
2673  * SECTION
2674  * Driver interface to the OS.
2675  */
2676 
2677 /*
2678  * The driver is responsible for managing the mapping between the file system
2679  * device types (major/minor pairs) and the corresponding instance of the driver
2680  * or device information pointer (dip).
2681  * sm_info - return the instance or dip corresponding to the dev_t.
2682  */
2683 /*ARGSUSED*/
2684 static int
2685 sm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
2686 {
2687         int res = DDI_SUCCESS;
2688 
2689         switch (infocmd) {
2690         case DDI_INFO_DEVT2DEVINFO:
2691                 if (sm_ssp == NULL)
2692                         res = DDI_FAILURE;
2693                 else
2694                         *result = (void *)sm_ssp->sm_dip;
2695                 break;
2696 
2697         case DDI_INFO_DEVT2INSTANCE:
2698                 *result = (void*)0;     /* single instance driver */
2699                 break;
2700 
2701         default:
2702                 res = DDI_FAILURE;
2703                 break;
2704         }
2705 
2706         return (res);
2707 }
2708 
2709 /*
2710  * End of driver implementation
2711  */
2712 
2713 /*
2714  * Loadable module interface to the kernel
2715  */
2716 
2717 /*
2718  * Firstly the Streams specific interface
2719  */
2720 
2721 /*
2722  * Solaris driver/STREAM initialisation structures.
2723  */
2724 static struct module_info uinfo =
2725 {
2726         SM_MOD_ID,
2727         TTYMUX_DRVNAME,
2728         0,              /* min packet size */
2729         INFPSZ,         /* max packet size */
2730         2048,           /* high water mark */
2731         256,            /* low water mark */
2732 };
2733 
2734 /*
2735  * Use zero water marks becuase the lower queues are used only for flow control.
2736  */
2737 static struct module_info linfo =
2738 {
2739         SM_MOD_ID,
2740         TTYMUX_DRVNAME,
2741         0,              /* min packet size */
2742         INFPSZ,         /* max packet size */
2743         0,              /* high water mark */
2744         0               /* low water mark       */
2745 };
2746 
2747 
2748 /*
2749  * Solaris upper read STREAM initialisation structure.
2750  */
2751 static struct qinit urinit =
2752 {
2753         sm_urput,       /* put */
2754         sm_ursrv,       /* service */
2755         sm_open,        /* open */
2756         sm_close,       /* close */
2757         NULL,           /* admin */
2758         &uinfo,             /* module info */
2759         NULL            /* stats */
2760 };
2761 
2762 /*
2763  * Solaris upper write STREAM initialisation structure.
2764  */
2765 static struct qinit uwinit =
2766 {
2767         sm_uwput,
2768         sm_uwsrv,
2769         NULL,
2770         NULL,
2771         NULL,
2772         &uinfo,
2773         NULL
2774 };
2775 
2776 /*
2777  * Solaris lower read STREAM initialisation structure.
2778  */
2779 static struct qinit lrinit =
2780 {
2781         sm_lrput,
2782         sm_lrsrv,
2783         NULL,
2784         NULL, NULL,
2785         &linfo,
2786         NULL
2787 };
2788 
2789 /*
2790  * Solaris lower write STREAM initialisation structure.
2791  */
2792 static struct qinit lwinit =
2793 {
2794         putq,
2795         sm_lwsrv,
2796         NULL,
2797         NULL,
2798         NULL,
2799         &linfo,
2800         NULL
2801 };
2802 
2803 /*
2804  * Multiplexing STREAM structure.
2805  */
2806 struct streamtab sm_streamtab =
2807 {
2808         &urinit,
2809         &uwinit,
2810         &lrinit,
2811         &lwinit
2812 };
2813 
2814 /*
2815  * Driver operations structure (struct cb_ops) and
2816  * driver dynamic loading functions (struct dev_ops).
2817  */
2818 
2819 /*
2820  * Fold the Stream interface to the kernel into the driver interface
2821  * to the OS.
2822  */
2823 
2824 DDI_DEFINE_STREAM_OPS(sm_ops, \
2825         nulldev, nulldev, \
2826         sm_attach, sm_detach, nodev, \
2827         sm_info, (D_NEW | D_MTQPAIR|D_MTOUTPERIM|D_MTOCEXCL | D_MP),
2828         &sm_streamtab, ddi_quiesce_not_supported);
2829 
2830 /*
2831  * Driver module information.
2832  */
2833 extern struct mod_ops mod_driverops;
2834 static struct modldrv modldrv =
2835 {
2836         &mod_driverops,
2837         "serial mux driver",
2838         &sm_ops
2839 };
2840 
2841 static struct modlinkage modlinkage =
2842 {
2843         MODREV_1,
2844         &modldrv,
2845         NULL
2846 };
2847 
2848 /*
2849  * Define the body of our interface to the OS.
2850  */
2851 
2852 /*
2853  * '_init' is called by Solaris to initialise any driver
2854  * specific state and to install the driver.
2855  */
2856 int
2857 _init(void)
2858 {
2859         return (mod_install(&modlinkage));
2860 }
2861 
2862 /*
2863  * _info - return this drivers interface to the kernel.
2864  */
2865 int
2866 _info(struct modinfo *modinfop)
2867 {
2868         return (mod_info(&modlinkage, modinfop));
2869 }
2870 
2871 /*
2872  * _fini - the OS is finished with the services provided by the driver.
2873  * remove ourself and then remove any footprint that remains.
2874  */
2875 int
2876 _fini(void)
2877 {
2878         return (mod_remove(&modlinkage));
2879 }