Unix V6 /usr/sys/dmr/rp.c

/*
 * RP disk driver
 */
 
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
 
struct {
	int	rpds;
	int	rper;
	int	rpcs;
	int	rpwc;
	int	rpba;
	int	rpca;
	int	rpda;
};
 
#define	RPADDR	0176710
#define	NRP	8
 
struct {
	char	*nblocks;
	int	cyloff;
} rp_sizes[] {
	40600,	0,		/* cyl 0 thru 202 */
	40600,	203,		/* cyl 203 thru 405 */
	9200,	0,		/* cyl 0 thru 45 */
	9200,	360,		/* cyl 360 thru 405 */
	-1,	0,		/* cyl 0 thru 327 */
	-1,	78,		/* cyl 78 thru 405 */
	15600,	0,		/* cyl 0 thru 77 */
	15600,	328,		/* cyl 328 thru 405 */
};
 
struct	devtab	rptab;
struct	buf	rrpbuf;
 
#define	GO	01
#define	RESET	0
#define	HSEEK	014
 
#define	IENABLE	0100
#define	READY	0200
 
#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
 
rpstrategy(abp)
struct buf *abp;
{
	register struct buf *bp;
	register char *p1, *p2;
 
	bp = abp;
	if(bp->b_flags&B_PHYS)
		mapalloc(bp);
	p1 = &rp_sizes[bp->b_dev.d_minor&07];
	if (bp->b_dev.d_minor >= (NRP<<3) ||
	    bp->b_blkno >= p1->nblocks) {
		bp->b_flags =| B_ERROR;
		iodone(bp);
		return;
	}
	bp->av_forw = 0;
	bp->cylin = p1->cyloff;
	p1 = bp->b_blkno;
	p2 = lrem(p1, 10);
	p1 = ldiv(p1, 10);
	bp->trksec = (p1%20)<<8 | p2;
	bp->cylin =+ p1/20;
	spl5();
	if ((p1 = rptab.d_actf)==0)
		rptab.d_actf = bp;
	else {
		for (; p2 = p1->av_forw; p1 = p2) {
			if (p1->cylin <= bp->cylin
			 && bp->cylin <  p2->cylin
			 || p1->cylin >= bp->cylin
			 && bp->cylin >  p2->cylin)
				break;
		}
		bp->av_forw = p2;
		p1->av_forw = bp;
	}
	if (rptab.d_active==0)
		rpstart();
	spl0();
}
 
rpstart()
{
	register struct buf *bp;
 
	if ((bp = rptab.d_actf) == 0)
		return;
	rptab.d_active++;
	RPADDR->rpda = bp->trksec;
	devstart(bp, &RPADDR->rpca, bp->cylin, bp->b_dev.d_minor>>3);
}
 
rpintr()
{
	register struct buf *bp;
	register int ctr;
 
	if (rptab.d_active == 0)
		return;
	bp = rptab.d_actf;
	rptab.d_active = 0;
	if (RPADDR->rpcs < 0) {		/* error bit */
		deverror(bp, RPADDR->rper, RPADDR->rpds);
		if(RPADDR->rpds & (SUFU|SUSI|HNF)) {
			RPADDR->rpcs.lobyte = HSEEK|GO;
			ctr = 0;
			while ((RPADDR->rpds&SUSU) && --ctr);
		}
		RPADDR->rpcs = RESET|GO;
		ctr = 0;
		while ((RPADDR->rpcs&READY) == 0 && --ctr);
		if (++rptab.d_errcnt <= 10) {
			rpstart();
			return;
		}
		bp->b_flags =| B_ERROR;
	}
	rptab.d_errcnt = 0;
	rptab.d_actf = bp->av_forw;
	bp->b_resid = RPADDR->rpwc;
	iodone(bp);
	rpstart();
}
 
rpread(dev)
{
 
	if(rpphys(dev))
	physio(rpstrategy, &rrpbuf, dev, B_READ);
}
 
rpwrite(dev)
{
 
	if(rpphys(dev))
	physio(rpstrategy, &rrpbuf, dev, B_WRITE);
}
 
rpphys(dev)
{
	register c;
 
	c = lshift(u.u_offset, -9);
	c =+ ldiv(u.u_count+511, 512);
	if(c > rp_sizes[dev.d_minor & 07].nblocks) {
		u.u_error = ENXIO;
		return(0);
	}
	return(1);
}
 
unix-history/unix-v6/usr/sys/dmr/rp.c.txt · Последние изменения: 2006/07/26 07:34
 
Copyright (C) 1996-2013 Serge Vakulenko
serge@vak.ru