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

📄 scsi_tape.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
 * * Side Effects: *			tzcommand() called. * */int tz_rcvdiag(dev)	register dev_t dev;{	register struct uba_device *ui;	register struct sz_softc *sc;	int unit = UNIT(dev);	int targid;	int i;	u_char *byteptr;	u_char minrev, actrev;	struct scsi_devtab *sdp;	ui = szdinfo[unit];	sc = &sz_softc[ui->ui_ctlr];	targid = ui->ui_slave;	sdp = (struct scsi_devtab *)sc->sc_devtab[targid];	/* zero the receive data area */	byteptr = (u_char *)&sc->sz_dat[targid];	for (i = 0; i < SZ_RECDIAG_LEN; i++)	    *byteptr++ = 0;	/*	 * TODO - TZxx:	 *	TZxx tapes may not support the RCV DIAG command.	 *	For now, we just return success. We should do the RCV	 *	DIAG command and look at the results if it succeeds.	 */	if (sdp->flags & SCSI_NODIAG) {	    sz_unit_rcvdiag[unit] = 1;	    return(SZ_SUCCESS);	}	/*	 * Try 10 times to receive diagnostic results.	 * First try after power up (or other unit attention)	 * will fail.	 */	for (i = 0; i < 10; i++) {	    tzcommand(dev, SZ_RECDIAG, 1, 0);	    if (sc->sc_c_status[targid] == SZ_GOOD)		break;	}	if (i >= 10) {	    printf("%s unit %d: receive diagnostics command failed.\n",		sc->sc_device[targid], unit);		if (sz_open_fst)		    return(SZ_NODEVICE);	}	if (sc->sz_dat[targid].dat.recdiag.ctlr_selftest != 0) {	    printf("%s unit %d: controller selftest failed.\n",		sc->sc_device[targid], unit);	    if (sz_open_fst)		return(SZ_NODEVICE);	}	if (sc->sz_dat[targid].dat.recdiag.drv_selftest != 0 ) {	    printf("%s unit %d: drive selftest failed, code = 0x%x\n",		sc->sc_device[targid], unit,		sc->sz_dat[targid].dat.recdiag.drv_selftest);	    if (sz_open_fst)		return(SZ_NODEVICE);	}	if (sc->sc_devtyp[targid] == TZK50)	    minrev = tz_tzk50_minrev;	else if (sc->sc_devtyp[targid] == TZ30)	    minrev = tz_tz30_minrev;	else	    minrev = 0;	if (minrev) {	    actrev = sc->sz_dat[targid].dat.recdiag.ctlr_fw_rev;	    if (actrev < minrev) {		printf("CAUTION: %s unit %d %s %d, should be %d or later!\n",		    sc->sc_device[targid], unit, "firmware revision is",		    actrev, minrev);	    }	}	/*	 * Clear unit_rcvdiag flag, only if everything is ok,	 * so we don't call tz_rcvdiag() on every open.	 */	sz_unit_rcvdiag[unit] = 1;	return(SZ_SUCCESS);}/* * Name:		tzclose		-Tape close routine * * Abstract:		This routine is called when the tape is closed. *			If the tape was opened for writing and actually *			written on, then write two file marks and back *			space over the second one so the tape ends up *			positioned between the two file marks. Rewind *			the tape unless it was opened for no rewind. * * Inputs: * * dev			ULTRIX major/minor device number. * flag			How opened flag (write or read). * * Outputs: *			Exclusive use open flag (sc_openf) cleared. * * Return Values:	none. * * Side Effects: *			tzcommand() called. * *//* TODO: what if - open FNDELAY then close (could rewind tape)? */tzclose(dev, flag)	register dev_t dev;	register int flag;{	register struct sz_softc *sc;	register struct uba_device *ui;	int unit = UNIT(dev);	int targid;	register int sel = SEL(dev);	struct scsi_devtab *sdp;        struct tape_opt_tab *todp;        struct tape_info *ddp;	ui = szdinfo[unit];	targid = ui->ui_slave;	sc = &sz_softc[ui->ui_ctlr];	sdp = (struct scsi_devtab *)sc->sc_devtab[targid];        /*         * get our tape option struct if available        */        if( sdp->opt_tab != NULL ){            todp = (struct tape_opt_tab *)sdp->opt_tab;            /*             * since there is no bp must do it by the dev number            */            ddp = &todp->tape_info[((minor(dev)&DENS_MASK)>>3)];        }	/* TODO: do we really need to clear this flag 3 times? */	sc->sc_flags[targid] &= ~DEV_EOM;	if (sz_unit_online[unit]) {	/* only if unit still on-line */	    if (flag == FWRITE || ((flag & FWRITE) &&	       (sc->sc_flags[targid] & DEV_WRITTEN))) {		/* TODO: may want to retry this one? */		/* TODO: need to check for errors */		/*                 * check to see if the one_fm flag is set..                 * we  write one file  mark...  This is                 * done for QIC type units.. blankchk                 * is the logical end of tape detection                */                if(sdp->opt_tab){                    if( (ddp->tape_flags & ONE_FM) == 0){                        tzcommand(dev, SZ_WFM, 2, 0);                    }		     else {                        tzcommand(dev, SZ_WFM, 1, 0);                    }                }		else{                    tzcommand(dev, SZ_WFM, 2, 0);                }		/* TODO: need to check for errors */		 if(sdp->opt_tab){                    if( (ddp->tape_flags & ONE_FM) == 0 ){                        tzcommand(dev, SZ_P_BSPACEF, 1, 0);                    }                }                else{                    tzcommand(dev, SZ_P_BSPACEF, 1, 0);                }		sc->sc_flags[targid] &= ~DEV_EOM;	    }	    /* if we need to rewind... */	    if ( (sel & NO_REWIND) == 0 ) {		/* no error check, because we don't wait for completion */		tzcommand(dev, SZ_REWIND, 0, 0);		/* 		 * must clear out the tpmark_pending flag for fixed		 * units.		*/	       sc->sc_category_flags[targid] = 0; 			    }	    /*	     * to maintain tape position across closes we look at the 	     * at the tape mark pending (fixed block unit) 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;}/* * * Name:		tzcommand	-Tape command rountine * * Abstract:		This routine is called to execute non data transfer *			commands (test unit ready, rewind, etc.). It *			sets up the command in cszbuf and calls tzstrategy *			to queue the command. * * Inputs: * * dev			ULTRIX major/minor device number. * com			SCSI command type (see scsivar.h). * count		Count argument to some commands. * retry		If 1, retry command if it fails. * * Outputs: *			B_ERROR can be set in bp->b_flags. * * Return Values:	None. * * Side Effects: *			iowait() on all commands except rewind. *			sleep() called. *			tzstrategy() called. * */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;}/* * Name:		tzstrategy	-Tape strategy routine * * Abstract:		This routine is called to queue a command for *			execution. The routine validates the command *			parameters then places it on the I/O queue *			of the specified unit. sz_start() is called *			if there is not activity. * * Inputs: * * bp			Buffer pointer of command to be queued. * * Outputs: *			Possible error messages (unit offline). * * Return Values:	None. * * bp->b_error: * ENOSPC		Reached end of media. * EIO			Cancel nbufio commands after end of file. * * Side Effects: *			IPL raised to 15 to queue buffer. * */tzstrategy(bp)	register struct buf *bp;{	register struct uba_ctlr *um;	register struct buf *dp;	register int s;	int unit = UNIT(bp->b_dev);	int targid;	int cntlr;	register struct sz_softc *sc;	struct uba_device *ui;	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 ..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;	}	s = spl5();	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);}/* * * Name:		tzread		-Tape physio read routine * * Abstract:		This routine is called to for RAW I/O reads. *			Calls physio() with appropriate arguments. * * Inputs: * * dev			ULTRIX major/minor device number. * uio			Pointer to user I/O (uio) structure. * * Outputs:		None. * * Return Values: *			Returns value returned by physio(). * * Side Effects: *			physio() and tzstrategy() called. *			minphys() limits maximum transfer size. * */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));				}/* * * Name:		tzwrite		-Tape physio write routine * * Abstract:		This routine is called to for RAW I/O writes. *			Calls physio() with appropriate arguments. * * Inputs: * * dev			ULTRIX major/minor device number. * uio			Pointer to user I/O (uio) structure. * * Outputs:		None. * * Return Values: *			Returns value returned by physio(). * * Side Effects:

⌨️ 快捷键说明

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