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

📄 scsi_disk.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifndef lintstatic char *sccsid = "@(#)scsi_disk.c	4.6	(ULTRIX)	3/7/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_disk.c	06/27/89 * * PVAX/FIREFOX/PMAX SCSI device driver (disk routines) * * Modification history: * * 05-Mar-91	Robin Miller *   o	Modified kernel allocation requests (KM_ALLOC) to include the flag *	KM_NOWAIT to prevent sleeping if resource isn't available.  This *	created a race condition when multiple processes were accessing *	the device which resulted in a "km_free: bad reference count" *	system panic. *   o	Corrected two places in the rzspecial() function where the wrong *	number of bytes were being returned for the CDROM_TOC_ENTRYS and *	CDROM_READ_SUBCHANNEL ioctl() commands. * * 19-Feb-91	Robin Miller *   o	Correct race condition in the rzcommand() function by adding the *	appropriate spl synchronization.  Previously, if multiple processes *	attempted simultaneous access to a drive, processes could be left *	in an uninterruptable sleep state. *   o	Correct sleep priority when waiting for prior I/O to complete. *   o	Catch signals if sleeping at an interruptable priority so buffer *	resources can be released and proper error code (EINTR) returned. *   o	Allow multiple processes to issue CD-ROM audio commands. * * 30-Jan-91	Robin Miller *	Modified check done on MODE SELECT commands, so non-super users *	can issue this command to set the volume levels in the audio *	control page. * * 20-Nov-90	Robin Miller *	Added support for CD-ROM audio commands. * * 11-Sep-90	Robin Miller *	Added check in DEVIOCGET ioctl() command for Extra Density (ED) *	2.88MB RX26 floppy diskette.  Also set Double Density (DD) flag *	appropriately for RX23/RX26 3.5" or RX33 5.25" diskettes. * * 07-Sept-90	Maria Vella *	Added support for new console turbo-channel ROMs. * * 09-Aug-90	Robin Miller *	Modified check for write protect status for DEVIOCGET ioctl() *	so write lock is returned for all CD-ROM's, not just RRD40. * * 06-Feb-90	Mitch McConnell *	Change error return from EIO to ENOSPC to more accurately reflect *	error. * * 06-Dec-89    Mitch McConnell *	Added test for sc_attached to sc_alive in rzopen, return  *	ENXIO if not. * * 11-Nov-89    Janet Schank *      Changed the refrence of nNSCSI to nNSCSIBUS * * 29-Oct-89	Fred Canter *	Changed the DEVGETGEOM ioctl mode sense code to validate the *	page code, i.e., make sure the disk gave us the page we asked for. *	One of the non-DEC disks returns page 56 instead of a check *	condition when we ask for page 5 (unsupported page for hard disks). * * 08-Oct-89	Fred Canter *	Remove error log #ifdef OLDWAY. * * 07-Oct-89	Fred Canter *	Added DEVGETGEOM ioctl to return disk geometry information. * * 01-Oct-89	Fred Canter *	Fixed a bug in the RX23 SoftPC hooks. Media type ID returned *	by DEVIOGET ioctl was incorrect because first read capacity *	after unit attention failed (media change). * *	Bug fix. Disks (except RRD40) were not reporting correct *	write locked status via the devioget ioctl. * * 23-Jul-89	Fred Canter *	Convert DBBR printfs to error log calls. * * 22-Jul-89	John A. Gallant *	Added SCSI_NODBBR flag for disks without BBR. *	Added error messages to DBBR code. * * 16-Jul-89	Fred Canter *	Do a mode select to get disk geometry. * * 27-Jun-89	John A. Gallant *	Added the disk command completion routine.  Added the DBBR code. * * 12-Jun-89	Fred Canter *	Restructured the RDCAP code in rzopen() to handle the case where *	RDCAP will fail if there is an unformatted floppy in the drive. * * 11-Jun-89	Fred Canter *	Added media changed and density information to devget structure. *	So softpc application can make better use of the floppy drive. * * 08-Jun-89	Fred Canter *	Removed RX23 RDCAP hack and handle case where RDCAP can fail if *	an unformatted floppy is in the RX23, in rzopen(). * * 06-Jun-89	Fred Canter *	Set iostat dk_mspw transfer rate for RX23 in rzopen(), depending *	on which type floppy (HD/DD) in loaded in the drive. * * 24-May-89	Fred Canter *	Changes to match the new, more general rzdisk utility. *	Changed the mode select data structures so an address and *	length are passed with the ioctl. This allows pages to be *	added to rzdisk without requiring a kernel rebuild. * * 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.  Removed the *	extra SSUNIT command during the online retry code in rzopen(). * * 12/14/88	John A. Gallant *	More merge with firefox code. *	Return an error if either of the KMALLOC calls in rzspecial fails. *	Changes to rzspecial(). Allow all commands except: format, *	reassign block, and read defect data on the CDROM. *	Return EROFS instead of ENXIO if command not allowed on CDROM. *	Wait 20 seconds in rzopen for CDROM to come on-line (was 10). * * 12/02/88	John A. Gallant *	Report DEV_WRTLCK flag with DEVIOCGET ioctl so RRD40 will return *	write locked and fsck will be NO WRITE. * * 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. *   COMMENTS from V3.0: *   03-Nov-88	Alan Frechette *	Added in support for disk maintainence. Added the commands *	FORMAT UNIT, REASSIGN BLOCK, READ DEFECT DATA, MODE SENSE, *	MODE SELECT, INQUIRY and VERIFY DATA. These are all new  *	ioctl calls. * * 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 disk specific files *	from the old combined driver (scsi.c) to scsi_disk.c. * ***********************************************************************/#include "../data/scsi_data.c"#include "scsi_debug.h"extern int geterror(), wakeup();extern int hz;extern int sz_unit_rcvdiag[];   /* If zero, need unit's selftest status */extern int sz_retries[];	/* retry counter *//* * 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[];/* * Disk open routine (need func header) */rzopen(dev, flag)dev_t dev;int flag;{	register struct sz_softc *sc;	register struct uba_device *ui;	int unit = minor(dev) >> 3;	int cntlr;	int targid;	int retry, retrylimit;	int retval;	int dev_ready, ssunit_cnt;	int i;	struct size *stp;	struct sz_rdcap_dt *rdp;	int rzstrategy();	/*	 * 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_alive[targid] == 0)		return (ENXIO);	if (((sc->sc_devtyp[targid] & SZ_DISK) == 0) &&	    ((sc->sc_devtyp[targid] & SZ_CDROM) == 0))		return (ENXIO);	/*	 * 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_szflags[targid] &= ~SZ_NODEVICE;	/*	 * Get selftest result, if we haven't already.	 * The rz_rcvdiag() routine will return	 * SZ_NODEVICE if anything is wrong.	 */	/*	 * TODO:	 *	The RRD40 is the only disk that supports the	 *	receive diagnostics command. We need to write	 *	a rz_rcvdiag() routine if we decide to use it.	 *//*	if (sz_unit_rcvdiag[unit] == 0)	*//*	    sc->sc_szflags[targid] |= rz_rcvdiag(dev);	*/	/*	 * Try to bring the drive on line.	 *	 * The disks take about 10 seconds to spin up.	 * They should already be spinning by the time we get here,	 * but we nust make sure the drive is spinning to cover	 * the remote possibility that it went off line.	 * We try for 20 seconds to bring the drive on-line.	 *	 * The RRD40 comes online almost instantly (about 1 second).	 * So, we try for 5 seconds to bring the drive on-line.	 * This allows the user some think time to realize the	 * CDROM is off-line and load the CD.	 */	dev_ready = 0;	ssunit_cnt = 0;	retrylimit = 20;	for (retry = 0; retry < retrylimit; retry++) {	    if (sc->sc_szflags[targid] & SZ_NODEVICE) {		if (flag & FNDELAY)		    break;		else		    return(ENXIO);	    }	    rzcommand(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) {		/* HERE */		/* Can't be here, call to rzcommand sets new status info. *//*		rzcommand(dev, SZ_P_SSUNIT, 1, 0);	*/		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:		    /*		     * Send start unit command twice. The first one		     * could fail due to unit attention.		     * We don't confuse the issue with error checking!		     */		    if (ssunit_cnt < 2) {			rzcommand(dev, SZ_P_SSUNIT, 1, 0);			ssunit_cnt++;		    }			PRINTD(targid, 0x8000, 			   ("rzopen: sleeping for disk spin-up\n"));			timeout(wakeup, (caddr_t)&sc->sc_alive[targid], hz);			/* 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? */		    /* TODO: tape specific? */		    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 {		/* TODO: debug */		printf("rzopen: impossible sc_c_status (val=%d)\n",		    sc->sc_c_status[targid]);		continue;	/* retry */	    }	}	/* end for loop */	if (retry >= retrylimit) {	    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 (i.e., the device exists)	 * and the device is off-line, do a mode select.	 * This sets the Logical Block Size to 512 bytes.	 * NOTE: RZ disk drives have 512 bytes as the	 *	 default LBN size, but we set and check it anyway.	 * NOTE: production RRD40 drives default to 512 byte lbn size.	 *	 The RRD40's physical sector size is 2KB.	 */	if (!(sc->sc_szflags[targid] & SZ_NODEVICE) &&	    (sz_unit_online[unit] == 0)) {	    /*	     * Use MODSEL to specify 512 byte LBNs.	     * TODO: later on we may want to change other parameters.	     */	    for (retry = 0; retry < 5; retry++) {		rzcommand(dev, SZ_MODSEL, 1, 0);		if (sc->sc_c_status[targid] == SZ_GOOD)		    break;	    }	    if ((retry >= 5) && ((flag & FNDELAY) == 0)) {		printf("rzopen: %s unit %d: mode select failed\n",		    sc->sc_device[targid], unit);		return(EIO);	    }	    /*	     * Use RDCAP to determine the size of the disk.	     * Also verify LBN size is really 512 bytes.	     * NOTE: CD size depends on how much data was mastered	     *	     on the CD. Must get size after each media change.	     * NOTE: RDCAP will fail if the floppy is unformatted.	     */	    for (retry = 0; retry < 5; retry++) {		rzcommand(dev, SZ_RDCAP, 1, 0);		if (sc->sc_c_status[targid] == SZ_GOOD)		    break;	    }	    if (retry >= 5) {		sc->sc_disksize[targid] = 0;		if ((flag & FNDELAY) == 0) {		    printf("rzopen: %s unit %d: read capacity failed\n",			sc->sc_device[targid], unit);		    return(EIO);		}	    }	    else {		rdp = (struct sz_rdcap_dt *)&sc->sz_dat[targid];		i = (rdp->lbaddr3 << 24) & 0xff000000;		i |= (rdp->lbaddr2 << 16) & 0x00ff0000;		i |= (rdp->lbaddr1 << 8) & 0x0000ff00;		i |= rdp->lbaddr0 & 0x000000ff;		/*		 * RDCAP returns the address of the last LBN.		 * We must add one to get the number of LBNs.		 */		sc->sc_disksize[targid] = (daddr_t)(i + 1);		/*		 * Verify LBN size is 512 bytes.		 */		i = (rdp->blklen3 << 24) & 0xff000000;		i |= (rdp->blklen2 << 16) & 0x00ff0000;		i |= (rdp->blklen1 << 8) & 0x0000ff00;		i |= rdp->blklen0 & 0x000000ff;		if (i != 512) {		    if (!(flag & FNDELAY)) {			printf("rzopen: %s unit %d: %s (size = %d)\n",			    sc->sc_device[targid], unit,			    "could not set LBN size to 512 bytes", i);			return(EIO);		    }		}	    }	}	/*	 *	See if we need to read in the partition table from the disk.	 *	The conditions we will have to read from the disk is if the 	 *	partition table valid bit has not been set for the volume	 *	is invalid.	 */	/*	 *	Assume that the default values before trying to	 *	see if the partition tables are on the disk. The	 *	reason that we do this is that the strategy routine	 *	is used to read in the superblock but uses the 	 *	partition info.  So we must first assume the	 *	default values.	 */	/* TODO1: this looks wrong. If rsblk fails next time

⌨️ 快捷键说明

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