V7/usr/sys/dev/rp.c

Find at most related files.
including files from this version of Unix.

#
/*
 * 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	8

struct {
	daddr_t	nblocks;
	int	cyloff;
} rp_sizes[] = {
	81000,	0,		/* cyl 0 thru 405 */
	5000,	0,		/* cyl 0 thru 24 */
	2000,	25,		/* cyl 25 thru 34 */
	74000,	35,		/* cyl 35 thru 405 */
	0,	0,
	0,	0,
	0,	0,
	0,	0,
};

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
 */
#define	DK_N	2

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

	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;
	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;
	dk_busy |= 1<<DK_N;
	dk_numb[DK_N] += 1;
	unit = bp->b_bcount>>6;
	dk_wds[DK_N] += unit;
}

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

	if (rptab.b_active == NULL)
		return;
	dk_busy &= ~(1<<DK_N);
	bp = rptab.b_actf;
	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);
}