32V/usr/src/slowsys/sys/mx2.c

Compare this file to the similar file:
Show the results in this format:

#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"
#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();

int	chzero;
short	cmask[16]	={
	01,	02,	04,
	010,	020,	040,
	0100,	0200,	0400,
	01000,	02000,	04000,
	010000,	020000,	040000, 0100000
};

char mcdebugs[NDEBUGS];
mxopen(dev,flag)
{
register struct group *gp;
register struct file *fp;
register struct chan *cp;
int d;

struct inode *ip;
	d = minor(dev);
	if (d>=NGROUPS) {
	bad:
		u.u_error = ENXIO;
		printf("bad mxopen\n");
		return;
	}
	gp = groups[d];
	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))==NULL)
		goto bad;
	cp->c_flags = XGRP;
	cp->c_ottyp = cp->c_ittyp = (struct tty *)cp;
	cp->c_iline = cp->c_oline = mpxline;
	fp->f_flag |= FMPY;
	fp->f_flag |= FREAD+FWRITE;
	fp->f_un.f_chan = cp;
	cp->c_pgrp = u.u_procp->p_pgrp;
#ifdef CTRACE
	printf("open pgrp %d\n",cp->c_pgrp);
#endif
	scontrol(cp, M_WATCH+(cp->c_index<<8), u.u_uid);
	sleep((caddr_t)cp,TTIPRI);
	if (cp->c_flags & WCLOSE) {
		printf("WCLOSE on %o\n",cp);
		chfree(cp,0);
		goto bad;
	}
	cp->c_fy = fp;
}


mxclose(dev,cp)
dev_t	dev;
struct chan *cp;
{
register i;
register struct group *gp;
register struct inode *ip;

	gp = groups[minor(dev)];
	ip = gp->g_inode;
	if (ip==NULL) {
		if (cp==NULL || (int)cp==FWRITE)
		printf("bad close gp %o gpi %o ip %o ipg %o\n",
			gp,gp->g_inode,ip,ip->i_un.i_group);
		if (cp==NULL)
			return;
	}
	if (cp!=NULL && (int)cp!=FWRITE) {
		i = cp->c_index;
		if (!cp->c_flags&WCLOSE) {
			chfree(cp,1);
			scontrol(cp, M_CLOSE, 0);
printf("x1 close\n");
		} else {
			chfree(cp,0);
#ifdef CTRACE
			printf("WC close\n");
#endif
		}
		gp->g_chans[i] = NULL;
		cp->c_pgrp = 0;
		cp->c_group = NULL;
		cp->c_flags |= WCLOSE;
		return;
	}
	if ((ip->i_mode&IFMT)!=IFMPC) {
		printf("close on inode %o\n",ip);
		return;
	}
	for(i=0;i<NINDEX;i++) {
		if ((cp=gp->g_chans[i])!=NULL) {
			if (cp->c_flags&ISGRP) {
				((struct group *)cp)->g_state &= ~ISGRP;
				((struct group *)cp)->g_group = NULL;
				continue;
			}
			cp->c_flags |= WCLOSE;
			wakeup((caddr_t)cp);
			signal(cp->c_pgrp,SIGHUP);
			chfree(cp,0);
			if (gp->g_chans[i])
				printf("chfree didn't clear inode\n");
		}
	}
	gp->g_state = NULL;
	groups[minor(dev)] = NULL;
	i = ip->i_mode;
	i &= ~IFMT;
	i |= IFCHR;
	ip->i_mode = i;
	ip->i_flag |= IUPD|ICHG;
	iput(ip);
}


mxread(dev)
{
register struct group *gp;
struct clist *q;
struct chan *cp;
register i;
struct file *fp;
struct header h;
caddr_t	base;
unsigned count;
int	s,xfr,more;
int esc;

	i = minor(dev);
	if (i>=NGROUPS) {
		u.u_error = ENXIO;
		return;
	}
	gp = groups[i];
	fp = getf(u.u_arg[0]);
	if ((fp->f_flag&FMP)!=FMP) {
		msread(fp,gp);
		return;
	}

	s = spl6();
	while (gp->g_datq == 0) {

		sleep((caddr_t)&gp->g_datq, TTIPRI);
	}

	while (gp->g_datq && u.u_count >= CNTLSIZ) {
		splx(s);
		esc = 0;
		cp = nextcp(gp);
		if (cp==NULL) {
			continue;
		}
		if (cp->c_ctlx.c_cc)
			esc = 2;
		base = u.u_base;
		count = u.u_count;
		u.u_base += HDRSIZE + esc;
		u.u_count -= HDRSIZE + esc;
		xfr = u.u_count;
		more = (*linesw[cp->c_iline].l_read)(cp->c_ittyp);
		if (esc || more > 0) {
			sdata(cp);
		}
		if (more<0) {
printf("m<0\n");
printf("x2 close\n");
			scontrol(cp, M_CLOSE, 0);
		}
		xfr -= u.u_count;
		if (xfr==0) {
			u.u_base = base;
			u.u_count = count;
			chzero++;
			continue;
		}
		h.index = cpx(cp);
		if (esc) {
			h.count = 0;
			h.ccount = xfr;
		} else
			h.count = xfr;
		if (xfr&1) {
			u.u_base++;
			u.u_count--;
		}
		copyout(&h, base, HDRSIZE+esc);

		q = &cp->cx.datq;
		if (cp->c_flags&BLOCK && esc==0) {
			if (q->c_cc<25) {
				wakeup((caddr_t)q+1);
				cp->c_flags &= ~BLOCK;
			} else {
			}
		}
		if (cp->c_flags&WFLUSH)
			wakeup((caddr_t)q+2);
		s = spl6();
	}
}


mcread(cp)
register struct chan *cp;
{
register struct clist *q;
register c;


	if (cp->c_ctlx.c_cc)
		q = &cp->c_ctlx; else
		q = &cp->cx.datq;

	while( (c=getc(q)) >= 0) {
		passc(c);
	}
	return(q->c_cc);

}

msread(fp, gp)
struct file *fp;
struct group *gp;
{
register struct clist *q;
register struct chan *cp;
register i;

	cp = fp->f_un.f_chan;
	q = (fp->f_flag&FMPX) ? &cp->cx.datq : &cp->cy.datq;
	i = spl6();
	if (!q->c_cc) {
		if (cp->c_flags&WCLOSE) {
			printf("ms sees it %o\n",cp);
			u.u_error = ENXIO;
			return;
		}
		sleep((caddr_t)q,TTIPRI);
	}
	splx(i);
	i = 0;
	while(u.u_count && q->c_cc) {
		passc(getc(q));
		i++;
	}
	if (cp->c_flags&SIGBLK && q->c_cc < 20) {
		cp->c_flags &= ~SIGBLK;
		if (cp->c_flags&ENAMSG) 
			scontrol(cp, M_UBLK, 0); else
			wakeup((caddr_t)q);
	}
	if (cp->c_flags&WFLUSH)
		wakeup((caddr_t)q+2);
}


mxwrite(dev)
{
register i;
register struct chan *cp;
struct	header h;
struct file *fp;
struct group *gp;
int	ucount;
caddr_t	ubase;

	i = minor(dev);
	if (i>=NGROUPS) {
		u.u_error = ENXIO;
		return;
	}
	gp = groups[i];
	fp = getf(u.u_arg[0]);
	if ((fp->f_flag&FMP)!=FMP) {
		ucount = mswrite(fp,gp);
		return;
	}
	while (u.u_count) {
		iomove(&h, sizeof(struct header), B_WRITE);
/*
		if (count==0) {
			esc++;
			h.count = h.ccount;
		}
*/
		cp = xcp(gp, h.index);
		if (cp==NULL)  {
printf("nullo %o %o\n",cp,chans);
			u.u_count -= h.count;
			u.u_base += h.count;
			continue;
		}
		ucount = u.u_count;
		ubase = u.u_base;
		u.u_count = h.count;
		u.u_base = h.addr;
		(*linesw[cp->c_oline].l_write)(cp->c_ottyp);
		u.u_count = ucount;
		u.u_base = ubase;
	}
}


mcwrite(cp)
register struct chan *cp;
{
register struct clist *q;
register c;
int	s;

	q = &cp->cy.datq;

	while ((c=cpass())>=0) {
		s = spl6();
		while (q->c_cc > 100) {
			cp->c_flags |= SIGBLK;
			splx(s);
			if (cp->c_flags&ENAMSG) {
				scontrol(cp, M_BLK, (short)u.u_count);
				wakeup((caddr_t)q);
				while (cpass()>=0);
				return;
			} else
				sleep((caddr_t)q, TTOPRI);

		}
		splx(s);
		putc(c, q);
	}
	wakeup((caddr_t)q);
}


mcttwrite(tp,cc)
register struct tty *tp;
register cc;
{
register c;
struct chan *cp;

	if ((tp->t_state&CARR_ON)==0)
		return;
	while (cc && (c=cpass())>=0) {
		spl5();
		if (tp->t_outq.c_cc > 10) {
			ttstart(tp);
			spl0();
			cp = tp->t_chan;
			cp->c_flags |= SIGBLK;
			scontrol(cp, M_BLK, cc);
			while (cc-- && cpass()>=0);
			return;
		}
		spl0();
		ttyoutput(c,tp);
		cc--;
	}
	ttstart(tp);
}
mcttstart(tp)
struct tty *tp;
{
register struct chan *cp;

	cp = tp->t_chan;
	if (cp->c_flags&(BLKMSG+ENAMSG)) {
		cp->c_flags &= ~BLKMSG;
		scontrol(cp, M_UBLK, 0);
	}
}
mswrite(fp,gp)
struct file *fp;
struct group *gp;
{
register struct clist *q;
struct chan *cp;
register c;
int cc;

	cp = fp->f_un.f_chan;
	q = (fp->f_flag&FMPX) ? &cp->cy.datq : &cp->cx.datq;
	cc = 0;
	while((c=cpass())>=0) {
		spl6();
		if (cp->c_flags&WCLOSE) {
		bad:
			u.u_error = ENXIO;
			printf("ms write sees it %o\n",cp);
			return(cc);
		}
		while (q->c_cc>100) {
			if (cp->c_flags&WCLOSE)
				goto bad;
			sdata(cp);
/*
			if (q->c_cc) {
				printf("choops\n");
				sdata(cp);
				printf("sent\n");
			}
*/
			cc = 0;
			cp->c_flags |= BLOCK;
			sleep((caddr_t)q+1,TTOPRI);
		}
		spl0();
		if (putc(c,q)>=0)
			cc++; else
			printf("qe\n");
	}
	if (fp->f_flag&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);
	}
	return(cc);
}



mxioctl(dev, cmd, addr, flag)
caddr_t addr;
{
/*
	u.u_error = ENOTTY;
*/
}




chfree(cp, flag)
register struct chan *cp;
{
register struct tty *tp;
struct group *gp;
struct inode *ip;

	if (chclear(cp))
		goto out;
	tp = cp->c_ittyp;
	if (tp->t_chan == cp) {
		cp->c_ittyp = NULL;
		tp->t_chan = NULL;
		if (flag && cp->c_iline==0)
			wflushtty(tp); else
			flushtty(tp);
	}
	if (flag) 
		wflush(cp,&cp->cx.datq); else
		flush(&cp->cx.datq);
	if (!(cp->c_flags&YGRP)) {
		flush(&cp->cy.datq);
	}
	cp->c_flags = NULL;
out:
	if (!flag) {
		gp = cp->c_group;
		cp->c_group = NULL;
		ip = gp->g_inode;
		if (ip==NULL || (ip->i_mode&IFMT)!=IFMPC) {
			printf("chfree on %o\n",ip);
			return;
		}
		gp->g_chans[cp->c_index] = NULL;
	}
}

chclear(cp)
register struct chan *cp;
{
register char *p;

#ifdef CTRACE
register struct file *fp;
	fp = cp->c_fy;
	if (fp) {
		printf(" count %d on cp %o\n",fp->f_count,cp);
	}
#endif
	p = (char *)&cp->cx.datq;
	wakeup(p); wakeup(++p); wakeup(++p);
	p = (char *)&cp->cy.datq;
	wakeup(p); wakeup(++p); wakeup(++p);
	return(0);
}



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();
	putw(event,q);
	putw(value,q);
	splx(s);
	sdata(cp);
}

sdata(cp)
register struct chan *cp;
{
register struct group *gp;
register short x;
register struct group *lgp;
int s;

	gp = cp->c_group;
	x = cp->c_index;

	s = spl6();
	while (gp) {
		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);
}



struct chan *
xcp(gp, x)
register struct group *gp;
register short x;
{
register i;

	i = 0;
	while (i<NLEVELS && gp->g_state&ISGRP) {
		gp = (struct group *)gp->g_chans[x&017];
		x >>= 4;
	}
	return((struct chan *)gp);
}

cpx(cp)
register struct chan *cp;
{
register x;
register struct group *gp;

	x = cp->c_index;
	gp = cp->c_group;
	gp = gp->g_group;
	while (gp) {
		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);
}