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

📄 scsi-linux-sg.c

📁 创建一个符合iso-9660标准的iso文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	int	f;	int	tmo;{	tmo *= HZ;	if (tmo)		tmo += HZ/2;	if (ioctl(f, SG_SET_TIMEOUT, &tmo) < 0)		comerr("Cannot set SG_SET_TIMEOUT.\n");}/* * Get misaligned int. * Needed for all recent processors (sparc/ppc/alpha) * because the /dev/sg design forces us to do misaligned * reads of integers. */#ifdef	MISALIGNLOCAL intscsi_getint(ip)	int	*ip;{		 int	ret;	register char	*cp = (char *)ip;	register char	*tp = (char *)&ret;	register int	i;	for (i = sizeof(int); --i >= 0; )		*tp++ = *cp++;		return (ret);}#define	GETINT(a)	scsi_getint(&(a))#else#define	GETINT(a)	(a)#endif#ifdef	SG_IOLOCAL intscsi_send(scgp, f, sp)	SCSI		*scgp;	int		f;	struct scg_cmd	*sp;{	int		ret;	sg_io_hdr_t	sg_io;	if (f < 0) {		sp->error = SCG_FATAL;		sp->ux_errno = EIO;		return (0);	}	if (scglocal(scgp)->isold > 0) {		return (scsi_rwsend(scgp, f, sp));	}	fillbytes((caddr_t)&sg_io, sizeof(sg_io), '\0');	sg_io.interface_id = 'S';	if (sp->flags & SCG_RECV_DATA) {		sg_io.dxfer_direction = SG_DXFER_FROM_DEV;	} else if (sp->size > 0) {		sg_io.dxfer_direction = SG_DXFER_TO_DEV;	} else {		sg_io.dxfer_direction = SG_DXFER_NONE;	}	sg_io.cmd_len = sp->cdb_len;	if (sp->sense_len > SG_MAX_SENSE)		sg_io.mx_sb_len = SG_MAX_SENSE;	else		sg_io.mx_sb_len = sp->sense_len;	sg_io.dxfer_len = sp->size;	sg_io.dxferp = sp->addr;	sg_io.cmdp = sp->cdb.cmd_cdb;	sg_io.sbp = sp->u_sense.cmd_sense;	sg_io.timeout = sp->timeout*1000;	sg_io.flags |= SG_FLAG_DIRECT_IO;	ret = ioctl(f, SG_IO, &sg_io);	if (scgp->debug)		printf("ioctl ret: %d\n", ret);	if (ret < 0) {		sp->ux_errno = geterrno();		/*		 * Check if SCSI command cound not be send at all.		 */		if (sp->ux_errno == EINVAL && scglocal(scgp)->isold < 0) {			scglocal(scgp)->isold = 1;			return (scsi_rwsend(scgp, f, sp));		}		if (sp->ux_errno == ENOTTY || sp->ux_errno == ENXIO ||		    sp->ux_errno == EINVAL || sp->ux_errno == EACCES) {			return (-1);		}	}	sp->u_scb.cmd_scb[0] = sg_io.status;	sp->sense_count = sg_io.sb_len_wr;	if (scgp->debug)		printf("host_status: %02X driver_status: %02X\n",				sg_io.host_status, sg_io.driver_status);	switch (sg_io.host_status) {	case DID_OK:			if ((sg_io.driver_status & DRIVER_SENSE) != 0)				sp->error = SCG_RETRYABLE;			break;	case DID_NO_CONNECT:	/* Arbitration won, retry NO_CONNECT? */	case DID_BAD_TARGET:			sp->error = SCG_FATAL;			break;		case DID_TIME_OUT:			sp->error = SCG_TIMEOUT;			break;	default:			sp->error = SCG_RETRYABLE;			break;	}	if (sp->error && sp->ux_errno == 0)		sp->ux_errno = EIO;	sp->resid = sg_io.resid;	return (0);}#else#	define	scsi_rwsend	scsi_send#endifLOCAL intscsi_rwsend(scgp, f, sp)	SCSI		*scgp;	int		f;	struct scg_cmd	*sp;{	struct sg_rq	*sgp;	struct sg_rq	*sgp2;	int	i;	int	pack_len;	int	reply_len;	int	amt = sp->cdb_len;	struct sg_rq {		struct sg_header	hd;		unsigned char		buf[MAX_DMA_LINUX+SCG_MAX_CMD];	} sg_rq;#ifdef	SG_GET_BUFSIZE		/* We may use a 'sg' version 2 driver	*/	char	driver_byte;	char	host_byte;	char	msg_byte;	char	status_byte;#endif	if (f < 0) {		sp->error = SCG_FATAL;		sp->ux_errno = EIO;		return (0);	}#ifdef	USE_PG	if (scgp->scsibus == scglocal(scgp)->pgbus)		return (pg_send(scgp, f, sp));#endif	if (sp->timeout != scgp->deftimeout)		sg_settimeout(f, sp->timeout);	sgp2 = sgp = &sg_rq;	if (sp->addr == scglocal(scgp)->SCSIbuf) {		sgp = (struct sg_rq *)			(scglocal(scgp)->SCSIbuf - (sizeof(struct sg_header) + amt));		sgp2 = (struct sg_rq *)			(scglocal(scgp)->SCSIbuf - (sizeof(struct sg_header)));	} else {		if (scgp->debug) {			printf("DMA addr: 0x%8.8lX size: %d - using copy buffer\n",				(long)sp->addr, sp->size);		}		if (sp->size > (int)(sizeof(sg_rq.buf) - SCG_MAX_CMD)) {			if (scglocal(scgp)->xbuf == NULL) {				scglocal(scgp)->xbufsize = scgp->maxbuf;				scglocal(scgp)->xbuf =					malloc(scglocal(scgp)->xbufsize +						SCG_MAX_CMD +						sizeof(struct sg_header));				if (scgp->debug) {					printf("Allocted DMA copy buffer, addr: 0x%8.8lX size: %ld\n",						(long)scglocal(scgp)->xbuf,						scgp->maxbuf);				}			}			if (scglocal(scgp)->xbuf == NULL ||				sp->size > scglocal(scgp)->xbufsize) {				errno = ENOMEM;				return (-1);			}			sgp2 = sgp = (struct sg_rq *)scglocal(scgp)->xbuf;		}	}	/*	 * This is done to avoid misaligned access of sgp->some_int	 */	pack_len = sizeof(struct sg_header) + amt;	reply_len = sizeof(struct sg_header);	if (sp->flags & SCG_RECV_DATA) {		reply_len += sp->size;	} else {		pack_len += sp->size;	}#ifdef	MISALIGN	/*	 * sgp->some_int may be misaligned if (sp->addr == SCSIbuf)	 * This is no problem on Intel porocessors, however	 * all other processors don't like it.	 * sizeof(struct sg_header) + amt is usually not a multiple of	 * sizeof(int). For this reason, we fill in the values into sg_rq	 * which is always corectly aligned and then copy it to the real	 * location if this location differs from sg_rq.	 * Never read/write directly to sgp->some_int !!!!!	 */	fillbytes((caddr_t)&sg_rq, sizeof(struct sg_header), '\0');	sg_rq.hd.pack_len = pack_len;	sg_rq.hd.reply_len = reply_len;	sg_rq.hd.pack_id = scglocal(scgp)->pack_id++;/*	sg_rq.hd.result = 0;	not needed because of fillbytes() */	if ((caddr_t)&sg_rq != (caddr_t)sgp)		movebytes((caddr_t)&sg_rq, (caddr_t)sgp, sizeof(struct sg_header));#else	fillbytes((caddr_t)sgp, sizeof(struct sg_header), '\0');	sgp->hd.pack_len = pack_len;	sgp->hd.reply_len = reply_len;	sgp->hd.pack_id = scglocal(scgp)->pack_id++;/*	sgp->hd.result = 0;	not needed because of fillbytes() */#endif	if (amt == 12)		sgp->hd.twelve_byte = 1;	for (i = 0; i < amt; i++ ) {		sgp->buf[i] = sp->cdb.cmd_cdb[i];;	}	if (!(sp->flags & SCG_RECV_DATA)) {		if ((void *)sp->addr != (void *)&sgp->buf[amt])			movebytes(sp->addr, &sgp->buf[amt], sp->size);		amt += sp->size;	}#ifdef	SG_GET_BUFSIZE	sgp->hd.want_new  = 1;			/* Order new behaviour	*/	sgp->hd.cdb_len	  = sp->cdb_len;	/* Set CDB length	*/	if (sp->sense_len > SG_MAX_SENSE)		sgp->hd.sense_len = SG_MAX_SENSE;	else		sgp->hd.sense_len = sp->sense_len;#endif	i = sizeof(struct sg_header) + amt;	if ((amt = write(f, sgp, i)) < 0) {			/* write */		sg_settimeout(f, scgp->deftimeout);		return (-1);	} else if (amt != i) {		errmsg("scsi_send(%s) wrote %d bytes (expected %d).\n",						scgp->cmdname, amt, i);	}	if (sp->addr == scglocal(scgp)->SCSIbuf) {		movebytes(sgp, sgp2, sizeof(struct sg_header));		sgp = sgp2;	}	sgp->hd.sense_buffer[0] = 0;	if ((amt = read(f, sgp, reply_len)) < 0) {		/* read */		sg_settimeout(f, scgp->deftimeout);		return (-1);	}	if (sp->flags & SCG_RECV_DATA && ((void *)sgp->buf != (void *)sp->addr)) {		movebytes(sgp->buf, sp->addr, sp->size);	}	sp->ux_errno = GETINT(sgp->hd.result);		/* Unaligned read */	sp->error = SCG_NO_ERROR;#ifdef	SG_GET_BUFSIZE	if (sgp->hd.grant_new) {		sp->sense_count = sgp->hd.sense_len;		pack_len    = GETINT(sgp->hd.sg_cmd_status);	/* Unaligned read */		driver_byte = (pack_len  >> 24) & 0xFF;		host_byte   = (pack_len  >> 16) & 0xFF;		msg_byte    = (pack_len  >> 8) & 0xFF;		status_byte =  pack_len  & 0xFF;		switch (host_byte) {		case DID_OK:				if ((driver_byte & DRIVER_SENSE ||				    sgp->hd.sense_buffer[0] != 0)							&& status_byte == 0) {					/*					 * The Linux SCSI system up to 2.1.xx					 * trashes the status byte in the					 * kernel. This is true at least for					 * ide-scsi emulation. Until this gets					 * fixed, we need this hack.					 */					sp->error = SCG_RETRYABLE;					status_byte = ST_CHK_COND;					if (sgp->hd.sense_len == 0)						sgp->hd.sense_len = SG_MAX_SENSE;				}				break;		case DID_NO_CONNECT:	/* Arbitration won, retry NO_CONNECT? */		case DID_BAD_TARGET:				sp->error = SCG_FATAL;				break;			case DID_TIME_OUT:				sp->error = SCG_TIMEOUT;				break;		default:				sp->error = SCG_RETRYABLE;				if ((driver_byte & DRIVER_SENSE ||				    sgp->hd.sense_buffer[0] != 0)							&& status_byte == 0)					status_byte = ST_CHK_COND;				if (status_byte != 0 && sgp->hd.sense_len == 0)					sgp->hd.sense_len = SG_MAX_SENSE;				break;		}		if ((host_byte != DID_OK || status_byte != 0) && sp->ux_errno == 0)			sp->ux_errno = EIO;		sp->u_scb.cmd_scb[0] = status_byte;		if (status_byte & ST_CHK_COND) {			sp->sense_count = sgp->hd.sense_len;			movebytes(sgp->hd.sense_buffer, sp->u_sense.cmd_sense, sp->sense_count);		}	} else#endif	{		if (GETINT(sgp->hd.result) == EBUSY) {	/* Unaligned read */			struct timeval to;			to.tv_sec = sp->timeout;			to.tv_usec = 500000;			scsitimes(scgp);			if (scgp->cmdstop->tv_sec < to.tv_sec ||			    (scgp->cmdstop->tv_sec == to.tv_sec &&				scgp->cmdstop->tv_usec < to.tv_usec)) {				sp->ux_errno = 0;				sp->error = SCG_TIMEOUT;	/* a timeout */			} else {				sp->error = SCG_RETRYABLE;	/* may be BUS_BUSY */			}		}		if (sp->flags & SCG_RECV_DATA)			sp->resid = (sp->size + sizeof(struct sg_header)) - amt;		else			sp->resid = 0;	/* sg version1 cannot return DMA resid count */		if (sgp->hd.sense_buffer[0] != 0) {			sp->error = SCG_RETRYABLE;			sp->scb.chk = 1;			sp->sense_count = SG_MAX_SENSE;			movebytes(sgp->hd.sense_buffer, sp->u_sense.cmd_sense, sp->sense_count);			if (sp->ux_errno == 0)				sp->ux_errno = EIO;		}	}	if (scgp->verbose > 0 && scgp->debug) {#ifdef	SG_GET_BUFSIZE		printf("status: 0x%08X pack_len: %d, reply_len: %d pack_id: %d result: %d wn: %d gn: %d cdb_len: %d sense_len: %d sense[0]: %02X\n",				GETINT(sgp->hd.sg_cmd_status),				GETINT(sgp->hd.pack_len),				GETINT(sgp->hd.reply_len),				GETINT(sgp->hd.pack_id),				GETINT(sgp->hd.result),				sgp->hd.want_new,				sgp->hd.grant_new,				sgp->hd.cdb_len,				sgp->hd.sense_len,					sgp->hd.sense_buffer[0]);#else		printf("pack_len: %d, reply_len: %d pack_id: %d result: %d sense[0]: %02X\n",				GETINT(sgp->hd.pack_len),				GETINT(sgp->hd.reply_len),				GETINT(sgp->hd.pack_id),				GETINT(sgp->hd.result),				sgp->hd.sense_buffer[0]);#endif#ifdef	DEBUG		printf("sense: ");		for (i=0; i < 16; i++)			printf("%02X ", sgp->hd.sense_buffer[i]);		printf("\n");#endif	}	if (sp->timeout != scgp->deftimeout)		sg_settimeout(f, scgp->deftimeout);	return 0;}

⌨️ 快捷键说明

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