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

📄 scsi_tape.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic  char    *sccsid = "@(#)scsi_tape.c	4.6  (ULTRIX)        1/22/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1988 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any	other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or	reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//************************************************************************ * * scsi_tape.c	06/27/89 * * PVAX/FIREFOX/PMAX SCSI device driver (tape routines) * * Modification history: * *  08-Jan-91	Robin Miller *	Modified DEVIOCGET ioctl() code to properly return tape density *	codes.  To resolve this problem, the density_table[] was defined *	to decode the mode sense density code, and additional code was *	added to return default density codes. * *  15-Nov-90	Robin Miller *	Removed clearing of the DEV_TPMARK flag in tzstrategy() for nbuf *	I/O requests (B_RAWASYNC).  This caused a race condition with code *	in the SCSI state machine with outstanding read requests.  This *	problem caused the queued reads to read past the tape file mark. * *  21-Sept-90	Bill Dallas *	Fixed 2 problems with the devget ioctl. *	Problem one caused a panic if someone made a minor *	number by hand (aka mknod) which was out side the *	controllers range. The second problem was minor, *	we never gave back to the user the lower 4 bits *	of the devget.category_stat field. * * 07-Sept-90	Maria Vella *	Added support for new console turbo-channel ROMs. * *  30-Jul-90	Bill Dallas    *	Added fixed block tape units tape mark handling. *	This included a new falg in sc_category_flags called *	TPMARK_PENDING * * 20-May-90	Bill Dallas *	Added the option table support and for semi tape drives.. *	IE. qic format units no end of file marks... Use blankchk *	detection if the ONE_FM flag is set in the option  *	table. * * 06-Dec-89    Mitch McConnell *	Added test for sc_attached to sc_alive in tzopen, return  *	ENXIO if not. * * 19-Oct-89    Janet L. Schank / John A. Gallant *      Added an immediate exit from the retry loop on SZ_NOTREADY *      if the FNDELAY flag is set in the open routine.  Changed the *      refrence of nNSCSI to nNSCSIBUS. *  * 01-Oct-89	Fred Canter *	Bug fix. Tapes were not reporting write locked status via the *	devioget ioctl. * * 09/22/89     Janet L. Schank *      Changed some defines and ifdefs to include and use sii.h. *      Removed alot of "ifdef vax"'s.  The softc structure is now *      used in the same way as on the vax.  The scsiaddr is now taken *      from the softc structure. * * 24-Jul-89	Fred Canter *	Bug fix for dump (MT CACHE ioctls not supported by SCSI). * * 16-Jul-89	Fred Canter *	Changed meaning of count field for MODSNS tzcommand/rzcommand. * * 15-Jul-89	Fred Canter *	Merged Dynamic BBR and error log changes. * * 13-Jul-89	Fred Canter *	Special mode select/sense handling for the EXABYTE tape. * * 27-Jun-89	John A. Gallant *	Added the tape command completion routine. * * 13-Jun-89	Fred Canter *	Added MTFLUSH to tzioctl (always returns ENXIO). * * 04/13/89	John A. Gallant *      Added b_comand to replace b_command for local command buffers. *      Use b_gid instead of b_resid to store command. *   * 03/01/89	John A. Gallant *	Added the pseudo command codes for to allow the tape to unload.  I *	followed the same conventions as the firefox/pvax code. * * 02/24/89	John A. Gallant *	In tzopen(), during the test for tape loop, the timeout for "NOT_READY" *	is increased to 6 seconds, giving an overall timeout loop of 2 minutes. * * 01/16/89	John A. Gallant *	Clear sc_category_flags in tzopen() so left over DEV_TPMARK *	does not casue drive to fail all commands after encountering *	a tape mark. *	Fixed a bug which caused a space command (via ioctl) to *	space over a tape mark without failing (as it should). *	In tzioctl(), fail the ioctl if DEV_TPMARK set. * * 11/22/88	John A. Gallant * 	If the device is already opened, EBUSY is returned instead of ENXIO. *	Added some more debug statements. * * 11/09/88	John A. Gallant *	Started the merge with the V3.0 source level.  Due to time constraints *	only the changes for the new IOCTL support will be merged.  Others *	changes will hopefully occur as time permits.  Minor re-orginization *	of code for minimization of the #ifdef/#endif changes. * * 25-Aug-88    Ricky Palmer *      Ifdef'ed again for vax and mips. This time it is based on *      my August 1, 1988 ifdef's of the original scsi.c "glob" driver. * * 17-Aug-88	Fred Canter *	Created this file by moving the SCSI tape specific files *	from the old combined driver (scsi.c) to scsi_tape.c. * ***********************************************************************/#include "sii.h"#include "scsi.h"#if NSCSI > 0 || NSII > 0 || defined(BINARY)#include "../data/scsi_data.c"#include "scsi_debug.h"/* * Define the tape density table. */static int density_table[] = {	0,				/* 0x00 - Default density.	*/	DEV_800BPI,			/* 0x01 - 800 BPI   (NRZI, R)	*/	DEV_1600BPI,			/* 0x02 - 1600 BPI  (PE, R)	*/	DEV_6250BPI,			/* 0x03 - 6250 BPI  (GCR, R)	*/	DEV_8000_BPI,			/* 0x04 - 8000 BPI  (GCR, C)	*/	DEV_8000_BPI,			/* 0x05 - 8000 BPI  (GCR, C)	*/	0,				/* 0x06 - 3200 BPI  (PE, R)	*/	0,				/* 0x07 - 6400 BPI  (IMFM, C)	*/	DEV_8000_BPI,			/* 0x08 - 8000 BPI  (GCR, CS)	*/	DEV_38000BPI,			/* 0x09 - 37871 BPI (GCR, C)	*/	DEV_6666BPI,			/* 0x0A - 6667 BPI  (MFM, C)	*/	DEV_1600BPI,			/* 0x0B - 1600 BPI  (PE, C)	*/	0,				/* 0x0C - 12690 BPI (GCR, C)	*/	DEV_10000_BPI,			/* 0x0D - QIC-120 with ECC.	*/	DEV_10000_BPI,			/* 0x0E - QIC-150 with ECC.	*/	DEV_10000_BPI,			/* 0x0F - QIC-120   (GCR, C)	*/	DEV_10000_BPI,			/* 0x10 - QIC-150   (GCR, C)	*/	DEV_16000_BPI,			/* 0x11 - QIC-320   (GCR, C)	*/	0,				/* 0x12 - QIC-1350  (RLL, C)	*/	DEV_61000_BPI,			/* 0x13 - 4mm Tape  (DDS, CS)	*/	DEV_54000_BPI			/* 0x14 - 8mm Tape  (???, CS)	*/};static int density_entrys = sizeof(density_table) / sizeof(int);/* * TODO: *	Temporary(?) debug variable. *	If nonzero, SZ_NODEVICE is returned from tz_rcvdiag() *	if the tape fails self test or its firmware revision *	level is too far out of date. *	If zero, tz_rcvdiag() results are ignored. */int sz_open_fst = 1;int	wakeup();extern int hz;extern int sz_unit_rcvdiag[];	/* If zero, need unit's selftest status *//* * Unit on line flag. Set to one if the * device is on-line. Set to zero on any unit * attention condition. */extern int sz_unit_online[];tzopen(dev, flag)	register dev_t dev;	register int flag;{	register struct uba_device *ui;	register struct sz_softc *sc;	int unit = UNIT(dev);	int cntlr;	int targid;	int retry = 0;	int retval;	int dev_ready;	struct sz_modsns_dt *sdp;	/*	 * Order of following checks is important.	 */	if (unit >= nNSZ)	    return(ENXIO);	ui = szdinfo[unit];	if ((ui == 0) || (ui->ui_alive == 0))	    return(ENXIO);	cntlr = ui->ui_ctlr;	if (cntlr >= nNSCSIBUS)	    return(ENXIO);	targid = ui->ui_slave;	sc = &sz_softc[cntlr];	if ((sc->sc_alive[targid] == 0) || (sc->sc_attached[targid] == 0))	    return (ENXIO);	if ((sc->sc_devtyp[targid] & SZ_TAPE) == 0)	    return(ENXIO);	/* Is the device already opened?, only one user at a time is allowed. */	if( sc->sc_openf[targid] ) 		return(EBUSY);	/*	 * This is a strange use of the FNDELAY flag.  It	 * is here to allow the installation finder program	 * to open the device when the tape cartridge is not	 * inserted.  The installation finder program needs	 * to do an ioctl, so open must succeed whether or	 * not a cartridge is present.	 */	/*	 * Clear sc_flags, device will lockup after any	 * hard error (DEV_HARDERR set) if we don't.	 * TODO: other driver look at dis_eot_??[]!	 */	sc->sc_flags[targid] = 0;	sc->sc_category_flags[targid] = 0;	sc->sc_szflags[targid] &= ~SZ_NODEVICE;	/*	 * Get selftest result, if we haven't already.	 * The tz_rcvdiag() routine will return	 * SZ_NODEVICE if anything is wrong.	 *	 * Fix for the nodiag flag in devtab..Some units	 * must have a senddiag cmd before a recvdiag cmd  	 * or data is garbage for the recv diag cmd. We 	 * will just look at the NO_DIAG flag in the devtab	 * struct for this type unit.	 */	if ((sz_unit_rcvdiag[unit] == 0) && 		((sc->sc_devtab[targid]->flags & SCSI_NODIAG) == 0))	    {	    sc->sc_szflags[targid] |= tz_rcvdiag(dev);	}	/*	 * Try to bring the drive on line.	 * The TZK50 takes about 25 seconds come ready after	 * a cartridge change. The TZ30 takes about 30 seconds.	 * The worst case in on an installtion with tape, not only	 * does the tape have to rewind, it also has to reposition.	 * The sleep time for NOT_READY, has been changed to allow for 2	 * minutes before the tape is determined to be "off-line".	 * This also should allow the user plenty of time to realize that the	 * tape is off-line and load the cartridge.	 */	dev_ready = 0;	for (retry = 0; retry < 20; retry++) {	    if (sc->sc_szflags[targid] & SZ_NODEVICE) {		if (flag & FNDELAY)		    break;		else		    return(ENXIO);	    }	    tzcommand(dev, SZ_TUR, 1, 0);	    if (sc->sc_c_status[targid] == SZ_GOOD) {		dev_ready = 1;		break;	    }	    else if (sc->sc_c_status[targid] == SZ_BAD) {		continue;	    }	    else if (sc->sc_c_status[targid] == SZ_CHKCND) {		retval = SZ_RETRY;		switch(sc->sc_c_snskey[targid]) {		/* TODO: this shouldn't happen! */		case SZ_NOSENSE:		case SZ_RECOVERR:		    retval = SZ_SUCCESS;		    dev_ready = 1;		    break;		case SZ_NOTREADY:		  /* If FNDELAY is set don't enter the stall loop.  The retry		    count is set to the limit and the loop will terminate with		    the device "off-line".  Worst case: a rewinding tape will		    be flaged as off-line, only if FNDELAY is set. */		    if (flag & FNDELAY) {			retry = 20; 		/* force exit of the loop */			break;		    }                    timeout(wakeup, (caddr_t)&sc->sc_alive[targid], (hz*2));                    /* TODO: check priority */		    sleep((caddr_t)&sc->sc_alive[targid], PZERO + 1);		    if (!(sc->sc_flags[targid] & DEV_EOM)) {			sc->sc_flags[targid] = 0;		    }		    break;		case SZ_UNITATTEN:		    sz_unit_online[unit] = 0;		    /* just retry */		    break;		default:		    /* TODO: may want to retry? */		    if (!(sc->sc_flags[targid] & DEV_EOM)) {			sc->sc_flags[targid] = 0;		    }		    if(flag & FNDELAY) {			sc->sc_szflags[targid] |= SZ_NODEVICE;			retval = SZ_SUCCESS;		    }		    else {			return(ENXIO);		    }		    break;		}	/* end of switch */		if (retval == SZ_SUCCESS)		    break;		/* from for loop */		else		    continue;		/* with for loop */	    }	    else {		printf("tzopen: impossible sc_c_status (val=%d)\n",		    sc->sc_c_status[targid]);		continue;	/* retry */	    }	}	/* end for loop */	if (retry >= 20) {	    if (!(flag & FNDELAY)) {	    	DEV_UGH(sc->sc_device[targid], unit, "offline");	    	return(EIO);	    }	    sc->sc_flags[targid] |= DEV_OFFLINE;	}	/*	 * If SZ_NODEVICE is not set, the device exists,	 * and we want to do a SZ_MODSEL command	 * TODO: would be nice not to do this on every open.	 */	if (!(sc->sc_szflags[targid] & SZ_NODEVICE)) {	    if (tz_exabyte_modsns) {		tzcommand(dev, SZ_MODSNS, -1, 0);		if (sc->sc_c_status[targid] != SZ_GOOD)		    printf("tzopen: %s unit %d: mode sense failed\n",			sc->sc_device[targid], unit);		sdp = (struct sz_modsns_dt *)&sc->sz_dat[targid];		printf("vu = 0x%x, mt = 0x%x, rt = 0x%x\n", sdp->vulen,			sdp->pad[0], sdp->pad[1]);	    }	    for (retry = 0; retry < 5; retry++) {		tzcommand(dev, SZ_MODSEL, 1, 0);		if (sc->sc_c_status[targid] == SZ_GOOD)		    break;	    }	    if ((retry >= 5) && ((flag & FNDELAY) == 0)) {		printf("tzopen: %s unit %d: mode select failed\n",		    sc->sc_device[targid], unit);		return(EIO);	    }	}/* If you want to see what was it set at..... uncomment *	tzcommand(dev, SZ_MODSNS, -1, 0); *	sdp = (struct sz_modsns_dt *)&sc->sz_dat[targid]; * *	printf("speed = %x bufmode = %x, wp %x bdeclen %x\n", sdp->speed,  *		sdp->bufmode, sdp->wp, sdp->bdeclen); *	printf("density = %x blk2 = %x blk1 = %x blk0 = %x\n", sdp->density, *		sdp->numofblk2, sdp->numofblk1, sdp->numofblk0); *	printf("bl2 = %x bl1 = %x bl0 =%x\n",sdp->blklen2, sdp->blklen1, *		sdp->blklen0); *	printf("vu = 0x%x, mt = 0x%x, rt = 0x%x\n", sdp->vulen, *		sdp->pad[0], sdp->pad[1]);*/	/* TODO: may not be wright place & use to cntl modsel? */	/* So open nodelay doesn't falsely set on-line! */	if (dev_ready)	    sz_unit_online[unit] = 1;	sc->sc_openf[targid] = 1;	return (0);}/* * TZ30/TZK50 Receive Diagnostics Routine */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;        ui = szdinfo[unit];        sc = &sz_softc[ui->ui_ctlr];        targid = ui->ui_slave;       	/* zero the receive data area */	byteptr = (u_char *)&sc->sz_dat[targid];	for (i = 0; i < SZ_RECDIAG_LEN; i++)	    *byteptr++ = 0;	/*	 * 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);	}	/*	 * 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);}/*TODO1: this and all other routines need function headers!*//* 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){	    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);		}		sc->sc_flags[targid] &= ~DEV_EOM;		/* 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, bucasue we don't wait for completion */		tzcommand(dev, SZ_REWIND, 0, 0);		/* 		 * must clear out the tpmark pending for fixed

⌨️ 快捷键说明

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