/*
 *	SCCS id	@(#)rf.c	2.1 (Berkeley)	8/5/83
 */

#include "rf.h"
#if	NRF > 0
#include "param.h"
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/rfreg.h>

#define	NRFBLK	1024

struct	rfdevice *RFADDR;

struct	buf	rftab;
struct	buf	rrfbuf;

rfattach(addr, unit)
struct rfdevice *addr;
{
	if (unit != 0)
		return(0);
	RFADDR = addr;
	return(1);
}

rfstrategy(bp)
register struct buf *bp;
{
	if (RFADDR == (struct rfdevice * NULL)) {
		bp->b_error = ENXIO;
		goto errexit;
	}
	if (bp->b_blkno >= NRFBLK * (minor(bp->b_dev) + 1)) {
		bp->b_error = EINVAL;
errexit:
		bp->b_flags |= B_ERROR;
		iodone(bp);
		return;
	}
#ifdef	UNIBUS_MAP
	mapalloc(bp);
#endif
	bp->av_forw = (struct buf *) NULL;
	(void) _spl5();
	if (rftab.b_actf == NULL)
		rftab.b_actf = bp;
	else
		rftab.b_actl->av_forw = bp;
	rftab.b_actl = bp;
	if (rftab.b_active == NULL)
		rfstart();
	(void) _spl0();
}

rfstart()
{
	register struct rfdevice *rfaddr = RFADDR;
	register struct buf *bp;
	register com;

	if ((bp = rftab.b_actf) == (struct buf *) NULL)
		return;
	rftab.b_active++;
	rfaddr->rfdar = (short) (bp->b_blkno << 8) & 0177777;
	rfaddr->rfdae = (short) (bp->b_blkno >> 8) & 037;
	rfaddr->rfcma = bp->b_un.b_addr;
	rfaddr->rfwc = - (bp->b_bcount >> 1);
	com = (bp->b_xmem & 3) << 4;
	if (bp->b_flags & B_READ)
		com |= RF_RCOM | RF_IENABLE | RF_GO;
	else
		com |= RF_WCOM | RF_IENABLE | RF_GO;
	rfaddr->rfdcs = com;

#ifdef	RF_DKN
	dk_busy |= 1 << RF_DKN;
	dk_numb[RF_DKN]++;
	dk_wds[RF_DKN] += (bp->b_bcount) >> 6;
#endif
}

rfintr()
{
	register struct rfdevice *rfaddr = RFADDR;
	register struct buf *bp;

	if (rftab.b_active == (struct buf *) NULL)
		return;
#ifdef	RF_DKN
	dk_busy &= ~ (1 << RF_DKN);
#endif
	bp = rftab.b_actf;
	rftab.b_active = (struct buf *) NULL;
	if (rfaddr->rfdcs & RF_ERR) {
		while ((rfaddr->rfdcs & RF_RDY) == 0)
			;
		if (rfaddr->rfdcs & RF_WLO)
			/*
			 *	Give up on write locked devices
			 *	immediately.
			 */
			printf("rf%d: write locked\n", minor(bp->b_dev));
		else
			{
#ifdef	UCB_DEVERR
			harderr(bp, "rf");
			printf("cs=%b dae=%b\n", rfaddr->rfdcs,
				RF_BITS, rfaddr->rfdae, RFDAE_BITS);
#else
			deverror(bp, rfaddr->rfdcs, rfaddr->rfdae);
#endif
			rfaddr->rfdcs = RF_CTLCLR;
			if (++rftab.b_errcnt <= 10) {
				rfstart();
				return;
			}
		}
		bp->b_flags |= B_ERROR;
	}
	rftab.b_errcnt = 0;
	rftab.b_actf = bp->av_forw;
	bp->b_resid = -(rfaddr->rfwc << 1);
	iodone(bp);
	rfstart();
}

rfread(dev)
dev_t	dev;
{
	physio(rfstrategy, &rrfbuf, dev, B_READ);
}

rfwrite(dev)
dev_t	dev;
{
	physio(rfstrategy, &rrfbuf, dev, B_WRITE);
}
#endif	NRF
