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

📄 scsi-linux-sg.c

📁 刻录光盘的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* @(#)scsi-linux-sg.c	1.39 99/09/17 Copyright 1997 J. Schilling */#ifndef lintstatic	char __sccsid[] =	"@(#)scsi-linux-sg.c	1.39 99/09/17 Copyright 1997 J. Schilling";#endif/* *	Interface for Linux generic SCSI implementation (sg). * *	This is the interface for the broken Linux SCSI generic driver. *	This is a hack, that tries to emulate the functionality *	of the scg driver. * *	Design flaws of the sg driver: *	-	cannot see if SCSI command could not be send *	-	cannot get SCSI status byte *	-	cannot get real dma count of tranfer *	-	cannot get number of bytes valid in auto sense data *	-	to few data in auto sense (CCS/SCSI-2/SCSI-3 needs >= 18) * *	This code contains support for the sg driver version 2 * *	Warning: you may change this source, but if you do that *	you need to change the _scg_version and _scg_auth* string below. *	You may not return "schily" for an SCG_AUTHOR request anymore. *	Choose your name instead of "schily" and make clear that the version *	string is related to a modified source. * *	Copyright (c) 1997 J. Schilling *//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING.  If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/version.h>#ifndef LINUX_VERSION_CODE	/* Very old kernel? */#	define LINUX_VERSION_CODE 0#endif#if LINUX_VERSION_CODE >= 0x01031a /* <linux/scsi.h> introduced in 1.3.26 */#if LINUX_VERSION_CODE >= 0x020000 /* <scsi/scsi.h> introduced somewhere. *//* Need to fine tune the ifdef so we get the transition point right. */#include <scsi/scsi.h>#else#include <linux/scsi.h>#endif#else#define __KERNEL__#include <linux/fs.h>#undef __KERNEL__#include "block/blk.h"#include "scsi/scsi.h"#endif#include "scsi/sg.h"/* *	Warning: you may change this source, but if you do that *	you need to change the _scg_version and _scg_auth* string below. *	You may not return "schily" for an SCG_AUTHOR request anymore. *	Choose your name instead of "schily" and make clear that the version *	string is related to a modified source. */LOCAL	char	_scg_trans_version[] = "scsi-linux-sg.c-1.39";	/* The version for this transport*/#ifndef	SCSI_IOCTL_GET_BUS_NUMBER#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386#endif/* * XXX There must be a better way than duplicating things from system include * XXX files. This is stolen from /usr/src/linux/drivers/scsi/scsi.h */#ifndef	DID_OK#define DID_OK          0x00 /* NO error                                */#define DID_NO_CONNECT  0x01 /* Couldn't connect before timeout period  */#define DID_BUS_BUSY    0x02 /* BUS stayed busy through time out period */#define DID_TIME_OUT    0x03 /* TIMED OUT for other reason              */#define DID_BAD_TARGET  0x04 /* BAD target.                             */#define DID_ABORT       0x05 /* Told to abort for some other reason     */#define DID_PARITY      0x06 /* Parity error                            */#define DID_ERROR       0x07 /* Internal error                          */#define DID_RESET       0x08 /* Reset by somebody.                      */#define DID_BAD_INTR    0x09 /* Got an interrupt we weren't expecting.  */ #endif/* *  These indicate the error that occurred, and what is available. */#ifndef DRIVER_BUSY#define DRIVER_BUSY         0x01#define DRIVER_SOFT         0x02#define DRIVER_MEDIA        0x03#define DRIVER_ERROR        0x04 #define DRIVER_INVALID      0x05#define DRIVER_TIMEOUT      0x06#define DRIVER_HARD         0x07#define DRIVER_SENSE        0x08#endif/* * XXX Should add extra space in buscookies and scgfiles for a "PP bus" * XXX and for two "ATAPI busses". */#define	MAX_SCG		16	/* Max # of SCSI controllers */#define	MAX_TGT		16#define	MAX_LUN		8struct scg_local {	int	scgfile;		/* Used for SG_GET_BUFSIZE ioctl()*/	short	scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];	short	buscookies[MAX_SCG];	int	pgbus;	int	pack_id;		/* Should be a random number	*/	char	*SCSIbuf;};#define scglocal(p)	((struct scg_local *)((p)->local)) #ifdef	SG_BIG_BUFF#define	MAX_DMA_LINUX	SG_BIG_BUFF	/* Defined in include/scsi/sg.h	*/#else#define	MAX_DMA_LINUX	(4*1024)	/* Old Linux versions		*/#endif#ifndef	SG_MAX_SENSE#	define	SG_MAX_SENSE	16	/* Too small for CCS / SCSI-2	*/#endif					/* But cannot be changed	*/#if	!defined(__i386) && !defined(i386) && !defined(mc68000)#define	MISALIGN#endif/*#define	MISALIGN*//*#undef	SG_GET_BUFSIZE*/#if	defined(USE_PG) && !defined(USE_PG_ONLY)#include "scsi-linux-pg.c"#endif#ifdef	MISALIGNLOCAL	int	scsi_getint	__PR((int *ip));#endifLOCAL	int	scsi_send	__PR((SCSI *scgp, int f, struct scg_cmd *sp));LOCAL	BOOL	sg_setup	__PR((SCSI *scgp, int f, int busno, int tgt, int tlun));LOCAL	void	sg_initdev	__PR((SCSI *scgp, int f));LOCAL	int	sg_mapbus	__PR((SCSI *scgp, int busno, int ino));LOCAL	BOOL	sg_mapdev	__PR((SCSI *scgp, int f, int *busp, int *tgtp, int *lunp,							int *chanp, int *inop));LOCAL	void	sg_settimeout	__PR((int f, int timeout));/* * Return version information for the low level SCSI transport code. * This has been introduced to make it easier to trace down problems * in applications. */EXPORT char *scg__version(scgp, what)	SCSI	*scgp;	int	what;{	if (scgp != (SCSI *)0) {		switch (what) {		case SCG_VERSION:			return (_scg_trans_version);		/*		 * If you changed this source, you are not allowed to		 * return "schily" for the SCG_AUTHOR request.		 */		case SCG_AUTHOR:			return (_scg_auth_schily);		case SCG_SCCS_ID:			return (__sccsid);		}	}	return ((char *)0);}EXPORT intscsi_open(scgp, device, busno, tgt, tlun)	SCSI	*scgp;	char	*device;	int	busno;	int	tgt;	int	tlun;{	register int	f;	register int	i;	register int	b;	register int	t;	register int	l;	register int	nopen = 0;	char		devname[64];	if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {		errno = EINVAL;		if (scgp->errstr)			js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,				"Illegal value for busno, target or lun '%d,%d,%d'",				busno, tgt, tlun);		return (-1);	}	if (scgp->local == NULL) {		scgp->local = malloc(sizeof(struct scg_local));		if (scgp->local == NULL)			return (0);		scglocal(scgp)->scgfile = -1;		scglocal(scgp)->pgbus = -2;		scglocal(scgp)->SCSIbuf = (char *)-1;		scglocal(scgp)->pack_id = 5;		for (b=0; b < MAX_SCG; b++) {			scglocal(scgp)->buscookies[b] = (short)-1;			for (t=0; t < MAX_TGT; t++) {				for (l=0; l < MAX_LUN ; l++)					scglocal(scgp)->scgfiles[b][t][l] = (short)-1;			}		}	}	if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2))		goto openbydev;	for (i=0; i < 32; i++) {		sprintf(devname, "/dev/sg%d", i);		f = open(devname, 2);		if (f < 0) {			if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {				if (scgp->errstr)					js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,							"Cannot open '%s'", devname);				return (0);			}		} else {			if (sg_setup(scgp, f, busno, tgt, tlun))				return (++nopen);			if (busno < 0 && tgt < 0 && tlun < 0)				nopen++;		}	}	if (nopen == 0) for (i=0; i <= 25; i++) {		sprintf(devname, "/dev/sg%c", i+'a');		f = open(devname, 2);		if (f < 0) {			if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {				if (scgp->errstr)					js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,						"Cannot open '%s'", devname);				return (0);			}		} else {			if (sg_setup(scgp, f, busno, tgt, tlun))				return (++nopen);			if (busno < 0 && tgt < 0 && tlun < 0)				nopen++;		}	}openbydev:	if (device != NULL && *device != '\0') {		f = open(device, 2);		if (f < 0 && errno == ENOENT)			goto openpg;		if (!sg_mapdev(scgp, f, &busno, &tgt, &tlun, 0, 0)) {			close(f);			goto openpg;		}		if (scgp->scsibus < 0)			scgp->scsibus = busno;		if (scgp->target < 0)			scgp->target = tgt;		if (scgp->lun < 0)			scgp->lun = tlun;		if (sg_setup(scgp, f, busno, tgt, tlun))			return (++nopen);	}openpg:#ifdef	USE_PG	nopen += pg_open(scgp, device, busno, tgt, tlun);#endif	if (scgp->debug) for (b=0; b < MAX_SCG; b++) {		printf("Bus: %d cookie: %X\n", b, scglocal(scgp)->buscookies[b]);		for (t=0; t < MAX_TGT; t++) {			for (l=0; l < MAX_LUN ; l++)				if (scglocal(scgp)->scgfiles[b][t][l] != (short)-1)					printf("file (%d,%d,%d): %d\n",						b, t, l, scglocal(scgp)->scgfiles[b][t][l]);		}	}	return (nopen);}EXPORT intscsi_close(scgp)	SCSI	*scgp;{	register int	f;	register int	b;	register int	t;	register int	l;	if (scgp->local == NULL)		return (-1);	for (b=0; b < MAX_SCG; b++) {		if (b == scglocal(scgp)->pgbus)			continue;		scglocal(scgp)->buscookies[b] = (short)-1;		for (t=0; t < MAX_TGT; t++) {			for (l=0; l < MAX_LUN ; l++)				f = scglocal(scgp)->scgfiles[b][t][l];				if (f >= 0)					close(f);				scglocal(scgp)->scgfiles[b][t][l] = (short)-1;		}	}#ifdef	USE_PG	pg_close(scgp);#endif	return (0);}LOCAL BOOLsg_setup(scgp, f, busno, tgt, tlun)	SCSI	*scgp;	int	f;	int	busno;	int	tgt;	int	tlun;{	int	n;	int	Chan;	int	Ino;	int	Bus;	int	Target;	int	Lun;	BOOL	onetarget = FALSE;	if (scgp->scsibus >= 0 && scgp->target >= 0 && scgp->lun >= 0)		onetarget = TRUE;	sg_mapdev(scgp, f, &Bus, &Target, &Lun, &Chan, &Ino);	/*	 * For old kernels try to make the best guess.	 */	Ino |= Chan << 8;	n = sg_mapbus(scgp, Bus, Ino);	if (Bus == -1) {		Bus = n;		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;

⌨️ 快捷键说明

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