diff -urN linux-2.4.19/drivers/scsi/scsi_scan.c linux-2.4.19.SuSE/drivers/scsi/scsi_scan.c --- linux-2.4.19/drivers/scsi/scsi_scan.c Sat Aug 3 02:39:44 2002 +++ linux-2.4.19.SuSE/drivers/scsi/scsi_scan.c Mon Dec 16 11:32:20 2002 @@ -527,6 +527,7 @@ int bflags, type = -1; extern devfs_handle_t scsi_devfs_handle; int scsi_level; + unsigned int addlen; SDpnt->host = shpnt; SDpnt->id = dev; @@ -562,7 +563,11 @@ SCSI_LOG_SCAN_BUS(3, printk("scsi: performing INQUIRY\n")); /* * Build an INQUIRY command block. + * Strategy: Send 36 byte INQUIRY first and a second, longer one in + * case the device is SCSI-3 and supports more. */ + memset (scsi_result, 0, 256); + scsi_cmd[0] = INQUIRY; if ((lun > 0) && (lun0_scsi_level <= SCSI_2)) scsi_cmd[1] = (lun << 5) & 0xe0; @@ -570,17 +575,18 @@ scsi_cmd[1] = 0; /* SCSI_3 and higher, don't touch */ scsi_cmd[2] = 0; scsi_cmd[3] = 0; - scsi_cmd[4] = 255; + scsi_cmd[4] = 36; scsi_cmd[5] = 0; SRpnt->sr_cmd_len = 0; SRpnt->sr_data_direction = SCSI_DATA_READ; scsi_wait_req (SRpnt, (void *) scsi_cmd, (void *) scsi_result, - 256, SCSI_TIMEOUT+4*HZ, 3); + scsi_cmd[4], SCSI_TIMEOUT+4*HZ, 3); - SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY %s with code 0x%x\n", - SRpnt->sr_result ? "failed" : "successful", SRpnt->sr_result)); + SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY(%i) %s with code 0x%x\n", + scsi_cmd[4], SRpnt->sr_result ? "failed" : "successful", + SRpnt->sr_result)); /* * Now that we don't do TEST_UNIT_READY anymore, we must be prepared @@ -599,6 +605,39 @@ } } + /* Send a longer INQUIRY again ... SCSI-3 specifies some bits in byte 56 + * which might be snooped by the HBA. + */ + addlen = (unsigned char)scsi_result[4] + 5; + if (addlen > 36 && ((unsigned char)scsi_result[2] & 0x7f) >= 3) { + if (addlen > 255) + addlen = 255; + scsi_cmd[4] = addlen; + SRpnt->sr_cmd_len = 0; + SRpnt->sr_data_direction = SCSI_DATA_READ; + + scsi_wait_req (SRpnt, (void *) scsi_cmd, + (void *) scsi_result, + scsi_cmd[4], SCSI_TIMEOUT+4*HZ, 3); + + SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY(%i) %s with code 0x%x\n", + addlen, SRpnt->sr_result ? "failed" : "successful", + SRpnt->sr_result)); + + if (SRpnt->sr_result) { + if ((driver_byte(SRpnt->sr_result) & DRIVER_SENSE) != 0 && + (SRpnt->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION && + SRpnt->sr_sense_buffer[12] == 0x28 && + SRpnt->sr_sense_buffer[13] == 0) { + /* not-ready to ready transition - good */ + } else { + /* assume no peripheral if any other sort of error */ + scsi_release_request(SRpnt); + return 0; + } + } + } + /* * Check for SPARSELUN before checking the peripheral qualifier, * so sparse lun devices are completely scanned.