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

Defined functions

chdrain defined in line 661; used 4 times
chfree defined in line 700; used 4 times
chwake defined in line 686; used 2 times
cpx defined in line 814; used 4 times
flush defined in line 717; used 4 times
getmpx defined in line 49; used 5 times
mcread defined in line 394; used 3 times
mcrint defined in line 885; never used
mcstart defined in line 571; used 1 times
mcwrite defined in line 419; never used
mcxint defined in line 890; never used
mpxname defined in line 117; used 1 times
  • in line 96
msread defined in line 447; used 1 times
mswrite defined in line 482; used 1 times
mxclose defined in line 138; never used
mxioctl defined in line 622; never used
mxmove defined in line 526; used 4 times
mxopen defined in line 64; used 2 times
mxread defined in line 217; never used
mxrstrt defined in line 546; used 2 times
mxwcontrol defined in line 584; used 1 times
mxwrite defined in line 306; never used
nextcp defined in line 837; used 2 times
rmdata defined in line 863; used 1 times
scontrol defined in line 748; used 6 times
sdata defined in line 764; used 7 times
wflush defined in line 726; used 1 times
xcp defined in line 796; used 8 times
zero defined in line 200; used 1 times

Defined variables

MP defined in line 45; never used
chans defined in line 17; never used
cmask defined in line 25; used 2 times
groups defined in line 18; used 2 times
m_eot defined in line 208; used 2 times
  • in line 281(2)
mcdebugs defined in line 39; never used
mpxline defined in line 19; used 1 times
  • in line 90
mxdummy defined in line 44; used 1 times
  • in line 45
mxnmbuf defined in line 114; used 4 times
mxnmcp defined in line 116; never used
nmsize defined in line 115; used 3 times

Defined macros

FP defined in line 35; used 6 times
HIQ defined in line 33; used 2 times
KERNEL defined in line 8; never used
LOQ defined in line 34; used 1 times
MIN defined in line 24; used 1 times
Last modified: 1979-05-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2297
Valid CSS Valid XHTML 1.0 Strict