V7M/sys/dev/rp.c

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

/*
 * RP disk driver
 */

#include "../h/param.h"
#include "../h/systm.h"
#include "../h/buf.h"
#include "../h/dir.h"
#include "../h/conf.h"
#include "../h/user.h"

struct device {
	int	rpds;
	int	rper;
	union {
		int	w;
		char	c;
	} rpcs;
	int	rpwc;
	char	*rpba;
	int	rpca;
	int	rpda;
};

#define RPADDR ((struct device *) 0176710)
#define	NRP	2

/*	char	rp_tr	0;	*/	/* tells iostat RP03 xfer rate */

struct {
	daddr_t	nblocks;
	int	cyloff;
} rp_sizes[] = {
	9600,	0,	/* cyl   0- 47, root file system 	*/
	8000,	48,	/* cyl  48- 87, swap area		*/
	7400,	88,	/* cyl  88-124, /sys (system sources)	*/
	55000,	125,	/* cyl 125-399, /usr (users + sources)	*/
	80000,	0,	/* cyl   0-399,	users- all of RP03 pack	*/
	0,	0,
	0,	0,
	0,	0,
};

char	rp_opn;
struct	buf	rptab;
struct	buf	rrpbuf;

#define	GO	01
#define	RESET	0
#define	HSEEK	014

#define	IENABLE	0100
#define	READY	0200
#define	RCOM	4
#define	WCOM	2

#define	SUFU	01000
#define	SUSU	02000
#define	SUSI	04000
#define	HNF	010000

/*
 * Use av_back to save track+sector,
 * b_resid for cylinder.
 */

#define	trksec	av_back
#define	cylin	b_resid

/*
 * Monitoring device number
 * and iostat structure.
 */
struct	ios	rp_ios[NRP];
#define	DK_N	4
#define	DK_T	8	/* RP03 transfer rate indicator */

rpstrategy(bp)
register struct buf *bp;
{
	register struct buf *dp;
	register int unit;
	long sz;

	if(bp->b_flags&B_PHYS)
		mapalloc(bp);
	unit = minor(bp->b_dev);
	sz = bp->b_bcount;
	sz = (sz+511)>>9;
	if (unit >= (NRP<<3) ||
	   bp->b_blkno+sz >= rp_sizes[unit&07].nblocks) {
		bp->b_flags |= B_ERROR;
		iodone(bp);
		return;
	}
	bp->av_forw = NULL;
	unit >>= 3;
	if(rp_opn == 0) {
		rp_opn++;
		spl6();
		dk_iop[DK_N] = &rp_ios[0];
		dk_nd[DK_N] = NRP;
		}
	spl5();
	dp = & rptab;
	if (dp->b_actf == NULL)
		dp->b_actf = bp;
	else
		dp->b_actl->av_forw = bp;
	dp->b_actl = bp;
	if (dp->b_active == NULL)
		rpstart();
	spl0();
}

rpstart()
{
	register struct buf *bp;
	register int unit;
	int com,cn,tn,sn,dn;
	daddr_t bn;


	if ((bp = rptab.b_actf) == NULL)
		return;
	rptab.b_active++;
	unit = minor(bp->b_dev);
	dn = unit>>3;
	bn = bp->b_blkno;
	cn = bn/(20*10) + rp_sizes[unit&07].cyloff;
	sn = bn%(20*10);
	tn = sn/10;
	sn = sn%10;
	RPADDR->rpcs.w = (dn<<8);
	RPADDR->rpda = (tn<<8) | sn;
	RPADDR->rpca = cn;
	RPADDR->rpba = bp->b_un.b_addr;
	RPADDR->rpwc = -(bp->b_bcount>>1);
	com = ((bp->b_xmem&3)<<4) | IENABLE | GO;
	if (bp->b_flags & B_READ)
		com |= RCOM; else
		com |= WCOM;
	RPADDR->rpcs.w |= com;
	rp_ios[dn].dk_tr = DK_T;
	rp_ios[dn].dk_busy++;	/* drive active */
	rp_ios[dn].dk_numb++;	/* count number of xfer's */
	unit = bp->b_bcount>>6;
	rp_ios[dn].dk_wds += unit;	/* count words xfer'd */
}

rpintr()
{
	register struct buf *bp;
	register int ctr;

	if (rptab.b_active == NULL)
		return;
	bp = rptab.b_actf;
	ctr = (bp->b_dev >> 3) & 7;
	rp_ios[ctr].dk_busy = 0;	/* drive no longer active */
	rptab.b_active = NULL;
	if (RPADDR->rpcs.w < 0) {		/* error bit */
		deverror(bp, RPADDR->rper, RPADDR->rpds);
		if(RPADDR->rpds & (SUFU|SUSI|HNF)) {
			RPADDR->rpcs.c = HSEEK|GO;
			ctr = 0;
			while ((RPADDR->rpds&SUSU) && --ctr)
				;
		}
		RPADDR->rpcs.w = RESET|GO;
		ctr = 0;
		while ((RPADDR->rpcs.w&READY) == 0 && --ctr)
			;
		if (++rptab.b_errcnt <= 10) {
			rpstart();
			return;
		}
		bp->b_flags |= B_ERROR;
	}
	rptab.b_errcnt = 0;
	rptab.b_actf = bp->av_forw;
	bp->b_resid = 0;
	iodone(bp);
	rpstart();
}

rpread(dev)
{

	physio(rpstrategy, &rrpbuf, dev, B_READ);
}

rpwrite(dev)
{

	physio(rpstrategy, &rrpbuf, dev, B_WRITE);
}