diff options
author | Kenneth D. Merry <ken@FreeBSD.org> | 2000-02-20 04:42:44 +0000 |
---|---|---|
committer | Kenneth D. Merry <ken@FreeBSD.org> | 2000-02-20 04:42:44 +0000 |
commit | 955f7e7474f4d5ebf690f7d2fe30dcc0da3a1d09 (patch) | |
tree | fa0057eb3220c36ea24af5507bcde3ac9b6cf6ea /sbin/camcontrol/camcontrol.c | |
parent | d98722bcb9f1a3801ed157843562d01f0dc87378 (diff) | |
download | src-955f7e7474f4d5ebf690f7d2fe30dcc0da3a1d09.tar.gz src-955f7e7474f4d5ebf690f7d2fe30dcc0da3a1d09.zip |
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>
Notes
Notes:
svn path=/head/; revision=57349
Diffstat (limited to 'sbin/camcontrol/camcontrol.c')
-rw-r--r-- | sbin/camcontrol/camcontrol.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 1d204f148b39..f415c2b6ab14 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -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, |