* or a LUN is seen that cannot have a device attached to it.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <asm/semaphore.h>
#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_driver.h>
#include <scsi/scsi_devinfo.h>
#include <scsi/scsi_host.h>
-#include <scsi/scsi_request.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_eh.h>
case TYPE_MEDIUM_CHANGER:
case TYPE_ENCLOSURE:
case TYPE_COMM:
+ case TYPE_RAID:
case TYPE_RBC:
sdev->writeable = 1;
break;
if (*bflags & BLIST_SELECT_NO_ATN)
sdev->select_no_atn = 1;
+ /*
+ * Maximum 512 sector transfer length
+ * broken RA4x00 Compaq Disk Array
+ */
+ if (*bflags & BLIST_MAX_512)
+ blk_queue_max_sectors(sdev->request_queue, 512);
+
/*
* Some devices may not want to have a start command automatically
* issued when a device is added.
static inline void scsi_destroy_sdev(struct scsi_device *sdev)
{
+ scsi_device_set_state(sdev, SDEV_DEL);
if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);
transport_destroy_device(&sdev->sdev_gendev);
put_device(&sdev->sdev_gendev);
}
+#ifdef CONFIG_SCSI_LOGGING
+/**
+ * scsi_inq_str - print INQUIRY data from min to max index,
+ * strip trailing whitespace
+ * @buf: Output buffer with at least end-first+1 bytes of space
+ * @inq: Inquiry buffer (input)
+ * @first: Offset of string into inq
+ * @end: Index after last character in inq
+ */
+static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq,
+ unsigned first, unsigned end)
+{
+ unsigned term = 0, idx;
+
+ for (idx = 0; idx + first < end && idx + first < inq[4] + 5; idx++) {
+ if (inq[idx+first] > ' ') {
+ buf[idx] = inq[idx+first];
+ term = idx+1;
+ } else {
+ buf[idx] = ' ';
+ }
+ }
+ buf[term] = 0;
+ return buf;
+}
+#endif
/**
* scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
if (scsi_probe_lun(sdev, result, result_len, &bflags))
goto out_free_result;
+ if (bflagsp)
+ *bflagsp = bflags;
/*
* result contains valid SCSI INQUIRY data.
*/
- if ((result[0] >> 5) == 3) {
+ if (((result[0] >> 5) == 3) && !(bflags & BLIST_ATTACH_PQ3)) {
/*
* For a Peripheral qualifier 3 (011b), the SCSI
* spec says: The device server is not capable of
* logical disk configured at sdev->lun, but there
* is a target id responding.
*/
- SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
- "scsi scan: peripheral qualifier of 3,"
- " no device added\n"));
+ SCSI_LOG_SCAN_BUS(2, sdev_printk(KERN_INFO, sdev, "scsi scan:"
+ " peripheral qualifier of 3, device not"
+ " added\n"))
+ if (lun == 0) {
+ SCSI_LOG_SCAN_BUS(1, {
+ unsigned char vend[9];
+ unsigned char mod[17];
+
+ sdev_printk(KERN_INFO, sdev,
+ "scsi scan: consider passing scsi_mod."
+ "dev_flags=%s:%s:0x240 or 0x800240\n",
+ scsi_inq_str(vend, result, 8, 16),
+ scsi_inq_str(mod, result, 16, 32));
+ });
+ }
+
res = SCSI_SCAN_TARGET_PRESENT;
goto out_free_result;
}
sdev->lockable = 0;
scsi_unlock_floptical(sdev, result);
}
- if (bflagsp)
- *bflagsp = bflags;
}
out_free_result:
* scsi_sequential_lun_scan - sequentially scan a SCSI target
* @starget: pointer to target structure to scan
* @bflags: black/white list flag for LUN 0
- * @lun0_res: result of scanning LUN 0
*
* Description:
* Generally, scan from LUN 1 (LUN 0 is assumed to already have been
* Modifies sdevscan->lun.
**/
static void scsi_sequential_lun_scan(struct scsi_target *starget,
- int bflags, int lun0_res, int scsi_level,
- int rescan)
+ int bflags, int scsi_level, int rescan)
{
unsigned int sparse_lun, lun, max_dev_lun;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
} else
sparse_lun = 0;
- /*
- * If not sparse lun and no device attached at LUN 0 do not scan
- * any further.
- */
- if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT))
- return;
-
/*
* If less than SCSI_1_CSS, and no special lun scaning, stop
* scanning; this matches 2.4 behaviour, but could just be a bug
* Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
* support more than 8 LUNs.
*/
- if ((bflags & BLIST_NOREPORTLUN) ||
- starget->scsi_level < SCSI_2 ||
- (starget->scsi_level < SCSI_3 &&
- (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) )
+ if (bflags & BLIST_NOREPORTLUN)
+ return 1;
+ if (starget->scsi_level < SCSI_2 &&
+ starget->scsi_level != SCSI_UNKNOWN)
+ return 1;
+ if (starget->scsi_level < SCSI_3 &&
+ (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8))
return 1;
if (bflags & BLIST_NOLUN)
return 0;
* do a sequential scan.
*/
scsi_sequential_lun_scan(starget, bflags,
- res, starget->scsi_level, rescan);
+ starget->scsi_level, rescan);
}
out_reap:
__FUNCTION__, channel, id, lun));
if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
- ((id != SCAN_WILD_CARD) && (id > shost->max_id)) ||
+ ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
return -EINVAL;