summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2010-07-02 23:57:47 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2010-07-02 23:57:47 +0000
commit9a8d40687e7af387d894c2b4fa066cb61ddc6bef (patch)
treeeed72445a626fbcbb102c60d3e6793409da26306 /sys
parent597d8df7a74a0278a147433e716390cddbef765f (diff)
Always try READ CAPACITY(16) on SCSI-3 devices. If it fails, return
the READ CAPACITY(10) values already retrieved. Creates the possibility to look at other interesting READ CAPACITY(16) data for future consideration. ok matthew@ marco@ deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/scsi/scsi_base.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c
index 0bbe0a8b931..7dec43e0cf0 100644
--- a/sys/scsi/scsi_base.c
+++ b/sys/scsi/scsi_base.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi_base.c,v 1.180 2010/07/02 00:04:11 krw Exp $ */
+/* $OpenBSD: scsi_base.c,v 1.181 2010/07/02 23:57:46 krw Exp $ */
/* $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $ */
/*
@@ -637,18 +637,14 @@ scsi_size(struct scsi_link *sc_link, int flags, u_int32_t *blksize)
*blksize = 0;
/*
- * make up a scsi command and ask the scsi driver to do it for you.
+ * Start with a READ CAPACITY(10).
*/
bzero(&rc, sizeof(rc));
bzero(&rdcap, sizeof(rdcap));
rc.opcode = READ_CAPACITY;
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks
- */
- rdcap = malloc(sizeof(*rdcap), M_TEMP, ((flags & SCSI_NOSLEEP) ? M_NOWAIT :
- M_WAITOK) | M_ZERO);
+ rdcap = malloc(sizeof(*rdcap), M_TEMP, ((flags & SCSI_NOSLEEP) ?
+ M_NOWAIT : M_WAITOK) | M_ZERO);
if (rdcap == NULL)
return (0);
error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&rc, sizeof(rc),
@@ -666,11 +662,12 @@ scsi_size(struct scsi_link *sc_link, int flags, u_int32_t *blksize)
*blksize = _4btol(rdcap->length);
free(rdcap, M_TEMP);
- if (max_addr != 0xffffffff)
- return (max_addr + 1);
+ if (SCSISPC(sc_link->inqdata.version) < 3 && max_addr != 0xffffffff)
+ goto exit;
/*
- * The device has more than 2^32-1 sectors. Use 16-byte READ CAPACITY.
+ * SCSI-3 devices, or devices reporting more than 2^32-1 sectors can try
+ * READ CAPACITY(16).
*/
bzero(&rc16, sizeof(rc16));
bzero(&rdcap16, sizeof(rdcap16));
@@ -681,7 +678,7 @@ scsi_size(struct scsi_link *sc_link, int flags, u_int32_t *blksize)
rdcap16 = malloc(sizeof(*rdcap16), M_TEMP, ((flags & SCSI_NOSLEEP) ?
M_NOWAIT : M_WAITOK) | M_ZERO);
if (rdcap16 == NULL)
- return (0);
+ goto exit;
error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&rc16,
sizeof(rc16), (u_char *)rdcap16, sizeof(*rdcap16), SCSI_RETRIES,
20000, NULL, flags | SCSI_DATA_IN);
@@ -689,15 +686,24 @@ scsi_size(struct scsi_link *sc_link, int flags, u_int32_t *blksize)
SC_DEBUG(sc_link, SDEV_DB1, ("READ CAPACITY 16 error (%#x)\n",
error));
free(rdcap16, M_TEMP);
- return (0);
+ goto exit;
}
max_addr = _8btol(rdcap16->addr);
if (blksize != NULL)
*blksize = _4btol(rdcap16->length);
+ /* XXX The other READ CAPACITY(16) info could be stored away somewhere. */
free(rdcap16, M_TEMP);
return (max_addr + 1);
+
+exit:
+ /* Return READ CAPACITY 10 values. */
+ if (max_addr != 0xffffffff)
+ return (max_addr + 1);
+ else if (blksize != NULL)
+ *blksize = 0;
+ return (0);
}
/*