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

📄 scsi_scan.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  scsi_scan.c Copyright (C) 2000 Eric Youngdale * *  Bus scan logic. * *  This used to live in scsi.c, but that file was just a laundry basket *  full of misc stuff.  This got separated out in order to make things *  clearer. */#define __NO_VERSION__#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/blk.h>#include "scsi.h"#include "hosts.h"#include "constants.h"#ifdef CONFIG_KMOD#include <linux/kmod.h>#endif/* The following devices are known not to tolerate a lun != 0 scan for * one reason or another.  Some will respond to all luns, others will * lock up. */#define BLIST_NOLUN     	0x001#define BLIST_FORCELUN  	0x002#define BLIST_BORKEN    	0x004#define BLIST_KEY       	0x008#define BLIST_SINGLELUN 	0x010#define BLIST_NOTQ		0x020#define BLIST_SPARSELUN 	0x040#define BLIST_MAX5LUN		0x080#define BLIST_ISDISK    	0x100#define BLIST_ISROM     	0x200static void print_inquiry(unsigned char *data);static int scan_scsis_single(unsigned int channel, unsigned int dev,		unsigned int lun, int lun0_scsi_level, 		unsigned int *max_scsi_dev, unsigned int *sparse_lun, 		Scsi_Device ** SDpnt, struct Scsi_Host *shpnt, 		char *scsi_result);static int find_lun0_scsi_level(unsigned int channel, unsigned int dev,				struct Scsi_Host *shpnt);struct dev_info {	const char *vendor;	const char *model;	const char *revision;	/* Latest revision known to be bad.  Not used yet */	unsigned flags;};/* * This is what was previously known as the blacklist.  The concept * has been expanded so that we can specify other types of things we * need to be aware of. */static struct dev_info device_list[] ={	{"Aashima", "IMAGERY 2400SP", "1.03", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */	{"CHINON", "CD-ROM CDS-431", "H42", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */	{"CHINON", "CD-ROM CDS-535", "Q14", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */	{"DENON", "DRD-25X", "V", BLIST_NOLUN},			/* Locks up if probed for lun != 0 */	{"HITACHI", "DK312C", "CM81", BLIST_NOLUN},		/* Responds to all lun - dtg */	{"HITACHI", "DK314C", "CR21", BLIST_NOLUN},		/* responds to all lun */	{"IMS", "CDD521/10", "2.06", BLIST_NOLUN},		/* Locks-up when LUN>0 polled. */	{"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN},		/* Locks-up when LUN>0 polled. */	{"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN},		/* Locks-up when LUN>0 polled. */	{"MAXTOR", "MXT-1240S", "I1.2", BLIST_NOLUN},		/* Locks up when LUN>0 polled */	{"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN},		/* Locks-up sometimes when LUN>0 polled. */	{"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN},		/* guess what? */	{"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN},	/*Responds to all lun */	{"MICROP", "4110", "*", BLIST_NOTQ},			/* Buggy Tagged Queuing */	{"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN},	/* Locks-up when LUN>0 polled. */	{"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN},		/* Responds to all lun */	{"RODIME", "RO3000S", "2.33", BLIST_NOLUN},		/* Locks up if polled for lun != 0 */	{"SANYO", "CRD-250S", "1.20", BLIST_NOLUN},		/* causes failed REQUEST SENSE on lun 1								 * for aha152x controller, which causes								 * SCSI code to reset bus.*/	{"SEAGATE", "ST157N", "\004|j", BLIST_NOLUN},		/* causes failed REQUEST SENSE on lun 1								 * for aha152x controller, which causes								 * SCSI code to reset bus.*/	{"SEAGATE", "ST296", "921", BLIST_NOLUN},		/* Responds to all lun */	{"SEAGATE", "ST1581", "6538", BLIST_NOLUN},		/* Responds to all lun */	{"SONY", "CD-ROM CDU-541", "4.3d", BLIST_NOLUN},		{"SONY", "CD-ROM CDU-55S", "1.0i", BLIST_NOLUN},	{"SONY", "CD-ROM CDU-561", "1.7x", BLIST_NOLUN},	{"SONY", "CD-ROM CDU-8012", "*", BLIST_NOLUN},	{"TANDBERG", "TDC 3600", "U07", BLIST_NOLUN},		/* Locks up if polled for lun != 0 */	{"TEAC", "CD-R55S", "1.0H", BLIST_NOLUN},		/* Locks up if polled for lun != 0 */	{"TEAC", "CD-ROM", "1.06", BLIST_NOLUN},		/* causes failed REQUEST SENSE on lun 1								 * for seagate controller, which causes								 * SCSI code to reset bus.*/	{"TEAC", "MT-2ST/45S2-27", "RV M", BLIST_NOLUN},	/* Responds to all lun */	{"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN},		/* causes failed REQUEST SENSE on lun 1								 * for seagate controller, which causes								 * SCSI code to reset bus.*/	{"QUANTUM", "LPS525S", "3110", BLIST_NOLUN},		/* Locks sometimes if polled for lun != 0 */	{"QUANTUM", "PD1225S", "3110", BLIST_NOLUN},		/* Locks sometimes if polled for lun != 0 */	{"QUANTUM", "FIREBALL ST4.3S", "0F0C", BLIST_NOLUN},	/* Locks up when polled for lun != 0 */	{"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN},		/* Locks up if polled for lun != 0 */	{"SANKYO", "CP525", "6.64", BLIST_NOLUN},		/* causes failed REQ SENSE, extra reset */	{"HP", "C1750A", "3226", BLIST_NOLUN},			/* scanjet iic */	{"HP", "C1790A", "", BLIST_NOLUN},			/* scanjet iip */	{"HP", "C2500A", "", BLIST_NOLUN},			/* scanjet iicx */	{"YAMAHA", "CDR100", "1.00", BLIST_NOLUN},		/* Locks up if polled for lun != 0 */	{"YAMAHA", "CDR102", "1.00", BLIST_NOLUN},		/* Locks up if polled for lun != 0  								 * extra reset */	{"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN},		/* Locks up if polled for lun != 0 */	{"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN},		/* Locks up if polled for lun != 0 */	{"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */	{"RELISYS", "Scorpio", "*", BLIST_NOLUN},		/* responds to all LUN */	{"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN},	/* responds to all LUN *//* * Other types of devices that have special flags. */	{"SONY", "CD-ROM CDU-8001", "*", BLIST_BORKEN},	{"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN},	{"IOMEGA", "Io20S         *F", "*", BLIST_KEY},	{"INSITE", "Floptical   F*8I", "*", BLIST_KEY},	{"INSITE", "I325VM", "*", BLIST_KEY},	{"LASOUND","CDX7405","3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},	{"NRC", "MBR-7", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"NRC", "MBR-7.4", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"REGAL", "CDC-4X", "*", BLIST_MAX5LUN | BLIST_SINGLELUN},	{"NAKAMICH", "MJ-4.8S", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"NAKAMICH", "MJ-5.16S", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"PIONEER", "CD-ROM DRM-600", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"PIONEER", "CD-ROM DRM-602X", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"PIONEER", "CD-ROM DRM-604X", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"EMULEX", "MD21/S2     ESDI", "*", BLIST_SINGLELUN},	{"CANON", "IPUBJD", "*", BLIST_SPARSELUN},	{"nCipher", "Fastness Crypto", "*", BLIST_FORCELUN},	{"DEC","HSG80","*", BLIST_FORCELUN},	{"COMPAQ","LOGICAL VOLUME","*", BLIST_FORCELUN},	{"COMPAQ","CR3500","*", BLIST_FORCELUN},	{"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"MATSHITA", "PD-1", "*", BLIST_FORCELUN | BLIST_SINGLELUN},	{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, 	{"TOSHIBA","CDROM","*", BLIST_ISROM}, 	{"TOSHIBA","CD-ROM","*", BLIST_ISROM},	{"MegaRAID", "LD", "*", BLIST_FORCELUN},	{"DGC",  "RAID",      "*", BLIST_SPARSELUN}, // Dell PV 650F (tgt @ LUN 0)	{"DGC",  "DISK",      "*", BLIST_SPARSELUN}, // Dell PV 650F (no tgt @ LUN 0) 	{"DELL", "PV660F",   "*", BLIST_SPARSELUN},	{"DELL", "PV660F   PSEUDO",   "*", BLIST_SPARSELUN},	{"DELL", "PSEUDO DEVICE .",   "*", BLIST_SPARSELUN}, // Dell PV 530F	{"DELL", "PV530F",    "*", BLIST_SPARSELUN}, // Dell PV 530F	{"EMC", "SYMMETRIX", "*", BLIST_SPARSELUN},	{"CMD", "CRA-7280", "*", BLIST_SPARSELUN},   // CMD RAID Controller	{"CNSI", "G7324", "*", BLIST_SPARSELUN},     // Chaparral G7324 RAID	{"CNSi", "G8324", "*", BLIST_SPARSELUN},     // Chaparral G8324 RAID	{"Zzyzx", "RocketStor 500S", "*", BLIST_SPARSELUN},	{"Zzyzx", "RocketStor 2000", "*", BLIST_SPARSELUN},	{"SONY", "TSL",       "*", BLIST_FORCELUN},  // DDS3 & DDS4 autoloaders	{"DELL", "PERCRAID", "*", BLIST_FORCELUN},	{"HP", "NetRAID-4M", "*", BLIST_FORCELUN},	{"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN},	{"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN},	{"COMPAQ", "MSA1000", "*", BLIST_FORCELUN},	/*	 * Must be at end of list...	 */	{NULL, NULL, NULL}};#define MAX_SCSI_LUNS 0xFFFFFFFF#ifdef CONFIG_SCSI_MULTI_LUNstatic unsigned int max_scsi_luns = MAX_SCSI_LUNS;#elsestatic unsigned int max_scsi_luns = 1;#endif#ifdef MODULEMODULE_PARM(max_scsi_luns, "i");MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 2^32-1)");#elsestatic int __init scsi_luns_setup(char *str){	unsigned int tmp;	if (get_option(&str, &tmp) == 1) {		max_scsi_luns = tmp;		return 1;	} else {		printk("scsi_luns_setup : usage max_scsi_luns=n "		       "(n should be between 1 and 2^32-1)\n");		return 0;	}}__setup("max_scsi_luns=", scsi_luns_setup);#endifstatic void print_inquiry(unsigned char *data){	int i;	printk("  Vendor: ");	for (i = 8; i < 16; i++) {		if (data[i] >= 0x20 && i < data[4] + 5)			printk("%c", data[i]);		else			printk(" ");	}	printk("  Model: ");	for (i = 16; i < 32; i++) {		if (data[i] >= 0x20 && i < data[4] + 5)			printk("%c", data[i]);		else			printk(" ");	}	printk("  Rev: ");	for (i = 32; i < 36; i++) {		if (data[i] >= 0x20 && i < data[4] + 5)			printk("%c", data[i]);		else			printk(" ");	}	printk("\n");	i = data[0] & 0x1f;	printk("  Type:   %s ",	       i < MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] : "Unknown          ");	printk("                 ANSI SCSI revision: %02x", data[2] & 0x07);	if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)		printk(" CCS\n");	else		printk("\n");}static int get_device_flags(unsigned char *response_data){	int i = 0;	unsigned char *pnt;	for (i = 0; 1; i++) {		if (device_list[i].vendor == NULL)			return 0;		pnt = &response_data[8];		while (*pnt && *pnt == ' ')			pnt++;		if (memcmp(device_list[i].vendor, pnt,			   strlen(device_list[i].vendor)))			continue;		pnt = &response_data[16];		while (*pnt && *pnt == ' ')			pnt++;		if (memcmp(device_list[i].model, pnt,			   strlen(device_list[i].model)))			continue;		return device_list[i].flags;	}	return 0;}/* *  Detecting SCSI devices : *  We scan all present host adapter's busses,  from ID 0 to ID (max_id). *  We use the INQUIRY command, determine device type, and pass the ID / *  lun address of all sequential devices to the tape driver, all random *  devices to the disk driver. */void scan_scsis(struct Scsi_Host *shpnt,		       uint hardcoded,		       uint hchannel,		       uint hid,		       uint hlun){	uint channel;	unsigned int dev;	unsigned int lun;	unsigned int max_dev_lun;	unsigned char *scsi_result;	unsigned char scsi_result0[256];	Scsi_Device *SDpnt;	Scsi_Device *SDtail;	unsigned int sparse_lun;	int lun0_sl;	scsi_result = NULL;	SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device),					GFP_ATOMIC);	if (SDpnt) {		memset(SDpnt, 0, sizeof(Scsi_Device));		/*		 * Register the queue for the device.  All I/O requests will		 * come in through here.  We also need to register a pointer to		 * ourselves, since the queue handler won't know what device		 * the queue actually represents.   We could look it up, but it		 * is pointless work.		 */		scsi_initialize_queue(SDpnt, shpnt);		SDpnt->request_queue.queuedata = (void *) SDpnt;		/* Make sure we have something that is valid for DMA purposes */		scsi_result = ((!shpnt->unchecked_isa_dma)			       ? &scsi_result0[0] : kmalloc(512, GFP_DMA));	}	if (scsi_result == NULL) {		printk("Unable to obtain scsi_result buffer\n");		goto leave;	}	/*	 * We must chain ourself in the host_queue, so commands can time out 	 */	SDpnt->queue_depth = 1;	SDpnt->host = shpnt;	SDpnt->online = TRUE;	initialize_merge_fn(SDpnt);        /*         * Initialize the object that we will use to wait for command blocks.         */	init_waitqueue_head(&SDpnt->scpnt_wait);	/*	 * Next, hook the device to the host in question.	 */	SDpnt->prev = NULL;	SDpnt->next = NULL;	if (shpnt->host_queue != NULL) {		SDtail = shpnt->host_queue;		while (SDtail->next != NULL)			SDtail = SDtail->next;		SDtail->next = SDpnt;		SDpnt->prev = SDtail;	} else {		shpnt->host_queue = SDpnt;	}	/*	 * We need to increment the counter for this one device so we can track	 * when things are quiet.	 */	if (hardcoded == 1) {		Scsi_Device *oldSDpnt = SDpnt;		struct Scsi_Device_Template *sdtpnt;		channel = hchannel;		if (channel > shpnt->max_channel)			goto leave;		dev = hid;		if (dev >= shpnt->max_id)			goto leave;		lun = hlun;		if (lun >= shpnt->max_lun)			goto leave;		if ((0 == lun) || (lun > 7))			lun0_sl = SCSI_3; /* actually don't care for 0 == lun */		else			lun0_sl = find_lun0_scsi_level(channel, dev, shpnt);		scan_scsis_single(channel, dev, lun, lun0_sl, &max_dev_lun, 				  &sparse_lun, &SDpnt, shpnt, scsi_result);		if (SDpnt != oldSDpnt) {			/* it could happen the blockdevice hasn't yet been inited */			/* queue_depth() moved from scsi_proc_info() so that			   it is called before scsi_build_commandblocks() */			if (shpnt->select_queue_depths != NULL)				(shpnt->select_queue_depths)(shpnt,							     shpnt->host_queue);			for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)				if (sdtpnt->init && sdtpnt->dev_noticed)					(*sdtpnt->init) ();			for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {				if (sdtpnt->attach) {					(*sdtpnt->attach) (oldSDpnt);					if (oldSDpnt->attached) {						scsi_build_commandblocks(oldSDpnt);						if (0 == oldSDpnt->has_cmdblocks) {							printk("scan_scsis: DANGER, no command blocks\n");							/* What to do now ?? */						}					}				}			}			scsi_resize_dma_pool();			for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {				if (sdtpnt->finish && sdtpnt->nr_dev) {					(*sdtpnt->finish) ();				}			}		}	} else {		/* Actual LUN. PC ordering is 0->n IBM/spec ordering is n->0 */		int order_dev;		for (channel = 0; channel <= shpnt->max_channel; channel++) {			for (dev = 0; dev < shpnt->max_id; ++dev) {				if (shpnt->reverse_ordering)					/* Shift to scanning 15,14,13... or 7,6,5,4, */					order_dev = shpnt->max_id - dev - 1;				else					order_dev = dev;				if (shpnt->this_id != order_dev) {					/*					 * We need the for so our continue, etc. work fine. We put this in					 * a variable so that we can override it during the scan if we					 * detect a device *KNOWN* to have multiple logical units.					 */					max_dev_lun = (max_scsi_luns < shpnt->max_lun ?					 max_scsi_luns : shpnt->max_lun);					sparse_lun = 0;					for (lun = 0, lun0_sl = SCSI_2; lun < max_dev_lun; ++lun) {						/* don't probe further for luns > 7 for targets <= SCSI_2 */						if ((lun0_sl < SCSI_3) && (lun > 7))							break;						if (!scan_scsis_single(channel, order_dev, lun, lun0_sl,							 	       &max_dev_lun, &sparse_lun, &SDpnt, shpnt,								       scsi_result)						    && !sparse_lun)							break;	/* break means don't probe further for luns!=0 */						if (SDpnt && (0 == lun))

⌨️ 快捷键说明

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