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

📄 scsi_scan.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 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(int channel, int dev, int lun, int *max_scsi_dev,		int *sparse_lun, Scsi_Device ** SDpnt,			     struct Scsi_Host *shpnt, char *scsi_result);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},	{"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},	{"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", "PV530F",    "*", BLIST_SPARSELUN}, // Dell PV 530F	{"SONY", "TSL",       "*", BLIST_FORCELUN},  // DDS3 & DDS4 autoloaders	{"DELL", "PERCRAID", "*", BLIST_FORCELUN},	{"HP", "NetRAID-4M", "*", BLIST_FORCELUN},	/*	 * Must be at end of list...	 */	{NULL, NULL, NULL}};#ifdef CONFIG_SCSI_MULTI_LUNstatic int max_scsi_luns = 8;#elsestatic 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 8)");#elsestatic int __init scsi_luns_setup(char *str){	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 8)\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;	int dev;	int lun;	int max_dev_lun;	unsigned char *scsi_result;	unsigned char scsi_result0[256];	Scsi_Device *SDpnt;	Scsi_Device *SDtail;	int sparse_lun;	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;		scan_scsis_single(channel, dev, lun, &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;

⌨️ 快捷键说明

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