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

📄 scsi_disk.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)scsi_disk.c	4.4  (ULTRIX)        2/21/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1984,86,87,88,89 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.			* *									* *   This software is  derived	from  software	received  from	the	* *   University    of	California,   Berkeley,   and	from   Bell	* *   Laboratories.  Use, duplication, or disclosure is	subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   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	23-Jun-89 * * VAX SCSI device driver (disk routines) * * Modification history: * * 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	Remove #ifdef FORMAT conditionalization since we always want this. * * 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. * * 20-Aug-90	Robin Miller *	Set iostat milliseconds per word transfer rate (dk_mspw) for *	RX26 in rzopen(), depending on which diskette type (ED/HD/DD) *	is loaded in the drive. * * 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. * * 13-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. *	RX33 support. * * 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. * * 23-Jun-89	John A. Gallant *	Added the disk command completion routine.  Added the DBBR code. * * 20-Jun-89	Fred Canter *	Convert to scsi_devtab. * * 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. * * 06-Apr-89	Fred Canter *	Added b_comand to replace b_command for local command buffers. *	Use b_gid instead of b_resid to store command. * * 12-Feb-89	Fred Canter *	Added function header comments to each routine. * * 17-Dec-88	Fred Canter *	Added pseudo commands to resolve the conflict between *	SZ_UNLOAD and SZ_SSUNIT both being opcode 0x1b. * * 08-Dec-88	Alan Frechette *	Return an error if either of the KMALLOC calls in rzspecial fails. * * 04-Dec-88	Fred Canter *	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). * * 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. * * 16-Oct-88	Fred Canter *	Clean up comments. * * 28-Sep-88	Fred Canter *	Clean up copmments. Report DEV_WRTLCK flag with DEVIOCGET ioctl *	so RRD40 will return write locked and fsck will be NO WRITE. *	Buf fix - rzopen() had a call to tzcommand(). * * 13-Sep-88	Fred Canter *	Increased RRD40 retry time to 10 seconds in rzopen to allow *	for RRD40 spin up delay, which could take up to 5 seconds. * * 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"/* * Disk open routine (need func header) */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[];/* * * Name:		rzopen		-Disk open routine * * Abstract:		This routine is called each time an RZ disk device *			is opened. This routine: makes sure the device *			exists, checks for device on-line via test unit *			ready, does a mode select (lbn size 512), finds *			disks size via read capacity, and reads in disk's *			partition table. * * Inputs: * * dev			ULTRIX major/minor device number. * flag			How to open flag (read, write, NDELAY). * * Outputs: *			Possible error messages (eg, device off-line). *			sz_unit_online flag set. * * Return Values: * * ENXIO		No such device or address (non extistent device). * EIO			I/O error (device off-line, could not get size, etc). * 0			Open succeeded. * * Side Effects: *			rzcommand() called. *			sleep() called. * */rzopen(dev, flag)dev_t dev;int flag;{	register struct uba_device *ui;	register struct sz_softc *sc;	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 in 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)	    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 drivers 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 must 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).	 * However, it can take 17.9 seconds for error recovery.	 * So, we try for 20 seconds to bring the drive on-line.	 * This also 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) {		retval = SZ_RETRY;		switch(sc->sc_c_snskey[targid]) {		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++;		    }		    timeout(wakeup, (caddr_t)&sc->sc_alive[targid], hz);		    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 {		/* 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);	    }	}	/*	 * 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);		    }		}	    }	    /*	     * Set the milliseconds per word transfer rate for the	     * RX23/26/33 SCSI floppy depending on the media size.	     * RX23: If size = 2880 (1.44MB) then the floppy is 18 sector	     * otherwise assume the floppy is 9 sector.	     * RX26: If size = 5760 (2.88MB) then the floppy is 36 sector	     *       If size = 2880 (1.44MB) then the floppy is 18 sector	     *       otherwise assume the floppy is 9 sector.	     * RX33: If size = 2400 (1.2MB) then the floppy is 15 sector	     * otherwise assume the floppy is 10 sector.	     */	    if (sc->sc_devtyp[targid] == RX23) {		if (sc->sc_disksize[targid] == 2880)		    dk_mspw[ui->ui_dk] = 0.0000434;		else		    dk_mspw[ui->ui_dk] = 0.0000868;	    }	    if (sc->sc_devtyp[targid] == RX26) {		if (sc->sc_disksize[targid] == 5760)		/* ED */		    dk_mspw[ui->ui_dk] = 0.0000217;		else if (sc->sc_disksize[targid] == 2880)	/* HD */		    dk_mspw[ui->ui_dk] = 0.0000434;		else						/* DD */		    dk_mspw[ui->ui_dk] = 0.0000868;	    }	    if (sc->sc_devtyp[targid] == RX33) {		if (sc->sc_disksize[targid] == 2400)		    dk_mspw[ui->ui_dk] = 0.0000434;		else		    dk_mspw[ui->ui_dk] = 0.0000781;	    }	}	/* NOTE: set for debug, but not used */	sc->sc_openf[targid] = 1;	/*	 *	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.	 */	/* TODO: this looks wrong. If rsblk fails next time	 * we will think the partition table is good, but	 * it will be the default pt not the one read from the disk.	 */	if ((sz_part[unit].pt_valid == 0) || (sz_unit_online[unit] == 0)) {		stp = sc->sc_dstp[targid];		for( i = 0; i < 8; i++ ) {			sz_part[unit].pt_part[i].pi_nblocks = stp[i].nblocks;			sz_part[unit].pt_part[i].pi_blkoff = stp[i].blkoffs;		}		sz_part[unit].pt_valid = PT_VALID;		/*	 *	Default partition are now set. Call rsblk to set	 *	the driver's partition tables, if any exists, from	 *	the "a" partition superblock	 */

⌨️ 快捷键说明

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