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

📄 cy.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
				yc->yc_blkno++;				goto opcont;			}		} else			/*			 * Hard or non-i/o errors on non-raw tape			 * cause it to close.			 */			if ((bp->b_flags&B_RAW) == 0 &&			    yc->yc_openf > 0)				yc->yc_openf = -1;		/*		 * Couldn't recover from error.		 */		tprintf(yc->yc_tpr,		    "yc%d: hard error bn%d status=%b, %s\n", YCUNIT(bp->b_dev),		    bp->b_blkno, yc->yc_status, CYS_BITS,		    (err < NCYERROR) ? cyerror[err] : "");		bp->b_flags |= B_ERROR;		goto opdone;	} else if (cy->cy_tpb.tpcmd == CY_BRCOM) {		int reclen = htoms(cy->cy_tpb.tprec);		/*		 * If we did a buffered read, check whether the read		 * was long enough.  If we asked the controller for less		 * than the user asked for because the previous record		 * was shorter, update our notion of record size		 * and retry.  If the record is longer than the buffer,		 * bump the errcnt so the retry will use direct read.		 */		if (reclen > yc->yc_blksize && bp->b_bcount > yc->yc_blksize) {			yc->yc_blksize = reclen;			if (reclen > cy->cy_bs)				vm->um_tab.b_errcnt++;			yc->yc_blkno++;			goto opcont;		}	}	/*	 * Advance tape control FSM.	 */ignoreerr:	/*	 * If we hit a tape mark update our position.	 */	if (yc->yc_status&CYS_FM && bp->b_flags&B_READ) {		cyseteof(bp);		goto opdone;	}	switch (state) {	case SIO:		/*		 * Read/write increments tape block number.		 */		yc->yc_blkno++;		yc->yc_blks++;		if (vm->um_tab.b_errcnt || yc->yc_status & CYS_CR)			yc->yc_softerrs++;		yc->yc_blksize = htoms(cy->cy_tpb.tpcount);		dlog((LOG_ERR, "blocksize %d", yc->yc_blksize));		goto opdone;	case SCOM:		/*		 * For forward/backward space record update current position.		 */		if (bp == &ccybuf[CYUNIT(bp->b_dev)])			switch ((int)bp->b_command) {			case CY_SFORW:				yc->yc_blkno -= bp->b_repcnt;				break;			case CY_SREV:				yc->yc_blkno += bp->b_repcnt;				break;			}		goto opdone;		case SSEEK:		yc->yc_blkno = bp->b_blkno;		goto opcont;	case SERASE:		/*		 * Completed erase of the inter-record gap due to a		 * write error; now retry the write operation.		 */		vm->um_tab.b_active = SERASED;		goto opcont;	}opdone:	/*	 * Reset error count and remove from device queue.	 */	vm->um_tab.b_errcnt = 0;	dp->b_actf = bp->av_forw;	/*	 * Save resid and release resources.	 */	bp->b_resid = bp->b_bcount - htoms(cy->cy_tpb.tpcount);	if (bp != &ccybuf[cyunit])		vbadone(bp, &cy->cy_rbuf);	biodone(bp);	/*	 * Circulate slave to end of controller	 * queue to give other slaves a chance.	 */	vm->um_tab.b_actf = dp->b_forw;	if (dp->b_actf) {		dp->b_forw = NULL;		if (vm->um_tab.b_actf == NULL)			vm->um_tab.b_actf = dp;		else			vm->um_tab.b_actl->b_forw = dp;	}	if (vm->um_tab.b_actf == 0)		return;opcont:	cystart(vm);}cytimer(dev)	int dev;{	register struct yc_softc *yc = &yc_softc[YCUNIT(dev)];	int s;	if (yc->yc_openf == 0 && yc->yc_timo == INF) {		yc->yc_tact = 0;		return;	}	if (yc->yc_timo != INF && (yc->yc_timo -= 5) < 0) {		printf("yc%d: lost interrupt\n", YCUNIT(dev));		yc->yc_timo = INF;		s = spl3();		cyintr(CYUNIT(dev));		splx(s);	}	timeout(cytimer, (caddr_t)dev, 5*hz);}cyseteof(bp)	register struct buf *bp;{	register int cyunit = CYUNIT(bp->b_dev);	register struct cy_softc *cy = &cy_softc[cyunit];	register struct yc_softc *yc = &yc_softc[YCUNIT(bp->b_dev)];	if (bp == &ccybuf[cyunit]) {		if (yc->yc_blkno > bp->b_blkno) {			/* reversing */			yc->yc_nxrec = bp->b_blkno - htoms(cy->cy_tpb.tpcount);			yc->yc_blkno = yc->yc_nxrec;		} else {			yc->yc_blkno = bp->b_blkno + htoms(cy->cy_tpb.tpcount);			yc->yc_nxrec = yc->yc_blkno - 1;		}		return;	}	/* eof on read */	yc->yc_nxrec = bp->b_blkno;}/*ARGSUSED*/cyioctl(dev, cmd, data, flag)	caddr_t data;	dev_t dev;{	int ycunit = YCUNIT(dev);	register struct yc_softc *yc = &yc_softc[ycunit];	register struct buf *bp = &ccybuf[CYUNIT(dev)];	register callcount;	int fcount, op;	struct mtop *mtop;	struct mtget *mtget;	/* we depend of the values and order of the MT codes here */	static cyops[] =	{CY_WEOF,CY_FSF,CY_BSF,CY_SFORW,CY_SREV,CY_REW,CY_OFFL,CY_SENSE};	switch (cmd) {	case MTIOCTOP:	/* tape operation */		mtop = (struct mtop *)data;		switch (op = mtop->mt_op) {		case MTWEOF:			callcount = mtop->mt_count;			fcount = 1;			break;		case MTFSR: case MTBSR:			callcount = 1;			fcount = mtop->mt_count;			break;		case MTFSF: case MTBSF:			callcount = mtop->mt_count;			fcount = 1;			break;		case MTREW: case MTOFFL: case MTNOP:			callcount = 1;			fcount = 1;			break;		default:			return (ENXIO);		}		if (callcount <= 0 || fcount <= 0)			return (EINVAL);		while (--callcount >= 0) {#ifdef notdef			/*			 * Gagh, this controller is the pits...			 */			if (op == MTFSF || op == MTBSF) {				do					cycommand(dev, cyops[op], 1);				while ((bp->b_flags&B_ERROR) == 0 &&				 (yc->yc_status&(CYS_EOT|CYS_BOT|CYS_FM)) == 0);			} else#endif				cycommand(dev, cyops[op], fcount);			dlog((LOG_INFO,			    "cyioctl: status %x, b_flags %x, resid %d\n",			    yc->yc_status, bp->b_flags, bp->b_resid));			if ((bp->b_flags&B_ERROR) ||			    (yc->yc_status&(CYS_BOT|CYS_EOT)))				break;		}		bp->b_resid = callcount + 1;		/*		 * Pick up the device's error number and pass it		 * to the user; if there is an error but the number		 * is 0 set a generalized code.		 */		if ((bp->b_flags & B_ERROR) == 0)			return (0);		if (bp->b_error)			return (bp->b_error);		return (EIO);	case MTIOCGET:		cycommand(dev, CY_SENSE, 1);		mtget = (struct mtget *)data;		mtget->mt_dsreg = yc->yc_status;		mtget->mt_erreg = yc->yc_control;		mtget->mt_resid = yc->yc_resid;		mtget->mt_type = MT_ISCY;		break;	default:		return (ENXIO);	}	return (0);}/* * Poll until the controller is ready. */cywait(cp)	register struct cyccb *cp;{	register int i = 5000;	uncache(&cp->cbgate);	while (i-- > 0 && cp->cbgate == GATE_CLOSED) {		DELAY(1000);		uncache(&cp->cbgate);	}	return (i <= 0);}/* * Load a 20 bit pointer into a Tapemaster pointer. */cyldmba(reg, value)	register u_char *reg;	caddr_t value;{	register int v = (int)value;	*reg++ = v;	*reg++ = v >> 8;	*reg++ = 0;	*reg = (v&0xf0000) >> 12;}/* * Unconditionally reset all controllers to their initial state. */cyreset(vba)	int vba;{	register caddr_t addr;	register int ctlr;	for (ctlr = 0; ctlr < NCY; ctlr++)		if (cyminfo[ctlr] && cyminfo[ctlr]->um_vbanum == vba) {			addr = cyminfo[ctlr]->um_addr;			CY_RESET(addr);			if (!cyinit(ctlr, addr)) {				printf("cy%d: reset failed\n", ctlr);				cyminfo[ctlr] = NULL;			}		}}cyuncachetpb(cy)	struct cy_softc *cy;{	register long *lp = (long *)&cy->cy_tpb;	register int i;	for (i = 0; i < howmany(sizeof (struct cytpb), sizeof (long)); i++)		uncache(lp++);}/* * Dump routine. */#define	DUMPREC	(32*1024)cydump(dev)	dev_t dev;{	register struct cy_softc *cy;	register int bs, num, start;	register caddr_t addr;	int unit = CYUNIT(dev), error;	if (unit >= NCY || cyminfo[unit] == 0 ||	    (cy = &cy_softc[unit])->cy_bs == 0 || YCUNIT(dev) >= NYC)		return (ENXIO);	if (cywait(&cy->cy_ccb))		return (EFAULT);#define	phys(a)	((caddr_t)((int)(a)&~0xc0000000))	addr = phys(cyminfo[unit]->um_addr);	num = maxfree, start = NBPG*2;	while (num > 0) {		bs = num > btoc(DUMPREC) ? btoc(DUMPREC) : num;		error = cydwrite(cy, start, bs, addr);		if (error)			return (error);		start += bs, num -= bs;	}	cyweof(cy, addr);	cyweof(cy, addr);	uncache(&cy->cy_tpb);	if (cy->cy_tpb.tpstatus&CYS_ERR)		return (EIO);	cyrewind(cy, addr);	return (0);}cydwrite(cy, pf, npf, addr)	register struct cy_softc *cy;	int pf, npf;	caddr_t addr;{	cy->cy_tpb.tpcmd = CY_WCOM;	cy->cy_tpb.tpcontrol = CYCW_LOCK|CYCW_25IPS|CYCW_16BITS;	cy->cy_tpb.tpstatus = 0;	cy->cy_tpb.tpsize = htoms(npf*NBPG);	cyldmba(cy->cy_tpb.tplink, (caddr_t)0);	cyldmba(cy->cy_tpb.tpdata, (caddr_t)(pf*NBPG));	cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb);	cy->cy_ccb.cbgate = GATE_CLOSED;	CY_GO(addr);	if (cywait(&cy->cy_ccb))		return (EFAULT);	uncache(&cy->cy_tpb);	if (cy->cy_tpb.tpstatus&CYS_ERR)		return (EIO);	return (0);}cyweof(cy, addr)	register struct cy_softc *cy;	caddr_t addr;{	cy->cy_tpb.tpcmd = CY_WEOF;	cy->cy_tpb.tpcount = htoms(1);	cy->cy_ccb.cbgate = GATE_CLOSED;		CY_GO(addr);	(void) cywait(&cy->cy_ccb);}cyrewind(cy, addr)	register struct cy_softc *cy;	caddr_t addr;{	cy->cy_tpb.tpcmd = CY_REW;		cy->cy_tpb.tpcount = htoms(1);	cy->cy_ccb.cbgate = GATE_CLOSED;		CY_GO(addr);	(void) cywait(&cy->cy_ccb);}#endif

⌨️ 快捷键说明

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