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, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 
  31 /*
  32  * Description: The pckt module packetizes messages on
  33  *              its read queue by pre-fixing an M_PROTO
  34  *              message type to certain incoming messages.
  35  */
  36 
  37 #include <sys/types.h>
  38 #include <sys/param.h>
  39 #include <sys/stream.h>
  40 #include <sys/stropts.h>
  41 #include <sys/kmem.h>
  42 #include <sys/errno.h>
  43 #include <sys/ddi.h>
  44 #include <sys/sunddi.h>
  45 #include <sys/debug.h>
  46 
  47 /*
  48  * This is the loadable module wrapper.
  49  */
  50 #include <sys/conf.h>
  51 #include <sys/modctl.h>
  52 
  53 static struct streamtab pcktinfo;
  54 
  55 /*
  56  * Per queue instances are single-threaded since the q_ptr
  57  * field of queues need to be shared among threads.
  58  */
  59 static struct fmodsw fsw = {
  60         "pckt",
  61         &pcktinfo,
  62         D_NEW | D_MTPERQ | D_MP
  63 };
  64 
  65 /*
  66  * Module linkage information for the kernel.
  67  */
  68 
  69 static struct modlstrmod modlstrmod = {
  70         &mod_strmodops,
  71         "pckt module",
  72         &fsw
  73 };
  74 
  75 static struct modlinkage modlinkage = {
  76         MODREV_1, &modlstrmod, NULL
  77 };
  78 
  79 
  80 int
  81 _init(void)
  82 {
  83         return (mod_install(&modlinkage));
  84 }
  85 
  86 int
  87 _fini(void)
  88 {
  89         return (mod_remove(&modlinkage));
  90 }
  91 
  92 int
  93 _info(struct modinfo *modinfop)
  94 {
  95         return (mod_info(&modlinkage, modinfop));
  96 }
  97 
  98 static int      pcktopen(queue_t *, dev_t *, int, int, cred_t *);
  99 static int      pcktclose(queue_t *, int, cred_t *);
 100 static void     pcktrput(queue_t *, mblk_t *);
 101 static void     pcktrsrv(queue_t *);
 102 static void     pcktwput(queue_t *, mblk_t *);
 103 static mblk_t   *add_ctl_info(queue_t *, mblk_t *);
 104 static void     add_ctl_wkup(void *);
 105 
 106 
 107 /*
 108  * Stream module data structure definitions.
 109  * Sits over the ptm module generally.
 110  *
 111  * Read side flow control strategy: Since we may be putting messages on
 112  * the read q due to allocb failures, these failures must get
 113  * reflected fairly quickly to the module below us.
 114  * No sense in piling on messages in times of memory shortage.
 115  * Further, for the case of upper level flow control, there is no
 116  * compelling reason to have more buffering in this module.
 117  * Thus use a hi-water mark of one.
 118  * This module imposes no max packet size, there is no inherent reason
 119  * in the code to do so.
 120  */
 121 static struct module_info pcktiinfo = {
 122         0x9898,                                 /* module id number */
 123         "pckt",                                 /* module name */
 124         0,                                      /* minimum packet size */
 125         INFPSZ,                                 /* maximum packet size */
 126         1,                                      /* hi-water mark */
 127         0                                       /* lo-water mark */
 128 };
 129 
 130 /*
 131  * Write side flow control strategy: There is no write service procedure.
 132  * The write put function is pass thru, thus there is no reason to have any
 133  * limits on the maximum packet size.
 134  */
 135 static struct module_info pcktoinfo = {
 136         0x9898,                                 /* module id number */
 137         "pckt",                                 /* module name */
 138         0,                                      /* minimum packet size */
 139         INFPSZ,                                 /* maximum packet size */
 140         0,                                      /* hi-water mark */
 141         0                                       /* lo-water mark */
 142 };
 143 
 144 static struct qinit pcktrinit = {
 145         (int (*)())pcktrput,
 146         (int (*)())pcktrsrv,
 147         pcktopen,
 148         pcktclose,
 149         NULL,
 150         &pcktiinfo,
 151         NULL
 152 };
 153 
 154 static struct qinit pcktwinit = {
 155         (int (*)())pcktwput,
 156         NULL,
 157         NULL,
 158         NULL,
 159         NULL,
 160         &pcktoinfo,
 161         NULL
 162 };
 163 
 164 static struct streamtab pcktinfo = {
 165         &pcktrinit,
 166         &pcktwinit,
 167         NULL,
 168         NULL
 169 };
 170 
 171 
 172 /*
 173  * Per-instance state struct for the pckt module.
 174  */
 175 struct pckt_info {
 176         queue_t         *pi_qptr;               /* back pointer to q */
 177         bufcall_id_t    pi_bufcall_id;
 178 #ifdef _MULTI_DATAMODEL
 179         model_t         model;
 180 #endif /* _MULTI_DATAMODEL */
 181 };
 182 
 183 /*
 184  * Dummy qbufcall callback routine used by open and close.
 185  * The framework will wake up qwait_sig when we return from
 186  * this routine (as part of leaving the perimeters.)
 187  * (The framework enters the perimeters before calling the qbufcall() callback
 188  * and leaves the perimeters after the callback routine has executed. The
 189  * framework performs an implicit wakeup of any thread in qwait/qwait_sig
 190  * when it leaves the perimeter. See qwait(9E).)
 191  */
 192 /* ARGSUSED */
 193 static void
 194 dummy_callback(void *arg)
 195 {}
 196 
 197 /*
 198  * pcktopen - open routine gets called when the
 199  *          module gets pushed onto the stream.
 200  */
 201 /*ARGSUSED*/
 202 static int
 203 pcktopen(
 204         queue_t *q,             /* pointer to the read side queue */
 205         dev_t   *devp,          /* pointer to stream tail's dev */
 206         int     oflag,          /* the user open(2) supplied flags */
 207         int     sflag,          /* open state flag */
 208         cred_t  *credp)         /* credentials */
 209 {
 210         struct pckt_info        *pip;
 211         mblk_t                  *mop; /* ptr to a setopts msg block */
 212         struct stroptions       *sop;
 213 
 214         if (sflag != MODOPEN)
 215                 return (EINVAL);
 216 
 217         if (q->q_ptr != NULL) {
 218                 /* It's already attached. */
 219                 return (0);
 220         }
 221 
 222         /*
 223          * Allocate state structure.
 224          */
 225         pip = kmem_zalloc(sizeof (*pip), KM_SLEEP);
 226 
 227 #ifdef _MULTI_DATAMODEL
 228         pip->model = ddi_model_convert_from(get_udatamodel());
 229 #endif /* _MULTI_DATAMODEL */
 230 
 231         /*
 232          * Cross-link.
 233          */
 234         pip->pi_qptr = q;
 235         q->q_ptr = pip;
 236         WR(q)->q_ptr = pip;
 237 
 238         qprocson(q);
 239 
 240         /*
 241          * Initialize an M_SETOPTS message to set up hi/lo water marks on
 242          * stream head read queue.
 243          */
 244 
 245         while ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
 246                 bufcall_id_t id = qbufcall(q, sizeof (struct stroptions),
 247                     BPRI_MED, dummy_callback, NULL);
 248                 if (!qwait_sig(q)) {
 249                         qunbufcall(q, id);
 250                         kmem_free(pip, sizeof (*pip));
 251                         qprocsoff(q);
 252                         return (EINTR);
 253                 }
 254                 qunbufcall(q, id);
 255         }
 256 
 257 
 258         /*
 259          * XXX: Should this module really control the hi/low water marks?
 260          * Is there any reason in this code to do so?
 261          */
 262         mop->b_datap->db_type = M_SETOPTS;
 263         mop->b_wptr += sizeof (struct stroptions);
 264         sop = (struct stroptions *)mop->b_rptr;
 265         sop->so_flags = SO_HIWAT | SO_LOWAT;
 266         sop->so_hiwat = 512;
 267         sop->so_lowat = 256;
 268 
 269         /*
 270          * Commit to the open and send the M_SETOPTS off to the stream head.
 271          */
 272         putnext(q, mop);
 273 
 274         return (0);
 275 }
 276 
 277 
 278 /*
 279  * pcktclose - This routine gets called when the module
 280  *      gets popped off of the stream.
 281  */
 282 
 283 /*ARGSUSED*/
 284 static int
 285 pcktclose(
 286         queue_t *q,     /* Pointer to the read queue */
 287         int     flag,
 288         cred_t  *credp)
 289 {
 290         struct pckt_info        *pip = (struct pckt_info *)q->q_ptr;
 291 
 292         qprocsoff(q);
 293         /*
 294          * Cancel outstanding qbufcall
 295          */
 296         if (pip->pi_bufcall_id) {
 297                 qunbufcall(q, pip->pi_bufcall_id);
 298                 pip->pi_bufcall_id = 0;
 299         }
 300         /*
 301          * Do not worry about msgs queued on the q, the framework
 302          * will free them up.
 303          */
 304         kmem_free(q->q_ptr, sizeof (struct pckt_info));
 305         q->q_ptr = WR(q)->q_ptr = NULL;
 306         return (0);
 307 }
 308 
 309 /*
 310  * pcktrput - Module read queue put procedure.
 311  *      This is called from the module or
 312  *      driver downstream.
 313  */
 314 static void
 315 pcktrput(
 316         queue_t *q,     /* Pointer to the read queue */
 317         mblk_t *mp)     /* Pointer to the current message block */
 318 {
 319         mblk_t          *pckt_msgp;
 320 
 321 
 322         switch (mp->b_datap->db_type) {
 323         case M_FLUSH:
 324                 /*
 325                  * The PTS driver swaps the FLUSHR and FLUSHW flags
 326                  * we need to swap them back to reflect the actual
 327                  * slave side FLUSH mode.
 328                  */
 329                 if ((*mp->b_rptr & FLUSHRW) != FLUSHRW)
 330                         if ((*mp->b_rptr & FLUSHRW) == FLUSHR)
 331                                 *mp->b_rptr = FLUSHW;
 332                         else if ((*mp->b_rptr & FLUSHRW) == FLUSHW)
 333                                 *mp->b_rptr = FLUSHR;
 334 
 335                 pckt_msgp = copymsg(mp);
 336                 if (*mp->b_rptr & FLUSHW) {
 337                         /*
 338                          * In the packet model we are not allowing
 339                          * flushes of the master's stream head read
 340                          * side queue. This is because all packet
 341                          * state information is stored there and
 342                          * a flush could destroy this data before
 343                          * it is read.
 344                          */
 345                         *mp->b_rptr = FLUSHW;
 346                         putnext(q, mp);
 347                 } else {
 348                         /*
 349                          * Free messages that only flush the
 350                          * master's read queue.
 351                          */
 352                         freemsg(mp);
 353                 }
 354 
 355                 if (pckt_msgp == NULL)
 356                         break;
 357 
 358                 mp = pckt_msgp;
 359                 /*
 360                  * Prefix M_PROTO and putnext.
 361                  */
 362                 goto prefix_head;
 363 
 364         case M_DATA:
 365         case M_IOCTL:
 366         case M_PROTO:
 367                 /*
 368                  * For non-priority messages, follow flow-control rules.
 369                  * Also, if there are messages on the q already, keep
 370                  * queueing them since they need to be processed in order.
 371                  */
 372                 if (!canputnext(q) || (qsize(q) > 0)) {
 373                         (void) putq(q, mp);
 374                         break;
 375                 }
 376                 /* FALLTHROUGH */
 377 
 378         /*
 379          * For high priority messages, skip flow control checks.
 380          */
 381         case M_PCPROTO:
 382         case M_READ:
 383         case M_STOP:
 384         case M_START:
 385         case M_STARTI:
 386         case M_STOPI:
 387 prefix_head:
 388                 /*
 389                  * Prefix an M_PROTO header to message and pass upstream.
 390                  */
 391                 if ((mp = add_ctl_info(q, mp)) != NULL)
 392                         putnext(q, mp);
 393                 break;
 394 
 395         default:
 396                 /*
 397                  * For data messages, queue them back on the queue if
 398                  * there are messages on the queue already. This is
 399                  * done to preserve the order of messages.
 400                  * For high priority messages or for no messages on the
 401                  * q, simply putnext() and pass it on.
 402                  */
 403                 if ((datamsg(mp->b_datap->db_type)) && (qsize(q) > 0))
 404                         (void) putq(q, mp);
 405                 else
 406                         putnext(q, mp);
 407                 break;
 408         }
 409 }
 410 
 411 /*
 412  * pcktrsrv - module read service procedure
 413  * This function deals with messages left in the queue due to
 414  *      (a) not enough memory to allocate the header M_PROTO message
 415  *      (b) flow control reasons
 416  * The function will attempt to get the messages off the queue and
 417  * process them.
 418  */
 419 static void
 420 pcktrsrv(queue_t *q)
 421 {
 422         mblk_t *mp;
 423 
 424         while ((mp = getq(q)) != NULL) {
 425                 if (!canputnext(q)) {
 426                         /*
 427                          * For high priority messages, make sure there is no
 428                          * infinite loop. Disable the queue for this case.
 429                          * High priority messages get here only for buffer
 430                          * allocation failures. Thus the bufcall callout
 431                          * will reenable the q.
 432                          * XXX bug alert - nooenable will *not* prevent
 433                          * putbq of a hipri messages frm enabling the queue.
 434                          */
 435                         if (!datamsg(mp->b_datap->db_type))
 436                                 noenable(q);
 437                         (void) putbq(q, mp);
 438                         return;
 439                 }
 440 
 441                 /*
 442                  * M_FLUSH msgs may also be here if there was a memory
 443                  * failure.
 444                  */
 445                 switch (mp->b_datap->db_type) {
 446                 case M_FLUSH:
 447                 case M_PROTO:
 448                 case M_PCPROTO:
 449                 case M_STOP:
 450                 case M_START:
 451                 case M_IOCTL:
 452                 case M_DATA:
 453                 case M_READ:
 454                 case M_STARTI:
 455                 case M_STOPI:
 456                         /*
 457                          * Prefix an M_PROTO header to msg and pass upstream.
 458                          */
 459                         if ((mp = add_ctl_info(q, mp)) == NULL) {
 460                                 /*
 461                                  * Running into memory or flow ctl problems.
 462                                  */
 463                                 return;
 464                         }
 465                         /* FALL THROUGH */
 466 
 467                 default:
 468                         putnext(q, mp);
 469                         break;
 470                 }
 471         }
 472 }
 473 
 474 /*
 475  * pcktwput - Module write queue put procedure.
 476  *      All messages are send downstream unchanged
 477  */
 478 
 479 static void
 480 pcktwput(
 481         queue_t *q,     /* Pointer to the read queue */
 482         mblk_t *mp)     /* Pointer to current message block */
 483 {
 484         putnext(q, mp);
 485 }
 486 
 487 #ifdef _MULTI_DATAMODEL
 488 /*
 489  * reallocb - copy the data block from the given message block into a new block.
 490  * This function is used in case data block had another message block
 491  * pointing to it (and hence we just copy this one data block).
 492  *
 493  * Returns new message block if successful. On failure it returns NULL.
 494  * It also tries to do a qbufcall and if that also fails,
 495  * it frees the message block.
 496  */
 497 static mblk_t *
 498 pckt_reallocb(
 499         queue_t *q,     /* Pointer to the read queue */
 500         mblk_t *mp      /* Pointer to the message block to be changed */
 501 )
 502 {
 503         mblk_t  *nmp;
 504 
 505         ASSERT(mp->b_datap->db_ref >= 1);
 506 
 507         /*
 508          * No reallocation is needed if there is only one reference
 509          * to this data block.
 510          */
 511         if (mp->b_datap->db_ref == 1)
 512                 return (mp);
 513 
 514         if ((nmp = copyb(mp)) == NULL) {
 515                 struct pckt_info        *pip = (struct pckt_info *)q->q_ptr;
 516 
 517                 noenable(q);
 518                 if (pip->pi_bufcall_id = qbufcall(q, mp->b_wptr - mp->b_rptr,
 519                     BPRI_MED, add_ctl_wkup, q)) {
 520                         /*
 521                          * Put the message back onto the q.
 522                          */
 523                         (void) putq(q, mp);
 524                 } else {
 525                         /*
 526                          * Things are pretty bad and serious if bufcall fails!
 527                          * Drop the message in this case.
 528                          */
 529                         freemsg(mp);
 530                 }
 531                 return ((mblk_t *)0);
 532         }
 533 
 534         nmp->b_cont = mp->b_cont;
 535         freeb(mp);
 536         return (nmp);
 537 }
 538 #endif /* _MULTI_DATAMODEL */
 539 
 540 /*
 541  * add_ctl_info: add message control information to in coming
 542  *      message.
 543  */
 544 static mblk_t *
 545 add_ctl_info(
 546         queue_t *q,             /* pointer to the read queue */
 547         mblk_t  *mp)            /* pointer to the raw data input message */
 548 {
 549         struct pckt_info        *pip = (struct pckt_info *)q->q_ptr;
 550         mblk_t  *bp;            /* pointer to the unmodified message block */
 551 
 552         /*
 553          * Waiting on space for previous message?
 554          */
 555         if (pip->pi_bufcall_id) {
 556                 /*
 557                  * Chain this message on to q for later processing.
 558                  */
 559                 (void) putq(q, mp);
 560                 return (NULL);
 561         }
 562 
 563         /*
 564          * Need to add the message block header as
 565          * an M_PROTO type message.
 566          */
 567         if ((bp = allocb(sizeof (char), BPRI_MED)) == (mblk_t *)NULL) {
 568 
 569                 /*
 570                  * There are two reasons to disable the q:
 571                  * (1) Flow control reasons should not wake up the q.
 572                  * (2) High priority messages will wakeup the q
 573                  *      immediately. Disallow this.
 574                  */
 575                 noenable(q);
 576                 if (pip->pi_bufcall_id = qbufcall(q, sizeof (char), BPRI_MED,
 577                     add_ctl_wkup, q)) {
 578                         /*
 579                          * Add the message to the q.
 580                          */
 581                         (void) putq(q, mp);
 582                 } else {
 583                         /*
 584                          * Things are pretty bad and serious if bufcall fails!
 585                          * Drop the message in this case.
 586                          */
 587                         freemsg(mp);
 588                 }
 589 
 590                 return (NULL);
 591         }
 592 
 593         /*
 594          * Copy the message type information to this message.
 595          */
 596         bp->b_datap->db_type = M_PROTO;
 597         *(unsigned char *)bp->b_rptr = mp->b_datap->db_type;
 598         bp->b_wptr++;
 599 
 600 #ifdef _MULTI_DATAMODEL
 601         /*
 602          * Check the datamodel and if the calling program is
 603          * an ILP32 application then we covert the M_IOCTLs and M_READs
 604          * into the native ILP32 format before passing them upstream
 605          * to user mode.
 606          */
 607         switch (pip->model) {
 608         case DDI_MODEL_ILP32:
 609                 switch (mp->b_datap->db_type) {
 610                         /*
 611                          * This structure must have the same shape as
 612                          * the * ILP32 compilation of `struct iocblk'
 613                          * from <sys/stream.h>.
 614                          */
 615                         struct iocblk32 {
 616                                 int32_t         ioc_cmd;
 617                                 caddr32_t       ioc_cr;
 618                                 uint32_t        ioc_id;
 619                                 int32_t         ioc_count;
 620                                 int32_t         ioc_error;
 621                                 int32_t         ioc_rval;
 622                                 int32_t         ioc_fill1;
 623                                 uint32_t        ioc_flag;
 624                                 int32_t         ioc_filler[2];
 625                         } niocblk_32;
 626                         struct iocblk           *iocblk_64;
 627 
 628                 case M_IOCTL:
 629                         if ((mp = pckt_reallocb(q, mp)) == (mblk_t *)0)
 630                                 return ((mblk_t *)0);
 631 
 632                         bzero(&niocblk_32, sizeof (niocblk_32));
 633                         iocblk_64 = (struct iocblk *)mp->b_rptr;
 634 
 635                         /* Leave the pointer to cred_t structure as it is. */
 636                         niocblk_32.ioc_cmd = iocblk_64->ioc_cmd;
 637                         niocblk_32.ioc_cr = (caddr32_t)(uintptr_t)
 638                             iocblk_64->ioc_cr;
 639                         niocblk_32.ioc_id = iocblk_64->ioc_id;
 640                         niocblk_32.ioc_count = iocblk_64->ioc_count;
 641                         niocblk_32.ioc_error = iocblk_64->ioc_error;
 642                         niocblk_32.ioc_rval = iocblk_64->ioc_rval;
 643                         niocblk_32.ioc_flag = iocblk_64->ioc_flag;
 644 
 645                         /* Copy the iocblk structure for ILP32 back */
 646                         *(struct iocblk32 *)mp->b_rptr = niocblk_32;
 647                         mp->b_wptr = mp->b_rptr + sizeof (struct iocblk32);
 648                         break;
 649 
 650                 case M_READ:
 651                         if ((mp = pckt_reallocb(q, mp)) == (mblk_t *)0)
 652                                 return ((mblk_t *)0);
 653 
 654                         /* change the size_t to size32_t for ILP32 */
 655                         *(size32_t *)mp->b_rptr = *(size_t *)mp->b_rptr;
 656                         mp->b_wptr = mp->b_rptr + sizeof (size32_t);
 657                         break;
 658                 }
 659                 break;
 660 
 661         case DATAMODEL_NONE:
 662                 break;
 663         }
 664 #endif /* _MULTI_DATAMODEL */
 665 
 666         /*
 667          * Now change the orginal message type to M_DATA and tie them up.
 668          */
 669         mp->b_datap->db_type = M_DATA;
 670         bp->b_cont = mp;
 671 
 672         return (bp);
 673 }
 674 
 675 static void
 676 add_ctl_wkup(void *arg)
 677 {
 678         queue_t *q = arg;       /* ptr to the read queue */
 679         struct pckt_info *pip = (struct pckt_info *)q->q_ptr;
 680 
 681         pip->pi_bufcall_id = 0;
 682         /*
 683          * Allow enabling of the q to allow the service
 684          * function to do its job.
 685          *
 686          * Also, qenable() to schedule the q immediately.
 687          * This is to ensure timely processing of high priority
 688          * messages if they are on the q.
 689          */
 690         enableok(q);
 691         qenable(q);
 692 }