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

📄 sr.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	cdb[2] = 0x81;	cdb[4] = 20;	pkt1 = get_pktiopb(ROUTE, (caddr_t *)&buffer1, 6, 1, 20, B_READ,			NULL_FUNC);	if (!pkt1) {		return (ENOMEM);	}	makecom_all(pkt1, devp, FLAG_NOINTR, 0, cdb);	if (scsi_poll(pkt1) || SCBP_C(pkt1) != STATUS_GOOD ||	    (pkt1->pkt_state & STATE_XFERRED_DATA) == 0 ||	    (pkt1->pkt_resid != 0)) {		DPRINTF("%s%d: MODE SENSE command failed.\n",			DNAME, DUNIT);		free_pktiopb(pkt1, (caddr_t)buffer1, 20);		return (EIO);	}	DPRINTF("%s%d: Parameter from Mode Sense:\n", DNAME, DUNIT);	if (DEBUGGING) {		int	i;		for (i=0; i!=20; i++) {			printf("0x%x ", buffer1[i]);		}	}	/*	 * then, do a mode select to set to mode-1 read	 */	bzero((caddr_t)cdb, 6);	cdb[0] = SCMD_MODE_SELECT;	cdb[4] = 20;	pkt2 = get_pktiopb(ROUTE, (caddr_t *)&buffer2, 6, 1, 20, B_WRITE,			NULL_FUNC);	if (!pkt2) {		return (ENOMEM);	}	/*	 * fill in the parameter list for mode select command	 * values obtained from default value.	 */	bzero(buffer2, 20);	buffer2[3] = 0x08;#ifdef	FIVETWELVE	/*	 * block length of 512 bytes - default mode 1 size	 */	buffer2[10] = 0x02;#else	/*	 * set block length to 2048 bytes	 */	buffer2[10] = 0x08;#endif	FIVETWELVE	buffer2[11] = 0x00;	buffer2[12] = 0x01;	buffer2[13] = 0x06;	buffer2[14] = buffer1[14];	buffer2[15] = buffer1[15];	/*	 * fire the command	 */	makecom_all(pkt2, devp, FLAG_NOINTR, 0, cdb);	if (scsi_poll(pkt2) || SCBP_C(pkt2) != STATUS_GOOD ||	    (pkt2->pkt_state & STATE_XFERRED_DATA) == 0 ||	    (pkt2->pkt_resid != 0)) {		DPRINTF("%s%d: MODE SELECT command failed.\n",			DNAME, DUNIT);		free_pktiopb(pkt2, (caddr_t)buffer2, 20);		return (EIO);	}	free_pktiopb(pkt1, (caddr_t)buffer1, 20);	free_pktiopb(pkt2, (caddr_t)buffer2, 20);	return (0);}#ifndef FIVETWELVE/* * This routine sets the drive to read 2048 bytes per sector */static intsr_two_k(devp)struct scsi_device	*devp;{	struct	scsi_pkt	*pkt1;	struct	scsi_pkt	*pkt2;	caddr_t	buffer1;	caddr_t	buffer2;	char	cdb[6];	DPRINTF("%s%d: switching to reading 2048 bytes per sector.\n",		DNAME, DUNIT);	/*	 * first, do a mode sense of page 1 code	 */	bzero((caddr_t)cdb, 6);	cdb[0] = SCMD_MODE_SENSE;	/* get default page 1 values */	cdb[2] = 0x81;	cdb[4] = 20;	pkt1 = get_pktiopb(ROUTE, (caddr_t *)&buffer1, 6, 1, 20, B_READ,			NULL_FUNC);	if (!pkt1) {		return (ENOMEM);	}	makecom_all(pkt1, devp, FLAG_NOINTR, 0, cdb);	if (scsi_poll(pkt1) || SCBP_C(pkt1) != STATUS_GOOD ||	    (pkt1->pkt_state & STATE_XFERRED_DATA) == 0 ||	    (pkt1->pkt_resid != 0)) {		DPRINTF("%s%d: MODE SENSE command failed.\n",			DNAME, DUNIT);		free_pktiopb(pkt1, (caddr_t)buffer1, 20);		return (EIO);	}	DPRINTF("%s%d: Parameter from Mode Sense:\n", DNAME, DUNIT);	if (DEBUGGING) {		int	i;		for (i=0; i!=20; i++) {			printf("0x%x ", buffer1[i]);		}	}	/*	 * then, do a mode select to set to reading 2048 bytes per sector	 */	bzero(cdb, 6);	cdb[0] = SCMD_MODE_SELECT;	cdb[4] = 20;	pkt2 = get_pktiopb(ROUTE, (caddr_t *)&buffer2, 6, 1, 20, B_WRITE,			NULL_FUNC);	if (!pkt2) {		return (ENOMEM);	}	/*	 * fill in the parameter list for mode select command	 * values obtained from default value.	 */	bzero(buffer2, 20);	buffer2[3] = 0x08;	/*	 * block length of 2048 bytes (hex 800)	 */	buffer2[10] = 0x08;	buffer2[11] = 0x00;	buffer2[12] = 0x01;	buffer2[13] = 0x06;	buffer2[14] = buffer1[14];	buffer2[15] = buffer1[15];	/*	 * fire the command	 */	makecom_all(pkt2, devp, FLAG_NOINTR, 0, cdb);	if (scsi_poll(pkt2) || SCBP_C(pkt2) != STATUS_GOOD ||	    (pkt2->pkt_state & STATE_XFERRED_DATA) == 0 ||	    (pkt2->pkt_resid != 0)) {		DPRINTF("%s%d: MODE SELECT command failed.\n",			DNAME, DUNIT);		free_pktiopb(pkt2, (caddr_t)buffer2, 20);		return (EIO);	}	free_pktiopb(pkt1, (caddr_t)buffer1, 20);	free_pktiopb(pkt2, (caddr_t)buffer2, 20);	return (0);}#endif/* * This routine locks the drive door */static intsr_lock_door(devp)struct scsi_device	*devp;{	struct	scsi_pkt	*pkt;	char	cdb[6];	DPRINTF("%s%d: locking the drive door\n",		DNAME, DUNIT);	bzero(cdb, 6);	cdb[0] = SCMD_DOORLOCK;	cdb[4] = 0x01;	pkt = scsi_pktalloc(ROUTE, CDB_GROUP0, 1, NULL_FUNC);	if (!pkt) {		return (ENOMEM);	}	makecom_all(pkt, devp, FLAG_NOINTR, 0, cdb);	if (scsi_poll(pkt) || SCBP_C(pkt) != STATUS_GOOD) {		DPRINTF("%s%d: Prevent/Allow Medium Removal command failed.\n",			DNAME, DUNIT);		scsi_resfree(pkt);		return (EIO);	}	scsi_resfree(pkt);	return (0);}/* * This routine read the drive's capacity and logical block size */static intsr_read_capacity(devp)struct scsi_device	*devp;{	struct	scsi_pkt	*pkt;	caddr_t	buffer;	register struct	scsi_disk	*un;	DPRINTF("%s%d: reading the drive's capacity\n",		DNAME, DUNIT);#ifdef OPENPROMS	sr_set_dkn(devp);#endif OPENPROMS	un = UPTR;	pkt = get_pktiopb(ROUTE, &buffer, CDB_GROUP1, 1,			sizeof (struct scsi_capacity), B_READ, NULL_FUNC);	if (!pkt) {		return (ENOMEM);	}	makecom_g1(pkt, devp, 0, SCMD_READ_CAPACITY, 0, 0);	if ((scsi_poll(pkt) == 0) && (SCBP_C(pkt) == STATUS_GOOD) &&		(pkt->pkt_state & STATE_XFERRED_DATA) &&		(pkt->pkt_resid == 0)) {		un->un_capacity = ((struct scsi_capacity *)buffer)->capacity+1;		un->un_lbasize = ((struct scsi_capacity *)buffer)->lbasize;		free_pktiopb(pkt, buffer, sizeof (struct scsi_capacity));		return (0);	} else {		free_pktiopb(pkt, buffer, sizeof (struct scsi_capacity));		return (EIO);	}}/* * *		Unit start and Completion * */static voidsrstart(devp)register struct scsi_device *devp;{	register struct buf *bp;	register struct scsi_disk *un = UPTR;	register struct diskhd *dp = &un->un_utab;	DPRINTF("srstart\n");	if (dp->b_forw) {		printf("srstart: busy already\n");		return;	} else if ((bp = dp->b_actf) == NULL) {		DPRINTF("%s%d: srstart idle\n", DNAME, DUNIT);		return;	}	if (!BP_PKT(bp)) {		make_sr_cmd(devp, bp, srrunout);		if (!BP_PKT(bp)) {			/*			 * XXX: actually, we should see whether or not			 * XXX:	we could fire up a SCMD_SEEK operation			 * XXX:	here. We may not have been able to go			 * XXX:	because DVMA had run out, not because			 * XXX:	we were out of command packets.			 */			New_state(un, SR_STATE_RWAIT);			return;		} else {			New_state(un, SR_STATE_OPEN);		}	}	dp->b_forw = bp;	dp->b_actf = bp->b_actf;	bp->b_actf = 0;	/*	 * try and link this command with the one that	 * is next	 */	if ((scsi_options & SCSI_OPTIONS_LINK) &&		(un->un_dp->options & SR_DOLINK) &&		dp->b_actf && bp != un->un_sbufp &&			CDBP(BP_PKT(bp))->g0_link == 0) {		if (BP_PKT(dp->b_actf)) {			CDBP(BP_PKT(bp))->g0_link = 1;		} else {			make_sr_cmd(devp, dp->b_actf, NULL_FUNC);			if (BP_PKT(dp->b_actf)) {				CDBP(BP_PKT(bp))->g0_link = 1;			}		}	}	if (pkt_transport(BP_PKT(bp)) == 0) {		printf("%s%d: transport rejected\n", DNAME, DUNIT);		bp->b_flags |= B_ERROR;		srdone(devp);	} else if (dp->b_actf && !BP_PKT(dp->b_actf)) {		make_sr_cmd(devp, dp->b_actf, NULL_FUNC);	}}static intsrrunout(){	register i, s = splr(srpri);	register struct scsi_device *devp;	register struct scsi_disk *un;	for (i = 0; i < nsr; i++) {		devp = srunits[i];		if (devp && devp->sd_present && (un=UPTR) && un->un_gvalid) {			if (un->un_state == SR_STATE_RWAIT) {				DPRINTF("%s%d: resource retry\n", DNAME,					DUNIT);				srstart(devp);				if (un->un_state == SR_STATE_RWAIT) {					(void) splx(s);					return (0);				}				DPRINTF("%s%d: resource gotten\n", DNAME,					DUNIT);			}		}	}	(void) splx(s);	return (1);}static voidsrdone(devp)register struct scsi_device *devp;{	register struct buf *bp;	register struct scsi_disk *un = UPTR;	register struct diskhd *dp = &un->un_utab;	bp = dp->b_forw;	dp->b_forw = NULL;	/*	 * Start the next one before releasing resources on this one	 */	if (dp->b_actf) {		DPRINTF("%s%d: srdone calling srstart\n", DNAME, DUNIT);		srstart(devp);	}	if (bp != un->un_sbufp) {		scsi_resfree(BP_PKT(bp));		iodone(bp);		DPRINTF("%s%d: regular done resid %d\n",			DNAME, DUNIT, bp->b_resid);	} else {		DPRINTF("%s%d: special done resid %d\n",			DNAME, DUNIT, bp->b_resid);		bp->b_flags |= B_DONE;		wakeup((caddr_t) bp);	}}static voidmake_sr_cmd(devp, bp, func)register struct scsi_device *devp;register struct buf *bp;int (*func)();{	register struct scsi_pkt *pkt;	register struct scsi_disk *un = UPTR;	register daddr_t blkno = 0;	int tval = DEFAULT_SR_TIMEOUT, count, com, flags;	char	*cdb;	flags = (scsi_options & SCSI_OPTIONS_DR) ? 0: FLAG_NODISCON;	if (bp != un->un_sbufp) {		long blkovr;		DPRINTF("make_sr_cmd: regular\n");		pkt = scsi_resalloc(ROUTE, CDB_GROUP0, 1, (opaque_t)bp, func);		if ((BP_PKT(bp) = pkt) == (struct scsi_pkt *) 0) {			return;		}		/* count is number of blocks */		count = bp->b_bcount >> SECDIV;#ifdef FIVETWELVE		blkno = dkblock(bp);#else		/* shift block number. since block size is 2048 */		blkno = dkblock(bp) >> 2;#endif FIVETWELVE		DPRINTF("bp->b_bcount is %d\n", bp->b_bcount);		DPRINTF("count is %d\n", count);		DPRINTF("blkno is %d\n", blkno);		/*		 * Make sure we don't run off the end of the CDROM		 */		if ((blkovr = blkno + count - un->un_capacity) > 0) {			DPRINTF("%s%d: (%d, %d) overrun by %d blocks\n",				DNAME, DUNIT, blkno, bp->b_bcount, blkovr);			bp->b_resid = (blkovr << SECDIV);			count -= blkovr;		} else {			bp->b_resid = 0;		}		if (bp->b_flags & B_READ) {			DPRINTF("%s%d: read", DNAME, DUNIT);			com = SCMD_READ;		} else {			DPRINTF("%s%d: write", DNAME, DUNIT);			com = SCMD_WRITE;		}		DPRINTF(" blk %d amt 0x%x (%d) resid %d\n", blkno,			count<<SECDIV, count<<SECDIV, bp->b_resid);		makecom_g0(pkt, devp, flags, com, (int) blkno, count);		pkt->pkt_pmon = un->un_dkn;	} else {		struct buf *abp = bp;		int group;		/*		 * Some commands are group 1 commands, some are group 0.		 * It is legitimate to allocate a cdb sufficient for any.		 * Therefore, we'll ask for a GROUP 1 cdb.		 */		/*		 * stored in bp->b_forw is a pointer to cdb		 */		cdb = (char *)bp->b_forw;		com  = (int)cdb_cmd(cdb);		group = ((unsigned char)com) >> 5;		blkno = bp->b_blkno;		count = bp->b_bcount;		DPRINTF("%s%d: blkno is %d, count is %d ", DNAME, DUNIT,			blkno, count);		switch (com) {		case SCMD_READ:			DPRINTF_IOCTL("special %s\n", (com==SCMD_READ)?"read":				"write");			count = bp->b_bcount >> SECDIV;			break;		default:			DPRINTF_IOCTL("scsi command 0x%x\n", com);			if (bp->b_bcount == 0) {				abp = (struct buf *)0;			}			break;		}		pkt = scsi_resalloc(ROUTE, CDB_GROUP1, 1,			(opaque_t)abp, SLEEP_FUNC);		makecom_all(pkt, devp, flags, group, cdb);		pkt->pkt_pmon = -1;	}	if (un->un_dp->options & SR_NODISC)		pkt->pkt_flags |= FLAG_NODISCON;	pkt->pkt_comp = srintr;	pkt->pkt_time = tval;	pkt->pkt_private = (opaque_t) bp;	BP_PKT(bp) = pkt;}/* * *		Interrupt Service Routines * *//* * */staticsrrestart(arg)caddr_t arg;{	struct scsi_device *devp = (struct scsi_device *) arg;	struct buf *bp;	register s = splr(srpri);	printf("srrestart\n");	if ((bp = UPTR->un_utab.b_forw) == 0) {		printf("%s%d: busy restart aborted\n", DNAME, DUNIT);	} else {		struct scsi_pkt *pkt;		if (UPTR->un_state == SR_STATE_SENSING) {			pkt = UPTR->un_rqs;		} else {			pkt = BP_PKT(bp);		}		if (pkt_transport(pkt) == 0) {			printf("%s%d: restart transport failed\n", DNAME,				DUNIT);			UPTR->un_state = UPTR->un_last_state;			bp->b_resid = bp->b_bcount;			bp->b_flags |= B_ERROR;			srdone(devp);		}	}	(void) splx(s);}/* * Command completion processing * */static voidsrintr(pkt)struct scsi_pkt *pkt;{	register struct scsi_device *devp;	register struct scsi_disk *un;	register struct buf *bp;	register action;	/*	 * Do some sanity checking	 */	if (!pkt) {		printf("sdintr: null packet?\n");		return;	} else if (pkt->pkt_flags & FLAG_NOINTR) {		printf("srintr:internal error - got a non-interrupting cmd\n");		return;	} else if ((bp = (struct buf *) pkt->pkt_private) == 0) {		printf("sdintr: packet with no buffer pointer\n");		return;	}	if (!(devp = srunits[SRUNIT(bp->b_dev)]) || !(un = UPTR)) {		printf("srintr: mangled data structures\n");		return;	} else if (bp != un->un_utab.b_forw) {		printf("srintr: completed packet's buffer not on queue\n");		return;	}	DPRINTF("srintr:\n");	if (pkt->pkt_reason != CMD_CMPLT) {		action = sr_handle_incomplete(devp);	/*	 * At this point we know that the command was successfully	 * completed. Now what?	 */	} else if (un->un_state == SR_STATE_SENSING) {		/*		 * okay. W

⌨️ 快捷键说明

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