1: /*
   2:  *	SCCS id	@(#)mx2.c	2.1 (Berkeley)	8/5/83
   3:  */
   4: 
   5: #include "param.h"
   6: #include <sys/systm.h>
   7: #include <sys/dir.h>
   8: #include <sys/user.h>
   9: #include <sys/proc.h>
  10: #include <sys/tty.h>
  11: #include <sys/inode.h>
  12: #include <sys/mx.h>
  13: #include <sys/file.h>
  14: #include <sys/conf.h>
  15: #include <sys/buf.h>
  16: 
  17: /*
  18:  * multiplexor driver
  19:  */
  20: struct  chan    chans[NCHANS];
  21: struct  group   *groups[NGROUPS];
  22: int mpxline;
  23: 
  24: short   cmask[16]   ={
  25:     01, 02, 04,
  26:     010,    020,    040,
  27:     0100,   0200,   0400,
  28:     01000,  02000,  04000,
  29:     010000, 020000, 040000, 0100000
  30: };
  31: 
  32: #define IOMOVE  iomove
  33: struct chan *xcp(),*addch(),*nextcp();
  34: 
  35: #define HIQ 100
  36: #define LOQ 20
  37: #define FP  ((struct file *)cp)
  38: 
  39: char mcdebugs[NDEBUGS];
  40: 
  41: struct group *
  42: getmpx(dev)
  43: dev_t dev;
  44: {
  45:     register d;
  46: 
  47:     d = minor(dev);
  48:     if (d >= NGROUPS) {
  49:         u.u_error = ENXIO;
  50:         return(NULL);
  51:     }
  52:     return(groups[d]);
  53: }
  54: 
  55: 
  56: /*ARGSUSED*/
  57: mxopen(dev, flag)
  58: {
  59:     register struct group *gp;
  60:     register struct file *fp;
  61:     register struct chan *cp;
  62:     int msg;
  63: 
  64:     if ((gp=getmpx(dev)) == NULL) {
  65:         return;
  66:     }
  67:     if (!(gp->g_state&INUSE)) {
  68:         u.u_error = ENXIO;
  69:         return;
  70:     }
  71:     fp = u.u_ofile[u.u_r.r_val1];
  72:     if (fp->f_inode != gp->g_inode) {
  73:         u.u_error = ENXIO;
  74:         return;
  75:     }
  76:     if ((cp=addch(gp->g_inode,0)) == NULL) {
  77:         u.u_error = ENXIO;
  78:         return;
  79:     }
  80: 
  81:     cp->c_flags = XGRP;
  82:     cp->c_ottyp = cp->c_ttyp = (struct tty *)cp;
  83:     cp->c_line = cp->c_oline = mpxline;
  84: 
  85:     fp->f_flag |= FMPY;
  86:     fp->f_flag |= FREAD+FWRITE;
  87:     fp->f_un.f_chan = cp;
  88: 
  89:     if (gp->g_inode == mpxip) {
  90:         plock(mpxip);
  91:         mpxname(cp);
  92:         msg = M_OPEN;
  93:     } else
  94:         msg = M_WATCH;
  95: 
  96:     scontrol(cp, msg+(cp->c_index<<8), u.u_uid);
  97:     sleep((caddr_t)cp,TTIPRI);
  98:     if (cp->c_flags&NMBUF)
  99:         prele(mpxip);
 100:     if (cp->c_flags & WCLOSE) {
 101:         chdrain(cp);
 102:         chfree(cp);
 103:         u.u_error = ENXIO;
 104:         return;
 105:     }
 106:     cp->c_fy = fp;
 107:     cp->c_pgrp = u.u_procp->p_pgrp;
 108: }
 109: 
 110: 
 111: char    mxnmbuf[NMSIZE];
 112: int nmsize;
 113: 
 114: mpxname(cp)
 115: register struct chan *cp;
 116: {
 117:     register char *np;
 118:     register c;
 119: 
 120:     np = mxnmbuf;
 121:     u.u_dirp = (caddr_t)u.u_arg[0];
 122: 
 123:     while (np < &mxnmbuf[NMSIZE]) {
 124:         c = uchar();
 125:         if (c <= 0)
 126:             break;
 127:         *np++ = c;
 128:     }
 129:     *np++ = '\0';
 130:     nmsize = np - mxnmbuf;
 131: 
 132:     cp->c_flags |= NMBUF;
 133: }
 134: 
 135: 
 136: mxclose(dev, flag, fp)
 137: dev_t   dev;
 138: register struct file *fp;
 139: {
 140: register struct group *gp;
 141: register struct inode *ip;
 142: register struct chan *cp = { fp->f_un.f_chan };
 143: int i, fmp;
 144: 
 145:     fmp = flag&FMP;
 146:     if ((gp=getmpx(dev)) == NULL)
 147:         return;
 148: 
 149:     ip = gp->g_inode;
 150:     if (ip==NULL || (ip->i_mode&IFMT)!=IFMPC) {
 151:         return;
 152:     }
 153: 
 154:     /*
 155: 	 * close a channel
 156: 	 */
 157:     if (cp!=NULL && fmp && fmp!=FMP) {
 158:         for(fp=file; fp< fileNFILE; fp++)
 159:             if(fp->f_count && fp->f_flag&FMP && fp->f_un.f_chan==cp){
 160:                 return;
 161:             }
 162:         chdrain(cp);
 163:         if ((cp->c_flags&WCLOSE)==0) {
 164:             scontrol(cp, M_CLOSE, 0);
 165:             cp->c_flags |= WCLOSE;
 166:         } else {
 167:             chfree(cp);
 168:         }
 169:         goto out;
 170:     }
 171: 
 172: 
 173:     for(fp=file; fp < fileNFILE; fp++) {
 174:         if (fp->f_count && (fp->f_flag&FMP)==FMP && fp->f_inode==ip)
 175:             return;
 176:     }
 177: 
 178:     if (ip == mpxip) {
 179:         mpxip = NULL;
 180:         prele(ip);
 181:     }
 182: 
 183:     for(i=0;i<NINDEX;i++)
 184:         (void) detach(gp->g_chans[i]);
 185: 
 186: out:
 187:     if (ip->i_count == 1) {
 188:         groups[minor(dev)] = NULL;
 189:         plock(ip);
 190:         zero((caddr_t)gp, sizeof (struct group));
 191:         ip->i_mode = IFREG + 0666;
 192:         ip->i_un.i_rdev = 0;
 193:         ip->i_flag |= IUPD|ICHG;
 194:         iput(ip);
 195:     }
 196: }
 197: 
 198: zero(s, cc)
 199: register char *s;
 200: register cc;
 201: {
 202:     while (cc--)
 203:         *s++ = 0;
 204: }
 205: 
 206: char    m_eot[] ={ M_EOT, 0, 0, 0};
 207: 
 208: /*
 209:  * Mxread + mxwrite are entered from cdevsw
 210:  * for all read/write calls.  Operations on
 211:  * an mpx file are handled here.
 212:  * Calls are made through linesw to handle actual
 213:  * data movement.
 214:  */
 215: mxread(dev)
 216: {
 217:     register struct group *gp;
 218:     register struct chan *cp;
 219:     register esc;
 220:     struct rh h;
 221:     caddr_t base;
 222:     unsigned count;
 223:     int s, xfr, more, fmp;
 224: 
 225:     if ((gp=getmpx(dev))==NULL || (FP=getf(u.u_arg[0]))==NULL) {
 226:         u.u_error = ENXIO;
 227:         return;
 228:     }
 229: 
 230:     fmp = FP->f_flag & FMP;
 231:     if (fmp != FMP) {
 232:         if (u.u_count == 0)
 233:             return;
 234:         msread(fmp, FP->f_un.f_chan);
 235:         return;
 236:     }
 237: 
 238:     if ((int)u.u_base & 1) {
 239:         u.u_error = ENXIO;
 240:         return;
 241:     }
 242: 
 243:     s = spl6();
 244:     if (u.u_count == 0)
 245:     {
 246:         if (gp->g_datq == 0)
 247:             u.u_error = ENXIO;
 248:         splx(s);
 249:         return;
 250:     }
 251:     while (gp->g_datq == 0) {
 252:         sleep((caddr_t)&gp->g_datq, TTIPRI);
 253:     }
 254:     splx(s);
 255: 
 256:     while (gp->g_datq && u.u_count >= CNTLSIZ + 2) {
 257:         esc = 0;
 258:         cp = nextcp(gp);
 259:         if (cp==NULL) {
 260:             continue;
 261:         }
 262:         h.index = cpx(cp);
 263:         if (count = cp->c_ctlx.c_cc) {
 264:             count += CNTLSIZ;
 265:             if (cp->c_flags&NMBUF)
 266:                 count += nmsize;
 267:             if (count > u.u_count) {
 268:                 (void) sdata(cp);
 269:                 return;
 270:             }
 271:             esc++;
 272:         }
 273:         base = u.u_base;
 274:         count = u.u_count;
 275:         u.u_base += sizeof h;
 276:         u.u_count -= sizeof h;
 277:         xfr = u.u_count;
 278:         if (esc) {
 279:             more = mcread(cp);
 280:         } else {
 281:             more = (*linesw[cp->c_line].l_read)(cp->c_ttyp);
 282:         }
 283:         if (more > 0)
 284:             (void) sdata(cp);
 285:         if (more < 0)
 286:             scontrol(cp, M_CLOSE, 0);
 287:         (void) _spl0();
 288:         if (xfr == u.u_count) {
 289:             esc++;
 290:             IOMOVE((caddr_t)m_eot, sizeof m_eot, B_READ);
 291:         }
 292:         xfr -= u.u_count;
 293:         if (esc) {
 294:             h.count = 0;
 295:             h.ccount = xfr;
 296:         } else {
 297:             h.count = xfr;
 298:             h.ccount = 0;
 299:             mxrstrt(cp, &cp->cx.datq, BLOCK|ALT);
 300:         }
 301:         if (u.u_count && (xfr&1)) {
 302:             u.u_base++;
 303:             u.u_count--;
 304:         }
 305:         (void) copyout((caddr_t)&h, base, sizeof h);
 306: 
 307:     }
 308: }
 309: 
 310: 
 311: mxwrite(dev)
 312: {
 313: register struct chan *cp;
 314: struct  wh h;
 315: struct group *gp;
 316: int ucount, esc, fmp, burpcount;
 317: caddr_t ubase, hbase;
 318: 
 319:     if ((gp=getmpx(dev))==NULL || (FP=getf(u.u_arg[0]))==NULL) {
 320:         return;
 321:     }
 322:     fmp = FP->f_flag & FMP;
 323:     if (fmp != FMP) {
 324:         mswrite(fmp, FP->f_un.f_chan);
 325:         return;
 326:     }
 327: 
 328:     burpcount = 0;
 329:     while (u.u_count >= sizeof h) {
 330:         hbase = u.u_base;
 331:         IOMOVE((caddr_t)&h, sizeof h, B_WRITE);
 332:         if (u.u_error)
 333:             return;
 334:         esc = 0;
 335:         if (h.count==0) {
 336:             esc++;
 337:             h.count = h.ccount;
 338:         }
 339:         cp = xcp(gp, h.index);
 340:         if (cp==NULL || cp->c_flags&ISGRP) {
 341:             u.u_error = ENXIO;
 342:             return;
 343:         }
 344:         ucount = u.u_count;
 345:         ubase = u.u_base;
 346:         u.u_count = h.count;
 347:         u.u_base = h.data;
 348: 
 349:         if (esc==0) {
 350:             struct tty *tp;
 351:             caddr_t waddr;
 352:             int line;
 353: 
 354:             if (cp->c_flags&PORT) {
 355:                 line = cp->c_line;
 356:                 tp = cp->c_ttyp;
 357:             } else {
 358:                 line = cp->c_oline;
 359:                 tp = cp->c_ottyp;
 360:             }
 361:         loop:
 362:             waddr = (caddr_t)(*linesw[line].l_write)(tp);
 363:             if (u.u_count) {
 364:                 if (gp->g_state&ENAMSG) {
 365:                     burpcount++;
 366:                     cp->c_flags |= BLKMSG;
 367: /*
 368: 					scontrol(cp, M_BLK, u.u_count);
 369: */
 370:                     h.ccount = -1;
 371:                     h.count = u.u_count;
 372:                     h.data = u.u_base;
 373:                     (void) copyout((caddr_t)&h, hbase, sizeof h);
 374:                 } else {
 375:                     if(waddr == 0) {
 376:                         u.u_error = ENXIO;
 377:                         return;
 378:                     }
 379:                     sleep(waddr, TTOPRI);
 380:                     goto loop;
 381:                 }
 382:             }
 383:         } else {
 384:             mxwcontrol(cp);
 385:         }
 386:         u.u_count = ucount;
 387:         u.u_base = ubase;
 388:     }
 389:     u.u_count = burpcount;
 390: }
 391: 
 392: 
 393: 
 394: /*
 395:  * Mcread and mcwrite move data on an mpx file.
 396:  * Transfer addr and length is controlled by mxread/mxwrite.
 397:  * Kernel-to-Kernel and other special transfers are not
 398:  * yet in.
 399:  */
 400: mcread(cp)
 401: register struct chan *cp;
 402: {
 403: register struct clist *q;
 404: register char *np;
 405: 
 406: 
 407:     q = (cp->c_ctlx.c_cc) ? &cp->c_ctlx : &cp->cx.datq;
 408:     (void) mxmove(q, B_READ);
 409: 
 410:     if (cp->c_flags&NMBUF && q == &cp->c_ctlx) {
 411:         np = mxnmbuf;
 412:         while (nmsize--)
 413:             (void) passc(*np++);
 414:         cp->c_flags &= ~NMBUF;
 415:         prele(mpxip);
 416:     }
 417:     if (cp->c_flags&PORT)
 418:         return(cp->c_ctlx.c_cc + cp->c_ttyp->t_rawq.c_cc); else
 419:         return(cp->c_ctlx.c_cc + cp->cx.datq.c_cc);
 420: 
 421: }
 422: 
 423: 
 424: caddr_t
 425: mcwrite(cp)
 426: register struct chan *cp;
 427: {
 428: register struct clist *q;
 429: int s;
 430: 
 431:     q = &cp->cy.datq;
 432:     while (u.u_count) {
 433:         s = spl6();
 434:         if (q->c_cc > HIQ || (cp->c_flags&EOTMARK)) {
 435:             cp->c_flags |= SIGBLK;
 436:             splx(s);
 437:             break;
 438:         }
 439:         splx(s);
 440:         (void) mxmove(q, B_WRITE);
 441:     }
 442:     wakeup((caddr_t)q);
 443:     return((caddr_t)q);
 444: }
 445: 
 446: 
 447: /*
 448:  * Msread and mswrite move bytes
 449:  * between user and non-multiplexed channel.
 450:  */
 451: msread(fmp, cp)
 452: register struct chan *cp;
 453: {
 454: register struct clist *q;
 455: int s;
 456: 
 457:     q = (fmp&FMPX) ? &cp->cx.datq : &cp->cy.datq;
 458:     s = spl6();
 459:     while (q->c_cc == 0) {
 460:         if (cp->c_flags&WCLOSE) {
 461:             u.u_error = ENXIO;
 462:             goto out;
 463:         }
 464:         if (cp->c_flags & EOTMARK) {
 465:             cp->c_flags &= ~EOTMARK;
 466:             if(msgenab(cp))
 467:                 scontrol(cp, M_UBLK, 0);
 468:             else {
 469:                 wakeup((caddr_t)cp);
 470:                 wakeup((caddr_t)q);
 471:             }
 472:             goto out;
 473:         }
 474:         sleep((caddr_t)q,TTIPRI);
 475:     }
 476:     if (cp->c_flags&WCLOSE) {
 477:         u.u_error = ENXIO;
 478:         goto out;
 479:     }
 480:     splx(s);
 481:     while (mxmove(q, B_READ) > 0)
 482:         ;
 483:     mxrstrt(cp, q, SIGBLK);
 484:     return;
 485: out:
 486:     splx(s);
 487: }
 488: 
 489: 
 490: mswrite(fmp, cp)
 491: register struct chan *cp;
 492: {
 493:     register struct clist *q;
 494:     register int cc;
 495: 
 496:     q = (fmp&FMPX) ? &cp->cy.datq : &cp->cx.datq;
 497:     while (u.u_count) {
 498:         (void) _spl6();
 499:         if (cp->c_flags&WCLOSE) {
 500:             gsignal(cp->c_pgrp, SIGPIPE);
 501:             (void) _spl0();
 502:             return;
 503:         }
 504:         if (q->c_cc>= HIQ || cp->c_flags&FBLOCK) {
 505:             if (cp->c_flags&WCLOSE) {
 506:                 gsignal(cp->c_pgrp, SIGPIPE);
 507:                 (void) _spl0();
 508:                 return;
 509:             }
 510:             (void) sdata(cp);
 511:             cp->c_flags |= BLOCK;
 512:             sleep((caddr_t)q+1,TTOPRI);
 513:             (void) _spl0();
 514:             continue;
 515:         }
 516:         (void) _spl0();
 517:         cc = mxmove(q, B_WRITE);
 518:         if (cc < 0)
 519:             break;
 520:     }
 521:     if (fmp&FMPX) {
 522:         if (cp->c_flags&YGRP)  (void) sdata(cp);
 523:         else               wakeup((caddr_t)q);
 524:     } else {
 525:         if (cp->c_flags&XGRP)  (void) sdata(cp);
 526:         else               wakeup((caddr_t)q);
 527:     }
 528: }
 529: 
 530: 
 531: /*
 532:  * move chars between clist and user space.
 533:  */
 534: 
 535: mxmove(q, dir)
 536: register struct clist *q;
 537: register dir;
 538: {
 539: register cc;
 540: char cbuf[HIQ];
 541: 
 542:     cc = MIN(u.u_count, sizeof cbuf);
 543:     if (dir == B_READ)
 544:         cc = q_to_b(q, cbuf, cc);
 545:     if (cc <= 0)
 546:         return(cc);
 547:     IOMOVE((caddr_t)cbuf, (unsigned)cc, dir);
 548:     if (dir == B_WRITE)
 549:         cc = b_to_q(cbuf, cc, q);
 550:     return(cc);
 551: }
 552: 
 553: 
 554: 
 555: mxrstrt(cp, q, b)
 556: register struct chan *cp;
 557: register struct clist *q;
 558: register b;
 559: {
 560: int s;
 561: 
 562:     s = spl6();
 563:     if (cp->c_flags&b && q->c_cc<LOQ) {
 564:         cp->c_flags &= ~b;
 565:         if (b&ALT)
 566:             wakeup((caddr_t)q+1); else
 567:             mcstart(cp, (caddr_t)q);
 568:     }
 569:     if (cp->c_flags&WFLUSH)
 570:         wakeup((caddr_t)q+2);
 571:     splx(s);
 572: }
 573: 
 574: 
 575: 
 576: /*
 577:  * called from driver start or xint routines
 578:  * to wakeup output sleeper.
 579:  */
 580: mcstart(cp, q)
 581: register struct chan *cp;
 582: register caddr_t q;
 583: {
 584: 
 585:     if (cp->c_flags&(BLKMSG)) {
 586:         cp->c_flags &= ~BLKMSG;
 587:         scontrol(cp, M_UBLK, 0);
 588:     } else
 589:         wakeup((caddr_t)q);
 590: }
 591: 
 592: 
 593: mxwcontrol(cp)
 594: register struct chan *cp;
 595: {
 596: short cmd;
 597: struct sgttyb vec;
 598: int s;
 599: 
 600:     IOMOVE((caddr_t)&cmd, sizeof cmd, B_WRITE);
 601:     if (u.u_error)
 602:         return;
 603:     switch(cmd) {
 604:     /*
 605: 	 * not ready to queue this up yet.
 606: 	 */
 607:     case M_EOT:
 608:         s = spl6();
 609:         while (cp->c_flags & EOTMARK)
 610:             if(msgenab(cp)){
 611:                 scontrol(cp, M_BLK, 0);
 612:                 goto out;
 613:             } else
 614:                 sleep((caddr_t)cp, TTOPRI);
 615:                 cp->c_flags |= EOTMARK;
 616:     out:
 617:         wakeup((caddr_t)&cp->cy.datq);
 618:         splx(s);
 619:         break;
 620:     case M_IOCTL:
 621:         break;
 622:     case M_IOANS:
 623:         if (cp->c_flags&SIOCTL) {
 624:             IOMOVE((caddr_t)&vec, sizeof vec, B_WRITE);
 625:             (void) b_to_q((caddr_t)&vec, sizeof vec, &cp->c_ctly);
 626:             cp->c_flags &= ~SIOCTL;
 627:             wakeup((caddr_t)cp);
 628:         }
 629:         break;
 630:     case M_BLK:
 631:         cp->c_flags |= FBLOCK;
 632:         break;
 633:     case M_UBLK:
 634:         cp->c_flags &= ~FBLOCK;
 635:         chwake(cp);
 636:         break;
 637:     default:
 638:         u.u_error = ENXIO;
 639:     }
 640: }
 641: 
 642: 
 643: 
 644: /*ARGSUSED*/
 645: mxioctl(dev, cmd, addr, flag)
 646: caddr_t addr;
 647: {
 648: struct group *gp;
 649: int fmp;
 650: struct file *fp;
 651: struct {
 652:     short c_ctl;
 653:     short c_cmd;
 654:     struct sgttyb c_vec;
 655: } ctlbuf;
 656: 
 657:     if ((gp=getmpx(dev))==NULL || (fp=getf(u.u_arg[0]))==NULL) {
 658:         return;
 659:     }
 660: 
 661:     fmp = fp->f_flag & FMP;
 662:     if (fmp == FMP) {
 663:         switch(cmd) {
 664: 
 665:         case MXLSTN:
 666:             if (mpxip == NULL) {
 667:                 mpxip = gp->g_inode;
 668:             } else {
 669:                 u.u_error = ENXIO;
 670:                 return;
 671:             }
 672:             break;
 673: 
 674:         case MXNBLK:
 675:             gp->g_state |= ENAMSG;
 676:             break;
 677: 
 678:         default:
 679:             u.u_error = ENXIO;
 680:             return;
 681:         }
 682:     } else {
 683:         ctlbuf.c_ctl = M_IOCTL;
 684:         ctlbuf.c_cmd = cmd;
 685:         (void) copyin(addr, (caddr_t)&ctlbuf.c_vec, sizeof (struct sgttyb));
 686:         sioctl(fp->f_un.f_chan, (char *)&ctlbuf, sizeof ctlbuf);
 687:         (void) copyout((caddr_t)&ctlbuf, addr, sizeof (struct sgttyb));
 688:     }
 689: }
 690: 
 691: 
 692: chdrain(cp)
 693: register struct chan *cp;
 694: {
 695: register struct tty *tp;
 696: int wflag;
 697: 
 698:     chwake(cp);
 699: 
 700:     wflag = (cp->c_flags&WCLOSE)==0;
 701:     tp = cp->c_ttyp;
 702:     if (tp == NULL)     /* prob not required */
 703:         return;
 704:     if (cp->c_flags&PORT && tp->t_chan == cp) {
 705:         cp->c_ttyp = NULL;
 706:         tp->t_chan = NULL;
 707:         return;
 708:     }
 709:     if (wflag)
 710:         wflush(cp,&cp->cx.datq); else
 711:         flush(&cp->cx.datq);
 712:     if (!(cp->c_flags&YGRP)) {
 713:         flush(&cp->cy.datq);
 714:     }
 715: }
 716: 
 717: chwake(cp)
 718: register struct chan *cp;
 719: {
 720: register char *p;
 721: 
 722:     wakeup((caddr_t)cp);
 723:     flush(&cp->c_ctlx);
 724:     p = (char *)&cp->cx.datq;
 725:     wakeup((caddr_t)p); wakeup((caddr_t)++p); wakeup((caddr_t)++p);
 726:     p = (char *)&cp->cy.datq;
 727:     wakeup((caddr_t)p); wakeup((caddr_t)++p); wakeup((caddr_t)++p);
 728: }
 729: 
 730: 
 731: chfree(cp)
 732: register struct chan *cp;
 733: {
 734: register struct group *gp;
 735: register i;
 736: 
 737:     gp = cp->c_group;
 738:     if (gp==NULL)
 739:         return;
 740:     i = cp->c_index;
 741:     if (cp == gp->g_chans[i]) {
 742:         gp->g_chans[i] = NULL;
 743:     }
 744:     cp->c_group = NULL;
 745:     wakeup((caddr_t)gp);
 746: }
 747: 
 748: 
 749: flush(q)
 750: register struct clist *q;
 751: {
 752: 
 753:     while(q->c_cc)
 754:         (void) getc(q);
 755: }
 756: 
 757: 
 758: wflush(cp,q)
 759: register struct chan *cp;
 760: register struct clist *q;
 761: {
 762: register s;
 763: 
 764:     s = spl6();
 765:     if(q->c_cc && (cp->c_flags&WCLOSE) == 0) {
 766:         cp->c_flags |= WFLUSH;
 767:         (void) sdata(cp);
 768:         sleep((caddr_t)q+2, TTOPRI);
 769:     }
 770:     flush(q);
 771:     cp->c_flags &= ~WFLUSH;
 772:     splx(s);
 773: }
 774: 
 775: 
 776: scontrol(cp,event,value)
 777: register struct chan *cp;
 778: short event,value;
 779: {
 780: register struct clist *q;
 781: int s;
 782: 
 783:     q = &cp->c_ctlx;
 784:     s = spl6();
 785:     if (sdata(cp) == NULL)
 786:         return;
 787:     (void) putw(event,q);
 788:     (void) putw(value,q);
 789:     splx(s);
 790: }
 791: 
 792: 
 793: 
 794: sioctl(cp, vec, cc)
 795: register struct chan *cp;
 796: char *vec;
 797: {
 798: register s;
 799: register struct clist *q;
 800: 
 801:     s = spl6();
 802:     q = &cp->cx.datq;
 803:     while (q->c_cc) {
 804:         cp->c_flags |= BLOCK;
 805:         if (sdata(cp)==NULL) {
 806:             u.u_error = ENXIO;
 807:             return;
 808:         }
 809:         sleep((caddr_t)q+1, TTOPRI);
 810:     }
 811:     (void) b_to_q(vec, cc, &cp->c_ctlx);
 812:     cp->c_flags |= SIOCTL;
 813:     while (cp->c_flags&SIOCTL) {
 814:         if (cp->c_ctlx.c_cc)
 815:             if (sdata(cp)==NULL) {
 816:                 u.u_error = ENXIO;
 817:                 return;
 818:             }
 819:         sleep((caddr_t)cp, TTOPRI);
 820:     }
 821:     (void) q_to_b(&cp->c_ctly, vec, cp->c_ctly.c_cc);
 822:     splx(s);
 823: }
 824: 
 825: sdata(cp)
 826: struct chan *cp;
 827: {
 828:     register struct group *gp = (struct group *)cp;
 829:     register struct group *ngp;
 830:     register int    s;
 831: 
 832:     ngp = gp->g_group;
 833:     if (ngp==NULL || (ngp->g_state&ISGRP)==0)
 834:         return(NULL);
 835: 
 836:     s = spl6();
 837:     do {
 838:         ngp->g_datq |= cmask[gp->g_index];
 839:         wakeup((caddr_t)&ngp->g_datq);
 840:         gp = ngp;
 841:     } while(ngp=ngp->g_group);
 842:     splx(s);
 843:     return((int)gp);
 844: }
 845: 
 846: 
 847: 
 848: struct chan *
 849: xcp(gp, x)
 850: register struct group *gp;
 851: register short x;
 852: {
 853:     register int i;
 854: 
 855:     while (gp->g_group) gp=gp->g_group;
 856:     for (i=0;i<NLEVELS;i++) {
 857:         if ((x&017) >= NINDEX)
 858:             break;
 859:         if (gp==NULL || (gp->g_state&ISGRP)==0)
 860:             return((struct chan *)NULL);
 861:         gp = (struct group *)gp->g_chans[x&017];
 862:         x >>= 4;
 863:     }
 864:     return((struct chan *)gp);
 865: }
 866: 
 867: cpx(cp)
 868: register struct chan *cp;
 869: {
 870:     register x;
 871:     register struct group *gp;
 872: 
 873:     x = (-1<<4) + cp->c_index;
 874:     gp = cp->c_group;
 875:     while (gp->g_group) {
 876:         x <<= 4;
 877:         x |= gp->g_index;
 878:         gp = gp->g_group;
 879:     }
 880:     return(x);
 881: }
 882: 
 883: 
 884: struct chan *
 885: nextcp(gp)
 886: register struct group *gp;
 887: {
 888:     register struct group *lgp, *ngp;
 889: 
 890:     do {
 891:         while ((gp->g_datq & cmask[gp->g_rot]) == 0) {
 892:             gp->g_rot = (gp->g_rot+1)%NINDEX;
 893:         }
 894:         lgp = gp;
 895:         gp = (struct group *)gp->g_chans[gp->g_rot];
 896:     } while (gp!=NULL && gp->g_state&ISGRP);
 897: 
 898:     lgp->g_datq &= ~cmask[lgp->g_rot];
 899:     lgp->g_rot  =  (lgp->g_rot+1)%NINDEX;
 900: 
 901:     while (ngp=lgp->g_group) {
 902:         ngp->g_datq &= ~cmask[lgp->g_index];
 903:         if (ngp->g_datq)
 904:             break;
 905:         lgp = ngp;
 906:     }
 907:     return((struct chan *)gp);
 908: }
 909: 
 910: 
 911: 
 912: msgenab(cp)
 913: register struct chan *cp;
 914: {
 915:     register struct group *gp;
 916: 
 917:     for(gp=cp->c_group;gp;gp=gp->g_group)
 918:         if(gp->g_state & ENAMSG)return(1);
 919:     return(0);
 920: }

Defined functions

chdrain defined in line 692; used 4 times
chfree defined in line 731; used 4 times
chwake defined in line 717; used 3 times
cpx defined in line 867; used 5 times
flush defined in line 749; used 4 times
getmpx defined in line 41; used 5 times
mcread defined in line 400; used 3 times
mcstart defined in line 580; used 1 times
mcwrite defined in line 424; never used
mpxname defined in line 114; used 1 times
  • in line 91
msgenab defined in line 912; used 2 times
msread defined in line 451; used 1 times
mswrite defined in line 490; used 1 times
mxclose defined in line 136; never used
mxioctl defined in line 645; never used
mxmove defined in line 535; used 4 times
mxopen defined in line 57; used 2 times
mxread defined in line 215; never used
mxrstrt defined in line 555; used 2 times
mxwcontrol defined in line 593; used 1 times
mxwrite defined in line 311; never used
nextcp defined in line 884; used 2 times
scontrol defined in line 776; used 6 times
sdata defined in line 825; used 9 times
sioctl defined in line 794; used 1 times
wflush defined in line 758; used 1 times
xcp defined in line 848; used 8 times
zero defined in line 198; used 1 times

Defined variables

chans defined in line 20; never used
cmask defined in line 24; used 4 times
groups defined in line 21; used 2 times
m_eot defined in line 206; used 2 times
  • in line 290(2)
mcdebugs defined in line 39; never used
mpxline defined in line 22; used 1 times
  • in line 83
mxnmbuf defined in line 111; used 4 times
nmsize defined in line 112; used 3 times

Defined macros

FP defined in line 37; used 6 times
HIQ defined in line 35; used 3 times
IOMOVE defined in line 32; used 5 times
LOQ defined in line 36; used 1 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2500
Valid CSS Valid XHTML 1.0 Strict