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

📄 sr.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#ident	"@(#)sr.c 1.1 92/07/30 SMI"/* @(#)sr.c 1.1 92/07/30 SMI *//* * Copyright (c) 1988-1991 by Sun Microsystems, Inc. */#include "sr.h"#if	NSR > 0/* * *		SCSI CDROM driver (for CDROM, read-only) * *//* * * *		Includes, Declarations and Local Data * * */#include <scsi/scsi.h>#include <scsi/targets/srdef.h>#include <scsi/impl/uscsi.h>#include <vm/hat.h>#include <vm/seg.h>#include <vm/as.h>/* * * Local definitions, for clarity of code * */#ifdef	OPENPROMS#define	DRIVER		sr_ops#define	DNAME		devp->sd_dev->devi_name#define	DUNIT		devp->sd_dev->devi_unit#define	CNAME		devp->sd_dev->devi_parent->devi_name#define	CUNIT		devp->sd_dev->devi_parent->devi_unit#else	OPENPROMS#define	DRIVER		srdriver#define	DNAME		devp->sd_dev->md_driver->mdr_dname#define	DUNIT		devp->sd_dev->md_unit#define	CNAME		devp->sd_dev->md_driver->mdr_cname#define	CUNIT		devp->sd_dev->md_mc->mc_ctlr#endif	OPENPROMS#define	UPTR		((struct scsi_disk *)(devp)->sd_private)#define	SCBP(pkt)	((struct scsi_status *)(pkt)->pkt_scbp)#define	SCBP_C(pkt)	((*(pkt)->pkt_scbp) & STATUS_MASK)#define	CDBP(pkt)	((union scsi_cdb *)(pkt)->pkt_cdbp)#define	ROUTE		(&devp->sd_address)#define	BP_PKT(bp)	((struct scsi_pkt *)bp->av_back)#define	Tgt(devp)	(devp->sd_address.a_target)#define	Lun(devp)	(devp->sd_address.a_lun)#define	SRUNIT(dev)	(minor((dev))>>3)#define	SRPART(dev)	(minor((dev))&0x7)#define	New_state(un, s) (un)->un_last_state=(un)->un_state, (un)->un_state=(s)#define	Restore_state(un)	\	{ u_char tmp = (un)->un_last_state; New_state((un), tmp); }/* * Parameters */	/*	 * 180 seconds is a reasonable amount of time for CDROM operations	 */#define	DEFAULT_SR_TIMEOUT	180	/*	 * 180 seconds is what we'll wait if we get a Busy Status back	 * Note: worse case timeout with 30 second x (1 + 5 retrys) = 180	 */#define	SRTIMEOUT		180*hz	/* 180 seconds Busy Waiting */	/*	 * Number of times we'll retry a normal operation.	 *	 * XXX This includes retries due to transport failure	 * XXX Need to distinguish between Target and Transport	 * XXX failure.	 */#define	SR_RETRY_COUNT		1	/*	 * Maximum number of retries to handle unit attention key	 */#define	SR_UNIT_ATTENTION_RETRY	40	/*	 * Maximum number of units (controlled by space in minor device byte)	 */#define	SR_MAXUNIT		32	/*	 * Maximum number of retry when trying to read the capacity from	 * the disk.	 */#define	MAX_RETRY	20/* * Debugging macros */#define	DEBUGGING	((scsi_options & SCSI_DEBUG_TGT) || srdebug > 1)#define	DEBUGGING_ALL	((scsi_options & SCSI_DEBUG_TGT) || srdebug)#define	DPRINTF		if (DEBUGGING) printf#define	DPRINTF_ALL	if (DEBUGGING || srdebug > 0) printf#define	DPRINTF_IOCTL	DPRINTF_ALL/* * * Global Data Definitions and references * */struct scsi_device *srunits[SR_MAXUNIT];int nsr = SR_MAXUNIT;extern int maxphys, dkn;/* * * Local Static Data * */static struct scsi_address *srsvdaddr[SR_MAXUNIT];static int srpri = 0;static int srdebug = 0;static int sr_error_reporting = SRERR_RETRYABLE;static struct sr_drivetype sr_drivetypes[] = {/* SONY CDU-541 */{ "Sony", 		0,		CTYPE_CCS,	4, "SONY" },{ "Hitachi",		0,		CTYPE_CCS,	7, "HITACHI" },};/* * Generic CCS scsi drive with very pessimistic assumptions as to capabilities. * Well, for now, assume it has reconnect capacities. */static struct sr_drivetype generic_ccs ={ "CCS",	0,		CTYPE_CCS,	4,	"<??>"	};#define	MAX_SRTYPES (sizeof sr_drivetypes/ (sizeof sr_drivetypes[0]))/* * Configuration Data */#ifdef	OPENPROMS/* * Device driver ops vector */int srslave(), srattach(), sropen(), srclose(), srread();int srstrategy(), srioctl(), srsize();extern int nulldev(), nodev();struct dev_ops sr_ops = {	1,	srslave,	srattach,	sropen,	srclose,	srread,	nodev,	srstrategy,	nodev,	srsize,	srioctl};#else	OPENPROMS/* * srdriver is only used to attach */int srslave(), srattach(), sropen(), srclose(), srread();int srstrategy(), srdump(), srioctl(), srsize();extern int nulldev(), nodev();struct mb_driver srdriver = {	nulldev, srslave, srattach, nodev, nodev, nulldev, 0, "sr", 0, 0, 0, 0};#endif/* * * Local Function Declarations * */static void clean_print(), srintr();static void srerrmsg(), srintr_adaptec(), srdone(), sr_offline();static void make_sr_cmd(), srstart(), srdone(), sr_error_code_print();static int srrunout(), sr_findslave(), sr_unit_ready(), sr_medium_removal();static	void	makecom_all();static	int	sr_pause_resume(), sr_play_msf(), sr_play_trkind();static	int	sr_read_tochdr(), sr_read_tocentry();static	void	sr_not_ready();static	void	sr_ejected();#ifdef OLDCODEstatic	int	sr_read_new_disc();#endif OLDCODEstatic	int	sr_read_mode2(), sr_read_mode1();static	int	sr_mode_1(), sr_mode_2();static	int	sr_handle_ua();static	int	sr_lock_door();static	void	sr_setup_openflags();#ifndef	FIVETWELVEstatic	int	sr_two_k();#endif	FIVETWELVE#ifdef OPENPROMSstatic	void	sr_set_dkn();#endif OPENPROMS/**//* * * *		Autoconfiguration Routines * * */intsrslave(devp)struct scsi_device *devp;{	int r;	/*	 * fill in our local array	 */	if (DUNIT >= nsr)		return (0);	srunits[DUNIT] = devp;#ifdef	OPENPROMS	srpri = MAX(srpri, ipltospl(devp->sd_dev->devi_intr->int_pri));#else	srpri = MAX(srpri, pritospl(devp->sd_dev->md_intpri));#endif	/*	 * Turn around and call real slave routine. If it returns -1,	 * then try and save the address structure for a possible later open.	 */	r = sr_findslave (devp, 0);	if (r < 0) {		srsvdaddr[DUNIT] = (struct scsi_address *)		    kmem_zalloc(sizeof (struct scsi_address));		if (srsvdaddr[DUNIT]) {			srunits[DUNIT] = 0;			*srsvdaddr[DUNIT] = devp->sd_address;		} else {			r = 0;		}	}	return (r);}static intsr_findslave(devp, canwait)register struct scsi_device *devp;int canwait;{	struct scsi_pkt *rqpkt;	struct scsi_disk *un;	struct sr_drivetype *dp;	auto int (*f)() = (canwait == 0)? NULL_FUNC: SLEEP_FUNC;	/*	 * Call the routine scsi_slave to do some of the dirty work.	 * All scsi_slave does is do a TEST UNIT READY (and possibly	 * a non-extended REQUEST SENSE or two), and an INQUIRY command.	 * If the INQUIRY command succeeds, the field sd_inq in the	 * device structure will be filled in. The sd_sense structure	 * will also be allocated.	 *	 */	switch (scsi_slave(devp, canwait)) {	default:	case SCSIPROBE_NOMEM:	case SCSIPROBE_FAILURE:	case SCSIPROBE_NORESP:	case SCSIPROBE_NONCCS:		if (devp->sd_inq) {			IOPBFREE (devp->sd_inq, sizeof (struct scsi_inquiry));			devp->sd_inq = (struct scsi_inquiry *) 0;		}		return (-1);	case SCSIPROBE_EXISTS:		/*		 * The only type of device that we're		 * interested in is READ ONLY DIRECT ACCESS.		 */		if (devp->sd_inq->inq_dtype != DTYPE_RODIRECT) {			IOPBFREE (devp->sd_inq, sizeof (struct scsi_inquiry));			devp->sd_inq = (struct scsi_inquiry *) 0;			return (-1);		}		/*		 * XXX: should you check to make sure that the inq_rmb		 * XXX: is set? So that all the eject code doesn't		 * XXX: barf?		 */		break;	}	/*	 * allocate a request sense packet	 */	rqpkt = get_pktiopb(ROUTE, (caddr_t *)&devp->sd_sense,			CDB_GROUP0, 1, SENSE_LENGTH, B_READ, f);	if (!rqpkt) {		return (0);	}	makecom_g0(rqpkt, devp, 0, SCMD_REQUEST_SENSE, 0, SENSE_LENGTH);	rqpkt->pkt_pmon = -1;	/*	 * fill up some of the scsi disk information.	 */	un = UPTR = (struct scsi_disk *)kmem_zalloc(sizeof (struct scsi_disk));	if (!un) {		printf("%s%d: no memory for disk structure\n", DNAME, DUNIT);		free_pktiopb(rqpkt, (caddr_t)devp->sd_sense, SENSE_LENGTH);		return (0);	}	un->un_rbufp = (struct buf *) kmem_zalloc(sizeof (struct buf));	un->un_sbufp = (struct buf *) kmem_zalloc(sizeof (struct buf));	if (!un->un_rbufp || !un->un_sbufp) {		printf("srslave: no memory for raw or special buffer\n");		if (un->un_rbufp)			(void) kmem_free((caddr_t)un->un_rbufp,					sizeof (struct buf));		(void) kmem_free((caddr_t)un, sizeof (struct scsi_disk));		free_pktiopb(rqpkt, (caddr_t)devp->sd_sense, SENSE_LENGTH);		return (0);	}	/*	 * For sure the drive is present, and we're going to keep it.	 * Since this is (we hope) removable media, we don't need to read the	 * media at this point. We'll do it during the first open.	 */	devp->sd_present = 1;	/*	 * Sigh. Look through our list of supported drives to dredge	 * up information that we haven't figured out a clever way	 * to get inference yet.	 */	for (dp = &sr_drivetypes[0]; dp < &sr_drivetypes[MAX_SRTYPES]; dp++) {		if (bcmp(devp->sd_inq->inq_vid, dp->id, dp->idlen) == 0) {			un->un_dp = dp;			break;		}	}	if (dp == &sr_drivetypes[MAX_SRTYPES]) {		/*		 * assume CCS drive, don't assume anything else.		 */		printf("%s%d: Unrecongized Vendor '", DNAME, DUNIT);		clean_print(&(devp->sd_inq->inq_vid[0]), 8);		printf("', product '");		clean_print(&(devp->sd_inq->inq_pid[0]), 16);		printf("'");		un->un_dp = (struct sr_drivetype *)			kmem_zalloc(sizeof (struct sr_drivetype));		if (!un->un_dp || !(un->un_dp->name = kmem_zalloc(8))) {			un->un_dp = &generic_ccs;		} else {			bcopy(devp->sd_inq->inq_vid, un->un_dp->name, 8);			un->un_dp->name[7] = 0;			bcopy(devp->sd_inq->inq_vid, un->un_dp->id, IDMAX);			un->un_dp->idlen = IDMAX;			un->un_dp->ctype = CTYPE_CCS;		}	}	un->un_capacity = -1;	un->un_lbasize = -1;	/*	 * initialize open and exclusive open flags	 */	un->un_open0 = un->un_open1 = 0;	un->un_exclopen = 0;	rqpkt->pkt_comp = srintr;	rqpkt->pkt_time = DEFAULT_SR_TIMEOUT;	if (un->un_dp->options & SR_NODISC)		rqpkt->pkt_flags |= FLAG_NODISCON;	un->un_rqs = rqpkt;	un->un_sd = devp;	un->un_dev = DUNIT<<3;#ifdef	OPENPROMS	devp->sd_dev->devi_driver = &sr_ops;#endif	return (1);}/* * Attach disk. The controller is there. Since this is a CDROM, * there is no need to check the label. */intsrattach(devp)struct scsi_device *devp;{	register struct scsi_disk *un;	if (!(un = UPTR)) {		return;	}#ifndef FIVETWELVE	/*	 * Set the drive's sector size to 2048	 */	(void)sr_two_k(devp);#endif	FIVETWELVE	/*	 * initialize the geometry and partition table.	 */	bzero((caddr_t) & un->un_g, sizeof (struct dk_geom));	bzero((caddr_t)un->un_map, NDKMAP * (sizeof (struct dk_map)));	/*	 * It's CDROM, therefore, no label. But it is still necessary	 * to set up various geometry information. And we are doing	 * this here.	 * For the number of sector per track, we put the maximum	 * number, assuming a CDROM can hold up to 600 Mbytes of data.	 * For the rpm, we use the minimum for the disk.	 */	un->un_g.dkg_ncyl = 1;	un->un_g.dkg_acyl = 0;	un->un_g.dkg_bcyl = 0;	un->un_g.dkg_nhead = 1;	un->un_g.dkg_nsect = 0;	un->un_g.dkg_intrlv = 1;	un->un_g.dkg_rpm = 200;	un->un_gvalid = 1;	/*	 * dk instrumentation	 */#ifdef	OPENPROMS	if ((un->un_dkn = (char) newdk("sr", DUNIT)) >= 0) {		int intrlv = un->un_g.dkg_intrlv;		if (intrlv <= 0 || intrlv >= un->un_g.dkg_nsect) {			intrlv = 1;		}		dk_bps[un->un_dkn] =			(SECSIZE * 60 * un->un_g.dkg_nsect) / intrlv;	}#endif	OPENPROMS	}static voidclean_print(p, l)char *p;int l;{	char a[2];	register unsigned i = 0, c;	while (i < l) {		if ((c = *p++) < ' ' || c >= 0177)			printf("\\%o", c&0xff);		else {			a[0] = c; a[1] = 0;			printf("%s", a);		}		i++;	}}#ifdef	OPENPROMSstatic voidsr_set_dkn(devp)struct scsi_device	*devp;{	register struct scsi_disk *un;	un = UPTR;	if ((un->un_dkn = (char) newdk("sr", DUNIT)) >= 0) {		int intrlv = un->un_g.dkg_intrlv;		if (intrlv <= 0 || intrlv >= un->un_g.dkg_nsect) {			intrlv = 1;		}		dk_bps[un->un_dkn] =			(SECSIZE * 60 * un->un_g.dkg_nsect) / intrlv;	}}#endif OPENPROMS/**//* * * *			Unix Entry Points * * *//*ARGSUSED*/intsropen(dev, flag)dev_t dev;int flag;{	register struct scsi_device *devp;	register struct scsi_disk *un;	register int unit, s;	DPRINTF("in sropen\n");	if ((unit = SRUNIT(dev)) >= nsr) {		return (ENXIO);	}	if (!(devp = srunits[unit])) {		struct scsi_address *sa = srsvdaddr[unit];		if (sa) {			if (scsi_add_device(sa, &DRIVER, "sr", unit) == 0) {				return (ENXIO);			}			devp = srunits[unit];			if (!devp)				panic("sropen");			(void) kmem_free((caddr_t) sa, sizeof (*sa));			srsvdaddr[unit] = (struct scsi_address *) 0;		} else {			return (ENXIO);		}	} else if (!devp->sd_present) {		s = splr(srpri);		if (sr_findslave (devp, 1) > 0) {			printf("%s%d at %s%d target %d lun %d\n", DNAME, DUNIT,				CNAME, CUNIT, Tgt(devp), Lun(devp));			srattach(devp);		} else {			(void) splx(s);			return (ENXIO);		}		(void) splx(s);	}	un = UPTR;	/*	 * check for previous exclusive open	 */	if ((un->un_exclopen) ||	    ((flag & FEXCL) && ((un->un_open0 != 0) ||				(un->un_open1 != 0)))) {		return (EBUSY);	}	DPRINTF("un->un_state is %d\n", un->un_state);	if ((un->un_state == SR_STATE_NIL) ||	    (un->un_state == SR_STATE_CLOSED) ||	    (un->un_state == SR_STATE_EJECTED)) {		u_char state;

⌨️ 快捷键说明

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