Fix 'camcontrol inquiry'. The inquiry data structure changes (increased to

256 bytes) caused it to break on many devices.

The SCSI spec says that for commands with 8-bit length fields, a value of 0
means 256 bytes.  As it turns out, many devices don't deal with that
properly.  Some interpret the 0 as 0, and return no data.  Others return
more than 256 bytes of data, and cause an overrun.

The fix is to tell the device we've only allocated SHORT_INQUIRY_LENGTH (36
bytes) of inquiry data, instead of sizeof(struct scsi_inquiry_data).

camcontrol.c:		Change inq_len in the call to scsi_inquiry() to
			SHORT_INQUIRY_LENGTH, and add a long comment
			explaining the reason for the change.

scsi_all.h:		Add a comment above the definitinon of
			SHORT_INQUIRY_LENGTH alerting people that it is
			both the initial probe inquiry length, and the
			minimum amount of data needed for scsi_print_inquiry()
			to function.

scsi_all.c:		Add a comment about SHORT_INQUIRY_LENGTH being the
			minimum amount of data needed for
			scsi_print_inquiry() to function.

Reviewed by:	gibbs
Approved by:	jkh
Reported by:	"John W. DeBoskey" <jwd@unx.sas.com>
This commit is contained in:
Kenneth D. Merry 2000-02-20 04:42:44 +00:00
parent d98722bcb9
commit 955f7e7474
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=57349
3 changed files with 48 additions and 3 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 1998, 1999 Kenneth D. Merry
* Copyright (c) 1997, 1998, 1999, 2000 Kenneth D. Merry
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -645,12 +645,45 @@ scsiinquiry(struct cam_device *device, int retry_count, int timeout)
}
bzero(inq_buf, sizeof(*inq_buf));
/*
* Note that although the size of the inquiry buffer is the full
* 256 bytes specified in the SCSI spec, we only tell the device
* that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
* two reasons for this:
*
* - The SCSI spec says that when a length field is only 1 byte,
* a value of 0 will be interpreted as 256. Therefore
* scsi_inquiry() will convert an inq_len (which is passed in as
* a u_int32_t, but the field in the CDB is only 1 byte) of 256
* to 0. Evidently, very few devices meet the spec in that
* regard. Some devices, like many Seagate disks, take the 0 as
* 0, and don't return any data. One Pioneer DVD-R drive
* returns more data than the command asked for.
*
* So, since there are numerous devices that just don't work
* right with the full inquiry size, we don't send the full size.
*
* - The second reason not to use the full inquiry data length is
* that we don't need it here. The only reason we issue a
* standard inquiry is to get the vendor name, device name,
* and revision so scsi_print_inquiry() can print them.
*
* If, at some point in the future, more inquiry data is needed for
* some reason, this code should use a procedure similar to the
* probe code. i.e., issue a short inquiry, and determine from
* the additional length passed back from the device how much
* inquiry data the device supports. Once the amount the device
* supports is determined, issue an inquiry for that amount and no
* more.
*
* KDM, 2/18/2000
*/
scsi_inquiry(&ccb->csio,
/* retries */ retry_count,
/* cbfcnp */ NULL,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* inq_buf */ (u_int8_t *)inq_buf,
/* inq_len */ sizeof(struct scsi_inquiry_data),
/* inq_len */ SHORT_INQUIRY_LENGTH,
/* evpd */ 0,
/* page_code */ 0,
/* sense_len */ SSD_FULL_SIZE,

View File

@ -2290,6 +2290,13 @@ scsi_interpret_sense(struct cam_device *device, union ccb *ccb,
return (error);
}
/*
* This function currently requires at least 36 bytes, or
* SHORT_INQUIRY_LENGTH, worth of data to function properly. If this
* function needs more or less data in the future, another length should be
* defined in scsi_all.h to indicate the minimum amount of data necessary
* for this routine to function properly.
*/
void
scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
{

View File

@ -477,7 +477,12 @@ struct scsi_start_stop_unit
#define T_REMOV 1
#define T_FIXED 0
/*
* This length is the initial inquiry length used by the probe code, as
* well as the legnth necessary for scsi_print_inquiry() to function
* correctly. If either use requires a different length in the future,
* the two values should be de-coupled.
*/
#define SHORT_INQUIRY_LENGTH 36
struct scsi_inquiry_data