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

📄 sr.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*^L*//* * *	Local Functions * *//* * Run a command for srioctl. */static intsrioctl_cmd(dev, data, addr_flag)dev_t dev;caddr_t data;int	addr_flag;{	register struct scsi_device *devp;	register struct buf *bp, *rbp;	register struct scsi_disk *un;	int err = 0, flag, s;	int err1;	struct uscsi_cmd	*scmd;	char	cmdblk[12], *cdb = cmdblk;	faultcode_t fault_err = -1;	int	blkno = 0;	/*	 * Checking for sanity done in srioctl	 */	devp = srunits[SRUNIT(dev)];	un = UPTR;	scmd = (struct uscsi_cmd *)data;	if (addr_flag & SR_USCSI_CDB_KERNEL) {		cdb = scmd->uscsi_cdb;	} else {		if (copyin(scmd->uscsi_cdb, (caddr_t)cdb,			(u_int)scmd->uscsi_cdblen)) {			return (EINVAL);		}	}	if (DEBUGGING) {		int	i;		printf("%s%d: cdb:", DNAME, DUNIT);		for (i=0; i!=scmd->uscsi_cdblen; i++) {			printf(" 0x%x", (u_char)cdb[i]);		}		printf("\n");	}	switch (cdb_cmd(cdb)) {	case SCMD_READ:		blkno = cdb0_blkno(cdb);/*		if (addr_flag & SR_MODE2) {			if (scmd->uscsi_buflen & (CDROM_MODE2_SIZE - 1)) {				return (EINVAL);			}		} else {*/		if (!(addr_flag & SR_MODE2)) {			if (scmd->uscsi_buflen & (SECSIZE-1)) {				return (EINVAL);			}		}		/* FALLTHRU */	default:		flag = (scmd->uscsi_flags & USCSI_READ) ? B_READ : B_WRITE;		break;	}	if (DEBUGGING_ALL) {		printf("srioctl_cmd:  cmd= %x  blk= %x buflen= 0x%x\n",			cdb_cmd(cdb), blkno, scmd->uscsi_buflen);		if (flag == B_WRITE && scmd->uscsi_buflen) {			auto u_int i, amt = min(64, (u_int)scmd->uscsi_buflen);			char bufarray[64], *buf=bufarray;			if (addr_flag & SR_USCSI_BUF_KERNEL) {				buf = scmd->uscsi_bufaddr;			} else {				if (copyin(scmd->uscsi_bufaddr, (caddr_t)buf,					amt)) {					return (EFAULT);				}			}			printf("user's buf:");			for (i = 0; i < amt; i++) {				printf(" 0x%x", buf[i]&0xff);			}			printf("\n");		}	}	/*	 * Get buffer resources...	 */	bp = UPTR->un_sbufp;	rbp = UPTR->un_rbufp;	s = splr(srpri);	while (bp->b_flags & B_BUSY) {		bp->b_flags |= B_WANTED;		(void) sleep((caddr_t) bp, PRIBIO);	}	bzero((caddr_t) bp, sizeof (struct buf));	bp->b_flags = B_BUSY | flag;	(void) splx(s);	/*	 * check to see if the command is mode-2 read. If it is,	 * the driver has to switch the drive to mode 2, fire	 * the command and switch the drive back to mode 1.	 * The bp->b_flags should be set to busy all the time	 * so that other I/O request will not be serviced.	 */	if (addr_flag & SR_MODE2) {		s = splr(srpri);		while (rbp->b_flags & B_BUSY) {			rbp->b_flags |= B_WANTED;			(void) sleep((caddr_t) rbp, PRIBIO);		}		bzero((caddr_t) rbp, sizeof (struct buf));		rbp->b_flags |= B_BUSY;		(void) splx(s);		New_state(un, SR_STATE_MODE2);		err = sr_mode_2(devp);		if (err) {			DPRINTF("srioctl_cmd: error in switching to mode-2\n");			New_state(un, SR_STATE_OPEN);			goto done;		}	}	/*	 * Set options.	 */	UPTR->un_soptions = 0;	if ((scmd->uscsi_flags & DK_SILENT) && !(DEBUGGING_ALL)) {		UPTR->un_soptions |= DK_SILENT;	}	if (scmd->uscsi_flags & DK_ISOLATE)		UPTR->un_soptions |= DK_ISOLATE;	if (scmd->uscsi_flags & DK_DIAGNOSE)		UPTR->un_soptions |= DK_DIAGNOSE;	/*	 * NB:	 * I don't know why, but changing the order of some of these things	 * below causes panics in kmem_free later on when ioctl(sys_generic.c)	 * attempt to kmem_free something it shouldn't.	 */	/*	 * Fill in the buffer with information we need	 *	 */	bp->b_forw = (struct buf *)cdb;	bp->b_dev = dev;	if ((bp->b_bcount = scmd->uscsi_buflen) > 0)		bp->b_un.b_addr = scmd->uscsi_bufaddr;	bp->b_blkno = blkno;	if ((scmd->uscsi_buflen) && !(addr_flag & SR_USCSI_BUF_KERNEL)) {		bp->b_flags |= B_PHYS;		bp->b_proc = u.u_procp;		u.u_procp->p_flag |= SPHYSIO;		/*		 * Fault lock the address range of the buffer.		 */		fault_err = as_fault(u.u_procp->p_as, bp->b_un.b_addr,				(u_int)bp->b_bcount, F_SOFTLOCK,				(bp->b_flags & B_READ) ? S_WRITE : S_READ);		if (fault_err != 0) {			if (FC_CODE(fault_err) == FC_OBJERR)				err = FC_ERRNO(fault_err);			else				err = EFAULT;		} else if (buscheck(bp) < 0) {			err = EFAULT;		}	}	/*	 * If no errors, make and run the command.	 */	if (err == 0) {		make_sr_cmd(devp, bp, SLEEP_FUNC);		srstrategy(bp);		s = splr(srpri);		while ((bp->b_flags & B_DONE) == 0) {			(void) sleep((caddr_t) bp, PRIBIO);		}		(void) splx(s);		/*		 * get the status block		 */		scmd->uscsi_status = (int)SCBP_C(BP_PKT(bp));		DPRINTF("%s%d: status is %d\n", DNAME, DUNIT,			scmd->uscsi_status);		/*		 * Release the resources.		 *		 */		err = geterror(bp);		if (fault_err == 0) {			(void) as_fault(u.u_procp->p_as, bp->b_un.b_addr,					(u_int)bp->b_bcount, F_SOFTUNLOCK,					(bp->b_flags&B_READ)? S_WRITE: S_READ);			u.u_procp->p_flag &= ~SPHYSIO;			bp->b_flags &= ~B_PHYS;		}		scsi_resfree(BP_PKT(bp));	}	/*	 * see if the request was for mode-2 read.	 * If it was, the driver has to turn the read-mode back	 * to mode-1.	 */	if (addr_flag & SR_MODE2) {		err1 = sr_mode_1(devp);		New_state(un, SR_STATE_OPEN);		if (err1) {			DPRINTF("srioctl_cmd: error in switching to mode-1\n");			goto done;		}	}	done:	s = splr(srpri);	if (bp->b_flags & B_WANTED) {		wakeup((caddr_t)bp);	}	UPTR->un_soptions = 0;	if (addr_flag & SR_MODE2) {		if (rbp->b_flags & B_WANTED) {			wakeup((caddr_t)rbp);		}		rbp->b_flags &= ~(B_BUSY|B_WANTED);	}	bp->b_flags &= ~(B_BUSY|B_WANTED);	(void) splx(s);	DPRINTF_IOCTL("returning %d from ioctl\n", err);	return (err);}static voidsr_offline(devp)register struct scsi_device *devp;{	register struct scsi_disk *un = UPTR;	printf("%s%d: offline or disc ejected\n", DNAME, DUNIT);#ifdef	OPENPROMS	(void) remdk((int) un->un_dkn);#endif	OPENPROMS	free_pktiopb(un->un_rqs, (caddr_t)devp->sd_sense, SENSE_LENGTH);	(void) kmem_free((caddr_t) un->un_rbufp,		(unsigned) (sizeof (struct buf)));	(void) kmem_free((caddr_t) un->un_sbufp,		(unsigned) (sizeof (struct buf)));	(void) kmem_free((caddr_t) un,		(unsigned) (sizeof (struct scsi_disk)));	devp->sd_private = (opaque_t) 0;	IOPBFREE (devp->sd_inq, sizeof (struct scsi_inquiry));	devp->sd_inq = 0;	devp->sd_sense = 0;	devp->sd_present = 0;}static voidsr_not_ready(devp)register struct scsi_device *devp;{	register u_char	*sb;	sb = (u_char *)devp->sd_sense;	switch (sb[12]) {	case 0x04:		printf("%s%d: logical unit not ready\n", DNAME, DUNIT);		break;	case 0x05:		printf("%s%d: unit does not respond to selection\n",		DNAME, DUNIT);		break;	case 0x3a:		DPRINTF("%s%d: Caddy not inserted in drive\n",		DNAME, DUNIT);		sr_ejected(devp);		break;	default:		printf("%s%d: Unit not Ready. Additional sense code %d\n",		DNAME, DUNIT, sb[12]);		break;	}}static voidsr_ejected(devp)register struct scsi_device *devp;{	register struct scsi_disk *un = UPTR;#ifdef	OPENPROMS	(void) remdk((int) un->un_dkn);#endif	OPENPROMS	un->un_capacity = -1;	un->un_lbasize = -1;}#ifdef OLDCODE/* * This routine checks and see if a new disc has been inserted. * It performs all the necessary actions. * It assumes the driver is in the SR_STATE_EJECTED driver state. */static intsr_read_new_disc(dev)dev_t	dev;{	register struct scsi_device *devp;	register struct scsi_disk *un;	u_char	state;	devp = srunits[SRUNIT(dev)];	un = UPTR;	New_state(un, SR_STATE_OPENING);	if (sr_unit_ready(dev) == 0) {		sr_not_ready(devp);		return (0);	}	state = un->un_last_state;	New_state(un, SR_STATE_OPENING);	if (sr_read_capacity(dev) != 0) {		un->un_state = un->un_last_state;		un->un_last_state = state;		return (0);	}	un->un_state = un->un_last_state;	un->un_last_state = state;	/* 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 (0);	}	un->un_state = un->un_last_state;	un->un_last_state = state;	New_state(un, SR_STATE_OPEN);	printf("%s%d: disc inserted in drive\n", DNAME, DUNIT);#ifdef	OPENPROMS	sr_set_dkn(devp);#endif	OPENPROMS	return (1);}#endif OLDCODE/* * This routine called to see whether unit is (still) there. Must not * be called when un->un_sbufp is in use, and must not be called with * an unattached disk. Soft state of disk is restored to what it was * upon entry- up to caller to set the correct state. */static intsr_unit_ready(dev)dev_t dev;{	struct scsi_device *devp = srunits[SRUNIT(dev)];	struct scsi_disk *un = UPTR;	auto struct uscsi_cmd cblk, *com = &cblk;	u_char state = un->un_last_state;	char	cdb[6];	New_state(un, SR_STATE_OPENING);	com->uscsi_bufaddr = 0;	com->uscsi_buflen = 0;	cdb[0] = SCMD_TEST_UNIT_READY;	cdb[1] = 0;	cdb[2] = 0;	cdb[3] = 0;	cdb[4] = 0;	cdb[5] = 0;	com->uscsi_flags = DK_DIAGNOSE|DK_SILENT;	com->uscsi_cdb = cdb;	com->uscsi_cdblen = 6;	/*	 * try it twice...	 */	if (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL) &&	    srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL)) {		un->un_state = un->un_last_state;		un->un_last_state = state;		return (0);	}	un->un_state = un->un_last_state;	un->un_last_state = state;	return (1);}/* * makecom_all * note: for now, only bit 7 and bit 6 of the control byte in the cdb is *	 assigned. Those are the two vendor-unique control bits. */static voidmakecom_all(pkt, devp, flag, group, cdb)struct 	scsi_pkt	*pkt;struct	scsi_device	*devp;int	flag;int	group;char	*cdb;{	register union	scsi_cdb	*scsi_cdb;	pkt->pkt_address = (devp)->sd_address;	pkt->pkt_flags = flag;	scsi_cdb = (union scsi_cdb *)pkt->pkt_cdbp;	scsi_cdb->scc_cmd = cdb_cmd(cdb);	scsi_cdb->scc_lun = pkt->pkt_address.a_lun;	switch (group) {	case 0:		scsi_cdb->g0_addr2 = cdb_tag(cdb);		scsi_cdb->g0_addr1 = (u_char)cdb[2];		scsi_cdb->g0_addr0 = (u_char)cdb[3];		scsi_cdb->g0_count0 = (u_char)cdb[4];		scsi_cdb->g0_vu_1 = cdb[5] & 0x80;		scsi_cdb->g0_vu_0 = cdb[5] & 0x40;		break;	case 1:	case 2:	case 6: /*		 *edu: only for now. eventually, we will not		 *support group 6.		 */		scsi_cdb->g1_reladdr = cdb_tag(cdb);		scsi_cdb->g1_addr3 = (u_char)cdb[2];		scsi_cdb->g1_addr2 = (u_char)cdb[3];		scsi_cdb->g1_addr1 = (u_char)cdb[4];		scsi_cdb->g1_addr0 = (u_char)cdb[5];		scsi_cdb->g1_rsvd0 = (u_char)cdb[6];		scsi_cdb->g1_count1 = (u_char)cdb[7];		scsi_cdb->g1_count0 = (u_char)cdb[8];		scsi_cdb->g1_vu_1 = cdb[9] & 0x80;		scsi_cdb->g1_vu_0 = cdb[9] & 0x40;		break;	default:		DPRINTF("makecom_all: does not support group %d\n",			group);	}}/* * This routine locks the cdrom door and prevent medium removal. */static intsr_medium_removal(dev, flag)dev_t dev;int flag;{	auto struct uscsi_cmd cblk, *com = &cblk;	char	cdb[6];	com->uscsi_bufaddr = 0;	com->uscsi_buflen = 0;	cdb[0] = SCMD_DOORLOCK;	cdb[1] = 0;	cdb[2] = 0;	cdb[3] = 0;	cdb[4] = flag;	cdb[5] = 0;	com->uscsi_flags = DK_DIAGNOSE|DK_SILENT;	com->uscsi_cdb = cdb;	com->uscsi_cdblen = 6;	return (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL));}/* * This routine does a pause or resume to the cdrom player. Only affect * audio play operation. */static intsr_pause_resume(dev, data)dev_t	dev;caddr_t	data;{	int	flag;	struct uscsi_cmd cblk, *com=&cblk;	char	cdb[10];	flag = (int)data;	bzero((caddr_t)cdb, 10);	cdb[0] = SCMD_PAUSE_RESUME;	cdb[8] = (flag == 0) ? 1 : 0;	com->uscsi_cdb = cdb;	com->uscsi_cdblen = 10;	com->uscsi_bufaddr = 0;	com->uscsi_buflen = 0;	com->uscsi_flags = DK_DIAGNOSE|DK_SILENT;	return (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL));}/* * This routine plays audio by msf */static intsr_play_msf(dev, data)dev_t	dev;caddr_t	data;{	struct uscsi_cmd cblk, *com=&cblk;	char	cdb[10];	register struct cdrom_msf	*msf;	msf = (struct cdrom_msf *)data;	bzero((caddr_t)cdb, 10);	cdb[0] = SCMD_PLAYAUDIO_MSF;	cdb[3] = msf->cdmsf_min0;	cdb[4] = msf->cdmsf_sec0;	cdb[5] = msf->cdmsf_frame0;	cdb[6] = msf->cdmsf_min1;	cdb[7] = msf->cdmsf_sec1;	cdb[8] = msf->cdmsf_frame1;	com->uscsi_cdb = cdb;	com->uscsi_cdblen = 10;	com->uscsi_bufaddr = 0;	com->uscsi_buflen = 0;	com->uscsi_flags = DK_DIAGNOSE|DK_SILENT;	return (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL));}/* * This routine plays audio by track/index */static intsr_play_trkind(dev, data)dev_t	dev;caddr_t	data;{	struct uscsi_cmd cblk, *com=&cblk;	char	cdb[10];	register struct cdrom_ti	*ti;	ti = (struct cdrom_ti *)data;	bzero((caddr_t)cdb, 10);	cdb[0] = SCMD_PLAYAUDIO_TI;	cdb[4] = ti->cdti_trk0;	cdb[5] = ti->cdti_ind0;	cdb[7] = ti->cdti_trk1;	cdb[8] = ti->cdti_ind1;	com->uscsi_cdb = cdb;	com->uscsi_cdblen = 10;	com->uscsi_bufaddr = 0;	com->uscsi_buflen = 0;	com->uscsi_flags = DK_DIAGNOSE|DK_SILENT;	return (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL));}/* * This routine starts the drive, stops the drive or ejects the disc

⌨️ 快捷键说明

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