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

📄 scsi_tape.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
		 * units		*/		sc->sc_category_flags[targid] = 0;	    }	    /* 	     * to maintain tape position across closes we	     * look at the tape mark pending flag (fixed block units)	     * if so we back space across it.	    */	  	    if( sc->sc_category_flags[targid] & TPMARK_PENDING){		tzcommand(dev, SZ_P_BSPACEF, 1, 0);		sc->sc_category_flags[targid] &= ~TPMARK_PENDING;		sc->sc_category_flags[targid] &= ~DEV_TPMARK;	    }	}	sc->sc_openf[targid] = 0;}tzcommand(dev, com, count, retry)	register dev_t dev;	register int com;	register int count;	register int retry;{	int unit = UNIT(dev);	register struct buf *bp = &cszbuf[unit];	while (bp->b_flags & B_BUSY) {		if(bp->b_bcount == 0 && (bp->b_flags & B_DONE))			break;		bp->b_flags |= B_WANTED;		sleep((caddr_t)bp, PRIBIO);	}	/* Load the buffer.  The b_count field gets used to hold the command	 * count.  The b_resid field gets used to hold the command mnermonic.	 * These two fields are "known" to be "save" to use for this purpose.	 * (Most other drivers also use these fields in this way.)	 */	bp->b_flags = B_BUSY|B_READ;	bp->b_dev = dev;	bp->b_comand = com;	bp->b_bcount = count;	bp->b_blkno = 0;	bp->b_retry = retry;	tzstrategy(bp);	/*	 * In the case of rewind from close, don't wait.	 * This is the only case where count can be 0.	 */	if (count == 0)		return;	iowait(bp);	if (bp->b_flags&B_WANTED)		wakeup((caddr_t)bp);	bp->b_flags &= B_ERROR;}tzstrategy(bp)	register struct buf *bp;{	struct uba_device *ui;	register struct uba_ctlr *um;	register struct sz_softc *sc;	register struct buf *dp;	register int s;	int unit = UNIT(bp->b_dev);	int targid;	int cntlr;	ui = szdinfo[unit];	targid = ui->ui_slave;	cntlr = ui->ui_ctlr;	sc = &sz_softc[cntlr];	if ((sc->sc_flags[targid]&DEV_EOM) && !((sc->sc_flags[targid]&DEV_CSE) ||	    (dis_eot_sz[unit] & DISEOT))) {		bp->b_resid = bp->b_bcount;		bp->b_error = ENOSPC;		bp->b_flags |= B_ERROR;		biodone(bp);		return;	}	if ((bp->b_flags&B_READ) && (bp->b_flags&B_RAWASYNC) && 	    ((sc->sc_category_flags[targid]&DEV_TPMARK) ||	    (sc->sc_flags[targid]&DEV_HARDERR))) {		bp->b_error = EIO;		bp->b_flags |= B_ERROR;		biodone(bp);		return;	}	/*	 * Fixed block tapes.... If the tape mark pending	 * flag is set then set DEV_TPMARK and clear pending	 * for nbuf ..and reads (sync). 	*/	if ((bp->b_flags&B_READ) && !(bp->b_flags&B_RAWASYNC) &&	    (sc->sc_category_flags[targid] & TPMARK_PENDING)) {		sc->sc_category_flags[targid] |= DEV_TPMARK;		sc->sc_category_flags[targid] &= ~TPMARK_PENDING;		bp->b_resid = bp->b_bcount;		biodone(bp);		return;	}	bp->av_forw = NULL;	/* 	 * If SZ_NODEVICE is set, the device was opened	 * with FNDELAY, but the device didn't respond.	 * We'll try again to see if the device is here,	 * if it is not, return an error	 */	if (sc->sc_szflags[targid] & SZ_NODEVICE) {	    DEV_UGH(sc->sc_device[targid],unit,"offline");	    bp->b_resid = bp->b_bcount;	    bp->b_error = ENOSPC;	    bp->b_flags |= B_ERROR;	    biodone(bp);	    return;	}#ifdef vax	s = spl5();#endif vax#ifdef mips	s = splbio();#endif mips	dp = &szutab[unit];	if (dp->b_actf == NULL)		dp->b_actf = bp;	else		dp->b_actl->av_forw = bp;	dp->b_actl = bp;	if ((dp->b_active == 0) && (sc->sc_active == 0)) {		sc->sc_xstate[targid] = SZ_NEXT;		sc->sc_xevent[targid] = SZ_BEGIN;		sz_start(sc, targid);	}	splx(s);}tzread(dev, uio)	register dev_t dev;	register struct uio *uio;{	int unit = UNIT(dev);	return (physio(tzstrategy, &rszbuf[unit], dev, B_READ, minphys, uio));}tzwrite(dev, uio)	register dev_t dev;	register struct uio *uio;{	int unit = UNIT(dev);	return (physio(tzstrategy, &rszbuf[unit], dev, B_WRITE, minphys, uio));}tzioctl(dev, cmd, data, flag)	dev_t dev;	register int cmd;	caddr_t data;	int flag;{	register struct uba_device *ui;	register struct sz_softc *sc;	register struct uba_ctlr *um;	int unit = UNIT(dev);	int cntlr;	int targid;	register int callcount;	register int fcount;	struct mtop *mtop;	struct mtget *mtget;	struct devget *devget;	struct sz_modsns_dt *msdp;	struct scsi_devtab *sdp;	struct tape_opt_tab *todp;	/* we depend of the values and order of the MT codes here 	 * static stops[] = { SZ_WFM,SZ_P_FSPACEF,SZ_P_BSPACEF,SZ_P_FSPACER,	 *		   SZ_P_BSPACER,SZ_REWIND,SZ_P_UNLOAD,SZ_P_CACHE,	 *		   SZ_P_NOCACHE,SZ_RQSNS };	*/#define SZ_SZNOP SZ_INQ	/* we depend on the values and order of the MT codes here */	static stops[] = { SZ_WFM,SZ_P_FSPACEF,SZ_P_BSPACEF,SZ_P_FSPACER,			/* MTWEOF    MTFSF       MTBSF       MTFSR	*/			   SZ_P_BSPACER,SZ_REWIND,SZ_P_UNLOAD,SZ_SZNOP,			/* MTBSR          MTREW     MTOFFL     MTNOP	*/			   SZ_P_CACHE,SZ_P_NOCACHE,SZ_RQSNS,SZ_RQSNS,			/* MTCACHE    MTNOCACHE    MTCSE    MTCLX	*/			   SZ_RQSNS,SZ_SZNOP,SZ_SZNOP,SZ_SZNOP,SZ_SZNOP,SZ_SZNOP,			/* MTCLS  MTENAEOT MTDISEOT MTFLUSH MTGTON MTGTOFF */			   SZ_P_RETENSION};			/* MTRETEN */	ui = szdinfo[unit];	cntlr = ui->ui_ctlr;        um = szminfo[cntlr];	targid = ui->ui_slave;	sc = &sz_softc[cntlr];	sdp = (struct scsi_devtab *)sc->sc_devtab[targid];		/* 	 * get our tape option struct if available	*/	if( sdp->opt_tab){	    todp = (struct tape_opt_tab *)sdp->opt_tab;	}	PRINTD(targid, 0x2, ("tzioctl: switch cmd %x\n", cmd ) );	switch (cmd) {	case MTIOCTOP:				/* tape operation */		/* 		 * If SZ_NODEVICE is set, the device was opened		 * with FNDELAY, but the device didn't respond.		 * We'll try again to see if the device is here,		 * if it is not, return an error		 */		if (sc->sc_szflags[targid] & SZ_NODEVICE) {		    DEV_UGH(sc->sc_device[targid],unit,"offline");		    return(ENXIO);		}		mtop = (struct mtop *)data;		PRINTD(targid, 0x2, ("tzioctl: switch MTIOCTOP data %x\n",		    mtop->mt_op));		switch (mtop->mt_op) {		case MTWEOF:			callcount = 1;			if( sc->sc_category_flags[targid] & TPMARK_PENDING){			    fcount = mtop->mt_count - 1;			    sc->sc_category_flags[targid] &= ~TPMARK_PENDING;			}			else {			    fcount = mtop->mt_count;			}			break;		case MTFSF: 			callcount = 1;			if( sc->sc_category_flags[targid] & TPMARK_PENDING){			    fcount = mtop->mt_count - 1;			    if (fcount < 0 ){				fcount = 0;			    }			    if( fcount == 0){				sc->sc_category_flags[targid] &= ~TPMARK_PENDING;				sc->sc_category_flags[targid] |= DEV_TPMARK;			    }			    else {				sc->sc_category_flags[targid] &= ~TPMARK_PENDING;			    }			}			else {			    fcount = mtop->mt_count;			}			break;		case MTBSF:			callcount = 1;			if( sc->sc_category_flags[targid] & TPMARK_PENDING){			    fcount = mtop->mt_count + 1;			    sc->sc_category_flags[targid] &= ~TPMARK_PENDING;			}			else {			    fcount = mtop->mt_count;			}			break;		case MTFSR:			callcount = 1;			if( sc->sc_category_flags[targid] & TPMARK_PENDING){			    fcount = mtop->mt_count - 1;			    if (fcount < 0 ){				fcount = 0;			    }			    if( fcount == 0){				sc->sc_category_flags[targid] &= ~TPMARK_PENDING;				sc->sc_category_flags[targid] |= DEV_TPMARK;			    }							    else {				sc->sc_category_flags[targid] &= ~TPMARK_PENDING;			    }			}			else {			    fcount = mtop->mt_count;			}			break;		case MTBSR:			callcount = 1;			if( sc->sc_category_flags[targid] & TPMARK_PENDING){			    fcount = mtop->mt_count + 1;			    sc->sc_category_flags[targid] &= ~TPMARK_PENDING;			}			else {			    fcount = mtop->mt_count;			}			break;		case MTOFFL:			sc->sc_flags[targid] |= DEV_OFFLINE;			sc->sc_category_flags[targid] &= ~TPMARK_PENDING;		case MTREW:			sc->sc_flags[targid] &= ~DEV_EOM;			sc->sc_category_flags[targid] &= ~TPMARK_PENDING;			callcount = 1;			fcount = 1;			break;		case MTNOP:			return(0);		case MTCACHE:		case MTNOCACHE:			return(ENXIO);		case MTFLUSH:			return (ENXIO);		case MTCSE:			/*			 * Clear Serious Exception, used by tape utilities			 * to clean up after Nbuf I/O and end of media.			 */			sc->sc_category_flags[targid] &= ~DEV_TPMARK;			sc->sc_flags[targid] |= DEV_CSE;			return(0);		case MTCLX: case MTCLS:			return(0);		case MTENAEOT:			dis_eot_sz[unit] = 0;			return(0);		case MTDISEOT:			dis_eot_sz[unit] = DISEOT;			sc->sc_flags[targid] &= ~DEV_EOM;			return(0);		case MTRETEN:	/* RETENSION command... */			sc->sc_flags[targid] &= ~DEV_EOM;			sc->sc_category_flags[targid] &= ~TPMARK_PENDING;			callcount = 1;			fcount = 1;			break;		default:			return (ENXIO);		}		if (callcount <= 0 || fcount <= 0)			return (EINVAL);		while (--callcount >= 0) {			tzcommand(dev, stops[mtop->mt_op], fcount, 0);			if (sc->sc_c_status[targid] != SZ_GOOD) {			    if ((sc->sc_c_snskey[targid] != SZ_NOSENSE) &&                                (sc->sc_c_snskey[targid] != SZ_RECOVERR))				    return(EIO);			    if (sc->sc_category_flags[targid] & DEV_TPMARK)				    return(EIO);			}		}		return(0);	/* TODO: these are bogus values, fix and test if possible! */	case MTIOCGET:				/* tape status */		mtget = (struct mtget *)data;		mtget->mt_dsreg = sc->sc_flags[targid];  /* send cur flags */		mtget->mt_erreg = 0;		/* TODO: not correct value? */		mtget->mt_resid = sc->sc_resid[targid];		mtget->mt_type = MT_ISST;		break;	case DEVIOCGET: 			/* device status */		devget = (struct devget *)data;		bzero(devget,sizeof(struct devget));		devget->category = DEV_TAPE;#ifdef vax		devget->bus = DEV_NB;		bcopy(DEV_VS_SCSI, devget->interface, strlen(DEV_VS_SCSI));#endif vax#ifdef mips		devget->bus = DEV_SCSI;		bcopy(DEV_SCSI_GEN, devget->interface, strlen(DEV_SCSI_GEN));#endif mips		bcopy(sc->sc_device[targid], devget->device, DEV_SIZE);		devget->adpt_num = um->um_adpt;		devget->nexus_num = 0;		devget->bus_num = 0;		devget->ctlr_num = cntlr;		devget->rctlr_num = 0;		devget->slave_num = targid;		bcopy("tz", devget->dev_name, 3);		devget->unit_num = unit;		devget->soft_count = sc->sc_softcnt[targid];		devget->hard_count = sc->sc_hardcnt[targid];		devget->stat = sc->sc_flags[targid];		/* 		 * we only want the lower 4 bits at this time 		 * the rest is density which gwts filled in later 		*/		devget->category_stat = (sc->sc_category_flags[targid] & 0X0F);		/*		 * Do a mode sense to check for write locked drive.		 * First one can fail due to unit attention.		 */		tzcommand(dev, SZ_MODSNS, -1, 0);		if (sc->sc_c_status[targid] != SZ_GOOD)		    tzcommand(dev, SZ_MODSNS, -1, 0);		if (sc->sc_c_status[targid] == SZ_GOOD) {		    msdp = (struct sz_modsns_dt *)&sc->sz_dat[targid];		    if (msdp->wp) {		/* Tape is write locked. */			devget->stat |= DEV_WRTLCK;		    }		    /*		     * Setup the tape density.		     */		    if (msdp->density <= density_entrys) {			devget->category_stat |= density_table[msdp->density];		    }		    /*		     * Setup default density codes.		     */		    if (msdp->density == SCSI_DENS_DEFAULT) {			switch (sdp->devtype) {			    case TZ05:				devget->category_stat |= DEV_1600BPI;				break;			    case TZ07:				devget->category_stat |= DEV_6250BPI;				break;			    case TZ30:			    case TZK50:				devget->category_stat |= DEV_6666BPI;				break;			    case TZK10:				devget->category_stat |= DEV_16000_BPI;				break;			    case TLZ04:				devget->category_stat |= DEV_61000_BPI;				break;			    case TZK08:				devget->category_stat |= DEV_54000_BPI;				break;			    default:				if (sdp->opt_tab) {		        	    if (todp->opt_flags & SCSI_QIC) {					devget->category_stat |= DEV_10000_BPI;		        	    } else if (todp->opt_flags & SCSI_9TRK) {					devget->category_stat |= DEV_6250BPI;				    }				}				break;			} /* End 'switch (sdp->devtype)' */		    } /* End 'if (msdp->density == SCSI_DENS_DEFAULT)' */		} /* End 'if (sc->sc_c_status[targid] == SZ_GOOD)' */		break;	default:		return (ENXIO);		break;	}	return (0);}/* * * Name:		tzcomplete	-Tape completion routine * * Abstract:		This routine is called from the scsi state machine *			to perform the completion work for the current data *			transfer. * * Inputs: * * bp			Buffer pointer of command to be completed. * * Outputs: *			Only printing debug messages. * * Return Values: 	Nothing formal, b_resid is updated. * * Side Effects: *			biodone() is called to free up the current bp. *			The buffer queue is changed to free up the front entry. * */int tzcomplete( bp )    struct buf *bp;{    struct uba_device *ui;    struct sz_softc *sc;    register struct buf *dp;    int unit;    int targid;    unit = UNIT(bp->b_dev);    ui = szdinfo[unit];    sc = &sz_softc[ui->ui_ctlr];    targid = ui->ui_slave;    dp = &szutab[unit];    PRINTD( targid, 0x01, ("tzcomplete called unit %d\n", UNIT(bp->b_dev)) );    /*     * Remove the completed request from the queue     * and release the buffer.     */    /* TODO: are we absolutely sure dp is valid? */    dp->b_actf = bp->av_forw;    bp->b_resid = sc->sc_resid[targid];    PRINTD(targid, 0x5,	("tzcomplete: resid = %d\n", bp->b_resid));    biodone(bp);    sc->sc_flags[targid] |= DEV_DONE;    sc->sc_xevent[targid] = SZ_BEGIN;    sz_retries[sc->sc_unit[targid]] = 0;    /*     * The comand has ended     */    dp->b_active = 0;}#endif 

⌨️ 快捷键说明

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