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

📄 scsi-linux-sg.c

📁 创建一个符合iso-9660标准的iso文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (scgp->debug)			printf("SCSI Bus: %d (mapped from %d)\n", Bus, Ino);	}	if (Bus < 0 || Bus >= MAX_SCG || Target < 0 || Target >= MAX_TGT ||						Lun < 0 || Lun >= MAX_LUN) {		return (FALSE);	}	if (scglocal(scgp)->scgfiles[Bus][Target][Lun] == (short)-1)		scglocal(scgp)->scgfiles[Bus][Target][Lun] = (short)f;	if (onetarget) {		if (Bus == busno && Target == tgt && Lun == tlun) {			sg_initdev(scgp, f);			scglocal(scgp)->scgfile = f;	/* remember file for ioctl's */			return (TRUE);		} else {			scglocal(scgp)->scgfiles[Bus][Target][Lun] = (short)-1;			close(f);		}	} else {		sg_initdev(scgp, f);		if (scglocal(scgp)->scgfile < 0)			scglocal(scgp)->scgfile = f;	/* remember file for ioctl's */	}	return (FALSE);}LOCAL voidsg_initdev(scgp, f)	SCSI	*scgp;	int	f;{	struct sg_rep {		struct sg_header	hd;		unsigned char		rbuf[100];	} sg_rep;	int	n;	/* Eat any unwanted garbage from prior use of this device */	n = fcntl(f, F_GETFL);	/* Be very proper about this */	fcntl(f, F_SETFL, n|O_NONBLOCK);	fillbytes((caddr_t)&sg_rep, sizeof(struct sg_header), '\0');	sg_rep.hd.reply_len = sizeof(struct sg_header);	while (read(f, &sg_rep, sizeof(sg_rep)) >= 0 || errno != EAGAIN)		;	fcntl(f, F_SETFL, n);	sg_settimeout(f, scgp->deftimeout);}LOCAL intsg_mapbus(scgp, busno, ino)	SCSI	*scgp;	int	busno;	int	ino;{	register int	i;	if (busno >= 0 && busno < MAX_SCG) {		/*		 * SCSI_IOCTL_GET_BUS_NUMBER worked.		 * Now we have the problem that Linux does not properly number		 * SCSI busses. The Bus number that Linux creates really is		 * the controller (card) number. I case of multi SCSI bus		 * cards we are lost.		 */		if (scglocal(scgp)->buscookies[busno] == (short)-1) {			scglocal(scgp)->buscookies[busno] = ino;			return (busno);		}		if (scglocal(scgp)->buscookies[busno] != (short)ino)			errmsgno(EX_BAD, "Warning Linux Bus mapping botch.\n");		return (busno);	} else for (i=0; i < MAX_SCG; i++) {		if (scglocal(scgp)->buscookies[i] == (short)-1) {			scglocal(scgp)->buscookies[i] = ino;			return (i);		}		if (scglocal(scgp)->buscookies[i] == ino)			return (i);	}	return (0);}LOCAL BOOLsg_mapdev(scgp, f, busp, tgtp, lunp, chanp, inop)	SCSI	*scgp;	int	f;	int	*busp;	int	*tgtp;	int	*lunp;	int	*chanp;	int	*inop;{	struct	sg_id {		long	l1; /* target | lun << 8 | channel << 16 | low_ino << 24 */		long	l2; /* Unique id */	} sg_id;	int	Chan;	int	Ino;	int	Bus;	int	Target;	int	Lun;	if (ioctl(f, SCSI_IOCTL_GET_IDLUN, &sg_id))		return (FALSE);	if (scgp->debug)		printf("l1: 0x%lX l2: 0x%lX\n", sg_id.l1, sg_id.l2);	if (ioctl(f, SCSI_IOCTL_GET_BUS_NUMBER, &Bus) < 0) {		Bus = -1;	}	Target	= sg_id.l1 & 0xFF;	Lun	= (sg_id.l1 >> 8) & 0xFF;	Chan	= (sg_id.l1 >> 16) & 0xFF;	Ino	= (sg_id.l1 >> 24) & 0xFF;	if (scgp->debug) {		printf("Bus: %d Target: %d Lun: %d Chan: %d Ino: %d\n",				Bus, Target, Lun, Chan, Ino);	}	*busp = Bus;	*tgtp = Target;	*lunp = Lun;	if (chanp)		*chanp = Chan;	if (inop)		*inop = Ino;	return (TRUE);}#if defined(SG_SET_RESERVED_SIZE) && defined(SG_GET_RESERVED_SIZE)/* * The way Linux does DMA resouce management is a bit curious. * It totally deviates from all other OS and forces long ugly code. * If we are opening all drivers for a SCSI bus scan operation, we need * to set the limit for all open devices. * This may use up all kernel memory ... so do the job carefully. * * A big problem is that SG_SET_RESERVED_SIZE does not return any hint * on whether the request did fail. The only way to find if it worked * is to use SG_GET_RESERVED_SIZE to read back the current values. */LOCAL longscsi_raisedma(scgp, newmax)	SCSI	*scgp;	long	newmax;{	register int	b;	register int	t;	register int	l;	register int	f;		 int	val;		 int	old;	/*	 * First try to raise the DMA limit to a moderate value that	 * most likely does not use up all kernel memory.	 */	val = 126*1024;	if (val > MAX_DMA_LINUX) {		for (b=0; b < MAX_SCG; b++) {			for (t=0; t < MAX_TGT; t++) {				for (l=0; l < MAX_LUN ; l++) {					if ((f = scsi_fileno(scgp, b, t, l)) < 0)						continue;					old = 0;					if (ioctl(f, SG_GET_RESERVED_SIZE, &old) < 0)						continue;					if (val > old)						ioctl(f, SG_SET_RESERVED_SIZE, &val);				}			}		}	}	/*	 * Now to raise the DMA limit to what we really need.	 */	if (newmax > val) {		val = newmax;		for (b=0; b < MAX_SCG; b++) {			for (t=0; t < MAX_TGT; t++) {				for (l=0; l < MAX_LUN ; l++) {					if ((f = scsi_fileno(scgp, b, t, l)) < 0)						continue;					old = 0;					if (ioctl(f, SG_GET_RESERVED_SIZE, &old) < 0)						continue;					if (val > old)						ioctl(f, SG_SET_RESERVED_SIZE, &val);				}			}		}	}	/*	 * To make sure we did not fail (the ioctl does not report errors)	 * we need to check the DMA limits. We return the smallest value.	 */	for (b=0; b < MAX_SCG; b++) {		for (t=0; t < MAX_TGT; t++) {			for (l=0; l < MAX_LUN ; l++) {				if ((f = scsi_fileno(scgp, b, t, l)) < 0)					continue;				if (ioctl(f, SG_GET_RESERVED_SIZE, &val) < 0)					continue;				if (scgp->debug)					printf("Target (%d,%d,%d): DMA max %d old max: %ld\n",							b, t, l, val, newmax);				if (val < newmax)					newmax = val;			}		}	}	return ((long)newmax);}#endifLOCAL longscsi_maxdma(scgp, amt)	SCSI	*scgp;	long	amt;{	long maxdma = MAX_DMA_LINUX;#if defined(SG_SET_RESERVED_SIZE) && defined(SG_GET_RESERVED_SIZE)	/*	 * Use the curious new kernel interface found on Linux >= 2.2.10	 * This interface first appeared in 2.2.6 but it was not working.	 */	if (scglocal(scgp)->drvers >= 20134)		maxdma = scsi_raisedma(scgp, amt);#endif#ifdef	SG_GET_BUFSIZE	/*	 * We assume that all /dev/sg instances use the same	 * maximum buffer size.	 */	maxdma = ioctl(scglocal(scgp)->scgfile, SG_GET_BUFSIZE, 0);#endif	if (maxdma < 0) {#ifdef	USE_PG		/*		 * If we only have a Parallel port, just return PP maxdma.		 */		if (scglocal(scgp)->pgbus == 0)			return (pg_maxdma(scgp, amt));#endif		if (scglocal(scgp)->scgfile >= 0)			maxdma = MAX_DMA_LINUX;	}#ifdef	USE_PG	if (scgp->scsibus == scglocal(scgp)->pgbus)		return (pg_maxdma(scgp, amt));	if ((scgp->scsibus < 0) && (pg_maxdma(scgp, amt) < maxdma))		return (pg_maxdma(scgp, amt));#endif	return (maxdma);}EXPORT void *scsi_getbuf(scgp, amt)	SCSI	*scgp;	long	amt;{	char	*ret;	if (amt <= 0 || amt > scsi_bufsize(scgp, amt))		return ((void *)0);	if (scgp->debug)		printf("scsi_getbuf: %ld bytes\n", amt);	/*	 * For performance reason, we allocate pagesize()	 * bytes before the SCSI buffer to avoid	 * copying the whole buffer contents when	 * setting up the /dev/sg data structures.	 */	ret = valloc((size_t)(amt+getpagesize()));	if (ret == NULL)		return (ret);	scgp->bufbase = ret;	ret += getpagesize();	scglocal(scgp)->SCSIbuf = ret;	return ((void *)ret);}EXPORT voidscsi_freebuf(scgp)	SCSI	*scgp;{	if (scgp->bufbase)		free(scgp->bufbase);	scgp->bufbase = NULL;}EXPORTBOOL scsi_havebus(scgp, busno)	SCSI	*scgp;	int	busno;{	register int	t;	register int	l;	if (busno < 0 || busno >= MAX_SCG)		return (FALSE);	if (scgp->local == NULL)		return (FALSE);	for (t=0; t < MAX_TGT; t++) {		for (l=0; l < MAX_LUN ; l++)			if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)				return (TRUE);	}	return (FALSE);}EXPORTint scsi_fileno(scgp, busno, tgt, tlun)	SCSI	*scgp;	int	busno;	int	tgt;	int	tlun;{	if (busno < 0 || busno >= MAX_SCG ||	    tgt < 0 || tgt >= MAX_TGT ||	    tlun < 0 || tlun >= MAX_LUN)		return (-1);	if (scgp->local == NULL)		return (-1);	return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);}EXPORT intscsi_initiator_id(scgp)	SCSI	*scgp;{#ifdef	USE_PG	if (scgp->scsibus == scglocal(scgp)->pgbus)		return (pg_initiator_id(scgp));#endif	return (-1);}EXPORTint scsi_isatapi(scgp)	SCSI	*scgp;{#ifdef	USE_PG	if (scgp->scsibus == scglocal(scgp)->pgbus)		return (pg_isatapi(scgp));#endif#ifdef	SG_EMULATED_HOST	{	int	emulated = FALSE;	int	f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);	if (ioctl(f, SG_EMULATED_HOST, &emulated) >= 0)		return (emulated != 0);	}#endif	return (-1);}EXPORTint scsireset(scgp)	SCSI	*scgp;{#ifdef	SG_SCSI_RESET	int	f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);	int	func = 0;#endif#ifdef	USE_PG	if (scgp->scsibus == scglocal(scgp)->pgbus)		return (pg_reset(scgp));#endif	/*	 * Do we have a SCSI reset in the Linux sg driver?	 */#ifdef	SG_SCSI_RESET	/*	 * Newer Linux sg driver seem to finally implement it...	 */#ifdef	SG_SCSI_RESET_NOTHING	func = SG_SCSI_RESET_NOTHING;	if (ioctl(f, SG_SCSI_RESET, &func) >= 0) {#ifdef	SG_SCSI_RESET_DEVICE		func = SG_SCSI_RESET_DEVICE;		if (ioctl(f, SG_SCSI_RESET, &func) >= 0)			return (0);#endif#ifdef	SG_SCSI_RESET_BUS		func = SG_SCSI_RESET_BUS;		if (ioctl(f, SG_SCSI_RESET, &func) >= 0)			return (0);#endif	}#endif#endif	return (-1);}LOCAL voidsg_settimeout(f, tmo)

⌨️ 快捷键说明

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