From: Dennis Ritchie Date: Mon, 14 May 1979 03:18:18 +0000 (-0500) Subject: Research V7 development X-Git-Tag: Research-V7~37 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/fc1656331f32f0d4a8dd657b3d0d59fff6a8b21e Research V7 development Work on file usr/sys/dev/mx2.c Synthesized-from: v7 --- diff --git a/usr/sys/dev/mx2.c b/usr/sys/dev/mx2.c new file mode 100644 index 0000000000..cd93315387 --- /dev/null +++ b/usr/sys/dev/mx2.c @@ -0,0 +1,915 @@ +#include "../h/param.h" +#include "../h/systm.h" +#include "../h/dir.h" +#include "../h/user.h" +#include "../h/proc.h" +#include "../h/tty.h" +#include "../h/inode.h" +#define KERNEL 1 +#include "../h/mx.h" +#include "../h/file.h" +#include "../h/conf.h" +#include "../h/buf.h" + +/* + * multiplexor driver + */ +struct chan chans[NCHANS]; +struct group *groups[NGROUPS]; +int mpxline; +struct chan *xcp(); +struct chan *addch(); +struct chan *nextcp(); + +#define MIN(a,b) ((a= NGROUPS) + return(NULL); + return(groups[d]); +} + + + + +mxopen(dev, flag) +{ +register struct group *gp; +register struct file *fp; +register struct chan *cp; +int msg; + gp = getmpx(dev); + if (gp == NULL) { + bad: + u.u_error = ENXIO; + return; + } + + if (gp->g_state == COPEN) { + gp->g_state = INUSE+ISGRP; + return; + } + if (!(gp->g_state&INUSE)) + goto bad; + fp = u.u_ofile[u.u_r.r_val1]; + if (fp->f_inode != gp->g_inode) + goto bad; + if ((cp=addch(gp->g_inode, 0))==NULL) + goto bad; + cp->c_flags = XGRP; + cp->c_ottyp = cp->c_ttyp = (struct tty *)cp; + cp->c_line = cp->c_oline = mpxline; + fp->f_flag |= FMPY; + fp->f_flag |= FREAD+FWRITE; + fp->f_un.f_chan = cp; + if (gp->g_inode == mpxip) { + plock(mpxip); + mpxname(cp); + msg = M_OPEN; + } else + msg = M_WATCH; + scontrol(cp, msg, u.u_uid); + sleep((caddr_t)cp,TTIPRI); + if (cp->c_flags&NMBUF) + prele(mpxip); + if (cp->c_flags & WCLOSE) { + chdrain(cp); + chfree(cp); + goto bad; + } + cp->c_fy = fp; + cp->c_pgrp = u.u_procp->p_pgrp; +} + + +char mxnmbuf[NMSIZE]; +int nmsize; +struct chan *mxnmcp; +mpxname(cp) +register struct chan *cp; +{ +register char *np; +register c; + np = mxnmbuf; + u.u_dirp = (caddr_t)u.u_arg[0]; + + while (np < &mxnmbuf[NMSIZE]) { + c = uchar(); + if (c <= 0) + break; + *np++ = c; + } + *np++ = '\0'; + nmsize = np - mxnmbuf; + + cp->c_flags |= NMBUF; +} + + +mxclose(dev, flag, cp) +dev_t dev; +register struct chan *cp; +{ +register struct group *gp; +register struct inode *ip; +register struct file *fp; +int i, fmp; + + fmp = flag&FMP; + + /* + * close a channel + */ + if (cp!=NULL && fmp && fmp!=FMP) { + for(fp=file; fp < &file[NFILE]; fp++) + if(fp->f_count && fp->f_flag&FMP && fp->f_un.f_chan==cp){ + return; + } + chdrain(cp); + if ((cp->c_flags&WCLOSE)==0) { + scontrol(cp, M_CLOSE, 0); + cp->c_flags |= WCLOSE; + } else { + chfree(cp); + } + return; + } + + if ((gp = getmpx(dev)) == NULL) + return; + ip = gp->g_inode; + if (ip==NULL || (ip->i_mode&IFMT)!=IFMPC) { + return; + } + + for(fp=file; fp < &file[NFILE]; fp++) { + if (fp->f_count && (fp->f_flag&FMP)==FMP && fp->f_inode==ip) { + return; + } + } + + if (ip == mpxip) { + mpxip = NULL; + prele(ip); + } + + for(i=0;ig_chans[i])!=NULL) + detach(cp); + + groups[minor(dev)] = NULL; + plock(ip); + i = ip->i_mode; + i &= ~IFMT; + i |= IFCHR; + ip->i_mode = i; + zero((caddr_t)gp, sizeof (struct group)); + ip->i_flag |= IUPD|ICHG; + iput(ip); +} + +zero(s, cc) +register char *s; +register cc; +{ + while (cc--) + *s++ = 0; +} + +char m_eot[] ={ M_EOT, 0, 0, 0}; + +/* + * Mxread + mxwrite are entered from cdevsw + * for all read/write calls. Operations on + * an mpx file are handled here. + * Calls are made through linesw to handle actual + * data movement. + */ +mxread(dev) +{ +register struct group *gp; +register struct chan *cp; +register esc; +struct rh h; +caddr_t base; +unsigned count; +int s, xfr, more, fmp; + + if ((gp=getmpx(dev))==NULL) { +bad: + u.u_error = ENXIO; + return; + } + FP = getf(u.u_arg[0]); + fmp = FP->f_flag & FMP; + if (fmp != FMP) { + msread(fmp, FP->f_un.f_chan); + return; + } + + if ((int)u.u_base & 1) + goto bad; + s = spl6(); + while (gp->g_datq == 0) { + + sleep((caddr_t)&gp->g_datq, TTIPRI); + } + + while (gp->g_datq && u.u_count >= CNTLSIZ + 2) { + splx(s); + esc = 0; + cp = nextcp(gp); + if (cp==NULL) { + continue; + } + h.index = cpx(cp); + if (count = cp->c_ctlx.c_cc) { + count += CNTLSIZ; + if (cp->c_flags&NMBUF) + count += nmsize; + if (count > u.u_count) { + sdata(cp); + return; + } + esc++; + } + base = u.u_base; + count = u.u_count; + u.u_base += sizeof h; + u.u_count -= sizeof h; + xfr = u.u_count; + if (esc && cp->c_flags&PORT) { + more = mcread(cp); + } else { + more = (*linesw[cp->c_line].l_read)(cp->c_ttyp); + } + if (more > 0) + sdata(cp); + if (more < 0) + scontrol(cp, M_CLOSE, 0); + if (xfr == u.u_count) { + esc++; + iomove((caddr_t)m_eot, sizeof m_eot, B_READ); + } + xfr -= u.u_count; + if (esc) { + h.count = 0; + h.ccount = xfr; + } else { + h.count = xfr; + h.ccount = 0; + mxrstrt(cp, &cp->cx.datq, BLOCK|ALT); + } + if (u.u_count && (xfr&1)) { + u.u_base++; + u.u_count--; + } + copyout((caddr_t)&h, base, sizeof h); + + s = spl6(); + } +} + + + + + +mxwrite(dev) +{ +register struct chan *cp; +struct wh h; +struct group *gp; +int ucount, esc, fmp, burpcount; +caddr_t ubase, hbase; + + if ((gp=getmpx(dev))==NULL) { + u.u_error = ENXIO; + return; + } + FP = getf(u.u_arg[0]); + fmp = FP->f_flag & FMP; + if (fmp != FMP) { + mswrite(fmp, FP->f_un.f_chan); + return; + } + burpcount = 0; + while (u.u_count >= sizeof h) { + hbase = u.u_base; + iomove((caddr_t)&h, sizeof h, B_WRITE); + if (u.u_error) + return; + esc = 0; + if (h.count==0) { + esc++; + h.count = h.ccount; + } + cp = xcp(gp, h.index); + if (cp==NULL) { + continue; + } + ucount = u.u_count; + ubase = u.u_base; + u.u_count = h.count; + u.u_base = h.data; + + if (esc==0) { + struct tty *tp; + caddr_t waddr; + int line; + + if (cp->c_flags&PORT) { + line = cp->c_line; + tp = cp->c_ttyp; + } else { + line = cp->c_oline; + tp = cp->c_ottyp; + } + loop: + waddr = (caddr_t)(*linesw[line].l_write)(tp); + if (u.u_count) { + if (gp->g_state&ENAMSG) { + burpcount++; + cp->c_flags |= BLKMSG; +/* + scontrol(cp, M_BLK, u.u_count); +*/ + h.ccount = -1; + h.count = u.u_count; + h.data = u.u_base; + copyout((caddr_t)&h, hbase, sizeof h); + } else { + if (waddr==0) { + u.u_error = ENXIO; + return; + } + sleep(waddr, TTOPRI); + goto loop; + } + } + } else + mxwcontrol(cp); + u.u_count = ucount; + u.u_base = ubase; + } + u.u_count = burpcount; +} + + + +/* + * Mcread and mcwrite move data on an mpx file. + * Transfer addr and length is controlled by mxread/mxwrite. + * Kernel-to-Kernel and other special transfers are not + * yet in. + */ +mcread(cp) +register struct chan *cp; +{ +register struct clist *q; +register char *np; + +int cc; + + q = (cp->c_ctlx.c_cc) ? &cp->c_ctlx : &cp->cx.datq; + cc = mxmove(q, B_READ); + + if (cp->c_flags&NMBUF && q == &cp->c_ctlx) { + np = mxnmbuf; + while (nmsize--) + passc(*np++); + cp->c_flags &= ~NMBUF; + prele(mpxip); + } + if (cp->c_flags&PORT) + return(cp->c_ctlx.c_cc + cp->c_ttyp->t_rawq.c_cc); else + return(cp->c_ctlx.c_cc + cp->cx.datq.c_cc); + +} + + +char * +mcwrite(cp) +register struct chan *cp; +{ +register struct clist *q; +register cc; +int s; + + q = &cp->cy.datq; + while (u.u_count) { + s = spl6(); + if (q->c_cc > HIQ || (cp->c_flags&EOTMARK)) { + cp->c_flags |= SIGBLK; + splx(s); + break; + } + splx(s); + cc = mxmove(q, B_WRITE); + } + wakeup((caddr_t)q); + return((caddr_t)q); +} + + +/* + * Msread and mswrite move bytes + * between user and non-multiplexed channel. + */ +msread(fmp, cp) +register struct chan *cp; +{ +register struct clist *q; +int s; + + q = (fmp&FMPX) ? &cp->cx.datq : &cp->cy.datq; + s = spl6(); + while (q->c_cc == 0) { + if (cp->c_flags & EOTMARK) { + cp->c_flags &= ~EOTMARK; + if (cp->c_flags&ENAMSG) + scontrol(cp, M_UBLK, 0); + else { + wakeup((caddr_t)cp); + wakeup((caddr_t)q); + } + goto out; + } + if (cp->c_flags&WCLOSE) { + u.u_error = ENXIO; + goto out; + } + sleep((caddr_t)q,TTIPRI); + } + splx(s); + while (mxmove(q, B_READ) > 0) + ; + mxrstrt(cp, q, SIGBLK); + return; +out: + splx(s); +} + + +mswrite(fmp, cp) +register struct chan *cp; +{ +register struct clist *q; +register int cc; + + q = (fmp&FMPX) ? &cp->cy.datq : &cp->cx.datq; + while (u.u_count) { + + spl6(); + if (cp->c_flags&WCLOSE) { + bad: + signal(SIGPIPE, cp->c_pgrp); + return; + } + + while (q->c_cc>100) { + if (cp->c_flags&WCLOSE) + goto bad; + sdata(cp); + cp->c_flags |= BLOCK; + sleep((caddr_t)q+1,TTOPRI); + } + spl0(); + cc = mxmove(q, B_WRITE); + if (cc < 0) + break; + } + if (fmp&FMPX) { + if (cp->c_flags&YGRP) + sdata(cp); else + wakeup((caddr_t)q); + } else { + if (cp->c_flags&XGRP) + sdata(cp); else + wakeup((caddr_t)q); + } +} + + + +/* + * move chars between clist and user space. + */ +mxmove(q, dir) +register struct clist *q; +register dir; +{ +register cc; +char buf[HIQ]; + + cc = MIN(u.u_count, sizeof buf); + if (dir == B_READ) + cc = q_to_b(q, buf, cc); + if (cc <= 0) + return(cc); + iomove((caddr_t)buf, cc, dir); + if (dir == B_WRITE) + cc = b_to_q(buf, cc, q); + return(cc); +} + + + +mxrstrt(cp, q, b) +register struct chan *cp; +register struct clist *q; +register b; +{ +int s; + + s = spl6(); + if (cp->c_flags&b && q->c_ccc_flags &= ~b; + if (b&ALT) + wakeup((caddr_t)q+1); else + mcstart(cp, (caddr_t)q); + } + if (cp->c_flags&WFLUSH) + wakeup((caddr_t)q+2); + splx(s); +} + + + +/* + * called from driver start or xint routines + * to wakeup output sleeper. + */ +mcstart(cp, q) +register struct chan *cp; +register caddr_t q; +{ + + if (cp->c_flags&(BLKMSG)) { + cp->c_flags &= ~BLKMSG; + scontrol(cp, M_UBLK, 0); + } else + wakeup((caddr_t)q); +} + + +mxwcontrol(cp) +register struct chan *cp; +{ +short cmd[2]; +int s; + + iomove((caddr_t)cmd, sizeof cmd, B_WRITE); + switch(cmd[0]) { + /* + * not ready to queue this up yet. + */ + case M_EOT: + s = spl6(); + while (cp->c_flags & EOTMARK) + if (cp->c_flags&ENAMSG) { + scontrol(cp, M_BLK, 0); + goto out; + } else + sleep((caddr_t)cp, TTOPRI); + cp->c_flags |= EOTMARK; + out: + splx(s); + break; + case M_IOCTL: +printf("M_IOCTL"); + break; + default: + u.u_error = ENXIO; + } +} + + + + + + + + +mxioctl(dev, cmd, addr, flag) +caddr_t addr; +{ +struct group *gp; +int fmp; +struct file *fp; + + if ((gp = getmpx(dev)) == NULL) { +bad: + u.u_error = ENXIO; + return; + } + + fp = getf(u.u_arg[0]); + if (fp==NULL) + goto bad; + + fmp = fp->f_flag & FMP; + + if (fmp == FMP) { + switch(cmd) { + case MXLSTN: + if (mpxip == NULL) { + mpxip = gp->g_inode; + } else + goto bad; + break; + case MXNBLK: + gp->g_state |= ENAMSG; + break; + default: + goto bad; + } + } +} + + + + +chdrain(cp) +register struct chan *cp; +{ +register struct tty *tp; +int wflag; + + chwake(cp); + + wflag = (cp->c_flags&WCLOSE)==0; + tp = cp->c_ttyp; + if (tp == NULL) /* prob not required */ + return; + if (cp->c_flags&PORT && tp->t_chan == cp) { + cp->c_ttyp = NULL; + tp->t_chan = NULL; + return; + } + if (wflag) + wflush(cp,&cp->cx.datq); else + flush(&cp->cx.datq); + if (!(cp->c_flags&YGRP)) { + flush(&cp->cy.datq); + } +} + +chwake(cp) +register struct chan *cp; +{ +register char *p; + + wakeup((caddr_t)cp); + flush(&cp->c_ctlx); + p = (char *)&cp->cx.datq; + wakeup((caddr_t)p); wakeup((caddr_t)++p); wakeup((caddr_t)++p); + p = (char *)&cp->cy.datq; + wakeup((caddr_t)p); wakeup((caddr_t)++p); wakeup((caddr_t)++p); +} + + +chfree(cp) +register struct chan *cp; +{ +register struct group *gp; +register i; + + gp = cp->c_group; + if (gp==NULL) + return; + i = cp->c_index; + if (cp == gp->g_chans[i]) { + gp->g_chans[i] = NULL; + } + cp->c_group = NULL; +} + + +flush(q) +register struct clist *q; +{ + + while(q->c_cc) + getc(q); +} + + +wflush(cp,q) +register struct chan *cp; +register struct clist *q; +{ +register s; + + s = spl6(); + while(q->c_cc) { + if (cp->c_flags & WCLOSE) { + flush(q); + goto out; + } + cp->c_flags |= WFLUSH; + sdata(cp); + sleep((caddr_t)q+2,TTOPRI); + } +out: + cp->c_flags &= ~WFLUSH; + splx(s); +} + + +scontrol(cp,event,value) +register struct chan *cp; +short event,value; +{ +register struct clist *q; +int s; + + q = &cp->c_ctlx; + s = spl6(); + if (sdata(cp) == NULL) + return; + putw(event,q); + putw(value,q); + splx(s); +} + +sdata(cp) +register struct chan *cp; +{ +register struct group *gp; +register short x; +register struct group *lgp; +int s; + + gp = cp->c_group; + if (gp==NULL) { + return(0); + } + x = cp->c_index; + + s = spl6(); + while (gp) { + if ((gp->g_state&ISGRP)==0) { + return(0); + } + gp->g_datq |= cmask[x]; + x = gp->g_index; + lgp = gp; + gp = gp->g_group; + } + gp = lgp; + splx(s); + wakeup((caddr_t)&gp->g_datq); + return((int)gp); +} + + + +struct chan * +xcp(gp, x) +register struct group *gp; +register short x; +{ +register i; + + i = 0; + while (ig_state&ISGRP) { + gp = (struct group *)gp->g_chans[x&017]; + x >>= 4; + if ((x&017) >= NINDEX) + break; + i++; + } + return((struct chan *)gp); +} + +cpx(cp) +register struct chan *cp; +{ +register x; +register struct group *gp; + + if (cp==NULL) + return(-1); + x = (-1<<4) + cp->c_index; + gp = cp->c_group; + if (gp==NULL || (gp->g_state&ISGRP)==0) + return(-1); + gp = gp->g_group; + while (gp && gp->g_state&ISGRP) { + x <<= 4; + x |= gp->g_index; + gp = gp->g_group; + } + return(x); +} + + + +struct chan * +nextcp(gp) +register struct group *gp; +{ + + if (gp->g_datq == 0) { + gp = NULL; + goto out; + } + + while (gp != NULL && gp->g_state&ISGRP) { + while ( (gp->g_datq & gp->g_rotmask) == 0) { + gp->g_rot++; + gp->g_rot &= 017; + if (gp->g_rot) + gp->g_rotmask <<= 1; else + gp->g_rotmask = 1; + } + gp = (struct group *)gp->g_chans[gp->g_rot]; + } + if (gp) + rmdata(gp); +out: + return((struct chan *)gp); +} + +rmdata(cp) +register struct chan *cp; +{ +register struct group *gp; +register short x; + + gp = cp->c_group; + x = cp->c_index; + + while (gp) { + gp->g_datq &= ~cmask[x]; + if (gp->g_datq) + return; + x = gp->g_index; + gp = gp->g_group; + } +} + + + + + +mcrint(c, tp) +struct tty *tp; +{ +} + +mcxint(tp) +struct tty *tp; +{ +} +/* +prstuff(s,cc) +register char *s; +register cc; +{ + while (cc--) + printf("%o ",*s++&0377); +} + +prascii(s, cc) +register char *s; +register cc; +{ +register c; + while (cc--) { + c = *s++; + if (c>=040 && c<=0176) + putchar(c); else + printf(" %o ", c&0377); + } +} +*/