⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rl.c

📁 unix v7是最后一个广泛发布的研究型UNIX版本
💻 C
字号:
/* * RL disk driver * Reworked to handle RL01/RL02 *	R.A.Mason	Oct.1980 * Intended to eventually handle overlapped seeks */#include "../h/param.h"#include "../h/buf.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/systm.h"#define DK_N	1struct device {	int rlcs;	int rlba;	int rlda;	int rlmp;};#define	RLADDR	((struct device *)0174400)#define	NPDISK	4#define	NLDISK	1	/* no subdivision into logical disks */#define RLCYLSZ		10240#define RLSECSZ		256#define RL01SIZE	10240#define RL02SIZE	20480/* rlcs bits */#define DRDY		0000001#define GETSTAT		0000004#define SEEK		0000006#define RDHDR		0000010#define WCOM		0000012#define RCOM		0000014#define IENABLE		0000100#define CRDY		0000200#define DS		0001400#define OPI		0002000#define CRC		0004000#define DLT		0010000#define NXM		0020000#define DE		0040000#define ERROR		0100000#define ACCESS_ERROR	(NXM|DLT|CRC|OPI)/* rlda bits	- during seek */#define SEEKLO		0000001#define SEEKHI		0000005/*		- during get status */#define GS		0000002#define RST		0000010#define RESET		(RST|GS|01)#define STAT		(GS|01)/* status bits */#define HO		0000020#define DT		0000200#define VC		0001000#define WL		0020000struct	buf	rltab;struct	buf	rrlbuf;struct rl{	int	status;		/* drive status */	int	headp;		/* location of heads */	struct buf *iop;	/* current transfer on drive */	int	errcnt;		/* error count on drive	*/	int	com;		/* read or write command word */	int	chn;		/* cylinder and head number */	unsigned int	bleft;	/* bytes left to be transferred */	unsigned int	bpart;	/* number of bytes transferred */	int	sn;		/* sector number */	union {		int	w[2];		long	l;	} addr;			/* address of memory for transfer */} rl[NPDISK];/* Bit sets for drive status */#define RL01		01#define RL02		02#define HEADKNOWN	010rlopen(dev,rw)dev_t dev;{	register struct rl *rlp;	register struct device *rp;	int drive,status;	drive = minor(dev);	if(drive >= NPDISK) {		u.u_error = ENXIO;		return;	}	rlp = &rl[drive];	rp = RLADDR;	spl5();	while((rp->rlcs & CRDY) == 0);	rp->rlda = STAT;	rp->rlcs = (drive << 8) | GETSTAT;	while((rp->rlcs & CRDY) == 0);	status = rp->rlmp;	rp->rlda = RESET;	rp->rlcs = (drive << 8) | GETSTAT;	while((rp->rlcs & CRDY) == 0);	spl0();	if((status&HO) == 0) {		u.u_error = ENXIO;		return;	}	if(rw && (status&WL)) {		u.u_error = EROFS;		return;	}	if(status&DT)		rlp->status |= RL02;	else		rlp->status |= RL01;}rlclose(dev)dev_t dev;{	register struct rl *rlp;	rlp = &rl[minor(dev)];	/* will do something on next rework */}rlstrategy(bp)register struct buf *bp;{	register struct rl *rlp;	int drive,dsize;#ifdef UNIBMAP	if(bp->b_flags&B_PHYS)		mapalloc(bp);#endif UNIBMAP	drive = minor(bp->b_dev);	rlp = &rl[drive];	dsize = 0;	if(rlp->status&RL01)		dsize = RL01SIZE;	else	if(rlp->status&RL02)		dsize = RL02SIZE;	if(bp->b_blkno >= dsize) {		if((bp->b_blkno == dsize) && (bp->b_flags&B_READ))			bp->b_resid = bp->b_bcount;		else {			bp->b_flags |= B_ERROR;			bp->b_error = ENXIO;		}		iodone(bp);		return;	}	bp->av_forw = NULL;	spl5();	if(rltab.b_actf == NULL)		rltab.b_actf = bp;	else		rltab.b_actl->av_forw = bp;	rltab.b_actl = bp;	if(rltab.b_active == NULL)		rlstart();	spl0();}rlstart(){	register struct buf *bp;	register struct rl *rlp;	int drive;	if((bp = rltab.b_actf) == NULL)		return;	rltab.b_active++;	drive = minor(bp->b_dev);	rlp = &rl[drive];	rlp->iop = bp;	rlp->chn = bp->b_blkno/20;	rlp->sn = (bp->b_blkno%20) << 1;	rlp->bleft = bp->b_bcount;	rlp->addr.w[0] = bp->b_xmem & 3;	rlp->addr.w[1] = (int)bp->b_un.b_addr;	rlp->com = (drive << 8) | IENABLE;	if(bp->b_flags & B_READ)		rlp->com |= RCOM;	else		rlp->com |= WCOM;	rlio(drive);}rlintr(){	register struct buf *bp;	register struct device *rp;	register struct rl *rlp;	int drive,status;	rp = RLADDR;	drive = (rp->rlcs&DS) >> 8;	rlp = &rl[drive];	if(rlp->iop == NULL) {/*		logstray(rp); */		return;	}	bp = rlp->iop;#ifdef INSTRM	dk_busy &= ~(1<<DK_N);#endif INSTRM	if(rp->rlcs&ERROR) {		if(rp->rlcs&ACCESS_ERROR) {			if(rlp->errcnt > 2)				deverror(bp, rp->rlcs, rp->rlda);		}		if(rp->rlcs&DE) {			rp->rlda = STAT;			rp->rlcs = (drive << 8) | GETSTAT;			while((rp->rlcs & CRDY) == 0);			status = rp->rlmp;			if(rlp->errcnt > 2)				deverror(bp, status, rp->rlda);			rp->rlda = RESET;			rp->rlcs = (drive << 8) | GETSTAT;			while((rp->rlcs & CRDY) == 0);			if(status&DT)		/* drive type */				rlp->status |= RL02;			else				rlp->status |= RL01;			if(status&VC) {		/* volume check */				rlstart();				return;			}		}		if(++rlp->errcnt <= 10) {			rlp->status &= ~HEADKNOWN;			rlstart();			return;		}		else {			bp->b_flags |= B_ERROR;			rlp->bpart = rlp->bleft;		}	}	if((rlp->bleft -= rlp->bpart) > 0) {		rlp->addr.l += rlp->bpart;		rlp->sn = 0;		rlp->chn++;		rlio(drive);		return;	}	rlp->iop = NULL;	rlp->errcnt = 0;	rltab.b_active = NULL;	rltab.b_actf = bp->av_forw;	bp->b_resid = 0;	iodone(bp);	rlstart();}rlio(dn)int dn;{	register struct device *rp;	register struct rl *rlp;	int dif,head;	rp = RLADDR;	rlp = &rl[dn];#ifdef INSTRM	dk_busy |= 1<<DK_N;	dk_numb[DK_N] += 1;	dk_wds[DK_N] += (rlp->bpart>>6);#endif INSTRM	if((rlp->status&HEADKNOWN) == 0) {		rp->rlcs = (dn << 8) | RDHDR;		while((rp->rlcs&CRDY) == 0);		rlp->headp = ((unsigned)(rp->rlmp&0177700)) >> 6;		rlp->status |= HEADKNOWN;	}	dif = (rlp->headp >> 1) - (rlp->chn >>1);	head = (rlp->chn & 1) << 4;	if(dif < 0)		rp->rlda = (-dif<<7) | SEEKHI | head;	else		rp->rlda = (dif<< 7) | SEEKLO | head;	rp->rlcs = (dn << 8) | SEEK;	rlp->headp = rlp->chn;	if(rlp->bleft < (rlp->bpart = RLCYLSZ - (rlp->sn * RLSECSZ)))		rlp->bpart = rlp->bleft;	while((rp->rlcs&CRDY) == 0);	rp->rlda = (rlp->chn << 6) | rlp->sn;	rp->rlba = rlp->addr.w[1];	rp->rlmp = -(rlp->bpart >> 1);	rp->rlcs = rlp->com | rlp->addr.w[0] << 4;}rlread(dev){	physio(rlstrategy, &rrlbuf, dev, B_READ);}rlwrite(dev){	physio(rlstrategy, &rrlbuf, dev, B_WRITE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -