#
/*
 * RF disk driver
 */

#include "../head/param.h"
#include "../head/systm.h"
#include "../head/buf.h"
#include "../head/bufx.h"
#include "../head/conf.h"
#include "../head/user.h"
#include "../head/userx.h"
#include "../head/elog.h"

struct rfregs {
	int	rfcs;
	int	rfwc;
	int	rfba;
	int	rfda;
	int	rfdae;
};

#define NRF	1
#define	NRFBLK	1024
#define	RFADDR	0177460

struct	devtab	rftab;
struct	buf	rrfbuf;

struct	iostat	rfstat[NRF];
struct	errtab	rfetab { etabinit(E_BLK,NRF,RF,rfstat) };

#define	GO	01
#define	RCOM	02
#define	WCOM	04
#define	CTLCLR	0400
#define	IENABLE	0100

/*
 * Monitoring device number
 */
#define	DK_N	0

rfopen(dev, flag)
{
	if(dev.d_minor >= NRF)
		u.u_error = ENXIO;
}

rfstrategy(abp)
struct buf *abp;
{
	register struct buf *bp;

	bp = abp;
	if(bp->b_flags&B_PHYS)
		mapalloc(bp);
	if (bp->b_blkno >= NRFBLK*(bp->b_dev.d_minor+1)) {
		if (bp->b_flags&B_READ)
			bp->b_resid = bp->b_wcount;
		else {
			bp->b_flags =| B_ERROR;
			bp->b_error = ENXIO;
		}
		iodone(bp);
		return;
	}
	bp->av_forw = 0;
	spl5();
	if (rftab.d_actf==0)
		rftab.d_actf = bp;
	else
		rftab.d_actl->av_forw = bp;
	rftab.d_actl = bp;
	if (rftab.d_active==0)
		rfstart();
	spl0();
}

rfstart()
{
	register struct buf *bp;

	if ((bp = rftab.d_actf) == 0)
		return;
	rftab.d_active++;
	rfetab.e_aunit = &rfstat[(bp->b_blkno.hibyte>>2)&07];
	rfetab.e_aunit->io_ops++;
	blkacty =| (1<<RF);
	RFADDR->rfdae = bp->b_blkno.hibyte;
	devstart(bp, &RFADDR->rfda, bp->b_blkno<<8, 0);
	dk_busy =| 1<<DK_N;
	dk_numb[DK_N] =+ 1;
	dk_wds[DK_N] =+ (-bp->b_wcount>>5) & 03777;
}

rfintr()
{
	register struct buf *bp;
	struct rfregs rfregs[0];

	if (rftab.d_active == 0)
		return;
	blkacty =& ~(1<<RF);
	dk_busy =& ~(1<<DK_N);
	bp = rftab.d_actf;
	rftab.d_active = 0;
	if (RFADDR->rfcs < 0) {		/* error bit */
/*		deverror(bp, RFADDR->rfcs, RFADDR->rfdae);  /**/
		fmtblk(&rfetab,RFADDR,sizeof(rfregs[0])/2,bp);
		RFADDR->rfcs = CTLCLR;
		if (rftab.d_errcnt < 10) {
			if(rftab.d_errcnt++ == 0)
				logerr(&rfetab,E_FIRST);
			rfstart();
			return;
		}
		bp->b_flags =| B_ERROR;
	}
	if(rfetab.e_emsg != NULL)
		logerr(&rfetab,E_RETRY);
	rftab.d_errcnt = 0;
	rftab.d_actf = bp->av_forw;
	bp->b_resid = RFADDR->rfwc;
	iodone(bp);
	rfstart();
}

rfread(dev)
{

	physio(rfstrategy, &rrfbuf, dev, B_READ, NRFBLK*(dev.d_minor+1));
}

rfwrite(dev)
{

	physio(rfstrategy, &rrfbuf, dev, B_WRITE, NRFBLK*(dev.d_minor+1));
}
