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

📄 ts.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
	/*	 * Tape positioned incorrectly;	 * set to seek forwards or backwards to the correct spot.	 * This happens for raw tapes only on error retries.	 */	um->um_tab.b_active = SSEEK;	if (blkno < bdbtofsb(bp->b_blkno)) {		bp->b_command = TS_SFORW;		tc->c_repcnt = bdbtofsb(bp->b_blkno) - blkno;	} else {		bp->b_command = TS_SREV;		tc->c_repcnt = blkno - bdbtofsb(bp->b_blkno);	}dobpcmd:	/*	 * Do the command in bp.	 */	tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command;	addr->tsdb = sc->sc_uba;	return;next:	/*	 * Done with this operation due to error or	 * the fact that it doesn't do anything.	 * Release UBA resources (if any), dequeue	 * the transfer and continue processing this slave.	 */	if (um->um_ubinfo)		ubadone(um);	um->um_tab.b_errcnt = 0;	um->um_tab.b_actf->b_actf = bp->av_forw;	iodone(bp);	goto loop;}/* * The BUS resources we needed have been * allocated to us; start the device. */tsdgo(um)	register struct uba_ctlr *um;{	register struct tsdevice *addr = (struct tsdevice *)um->um_addr;	register struct ts_softc *sc = &ts_softc[um->um_ctlr];	register int i;	i = um->um_ubinfo & 0777776;	/* odd address transfer fix */	sc->sc_cmd.c_loba = i;	sc->sc_cmd.c_hiba = (i>>16)&3;	addr->tsdb = sc->sc_uba;}/* * Ts interrupt routine. */tsintr(ts11)	int ts11;{	register struct buf *bp;	register struct uba_ctlr *um = tsminfo[ts11];	register struct tsdevice *addr;	register struct ts_softc *sc;	register int state;	register int unit;	if ((bp = um->um_tab.b_actf->b_actf) == NULL)		return;	unit = UNIT(bp->b_dev);	addr = (struct tsdevice *)tsdinfo[unit]->ui_addr;	/*	 * If last command was a rewind, and tape is still	 * rewinding, wait for the rewind complete interrupt.	 */	if (um->um_tab.b_active == SREW) {		um->um_tab.b_active = SCOM;		if ((addr->tssr&TS_SSR) == 0)			return;	}	/*	 * An operation completed... record status	 */	sc = &ts_softc[unit];#ifdef mips	clean_dcache(PHYS_TO_K0(svtophy(&sc->sc_sts)), sizeof(struct ts_sts));#endif mips	if ((bp->b_flags & B_READ) == 0)		sc->sc_flags |= DEV_WRITTEN;	state = um->um_tab.b_active;	um->um_tab.b_active = 0;	/*	 * Check for errors.	 */	if (addr->tssr&TS_SC) {		switch (addr->tssr & TS_TC) {		case TS_UNREC:		/* unrecoverable */		case TS_FATAL:		/* fatal error */		case TS_ATTN:		/* attention */		case TS_RECNM:		/* recoverable, no motion */			break;		case TS_SUCC:		/* success termination */			goto ignoreerr;		case TS_ALERT:		/* tape status alert */			/*			 * If we hit the end-of-tape (EOT),			 * just return.			 */			if (sc->sc_sts.s_xs0 & TS_EOT) {				sc->sc_flags |= DEV_EOM;				goto opdone;			}			/*			 * If we hit a tapemark,			 * update our position.			 */			if (sc->sc_sts.s_xs0 & TS_TMK) {			    sc->sc_category_flags |= DEV_TPMARK;			    if (bp == &ctsbuf[unit]) {				    if (sc->sc_blkno >					bdbtofsb(bp->b_blkno)) {					/* reversing */					sc->sc_nxrec =						bdbtofsb(bp->b_blkno) -						sc->sc_sts.s_rbpcr;					sc->sc_blkno = sc->sc_nxrec;				    } else {					/* spacing forward */					sc->sc_blkno =						bdbtofsb(bp->b_blkno) +						sc->sc_sts.s_rbpcr;					sc->sc_nxrec = sc->sc_blkno - 1;				    }				    goto seteof;			    }			    /* eof on read */			    sc->sc_nxrec = bdbtofsb(bp->b_blkno);seteof:			    state = SCOM;	/* force completion */			    /*			     * Stuff bc so it will be unstuffed correctly			     * later to get resid.			     */			    sc->sc_sts.s_rbpcr = bp->b_bcount;			    goto opdone;			}			/*			 * If we were reading raw tape and the record was			 * too long or too short, then we don't consider			 * this an error.			 */			if (bp != &ctsbuf[unit] &&			    (bp->b_flags&B_READ) &&			    sc->sc_sts.s_xs0&(TS_RLS|TS_RLL)) {				sc->sc_category_flags |= DEV_SHRTREC;				goto ignoreerr;			}		case TS_RECOV:		/* recoverable, tape moved */			/*			 * If this was an i/o operation retry 8 times.			 */			if (state==SIO) {				if (++um->um_tab.b_errcnt < 7) {					/* for soft error reporting - dallas */					if(ts_softerr) {						mprintf("%s: unit#:%d soft err blk#:%d \						xs0:%b xs1:%b xs2:%b xs3:%b xs4:%b\n",						sc->sc_device, unit, bp->b_blkno,						sc->sc_sts.s_xs0, TSXS0_BITS,						sc->sc_sts.s_xs1, TSXS1_BITS,						sc->sc_sts.s_xs2, TSXS2_BITS,						sc->sc_sts.s_xs3, TSXS3_BITS,						sc->sc_sts.s_xs4, TSXS4_BITS);						}					sc->sc_softcnt++;					ubadone(um);					goto opcont;				} else					sc->sc_blkno++;			} else {				/*				 * Non-i/o errors on non-raw tape				 * cause it to close.				 */				if (sc->sc_openf>0 &&				    bp == &ctsbuf[unit])					sc->sc_openf = -1;			}			break;		case TS_REJECT: 	/* function reject */			if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE)				sc->sc_flags |= DEV_WRTLCK;			if ((sc->sc_sts.s_xs0 & TS_ONL) == 0)				sc->sc_flags |= DEV_OFFLINE;			break;		}		/*		 * Couldn't recover error		 */		sc->sc_flags |= DEV_HARDERR;		sc->sc_hardcnt++;		mprintf("%s: unit#:%d hard err blk#:%d \			xs0:%b xs1:%b xs2:%b xs3:%b xs4:%b\n",			sc->sc_device, unit, bp->b_blkno,			sc->sc_sts.s_xs0, TSXS0_BITS,			sc->sc_sts.s_xs1, TSXS1_BITS,			sc->sc_sts.s_xs2, TSXS2_BITS,			sc->sc_sts.s_xs3, TSXS3_BITS,			sc->sc_sts.s_xs4, TSXS4_BITS);		bp->b_flags |= B_ERROR;		goto opdone;	}	/*	 * Advance tape control FSM.	 */ignoreerr:	if (sc->sc_sts.s_xs0 & TS_EOT) {		sc->sc_flags |= DEV_EOM;	}	switch (state) {	case SIO:		/*		 * Read/write increments tape block number		 */		sc->sc_blkno++;		goto opdone;	case SCOM:		/*		 * For forw./back. space record update current position.		 */		if (bp == &ctsbuf[unit])		switch (bp->b_command) {		case TS_SFORW:			sc->sc_blkno += bp->b_repcnt;			break;		case TS_SREV:			sc->sc_blkno -= bp->b_repcnt;			break;		}		goto opdone;	case SSEEK:		sc->sc_blkno = bdbtofsb(bp->b_blkno);		goto opcont;	default:		panic("tsintr");	}opdone:	/*	 * Reset error count and remove	 * from device queue.	 */	sc->sc_flags |= DEV_DONE;	um->um_tab.b_errcnt = 0;	um->um_tab.b_actf->b_actf = bp->av_forw;	bp->b_resid = sc->sc_sts.s_rbpcr;	ubadone(um);/* hsieh - Due to the delay in processing large nbuf io (> 24k buffer)  * with the bufflush routine we must see if there * is anything on the queue first and then start it. * We must keep the tape streaming.  Thrashing occurs if tape * drive hit the next tape gap and we are still hanging in * the bufflush code.  The problem is seen at buffer size greater * than 24kb system.  Dallas suggested I kicked the controller * with next command before calling bufflush.	 */	if (um->um_tab.b_actf->b_actf != 0)		tsstart(um);#ifdef mips	if(cpu != DS_5800 && (bp->b_flags & B_READ)){		bufflush(bp);	}#endif mips	iodone(bp);	return;opcont:	tsstart(um);}tsread(dev, uio)	register dev_t dev;	register struct uio *uio;{	register int unit = UNIT(dev);	return (physio(tsstrategy, &rtsbuf[unit], dev, B_READ,		minphys, uio));}tswrite(dev, uio)	register dev_t dev;	register struct uio *uio;{	register int unit = UNIT(dev);	return (physio(tsstrategy, &rtsbuf[unit], dev, B_WRITE,		minphys, uio));}tsreset(uban)	register int uban;{	register struct uba_ctlr *um;	register struct uba_device *ui;	register struct ts_softc *sc;	register struct buf *dp;	register ts11;	for (ts11 = 0; ts11 < nNTS; ts11++) {		if ((um = tsminfo[ts11]) == 0 || um->um_alive == 0 ||		   um->um_ubanum != uban)			continue;		sc = &ts_softc[ts11];		mprintf("ts reset");		um->um_tab.b_active = 0;		um->um_tab.b_actf = um->um_tab.b_actl = 0;		if (sc->sc_openf > 0)			sc->sc_openf = -1;		if (um->um_ubinfo) {			mprintf("<%d>", (um->um_ubinfo>>28)&0xf);			um->um_ubinfo = 0;		}		if ((ui = tsdinfo[ts11]) && ui->ui_mi == um &&		    ui->ui_alive) {			dp = &tsutab[ts11];			dp->b_active = 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;		}		sc->sc_mapped = 0;		/* so it won't think						 * it is still						 * allocated						 * and tsinit will remap						 * itself						 */		(void) tsinit(ts11);		tsstart(um);	}}tsioctl(dev, cmd, data, flag)	dev_t dev;	register int cmd;	caddr_t data;	int flag;{	register struct uba_device *ui = tsdinfo[UNIT(dev)];	register struct ts_softc *sc = &ts_softc[UNIT(dev)];	register struct buf *bp = &ctsbuf[UNIT(dev)];	register 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 tsops[] = { TS_WEOF, TS_SFORWF, TS_SREVF, TS_SFORW,			   TS_SREV, TS_REW, TS_OFFL, TS_SENSE };	switch (cmd) {	case MTIOCTOP:				/* tape operation */		mtop = (struct mtop *)data;		switch (mtop->mt_op) {		case MTWEOF:			callcount = mtop->mt_count;			fcount = 1;			break;		case MTFSF: case MTBSF:		case MTFSR: case MTBSR:			callcount = 1;			fcount = mtop->mt_count;			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_ts[unit] = 0;			return(0);		case MTDISEOT:			dis_eot_ts[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) {			tscommand(dev, tsops[mtop->mt_op], fcount);			if ((mtop->mt_op == MTFSR ||			    mtop->mt_op == MTBSR) &&			    bp->b_resid)				return (EIO);			if ((bp->b_flags & B_ERROR) ||			    sc->sc_sts.s_xs0 & TS_BOT)				break;		}		return (geterror(bp));	case MTIOCGET:				/* tape status */		mtget = (struct mtget *)data;		mtget->mt_dsreg = 0;		mtget->mt_erreg = sc->sc_sts.s_xs0;		mtget->mt_resid = sc->sc_resid;		mtget->mt_type = MT_ISTS;		break;	case DEVIOCGET: 			/* device status */		devget = (struct devget *)data;		bzero(devget,sizeof(struct devget));		devget->category = DEV_TAPE;		if(ui->ui_hd->uba_type & (UBAUVI|UBAUVII)) {			devget->bus = DEV_QB;		} else {			devget->bus = DEV_UB;		}		switch (devget->bus) {		case DEV_UB:			if(sc->sc_sts.s_xs2 & TS_TU80) {				bcopy(DEV_TUU80,devget->interface,				      strlen(DEV_TUU80));			} else {				if (sc->sc_sts.s_xs4 & TS_HSP) {					bcopy(DEV_TSU05,					      devget->interface,					      strlen(DEV_TSU05));				} else {					bcopy(DEV_TSU11,					      devget->interface,					      strlen(DEV_TSU11));				}			}			break;		case DEV_QB:			bcopy(DEV_TSV05,devget->interface,			      strlen(DEV_TSV05));			break;		}		bcopy(sc->sc_device,devget->device,		      strlen(sc->sc_device));		/* t[su]	*/		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 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 "ts"	*/		devget->unit_num = unit;		/* which t[su]??*/		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);}tsdump(){	register struct uba_device *ui;	register struct uba_regs *up;	register struct tsdevice *addr;	register int blk;	register int num;	register int start;	int	ubatype;	start = 0;	num = maxfree;	if (tsdinfo[0] == 0)		return (ENXIO);	ui = PHYS(tsdinfo[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(1000000);	addr = (struct tsdevice *)ui->ui_physaddr;	addr->tssr = 0;	tswait(addr);	while (num > 0) {		blk = num > DBSIZE ? DBSIZE : num;		tsdwrite(start, blk, addr, up);		start += blk;		num -= blk;	}	tseof(addr);	tseof(addr);	tswait(addr);	if (addr->tssr&TS_SC)		return (EIO);	addr->tssr = 0;	tswait(addr);	return (0);}tsdwrite(dbuf, num, addr, up)	register int dbuf;	register int num;	register struct tsdevice *addr;	struct uba_regs *up;{	register struct pte *io;	register struct ts_softc *sc = &ts_softc[0];	register int npf;	tswait(addr);	io = up->uba_map;	npf = num+1;	while (--npf != 0)		 *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) |				 UBAMR_MRV);	*(int *)io = 0;	sc->sc_cmd.c_size = -(num*NBPG);	/* byte count */	sc->sc_cmd.c_loba = 0;			/* low buffer address */	sc->sc_cmd.c_hiba = 0;			/* high buf. address */	sc->sc_cmd.c_cmd = TS_ACK | TS_CVC | TS_IE | TS_WCOM;	/* doit */}tswait(addr)	register struct tsdevice *addr;{	register volatile int s;	do		s = addr->tssr;	while ((s & TS_SSR) == 0);}tseof(addr)	register struct tsdevice *addr;{	register struct ts_softc *sc = &ts_softc[0];	tswait(addr);	sc->sc_cmd.c_cmd = TS_ACK | TS_CVC | TS_IE | TS_WEOF;	/* doit */}#endif

⌨️ 快捷键说明

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