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

📄 sr.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		state = un->un_last_state;		New_state(un, SR_STATE_OPENING);		if (sr_unit_ready(dev) == 0) {			sr_not_ready(devp);			un->un_state = un->un_last_state;			un->un_last_state = state;			return (ENXIO);		}		state = un->un_last_state;		New_state(un, SR_STATE_OPENING);		if (sr_read_capacity(devp) != 0) {			un->un_state = un->un_last_state;			un->un_last_state = state;			return (ENXIO);		}		un->un_state = un->un_last_state;		un->un_last_state = state;		/*		 * now lock the drive door, if it is the first time open		 */		if ((un->un_open0 == 0) &&		    (un->un_open1 == 0)) {			state = un->un_last_state;			New_state(un, SR_STATE_OPENING);			if (sr_medium_removal(dev, SR_REMOVAL_PREVENT) != 0) {				un->un_state = un->un_last_state;				un->un_last_state = state;				return (ENXIO);			}			un->un_state = un->un_last_state;			un->un_last_state = state;		}	} else if (un->un_state == SR_STATE_DETACHING) {		u_char state;		if (sr_unit_ready(dev) == 0) {			return (ENXIO);		}		/*		 * disk now back on line...		 */		New_state(un, SR_STATE_OPENING);		printf("%s%d: disk okay\n", DNAME, DUNIT);		if (sr_read_capacity(devp) != 0) {			return (ENXIO);		}		/* now lock the drive door */		state = un->un_last_state;		New_state(un, SR_STATE_OPENING);		if (sr_medium_removal(dev, SR_REMOVAL_PREVENT) != 0) {			un->un_state = un->un_last_state;			un->un_last_state = state;			return (ENXIO);		}		un->un_state = un->un_last_state;		un->un_last_state = state;	}	New_state(un, SR_STATE_OPEN);#ifndef FIVETWELVE	/*	 * to be safe, set the block size to 2048 here	 */	(void)sr_two_k(devp);#endif	FIVETWELVE	/*	 * set up open and exclusive open flags	 */	sr_setup_openflags(devp, un, major(dev));	if (flag & FEXCL) {		un->un_exclopen = 1;	}	return (0);}/* * sr_setup_openflags: setup un->un_open0, un->un_open1 * * Look, this is a *hack* to make the driver to distinguish * between the close() call on the character device and the * the close() call on the block device. We have to assume * that the major numbers of the block device and character * device are DIFFERENT. This is the only way to let the * driver to unlock the drive and set the state to CLOSED * on the very last close() call. */static voidsr_setup_openflags(devp, un, major_num)register struct	scsi_device *devp;register struct	scsi_disk *un;int	major_num;{	/*	 * set up open flag and exclusive open flag if necessary	 */	if ((un->un_open0 == 0) &&	    (un->un_open1 == 0)) {		un->un_open0 = major_num;	} else if ((un->un_open0 != major_num) &&		    (un->un_open1 != major_num)) {		if (un->un_open0 == 0) {			un->un_open0 = major_num;		} else if (un->un_open1 == 0) {			un->un_open1 = major_num;		} else {			printf("%s%d: sropen: open flags corrupted\n",				DNAME, DUNIT);		}	}}intsrclose(dev)dev_t dev;{	register struct scsi_device *devp;	register struct scsi_disk *un;	int unit;	DPRINTF("sr: last close on dev %d.%d\n", major(dev), minor(dev));	if ((unit = SRUNIT(dev)) >= nsr) {		return (ENXIO);	} else if (!(devp = srunits[unit]) || !devp->sd_present) {		return (ENXIO);	} else if (!(un = UPTR) || un->un_state < SR_STATE_OPEN) {		return (ENXIO);	}	if (un->un_open0 == major(dev)) {		un->un_open0 = 0;	} else if (un->un_open1 == major(dev)) {		un->un_open1 = 0;	} else {		printf("%s%d: srclose: open flags corrupted\n",			DNAME, DUNIT);	}	if (un->un_exclopen) {		un->un_exclopen = 0;	}	DPRINTF("un->un_state is %d\n", un->un_state);	if ((un->un_open0 == 0) && (un->un_open1 == 0)) {		if (un->un_state == SR_STATE_DETACHING) {			sr_offline(devp);		} else if (un->un_state != SR_STATE_EJECTED) {			if (sr_medium_removal(dev, SR_REMOVAL_ALLOW) != 0) {				return (ENXIO);			}#ifdef OPENPROMS			(void) remdk((int) un->un_dkn);#endif OPENPROMS		}		New_state(un, SR_STATE_CLOSED);		/*		 * here is where we would invalidate the whole		 * schmeer, so that the next open would go out		 * and make sure people hadn't switched things		 * out from under us. I haven't put it in yet		 * because I need to fiddle with the attach		 * routine to not bother to print a label in		 * cases where the disk isn't actually changed		 */	}	return (0);}intsrsize(dev)dev_t dev;{	struct scsi_device *devp;	int unit;	DPRINTF("srsize:\n");	if ((unit = SRUNIT(dev)) >= nsr) {		return (-1);	} else if (!(devp = srunits[unit]) || !devp->sd_present) {		return (-1);	}	return (UPTR->un_capacity);}/* * These routines perform raw i/o operations. */srread(dev, uio)dev_t dev;struct uio *uio;{	DPRINTF("in srread:\n");	return (srrw(dev, uio, B_READ));}static voidsrmin(bp)struct buf *bp;{	if (bp->b_bcount > maxphys)		bp->b_bcount = maxphys;}static intsrrw(dev, uio, flag)dev_t dev;struct uio *uio;int flag;{	struct scsi_device *devp;	register int unit;	DPRINTF("srrw\n");	if ((unit = SRUNIT(dev)) >= nsr) {		return (ENXIO);	} else if (!(devp = srunits[unit]) || !devp->sd_present) {		return (ENXIO);	} else if ((uio->uio_fmode & FSETBLK) == 0 &&	    (uio->uio_offset & (SECSIZE - 1)) != 0) {		DPRINTF("srrw:  file offset not modulo %d\n", SECSIZE);		return (EINVAL);	} else if (uio->uio_iov->iov_len & (SECSIZE - 1)) {		DPRINTF("srrw:  block length not modulo %d\n", SECSIZE);		return (EINVAL);	}	return (physio(srstrategy, UPTR->un_rbufp, dev, flag, srmin, uio));}/* * * strategy routine * */intsrstrategy(bp)register struct buf *bp;{	register struct scsi_device *devp;	register struct scsi_disk *un;	register struct diskhd *dp;	register s;	DPRINTF("srstrategy\n");	devp = srunits[SRUNIT(bp->b_dev)];	if (!devp || !devp->sd_present || !(un = UPTR)) {nothere:		bp->b_resid = bp->b_bcount;		bp->b_flags |= B_ERROR;		bp->b_error = ENXIO;		iodone(bp);		return;	}	if ((bp != un->un_sbufp) && (bp != un->un_rbufp) &&	    (un->un_state == SR_STATE_MODE2)) {		goto nothere;	}	if (bp != un->un_sbufp && un->un_state == SR_STATE_DETACHING) {		if (sr_unit_ready(bp->b_dev) == 0) {			goto nothere;		}		New_state(un, SR_STATE_OPEN);		printf("%s%d: disk okay\n", DNAME, DUNIT);		/*		 * disk now back on line...		 */	}	bp->b_flags &= ~(B_DONE|B_ERROR);	bp->b_resid = 0;	bp->av_forw = 0;	DPRINTF("bp->b_bcount is %d\n", bp->b_bcount);	dp = &un->un_utab;	if (bp != un->un_sbufp) {		/*		 * this is regular read, therefore, it needs to be in		 * mode one.		 *//*		s = splr(srpri);		while (un->un_state == SR_STATE_MODE2) {			(void) sleep((caddr_t)un, PRIBIO);		}		(void) splx(s);*/#ifdef FIVETWELVE		DPRINTF("dkblock(bp) is %d\n", dkblock(bp));		if (dkblock(bp) > (un->un_capacity - 1)) {#else		DPRINTF("dkblock(bp) >> 2 is %d\n", dkblock(bp)>>2);		if ((dkblock(bp) >> 2) > (un->un_capacity - 1)) {#endif FIVETWELVEDPRINTF("%s%d: Requested Block number is greater than disc's capacity\n",	DNAME, DUNIT);			bp->b_flags |= B_ERROR;			bp->b_resid = bp->b_bcount;			iodone(bp);		}		if (bp->b_bcount & (SECSIZE - 1)) {			bp->b_resid = bp->b_bcount;			bp->b_flags |= B_ERROR;		} else {			/*			 * sort by absolute block number			 */			bp->b_resid = dkblock(bp);			BP_PKT(bp) = 0;		}	} else {		DPRINTF_IOCTL("srstrategy: special\n");	}	if ((s = (bp->b_flags & (B_DONE|B_ERROR))) == 0) {		s = splr(srpri);		/*		 * We are doing it a bit non-standard. That is, the		 * head of the b_actf chain is *not* the active command-		 * it is just the head of the wait queue. The reason		 * we do this is that the head of the b_actf chain is		 * guaranteed to not be moved by disksort(), so that		 * our actual current active command (pointed to by		 * b_forw) and the head of the wait queue (b_actf) can		 * have resources granted without it getting lost in		 * the queue at some later point (where we would have		 * to go and look for it).		 */		disksort(dp, bp);#ifdef	CHECK_OVERLAP		check_overlap(devp);#endif		if (dp->b_forw == NULL) { /* this device inactive? */			srstart(devp);		} else if (BP_PKT(dp->b_actf) == 0) {			/*			 * try and map this one			 */			make_sr_cmd(devp, dp->b_actf, NULL_FUNC);		}		(void) splx(s);	} else if ((s & B_DONE) == 0) {		iodone(bp);	}}#ifdef	CHECK_OVERLAPcheck_overlap(devp)struct scsi_device *devp;{	struct scsi_disk *un = UPTR;	register struct buf *bp;}#endif/* * This routine implements the ioctl calls.  It is called * from the device switch at normal priority. *//* * XX- what is 'flag' used for? *//*ARGSUSED3*/srioctl(dev, cmd, data, flag)dev_t dev;int cmd;caddr_t data;int flag;{	extern char *strcpy();	register struct scsi_device *devp;	register struct scsi_disk *un;	struct dk_info *info;	struct dk_conf *conf;	struct dk_diag *diag;	int unit, i;	if ((unit = SRUNIT(dev)) >= nsr) {		return (ENXIO);	} else if (!(devp = srunits[unit]) || !devp->sd_present ||!(un=UPTR)) {		return (ENXIO);	} else if (un->un_state == SR_STATE_DETACHING) {		return (ENXIO);	}	switch (cmd) {	/*	 * Return info concerning the controller.	 */	case DKIOCINFO:		DPRINTF_IOCTL("srioctl:  get info\n");		info = (struct dk_info *)data;#ifdef	OPENPROMS		info->dki_ctlr =			(int) devp->sd_dev->devi_parent->devi_reg->reg_addr;		info->dki_unit = (Tgt(devp)<<3)|Lun(devp);#else		info->dki_ctlr = getdevaddr(devp->sd_dev->md_mc->mc_addr);		info->dki_unit = devp->sd_dev->md_slave;#endif		switch (un->un_dp->ctype) {		case CTYPE_MD21:			info->dki_ctype = DKC_MD21;			break;		case CTYPE_ACB4000:			info->dki_ctype = DKC_ACB4000;			break;		default:			info->dki_ctype = DKC_SCSI_CCS;			break;		}		info->dki_flags = DKI_FMTVOL;		return (0);	/*	 * Return the geometry of the specified unit.	 */	case DKIOCGGEOM:		DPRINTF_IOCTL("srioctl:  get geometry\n");		*(struct dk_geom *)data = un->un_g;		return (0);	/*	 * Set the geometry of the specified unit.	 */	case DKIOCSGEOM:		DPRINTF_IOCTL("srioctl:  set geometry\n");		un->un_g = *(struct dk_geom *)data;		return (0);	/*	 * Return the map for the specified logical partition.	 * This has been made obsolete by the get all partitions	 * command.	 */	case DKIOCGPART:		DPRINTF_IOCTL("srioctl:  get partitions\n");		bzero((caddr_t)data, sizeof (struct dk_map));		return (0);	/*	 * Return configuration info	 */	case DKIOCGCONF:		DPRINTF_IOCTL("srioctl:  get configuration info\n");		conf = (struct dk_conf *)data;		switch (un->un_dp->ctype) {		case CTYPE_MD21:			conf->dkc_ctype = DKC_MD21;			break;		case CTYPE_ACB4000:			conf->dkc_ctype = DKC_ACB4000;			break;		default:			conf->dkc_ctype = DKC_SCSI_CCS;			break;		}		conf->dkc_dname[0] = 's';		conf->dkc_dname[1] = 'r';		conf->dkc_dname[2] = 0;		conf->dkc_flags = DKI_FMTVOL;#ifndef	OPENPROMS		conf->dkc_cnum = devp->sd_dev->md_mc->mc_ctlr;		conf->dkc_addr = getdevaddr(devp->sd_dev->md_mc->mc_addr);		conf->dkc_space = devp->sd_dev->md_mc->mc_space;		conf->dkc_prio = devp->sd_dev->md_mc->mc_intpri;		if (devp->sd_dev->md_mc->mc_intr)			conf->dkc_vec = devp->sd_dev->md_mc->mc_intr->v_vec;		else			conf->dkc_vec = 0;		(void) strncpy(conf->dkc_cname,				devp->sd_dev->md_driver->mdr_cname, DK_DEVLEN);		conf->dkc_unit = devp->sd_dev->md_unit;		conf->dkc_slave = devp->sd_dev->md_slave;#else	OPENPROMS		conf->dkc_cnum = devp->sd_dev->devi_parent->devi_unit;		conf->dkc_addr = (int)			devp->sd_dev->devi_parent->devi_reg->reg_addr;		conf->dkc_space =			devp->sd_dev->devi_parent->devi_reg->reg_bustype;		conf->dkc_prio =		ipltospl(devp->sd_dev->devi_parent->devi_intr->int_pri);		(void) strcpy(conf->dkc_cname, CNAME);		conf->dkc_cname[3] = CUNIT;		conf->dkc_unit = unit;		conf->dkc_slave = (Tgt(devp)<<3)|Lun(devp);#endif	OPENPROMS		return (0);	/*	 * Return the map for all logical partitions.	 */	case DKIOCGAPART:		DPRINTF_IOCTL("srioctl:  get all logical partitions\n");		for (i = 0; i < NDKMAP; i++)			((struct dk_map *)data)[i] = un->un_map[i];		return (0);	/*	 * Get error status from last command.	 */	case DKIOCGDIAG:		DPRINTF_IOCTL("srioctl:  get error status\n");		diag = (struct dk_diag *) data;		diag->dkd_errcmd  = un->un_last_cmd;		diag->dkd_errsect = un->un_err_blkno;		diag->dkd_errno = un->un_status;		diag->dkd_severe = un->un_err_severe;		un->un_last_cmd   = 0;	/* Reset */		un->un_err_blkno  = 0;		un->un_err_code   = 0;		un->un_err_severe = 0;		return (0);	case CDROMPAUSE:		return (sr_pause_resume(dev, (caddr_t)1));	case CDROMRESUME:		return (sr_pause_resume(dev, (caddr_t)0));	case CDROMPLAYMSF:		return (sr_play_msf(dev, data));	case CDROMPLAYTRKIND:		return (sr_play_trkind(dev, data));	case CDROMREADTOCHDR:		return (sr_read_tochdr(dev, data));	case CDROMREADTOCENTRY:		return (sr_read_tocentry(dev, data));	case CDROMSTOP:		return (sr_start_stop(dev, (caddr_t)0));	case CDROMSTART:		return (sr_start_stop(dev, (caddr_t)1));	case FDKEJECT:	/* for eject command */	case CDROMEJECT:		return (sr_eject(dev));	case CDROMVOLCTRL:		return (sr_volume_ctrl(dev, data));	case CDROMSUBCHNL:		return (sr_read_subchannel(dev, data));	case CDROMREADMODE2:		return (sr_read_mode2(dev, data));	case CDROMREADMODE1:		return (sr_read_mode1(dev, data));	/*	 * Run a generic scsi command (CDROM)	 * user-scsi command	 */	case USCSICMD:		return (srioctl_cmd(dev, data, 0));	/*	 * Handle unknown ioctls here.	 */	default:		DPRINTF_IOCTL("srioctl:  unknown ioctl %x\n", cmd);		return (ENOTTY);	}}

⌨️ 快捷键说明

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