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: */