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

📄 ut.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
	bp = dp->b_actf;	utunit = UTUNIT(bp->b_dev);	unit = UNIT(bp->b_dev);	addr = (struct utdevice *)tjdinfo[unit]->ui_addr;	sc = &tj_softc[unit];	/*	 * Record status...	 */	sc->sc_timo = INF;	sc->sc_dsreg = addr->utds;	sc->sc_erreg = addr->uter;	sc->sc_resid = MASKREG(addr->utfc);	if ((bp->b_flags&B_READ) == 0)		sc->sc_flags |= DEV_WRITTEN;	state = um->um_tab.b_state;	um->um_tab.b_state = 0;	/*	 * Check for errors...	 */	if ((addr->utds & UTDS_ERR) || (addr->utcs1 & UT_TRE)) {		/*		 * To clear the ERR bit, we must issue a drive clear		 * command, and to clear the TRE bit we must set the		 * controller clear bit.		 */		cs2 = addr->utcs2;		if ((cs1 = addr->utcs1)&UT_TRE)			addr->utcs2 |= UTCS2_CLR;		while ((addr->utcs1&UT_RDY) == 0)			;		addr->utcs1 = UT_CLEAR|UT_GO;		if (sc->sc_dsreg & UTDS_EOT) {			sc->sc_flags |= DEV_EOM;			goto opdone;		}		/*		 * If we were reading at 1600 or 6250 bpi and the error		 * was corrected, then don't consider this an error.		 */		if (sc->sc_erreg & UTER_COR && (bp->b_flags & B_READ) &&		    (addr->uttc & UTTC_DEN) != UTTC_NRZI) {			mprintf("%s: unit# %d: soft error block# %d\n",				sc->sc_device, unit, bp->b_blkno);			mprintf("utcs1=%b uter=%b utcs2=%b utds=%b\n",				cs1, UT_BITS, sc->sc_erreg,				UTER_BITS, cs2, UTCS2_BITS,				sc->sc_dsreg, UTDS_BITS);			sc->sc_erreg &= ~UTER_COR;		}		/*		 * If we were reading from a raw tape and the only error		 * was that the record was too long, then we don't		 * consider this an error.		 */		if (bp != &cutbuf[utunit] && (bp->b_flags&B_READ) &&		    (sc->sc_erreg&UTER_FCE))			sc->sc_erreg &= ~UTER_FCE;		if (sc->sc_erreg == 0)			goto ignoreerr;		/*		 * Fix up errors which occur due to backspacing		 * "over" the front of the tape.		 */		if ((sc->sc_dsreg & UTDS_BOT) && bp->b_command ==		    UT_SREV && ((sc->sc_erreg &=		    ~(UTER_NEF|UTER_FCE)) == 0))			goto opdone;		/*		 * Retry soft errors up to 8 times		 */		if ((sc->sc_erreg&UTER_HARD) == 0 && state == SIO) {			if (++um->um_tab.b_errcnt < 7) {				sc->sc_blkno++;				sc->sc_flags |= DEV_RETRY;				ubadone(um);				goto opcont;			}		}		/*		 * Hard or non-I/O errors on non-raw tape		 * cause it to close.		 */		if (sc->sc_openf > 0 && bp == &cutbuf[utunit])			sc->sc_openf = -1;		/*		 * Couldn't recover error.		 */		sc->sc_flags |= DEV_HARDERR;		mprintf("%s: unit# %d: hard error block# %d\n",			sc->sc_device, unit, bp->b_blkno);		mprintf("utcs1=%b uter=%b utcs2=%b utds=%b\n",			cs1, UT_BITS, sc->sc_erreg,			UTER_BITS, cs2, UTCS2_BITS,			sc->sc_dsreg, UTDS_BITS);		bp->b_flags |= B_ERROR;		goto opdone;	}ignoreerr:	/*	 * If we hit EOT set flag.	 */		if (sc->sc_dsreg & UTDS_EOT) {			sc->sc_flags |= DEV_EOM;		}	/*	 * If we hit a tape mark update our position.	 */	if (sc->sc_dsreg & UTDS_TM && bp->b_flags & B_READ) {		    sc->sc_category_flags |= DEV_TPMARK;		/*		 * Set blkno and nxrec		 */		if (bp == &cutbuf[utunit]) {			if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {				sc->sc_nxrec =				     bdbtofsb(bp->b_blkno) - addr->utfc;				sc->sc_blkno = sc->sc_nxrec;			} else {				sc->sc_blkno =				     bdbtofsb(bp->b_blkno) + addr->utfc;				sc->sc_nxrec = sc->sc_blkno-1;			}		} else			sc->sc_nxrec = bdbtofsb(bp->b_blkno);		/*		 * Note: if we get a tape mark on a read, the		 * frame count register will be zero, so b_resid		 * will be calculated correctly below.		 */		goto opdone;	}	/*	 * Advance tape control FSM.	 */	switch (state) {	case SIO:		/* read/write increments tape block # */		sc->sc_blkno++;		break;	case SCOM:		/* motion commands update position */		if (bp == &cutbuf[utunit])		switch (bp->b_command) {		case UT_SFORW:			sc->sc_blkno -= bp->b_repcnt;			break;		case UT_SREV:			sc->sc_blkno += bp->b_repcnt;			break;		case UT_REWOFFL:			addr->utcs1 = UT_CLEAR|UT_GO;			break;		}		break;	case SSEEK:		sc->sc_blkno = bdbtofsb(bp->b_blkno);		goto opcont;	case SERASE:		/*		 * Completed erase of the inter-record gap due to a		 * write error; now retry the write operation.		 */		um->um_tab.b_state = SERASED;		goto opcont;	case SREW:			/* clear attention bit */		addr->utcs1 = UT_CLEAR|UT_GO;		break;	default:		mprintf("bad state %d\n", state);		panic("utintr");	}opdone:	/*	 * Reset error count and remove	 * from device queue	 */	um->um_tab.b_errcnt = 0;	dp->b_actf = bp->av_forw;	sc->sc_flags |= DEV_DONE;	/*	 * For read command, frame count register contains	 * actual length of tape record.  Otherwise, it	 * holds negative residual count.	 */	if (state == SIO && um->um_cmd == UT_RCOM) {		bp->b_resid = 0;		if (bp->b_bcount > MASKREG(addr->utfc))			bp->b_resid = bp->b_bcount - MASKREG(addr->utfc);	} else		bp->b_resid = MASKREG(-addr->utfc);	ubadone(um);	iodone(bp);	/*	 * Circulate slave to end of controller queue	 * to give other slaves a chance	 */	um->um_tab.b_actf = dp->b_forw;	if (dp->b_actf) {		dp->b_forw = NULL;		if (um->um_tab.b_actf == NULL)			um->um_tab.b_actf = dp;		else			um->um_tab.b_actl->b_forw = dp;		um->um_tab.b_actl = dp;	}	if (um->um_tab.b_actf == 0)		return;opcont:	utstart(um);}/* * Watchdog timer routine. */uttimer(dev)	register int dev;{	register struct tj_softc *sc = &tj_softc[UNIT(dev)];	register int utunit = UTUNIT(dev);	register int unit = UNIT(dev);	register short x;	if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {		mprintf("%s: unit# %d: lost interrupt\n", sc->sc_device, unit);		sc->sc_timo = INF;		x = spl5();		utintr(utunit);		(void) splx(x);	}	timeout(uttimer, (caddr_t)dev, 5*hz);}/* * Raw interface for a read */utread(dev, uio)	register dev_t dev;	register struct uio *uio;{	register int utunit = UTUNIT(dev);	return (physio(utstrategy, &rutbuf[utunit], dev, B_READ,		minphys, uio));}/* * Raw interface for a write */utwrite(dev, uio)	register dev_t dev;	register struct uio *uio;{	register int utunit = UTUNIT(dev);	return (physio(utstrategy, &rutbuf[utunit], dev, B_WRITE,		minphys, uio));}utioctl(dev, cmd, data, flag)	dev_t dev;	register int cmd;	caddr_t data;	int flag;{	register struct uba_device *ui = tjdinfo[UTUNIT(dev)];	register struct tj_softc *sc = &tj_softc[UNIT(dev)];	register struct buf *bp = &cutbuf[UTUNIT(dev)];	register int callcount;	register int fcount;	struct mtop *mtop;	struct mtget *mtget;	struct devget *devget;	int unit = UNIT(dev);	/* we depend of the values and order of the MT codes here */	static utops[] = { UT_WEOF, UT_SFORWF, UT_SREVF, UT_SFORW,			   UT_SREV, UT_REW, UT_REWOFFL, UT_SENSE };	switch (cmd) {	case MTIOCTOP:				/* tape operation */		mtop = (struct mtop *)data;		switch(mtop->mt_op) {		case MTWEOF:		case MTFSF: case MTBSF:		case MTFSR: case MTBSR:			callcount = mtop->mt_count;			fcount = 1;			break;		case MTREW: case MTOFFL:			sc->sc_flags &= ~DEV_EOM;			callcount = 1;			fcount = 1;			break;		case MTNOP: case MTCACHE: case MTNOCACHE:		case MTCLX: case MTCLS: 			return(0);		case MTCSE:			sc->sc_flags |= DEV_CSE;			sc->sc_category_flags &= ~DEV_TPMARK;			return(0);		case MTENAEOT:			dis_eot_tj[unit] = 0;			return(0);		case MTDISEOT:			dis_eot_tj[unit] = DISEOT;			sc->sc_flags &= ~DEV_EOM;			return(0);			case MTFLUSH:			/*			 * Flush controller's write back cache.  Since this			 * driver can not support this functionality, return			 * ENXIO to indicate the lack of support.			 */			return (ENXIO);		default:			return (ENXIO);		}		if (callcount <= 0 || fcount <= 0)			return (EINVAL);		while (--callcount >= 0) {			utcommand(dev, utops[mtop->mt_op], fcount);			if ((bp->b_flags & B_ERROR) ||			    (sc->sc_dsreg & UTDS_BOT))				break;		}		return (geterror(bp));	case MTIOCGET:				/* tape status */		mtget = (struct mtget *)data;		mtget->mt_dsreg = sc->sc_dsreg;		mtget->mt_erreg = sc->sc_erreg;		mtget->mt_resid = sc->sc_resid;		mtget->mt_type = MT_ISUT;		break;	case DEVIOCGET: 			/* device status */		devget = (struct devget *)data;		bzero(devget,sizeof(struct devget));		devget->category = DEV_TAPE;		devget->bus = DEV_UB;		bcopy(DEV_UNKNOWN,devget->interface,		      strlen(DEV_UNKNOWN));		bcopy(sc->sc_device,devget->device,		      strlen(sc->sc_device));		devget->adpt_num = ui->ui_adpt; 	/* which adapter*/		devget->nexus_num = ui->ui_nexus;	/* which nexus	*/		devget->bus_num = ui->ui_ubanum;	/* which UBA	*/		devget->ctlr_num = ui->ui_ctlr; 	/* which interf.*/		devget->slave_num = ui->ui_slave;	/* which plug	*/		bcopy(ui->ui_driver->ud_dname,		      devget->dev_name,		      strlen(ui->ui_driver->ud_dname)); /* Ultrix "tj"	*/		devget->unit_num = unit;		/* which tj??	*/		devget->soft_count = sc->sc_softcnt;	/* soft er. cnt.*/		devget->hard_count = sc->sc_hardcnt;	/* hard er. cnt.*/		devget->stat = sc->sc_flags;		/* status	*/		devget->category_stat = sc->sc_category_flags;	/* c.st.*/		break;	default:		return (ENXIO);	}	return (0);}utreset(uban)	register int uban;{	register struct uba_ctlr *um;	register struct uba_device *ui;	register struct buf *dp;	register int ut11;	register int unit;	struct tj_softc *sc;	for (ut11 = 0; ut11 < nNUT; ut11++) {		if ((um = utminfo[ut11]) == 0 || um->um_alive == 0 ||		   um->um_ubanum != uban)			continue;		um->um_tab.b_state = 0;		um->um_tab.b_actf = um->um_tab.b_actl = 0;		if (um->um_ubinfo) {			mprintf("ut reset");			mprintf("<%d>", (um->um_ubinfo>>28)&0xf);			um->um_ubinfo = 0;		}		((struct utdevice *)(um->um_addr))->utcs1 =							 UT_CLEAR|UT_GO;		((struct utdevice *)(um->um_addr))->utcs2 |= UTCS2_CLR;		for (unit = 0; unit < nNTJ; unit++) {			if ((ui = tjdinfo[unit]) == 0 || ui->ui_mi != um ||			    ui->ui_alive == 0)				continue;			sc = &tj_softc[unit];			dp = &tjutab[unit];			dp->b_state = 0;			dp->b_forw = 0;			if (um->um_tab.b_actf == NULL)				um->um_tab.b_actf = dp;			else				um->um_tab.b_actl->b_forw = dp;			um->um_tab.b_actl = dp;			if (sc->sc_openf > 0)				sc->sc_openf = -1;		}		utstart(um);	}}/* * Do a stand-alone core dump to tape -- * from here down, routines are used only in dump context */utdump(){	register struct uba_device *ui;	register struct uba_regs *up;	register struct utdevice *addr;	register int blk;	register int num = maxfree;	register int start = 0;	int	ubatype;	if (tjdinfo[0] == 0)		return (ENXIO);	ui = PHYS(tjdinfo[0], struct uba_device *);	up = PHYS(ui->ui_hd, struct uba_hd *)->uh_physuba;	ubatype = PHYS(ui->ui_hd, struct uba_hd *)->uba_type;	ubainit(up,ubatype);	DELAY(500000);	addr = (struct utdevice *)ui->ui_physaddr;	utwait(addr);	/*	 * Be sure to set the appropriate density here.  We use	 * 6250, but maybe it should be done at 1600 to insure the	 * tape can be read by most any other tape drive available.	 */	addr->uttc = UTTC_GCR|UTTC_PDP11FMT;   /* implicit slave 0 */	addr->utcs1 = UT_CLEAR|UT_GO;	while (num > 0) {		blk = num > DBSIZE ? DBSIZE : num;		utdwrite(start, blk, addr, up);		if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))			return(EIO);		start += blk;		num -= blk;	}	uteof(addr);	uteof(addr);	utwait(addr);	if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))		return(EIO);	addr->utcs1 = UT_REW|UT_GO;	return (0);}utdwrite(dbuf, num, addr, up)	register int dbuf;	register int num;	register struct utdevice *addr;	register struct uba_regs *up;{	register struct pte *io;	register int npf;	utwait(addr);	io = up->uba_map;	npf = num + 1;	while (--npf != 0)		*(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV);	*(int *)io = 0;	addr->utwc = -((num*NBPG)>>1);	addr->utfc = -(num*NBPG);	addr->utba = 0;	addr->utcs1 = UT_WCOM|UT_GO;}utwait(addr)	register struct utdevice *addr;{	register int s;	do		s = addr->utds;	while ((s&UTDS_DRY) == 0);}uteof(addr)	register struct utdevice *addr;{	utwait(addr);	addr->utcs1 = UT_WEOF|UT_GO;}#endif

⌨️ 快捷键说明

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