static char rcsid[] = "$Header: hcm.c,v 820.1 86/12/04 19:55:31 root Exp $";
static char sccsid[]="@(#)hcm.c	1.7 (Valid) Release 7.25 3/20/85";

/************************************************************************
*									*
*				Copyright 1984				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"		/* added to get new def'ns. (NEEDED?) */
#include "../h/buf.h"		/* added to get new def'ns. (NEEDED?) */
#include "../h/conf.h"		/* added to get 'cdevsw' def'n.  MDH 850304 */
#include "../h/proc.h"		/* added to get new def'ns. (NEEDED?) */
#include "../h/errno.h"
#include "../h/file.h"
#include "../h/uio.h"
#include "../h/user.h"		/* added to get new def'ns. (NEEDED?) */
#include "../s32dev/circbuf.h"
#include "../s32dev/useful.h"	/* added to get new def'ns. */
#define NBD 1		/* Here don't care about exact dimension 	*/
#include "../s32dev/vpb.h"	/* added to get 'bdt' def'n. MDH 850304 */


/* This driver enforces serial, exlusive use of (portions of) vgHardCopyMem.
/* Before release 7.25, there was only one buffer, so plotting and vgb screen
/* saving were mutually exclusive.  The buffer also serves as the lock for
/* V-80 printing, although print data is sent through PIB buffer chains.
/* In release 7.25 the buffer was divided into 5 sections, so that plotting
/* and vgb screen save on four screens (for full-screen windowing or generation
/* of vgb-rasterized spooled plotfiles) could all happen simultaneously.
/*
/*	850503	mdh	Added additional flags in upper byte of cb2fwa.
/*			VGB sets MSB while writing.  Clear when done.
/*			Because of this, cb2fwa must now be anded with 0xFF always.
/*
/*	850516	mdh	Several changes to fix various VG hang problems.
/*			Also cleaned-up 0503 stuff, added VGHANDSHAKE ifdef's.
/*	850529	mdh	Removed VGHANDSHAKE and associated code.
*/


#define NHCM 5
struct hcm {
	caddr_t mba;		/* multibus address */
	u_short len;		/* length in bytes */
	char busy;		/* CPU use: FREAD/FWRITE flags */
} hcm[NHCM] = {/*  fe0: leave 0x20 bytes for possible 8086 stack */
	{(caddr_t) 0x0000,0x7fe0,0},		/* PIB reads plot data from here */
	{(caddr_t) 0x8000,0x1fe0,0}, {(caddr_t) 0xa000,0x1fe0,0},
	{(caddr_t) 0xc000,0x1fe0,0}, {(caddr_t) 0xe000,0x1fe0,0},	/* VGB[0-3] */
};

extern int vgHardCopyMem;
extern int pagemask;

hcminit()
{
	register int k;
	register struct hcm *hcmp;
	if (vgHardCopyMem) for (hcmp=hcm,k=NHCM; --k>=0; ++hcmp) {
		register union cb2 *cbp;
		hcmp->mba+=vgHardCopyMem;
		cbp=(union cb2 *)iosetmap(hcmp->mba);
		/* constant (8) below is "sizeof(cb2.ptrs)" from "circbuf.h" */
		cbp->cb2fwa = cbp->cb2in = cbp->cb2out = 8;
		cbp->cb2lwa=hcmp->len;
		iounsetmap(hcmp->mba);
	}
}

hcmwait(mba)
{
	wakeup(mba);
}

/* So we can check the Versatek status, we force the dev numbers here */
#define	VPLOTMAJDEV	14		/* major dev number forced */
#define	VPLOTMNRDEV	12		/* minor dev number forced */
#define	BP		(&(((struct bdt*)cdevsw[VPLOTMAJDEV].d_ttys)->b[0]))

union cb2 *		/* Returns 0 if device error. MDH-850228 */
hcmpause(hcmp,ticks,pri,flag)	/* map is UNSET on an error exit! */
register struct hcm *hcmp;
{
	iounsetmap(hcmp->mba);
	timeout(hcmwait,hcmp->mba,ticks); sleep(hcmp->mba,pri);
	if (hcmp == hcm)  {	/* if is Versatek, check for error */
		register struct bdata *bp= BP;
		if (pibstat(VPLOTMNRDEV, bp, flag))  return(0);
		}
	return((union cb2 *)iosetmap(hcmp->mba));
}

hcmflush(hcmp, flag)		/* Now returns possible error.  MDH-850228 */
register struct hcm *hcmp;
{
	register union cb2 *cbp;
	register struct bdata *bp= BP;
	register int	to_cnt= 120;	/* number of times to try flush */
	/* if is vplot device, check PIB status first */
	if ( (hcmp == hcm)  &&  pibstat(VPLOTMNRDEV, bp, flag) )
		return(EIO);
	cbp=(union cb2 *)iosetmap(hcmp->mba);
	while ( (cbp->cb2in!=cbp->cb2out)  &&  --to_cnt )
		if (0 == (cbp=hcmpause(hcmp,HZ,PZERO,flag)) )
			return(EIO);
	iounsetmap(hcmp->mba);
	return((to_cnt)? 0 : EIO);
}

#define	WATCHTIME	(3*HZ)		/* watchdog timer length */

hcmwatchdog(mba)	/* watchdog timer to avoid locking on buffer when
caddr_t mba;		 * Versatek device is dead.   MDH 850304  */	
{		
	register struct bdata *bp= BP;
	if (pibstat(VPLOTMNRDEV, bp, ~0))  {	/* clear buffer on error */
		register union cb2 *cbp;
		cbp=(union cb2 *)iosetmap(mba);
		cbp->cb2out = cbp->cb2in;
		iounsetmap(mba);
	}
	/* No matter what happened above, reset the watchdog timer */
	timeout(hcmwatchdog, mba, WATCHTIME);
}
		


/* device numbering:
/*	0	/dev/vghcm	old screen save/restore
/*	[1-4]	/dev/vgdpy[0-3]	new per-screen save/restore
/*	12	/dev/vplot	graphic output for V-80
/*	28	/dev/vprint	lineprinter output for V-80
*/
static char devmap[32]={
	 0, 1, 2, 3, 4,-1,-1,-1,
	-1,-1,-1,-1, 0,-1,-1,-1,
	-1,-1,-1,-1,-1,-1,-1,-1,
	-1,-1,-1,-1, 0,-1,-1,-1,
};

hcmopen(dev,flag)
{
	register struct hcm *hcmp;
	register union cb2 *cbp;
	if (flag==0) panic("hcmopen flag==0");
	if (flag&FREAD && flag&FWRITE) return(ENODEV); /* one-way at a time */
	dev=minor(dev); hcmp=hcm+devmap[dev];
	if (dev>0x1f || devmap[dev]<0) return(ENODEV);
	if (hcmp->busy) return(EBUSY);
	hcmp->busy|=flag;
	cbp=(union cb2 *)iosetmap(hcmp->mba);
	cbp->cb2out=cbp->cb2in;
	iounsetmap(hcmp->mba);
	/* if is open of plot device for writing, start watchdog timer */
	if ( (flag&FWRITE)  &&  (dev == VPLOTMNRDEV) )
		timeout(hcmwatchdog, hcmp->mba, WATCHTIME);
	return(0);
}

#define VERSPRINT 28
#define IBMPRINT VERSPRINT

hcmclose(dev,flag)
{
	register struct hcm *hcmp;
	register int error=0;
	hcmp=hcm+devmap[minor(dev)];
	if (flag&FWRITE && minor(dev)!=IBMPRINT) {/* terminate */
		struct iovec iov;
		struct uio uio;
		iov.iov_base="\300";  /* 0xc0 magic cookie */
		iov.iov_len=1;
		uio.uio_iov= &iov;
		uio.uio_iovcnt=1;
		uio.uio_offset=0;
		uio.uio_segflg=1;  /* kernel address for "\300" */
		uio.uio_resid=1;
		if  (hcmflush(hcmp, 0))  {	/* throw away data if error */
			register union cb2 *cbp;
			cbp=(union cb2 *)iosetmap(hcmp->mba);
			cbp->cb2out = cbp->cb2in;
			iounsetmap(hcmp->mba);
			error = EIO;
		}
		else  hcmwrite(dev,&uio);
	}
	if ( (flag&FWRITE)  &&  (minor(dev) == VPLOTMNRDEV) )  {
		register struct bdata *bp= BP;
		untimeout(hcmwatchdog, hcmp->mba);	/* remove watchdog (ALL timers!) */
		(void) pibstat(VPLOTMNRDEV, bp, 0);	/* assure that status is clear */
	}
	hcmp->busy=0;
	return(error);
}


hcmread(dev,uio)
register struct uio *uio;
{
	register struct hcm *hcmp;
	register union cb2 *cbp;
	int error=0;

	dev=minor(dev); hcmp=hcm+devmap[dev];
	cbp=(union cb2 *)iosetmap(hcmp->mba);
	while (uio->uio_resid>0) {
		char buf[256];
		register int n,o,j;
		o=cbp->cb2out;
		if (0==(n=cbp->cb2in-o))  {	/* empty buffer */
			if (0 == (cbp=hcmpause(hcmp,HZ/4,PZERO+1,~0)) )  {
				error = EIO;
				cbp=(union cb2 *)iosetmap(hcmp->mba);
				break;
			}
		}
		if (0==(n=cbp->cb2in-o))  /* still empty */
			break;  /* in any event, we're done */
		if (n<0) n=cbp->cb2lwa-o; /* out>in, wraparound */
		iounsetmap(hcmp->mba);
		j=1+(o|pagemask)-o; /* bytes to page boundary */
		if (n>j) n=j;
		if (n>uio->uio_resid) n=uio->uio_resid;
		if (n>sizeof(buf)) n=sizeof(buf);
		bcopy((caddr_t)iosetmap(hcmp->mba+o),buf,n);
		iounsetmap(hcmp->mba+o);
		error=uiomove(buf,n,UIO_READ,uio);
		cbp=(union cb2 *)iosetmap(hcmp->mba);
		if (error) break;
		o+=n; if (o==cbp->cb2lwa) o=cbp->cb2fwa;
		cbp->cb2out=o;
	}
	iounsetmap(hcmp->mba);
	return(error);
}

hcmwrite(dev,uio)
register struct uio *uio;
{
	register struct hcm *hcmp;
	register union cb2 *cbp;
	int error=0;
	dev=minor(dev); hcmp=hcm+devmap[dev];
	cbp=(union cb2 *)iosetmap(hcmp->mba);
	while (uio->uio_resid>0) {
		char buf[256];
		register int n,i,j;
		i=cbp->cb2in;
		for (;;) {
			j=cbp->cb2out-1; /* must not fill last byte */
			if (i>j) j+=cbp->cb2lwa - (cbp->cb2fwa); /* wraparound */
			if (i!=j) break; /* there is some room */
			if (0 == (cbp=hcmpause(hcmp,HZ,PZERO+1,~0)) )
				return(EIO);
		}
		if (j>cbp->cb2lwa) j=cbp->cb2lwa;
		iounsetmap(hcmp->mba);
		n=1+(i|pagemask); /* next higher page boundary */
		if (j>n) j=n;
		n=j-i;
		if (n>uio->uio_resid) n=uio->uio_resid;
		if (n>sizeof(buf)) n=sizeof(buf);
		error=uiomove(buf,n,UIO_WRITE,uio);
		if (error) {cbp=(union cb2 *)iosetmap(hcmp->mba); break;}
		bcopy(buf,(caddr_t)iosetmap(hcmp->mba+i),n);
		iounsetmap(hcmp->mba+i);
		cbp=(union cb2 *)iosetmap(hcmp->mba);
		i+=n; if(i==cbp->cb2lwa) i=cbp->cb2fwa;
		cbp->cb2in=i;
	}
	iounsetmap(hcmp->mba);
	return(error);
}

hcmioctl(dev,cmd,addr,flag)
{
}
