📄 scsi_scan.c
字号:
/* * 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 + -