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

📄 rl.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
{	register struct rldevice *rladdr = (struct rldevice *)um->um_addr;	rldwait(rladdr);		/* DS - Add drive ready test */	rladdr->rlba = um->um_ubinfo;	rladdr->rlcs = um->um_cmd|((um->um_ubinfo>>12)&RL_BAE);}/* * Handle a disk interrupt. */rlintr(rl21)	int rl21;{	register struct uba_ctlr *um = rlminfo[rl21];	register struct uba_device *ui;	register struct rldevice *rladdr = (struct rldevice *)um->um_addr;	register struct buf *bp, *dp;	register struct rl_softc *sc = &rl_softc[um->um_ctlr];	int unit;	struct rl_stat *st = &rl_stat[um->um_ctlr];	int as = sc->rl_softas, status;	sc->rl_wticks = 0;	sc->rl_softas = 0;	dp = um->um_tab.b_actf;	bp = dp->b_actf;	ui = rldinfo[dkunit(bp)];	dk_busy &= ~(1 << ui->ui_dk);	/*	 * Check for and process errors on	 * either the drive or the controller.	 */	if (rladdr->rlcs & RL_ERR) {		u_short err;		rlwait(rladdr);		err = rladdr->rlcs;		/* get status and reset controller */		rladdr->rlda.getstat = RL_GSTAT;		rladdr->rlcs = (ui->ui_slave << 8) | RL_GETSTAT;		rlwait(rladdr);		status = rladdr->rlmp.getstat;		/* reset drive */		rladdr->rlda.getstat = RL_RESET;		rladdr->rlcs = (ui->ui_slave <<8) | RL_GETSTAT; /* Get status*/		rlwait(rladdr);		if ((status & RLMP_WL) == RLMP_WL) {			/*			 * Give up on write protected devices			 * immediately.			 */			bp->b_flags |= B_ERROR;			sc->sc_flags[ui->ui_unit] |= DEV_WRTLCK;		} else if (++um->um_tab.b_errcnt > 10) {			/*			 * After 10 retries give up.			 */			harderr(bp, "rl");			sc->sc_hardcnt[ui->ui_unit]++;			sc->sc_flags[ui->ui_unit] |= DEV_HARDERR;			mprintf("%s: unit#:%d hard err blk#:%d cs:%b mp:%b\n",			    sc->sc_device[ui->ui_unit], ui->ui_unit,			    bp->b_blkno, err, RLCS_BITS, status, RLER_BITS);			bp->b_flags |= B_ERROR;		} else {			sc->sc_softcnt[ui->ui_unit]++;			sc->sc_flags[ui->ui_unit] |= DEV_SOFTERR;			um->um_tab.b_active = 0;	 /* force retry */		}		/* determine disk position */		rladdr->rlcs = (ui->ui_slave << 8) | RL_RHDR;		rlwait(rladdr);		/* save disk drive position */		st->rl_cyl[ui->ui_slave] =		    (rladdr->rlmp.readhdr & 0177700) >> 6;	}	/*	 * If still ``active'', then don't need any more retries.	 */	if (um->um_tab.b_active) {		/* RL02 check if more data from previous request */		if ((bp->b_flags & B_ERROR) == 0 &&		     (int)(st->rl_bleft -= st->rl_bpart) > 0) {			/*			 * The following code was modeled from the rk07			 * driver when an ECC error occured.  It has to			 * fix the bits then restart the transfer which is			 * what we have to do (restart transfer).			 */			int reg, npf, o, cmd, ubaddr, diff, head;			/* seek to next head/track */			/* increment head and/or cylinder */			st->rl_cylnhd++;			diff = (st->rl_cyl[ui->ui_slave] >> 1) -				(st->rl_cylnhd >> 1);			st->rl_cyl[ui->ui_slave] = st->rl_cylnhd;			head = st->rl_cylnhd & 1;			rlwait(rladdr);			if (diff < 0)				rladdr->rlda.seek =				    -diff << 7 | RLDA_HGH | head << 4;			else				rladdr->rlda.seek =				    diff << 7 | RLDA_LOW | head << 4;			rladdr->rlcs = (ui->ui_slave << 8) | RL_SEEK;			npf = btop( bp->b_bcount - st->rl_bleft );			reg = btop(um->um_ubinfo&0x3ffff) + npf;			o = (int)bp->b_un.b_addr & PGOFSET;			ubapurge(um);			um->um_tab.b_active++;			rlwait(rladdr);			rladdr->rlda.rw = st->rl_cylnhd << 6;			if (st->rl_bleft < (st->rl_bpart = rl02.btrak))				st->rl_bpart = st->rl_bleft;			rladdr->rlmp.rw = -(st->rl_bpart >> 1);			cmd = (bp->b_flags&B_READ ? RL_READ : RL_WRITE) |			    RL_IE | (ui->ui_slave << 8);			ubaddr = (int)ptob(reg) + o;			cmd |= ((ubaddr >> 12) & RL_BAE);			rladdr->rlba = ubaddr;			rladdr->rlcs = cmd;			/* since we clear the atten sum previously if we don't			   forget about it here we must set it back - dallas			*/			sc->rl_softas |= as;			return;		}		um->um_tab.b_active = 0;		um->um_tab.b_errcnt = 0;		dp->b_active = 0;		dp->b_errcnt = 0;		/* "b_resid" words remaining after error */		bp->b_resid = st->rl_bleft;		um->um_tab.b_actf = dp->b_forw;		dp->b_actf = bp->av_forw;		st->rl_dn = -1;		st->rl_bpart = st->rl_bleft = 0;		iodone(bp);		/*		 * If this unit has more work to do,		 * then start it up right away.		 */		if (dp->b_actf)			rlustart(ui);		as &= ~(1<<ui->ui_slave);	} else		as |= (1<<ui->ui_slave);	ubadone(um);	/* reset state info */	st->rl_dn = -1;	st->rl_cylnhd = st->rl_bpart = st->rl_bleft = 0;	/*	 * Process other units which need attention.	 * For each unit which needs attention, call	 * the unit start routine to place the slave	 * on the controller device queue.	 */	while (unit = ffs(as)) {		unit--; 	/* was 1 origin */		as &= ~(1<<unit);		rlustart(rlip[rl21][unit]);	}				/*	 * If the controller is not transferring, but	 * there are devices ready to transfer, start	 * the controller.	 */	if (um->um_tab.b_actf && um->um_tab.b_active == 0)		rlstart(um);}rldwait(rladdr)	register struct rldevice *rladdr;{	register int totaldelay = 0;	/*	 * Spin waiting for the DRDY bit to clear.  Wait a maximum of	 * 10 seconds to prevent system hangs.	 */	while (((rladdr->rlcs & RL_DRDY) == 0) && (totaldelay <= 1000)) {		totaldelay++;		DELAY(10000);	/* Wait .01 seconds - smallest allowable */	}	if ((rldebug) && ((rladdr->rlcs & RL_DRDY) == 0)) {		printf("rldwait: RL_DRDY failed to clear.\n");	}}rlwait(rladdr)	register struct rldevice *rladdr;{	register int totaldelay = 0;	/*	 * Spin waiting for the CRDY bit to clear.  Wait a maximum of	 * 10 seconds to prevent system hangs.	 */	while (((rladdr->rlcs & RL_CRDY) == 0) && (totaldelay <= 1000)) {		totaldelay++;		DELAY(10000);	/* Wait .01 seconds */	}	if ((rldebug) && ((rladdr->rlcs & RL_CRDY) == 0)) {		printf("rlwait: RL_CRDY failed to clear.\n");	}}rlread(dev, uio)	register dev_t dev;	register struct uio *uio;{	register int unit = minor(dev) >> 3;	return (physio(rlstrategy, &rrlbuf[unit], dev, B_READ, minphys, uio));}rlwrite(dev, uio)	register dev_t dev;	register struct uio *uio;{	register int unit = minor(dev) >> 3;	return (physio(rlstrategy, &rrlbuf[unit], dev, B_WRITE, minphys, uio));}/*ARGSUSED*/rlioctl(dev, cmd, data, flag)	dev_t dev;	int cmd;	caddr_t data;	int flag;{	register int unit = minor(dev) >> 3;	register struct uba_device *ui = rldinfo[unit];	register struct pt *pt = (struct pt *)data;	register struct rl_softc *sc = &rl_softc[ui->ui_ctlr];	struct dkop *dkop;	struct dkget *dkget;	struct devget *devget;	register int i;	int error;	int nbpc;	switch (cmd) {	case DKIOCHDR:	/* do header read/write */		break;	case DIOCGETPT: /* 001 get partition table info */		/*		 *	Do a structure copy into the user's data area		 */		*pt = rl_part[unit];		break;	case DIOCDGTPT: /* 002 Return the default partition table		/*		 * Get number bytes per cylinder group		 */		nbpc = rl02.nbpc;		/*		 * Get and store the default block count and offset		 */		for( i = 0; i <= 7; i++ ) {			pt->pt_part[i].pi_nblocks = rl02_sizes[i].nblocks;			pt->pt_part[i].pi_blkoff =				rl02_sizes[i].cyloff * nbpc;		}		break;	case DIOCSETPT: /* 001 set the driver partition tables */		/*		 *	Only super users can set the pack's partition		 *	table		 */		if ( !suser() )			return(EACCES);		/*	   	 * Don't mess with an offline disk.		 */		if (sc->sc_flags[ui->ui_unit] & DEV_OFFLINE)			return(EIO);		/*		 *	Before we set the new partition tables make sure		 *	that it will no corrupt any of the kernel data		 *	structures		 */		if ( ( error = ptcmp( dev, &rl_part[unit], pt ) ) != 0 )			return(error);		/*		 *	Using the user's data to set the partition table		 *	for the pack		 */		rl_part[unit] = *pt;		/*		 *	See if we need to update the superblock of the		 *	"a" partition of this disk		 */		ssblk(dev,pt);		/*		 *	Just make sure that we set the valid bit		 */		rl_part[unit].pt_valid = PT_VALID;		break;	case DKIOCDOP:				/* Disk operation */		if ( !suser() )			return(EACCES);		break;	case DKIOCGET:				/* Get disk status */		break;	case DEVIOCGET: 			/* Device status */		devget = (struct devget *)data;		bzero(devget,sizeof(struct devget));		devget->category = DEV_DISK;		/* Disk 	*/		if(ui->ui_hd->uba_type & (UBAUVI|UBAUVII)) {			devget->bus = DEV_QB;		} else {			devget->bus = DEV_UB;		}		switch (devget->bus) {		case DEV_UB:			bcopy(DEV_RLU211,devget->interface,			      strlen(DEV_RLU211));	/* RLU211	*/			break;		case DEV_QB:			bcopy(DEV_RLV211,devget->interface,			      strlen(DEV_RLV211));	/* RLV211	*/			break;		}		bcopy(sc->sc_device[ui->ui_unit],		      devget->device,		      strlen(sc->sc_device[ui->ui_unit])); /* RL02	*/		devget->adpt_num = ui->ui_adpt; 	/* which adapter*/		devget->nexus_num = ui->ui_nexus;	/* which nexus	*/		devget->bus_num = ui->ui_ubanum;	/* which UBA/QB */		devget->ctlr_num = ui->ui_ctlr; 	/* which RL211	*/		devget->slave_num = ui->ui_slave;	/* which plug	*/		bcopy(ui->ui_driver->ud_dname,		      devget->dev_name,		      strlen(ui->ui_driver->ud_dname)); /* Ultrix "rl"	*/		devget->unit_num = unit;		/* which rl??	*/		devget->soft_count = sc->sc_softcnt[ui->ui_unit];    /* soft er. cnt.*/		devget->hard_count = sc->sc_hardcnt[ui->ui_unit];    /* hard er. cnt.*/		devget->stat = sc->sc_flags[ui->ui_unit];	     /* status	     */		devget->category_stat = DEV_DISKPART;	/* which prtn.	*/		break;	default:		return (ENXIO);	}	return(0);}/* * Reset driver after UBA init. * Cancel software state of all pending transfers * and restart all units and the controller. */rlreset(uban)	int uban;{	register struct uba_ctlr *um;	register struct uba_device *ui;	register struct rldevice *rladdr;	register struct rl_stat *st;	register int rl21, unit;	for (rl21 = 0; rl21 < nNHL; rl21++) {		if ((um = rlminfo[rl21]) == 0 || um->um_ubanum != uban ||		    um->um_alive == 0)			continue;		printf(" hl%d", rl21);		rladdr = (struct rldevice *)um->um_addr;		st = &rl_stat[rl21];		um->um_tab.b_active = 0;		um->um_tab.b_actf = um->um_tab.b_actl = 0;		if (um->um_ubinfo) {			printf("<%d>", (um->um_ubinfo>>28)&0xf);			um->um_ubinfo = 0;		}		/* reset controller */		st->rl_dn = -1;		st->rl_cylnhd = 0;		st->rl_bleft = 0;		st->rl_bpart = 0;		rlwait(rladdr);		for (unit = 0; unit < nNRL; unit++) {			rladdr->rlcs = (unit << 8) | RL_GETSTAT;			rlwait(rladdr);			/* Determine disk posistion */			rladdr->rlcs = (unit << 8) | RL_RHDR;			rlwait(rladdr);			/* save disk drive posistion */			st->rl_cyl[unit] =				(rladdr->rlmp.readhdr & 0177700) >> 6;			if ((ui = rldinfo[unit]) == 0)				continue;			if (ui->ui_alive == 0 || ui->ui_mi != um)				continue;			rlutab[unit].b_active = 0;			rlustart(ui);		}		rlstart(um);	}}/* * Wake up every second and if an interrupt is pending * but nothing has happened increment a counter. * If nothing happens for 20 seconds, reset the UNIBUS * and begin anew. */rlwatch(){	register struct uba_ctlr *um;	register rl21, unit;	register struct rl_softc *sc;	timeout(rlwatch, (caddr_t)0, hz);	for (rl21 = 0; rl21 < nNHL; rl21++) {		um = rlminfo[rl21];		if (um == 0 || um->um_alive == 0)			continue;		sc = &rl_softc[rl21];		if (um->um_tab.b_active == 0) {			for (unit = 0; unit < nNRL; unit++)				if (rlutab[unit].b_active &&				    rldinfo[unit]->ui_mi == um)					goto active;			sc->rl_wticks = 0;			continue;		}active:		sc->rl_wticks++;		if (sc->rl_wticks >= 20) {			sc->rl_wticks = 0;			printf("hl%d: lost interrupt\n", rl21);			/* get rid of this - dallas			ubareset(um->um_ubanum);			*/			printf("RESETING RL\n");			rlreset(um->um_ubanum); /* and do this */		}	}}/*ARGSUSED*/rldump(dev)	dev_t dev;{	/* should do a partial dump if possible. */}rlsize(dev)	dev_t dev;{	register int unit = minor(dev) >> 3;	register struct uba_device *ui;	if (unit >= nNRL || (ui = rldinfo[unit]) == 0 || ui->ui_alive == 0)		return (-1);	/*	 *	Sanity check		001	 */	if ( rl_part[unit].pt_valid != PT_VALID )		panic("rlsize: invalid partition table ");	return (rl_part[unit].pt_part[minor(dev) & 07].pi_nblocks);	/*001*/}#endif

⌨️ 快捷键说明

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