SysIII/usr/src/uts/vax/io/vpmt.c

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

/*Version 2*/
#include "sys/param.h"
#include "sys/tty.h"
#include "sys/dir.h"
#include "sys/user.h"
#include "sys/buf.h"
#include "sys/file.h"
#include "sys/vpm.h"
#include "sys/vpmd.h"
#include "sys/ioctl.h"

#define BISYNC	6		/*BISYNC interpreter*/
#define VPMTS	4		/*Number of Virtual Protocol Machines*/
#define XBQMAX	2		/*Max xmit buffers in xmit queue*/
#define BUFDES	(XBQMAX + 2)*VPMTS		/*Number of buffer descriptors*/
#define BUFSIZE	512		/*Buffer size*/
#define NOARG	0		/*Null argument*/
#define VPMPRI	(PZERO+5)

/*vpm state bits*/

#define OPEN	01
#define WCLOSE	02
#define VPMERR	04
#define XOPEN	010

int vpm_cnt;

/*Buffer discriptors*/

struct vpmbd vpmbd[BUFDES];

/*Per vmp structure*/

struct vpmt {
	struct clist vt_rcvq;
	struct vpmbd *vt_rbc;
	short	vt_state;	/*Status info*/
} vpmt[VPMTS];
extern struct vpmbd *vpmdeq();
extern struct buf *getablk();
extern struct buf *geteblk();

vpmopen(dev, flag)
{
	register struct vpmt *vp;
	register int ec;
	extern struct vpmbd *vpmbget();
	extern vpmtrint();

	if (TDEV(dev) >= vpm_cnt) {
		u.u_error = ENXIO;
		return;
	}
	if (((vp = &vpmt[TDEV(dev)])->vt_state&OPEN) == 0) {
		if (ec = vpmstart(dev, BISYNC, vpmtrint)) {
			vpmsave('p', dev, ec, 0);
			u.u_error = ec;
			return;
		}
		if ((flag&FREAD) && (flag&FWRITE))
			vp->vt_state |= (XOPEN|OPEN);
		else
			vp->vt_state |= OPEN;
		vpmemptq(dev, vpmbget(dev));
		vpmemptq(dev, vpmbget(dev));
	} else {
		if ((vp->vt_state&XOPEN) || ((flag&FREAD) && (flag&FWRITE))) {
			u.u_error = EBUSY;
			return;
		}
	}
	vpmsave('o', dev, vp->vt_state, 0);
}
vpmclose(dev)
{
	struct vpmt *vp;
	struct vpmbd *bdp;

	vp = &vpmt[TDEV(dev)];
	vp->vt_state |= WCLOSE;
	vpmstop(dev);
	while(vpmdeq(&vp->vt_rcvq));
	for(bdp = &vpmbd[0];bdp < &vpmbd[BUFDES];bdp++)
		if (bdp->d_vpmtdev == TDEV(dev))
			vpmbrtn(bdp);
	vpmsave('c', dev, vp->vt_state, 0);
	vp->vt_state = 0;
	vp->vt_rbc = 0;
	if (vp->vt_state&VPMERR)
		u.u_error = EIO;
}
vpmwrite(dev)
{
	register struct vpmt *vp;
	register struct vpmbd *dp;
	register ct;

	vp = &vpmt[TDEV(dev)];
	if (vp->vt_state&VPMERR) {
		u.u_error = EIO;
		return;
	}
	while(u.u_count) {
		spl5();
		while(vpmxmtq(dev, 0) >= XBQMAX && (vp->vt_state&VPMERR) == 0)
			sleep((caddr_t)&vp->vt_state, VPMPRI);
		spl0();
		if (vp->vt_state&VPMERR) {
			u.u_error = EIO;
			return;
		}
		dp = vpmbget(dev);
		ct = min(u.u_count, BUFSIZE);
		MOVE(paddr(dp->d_buf), ct, B_WRITE);
		dp->d_ct = ct;
		vpmsave('w', dev, ct, dp);
		vpmxmtq(dev, dp);
	}
}
vpmread(dev)
{
	register struct vpmt *vp;
	register struct vpmbd *dp;
	register cnt;

	vp = &vpmt[TDEV(dev)];
	if (vp->vt_state&VPMERR) {
		u.u_error = EIO;
		return;
	}
	if (vp->vt_rbc == 0) {
		spl5();
		while((vp->vt_rbc = vpmdeq(&vp->vt_rcvq)) == 0 && (vp->vt_state&VPMERR) == 0)
			sleep((caddr_t)&vp->vt_rcvq, VPMPRI);
		spl0();
		if (vp->vt_state&VPMERR) {
			u.u_error = EIO;
			return;
		}
	}
	dp = vp->vt_rbc;
	cnt = dp->d_ct - dp->d_bos;
	cnt = min(cnt, u.u_count);
	MOVE(paddr(dp->d_buf) + dp->d_bos, cnt, B_READ);
	vpmsave('r', dev, cnt, dp->d_bos);
	if ((dp->d_bos += cnt) == (dp->d_ct)) {
		vp->vt_rbc = 0;
		dp->d_ct = BUFSIZE;
		dp->d_bos = 0;
		vpmemptq(dev, dp);
	}
}
vpmioctl(dev, cmd, arg, mode)
{
	register struct vpmt *vp;
	char cmdar[4], *cp;
	extern char *vpmrpt(), *vpmerrs();

	vp = &vpmt[TDEV(dev)];
	switch(cmd) {
	case VPMCMD:
		copyin(arg, cmdar, sizeof(cmdar));
		vpmcmd(dev, cmdar);
		return;
	case VPMERRS:
		cp = vpmerrs(dev, 8);
		copyout(cp, arg, 8);
		return;
	case VPMRPT:
		if (cp = vpmrpt(dev)) {
			copyout(cp, arg, 4);
			u.u_rval1 = 1;
		}
		return;
	default:
		u.u_error = EINVAL;
		return;
	}
}
vpmtrint(dev, type, bdp)
{
	register struct vpmt *vp;

	vp = &vpmt[TDEV(dev)];
	switch(type) {
		case RRTNXBUF:
			vpmbrtn(bdp);
			wakeup((caddr_t)&vp->vt_state);
			break;
		case RRTNRBUF:
			vpmenq(bdp, &vp->vt_rcvq);
			wakeup((caddr_t)&vp->vt_rcvq);
			break;
		case RRTNEBUF:
			vpmbrtn(bdp);
			break;
		case ERRTERM:
			vp->vt_state |= VPMERR;
			wakeup((caddr_t)&vp->vt_rcvq);
			wakeup((caddr_t)&vp->vt_state);
			break;
	}
}
struct vpmbd *
vpmbget(dev)
{

	register struct vpmbd *dp;
	paddr_t	addr;

	for(dp = &vpmbd[0];dp < &vpmbd[BUFDES];dp++)
		if (dp->d_buf == 0) {
			dp->d_buf = (struct buf *)1;
			break;
		}
	if (dp < &vpmbd[BUFDES]) {
		dp->d_buf = GETBLK;
		addr = ubmaddr(dp->d_buf, 0);
		dp->d_adres = loword(addr);
		dp->d_hbits = hiword(addr);
		dp->d_bos = 0;
		dp->d_ct = BUFSIZE;
		dp->d_vpmtdev = TDEV(dev);
		return(dp);
	}
	return(0);
}
vpmbrtn(dp)
struct vpmbd *dp;
{

	if (dp->d_buf != NULL) {
		brelse(dp->d_buf);
		dp->d_buf = NULL;
	}
}