summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/scsi/scsi_all.h27
-rw-r--r--sys/scsi/scsi_base.c110
-rw-r--r--sys/scsi/scsi_disk.h8
-rw-r--r--sys/scsi/scsiconf.h7
-rw-r--r--sys/scsi/sd_scsi.c148
5 files changed, 213 insertions, 87 deletions
diff --git a/sys/scsi/scsi_all.h b/sys/scsi/scsi_all.h
index 49b8faf46c7..62edd4be07e 100644
--- a/sys/scsi/scsi_all.h
+++ b/sys/scsi/scsi_all.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi_all.h,v 1.22 2005/04/06 20:50:31 marco Exp $ */
+/* $OpenBSD: scsi_all.h,v 1.23 2005/05/25 20:52:41 krw Exp $ */
/* $NetBSD: scsi_all.h,v 1.10 1996/09/12 01:57:17 thorpej Exp $ */
/*
@@ -294,6 +294,19 @@ struct scsi_blk_desc {
u_int8_t blklen[3];
};
+struct scsi_mode_direct_blk_desc {
+ u_int8_t nblocks[4];
+ u_int8_t density;
+ u_int8_t blklen[3];
+};
+
+struct scsi_mode_blk_desc_big {
+ u_int8_t nblocks[8];
+ u_int8_t density;
+ u_int8_t reserved[3];
+ u_int8_t blklen[4];
+};
+
struct scsi_mode_header {
u_int8_t data_length; /* Sense data length */
u_int8_t medium_type;
@@ -305,10 +318,20 @@ struct scsi_mode_header_big {
u_int8_t data_length[2]; /* Sense data length */
u_int8_t medium_type;
u_int8_t dev_spec;
- u_int8_t unused[2];
+ u_int8_t reserved;
+#define LONGLBA 0x01
+ u_int8_t reserved2;
u_int8_t blk_desc_len[2];
};
+struct scsi_mode_sense_buf {
+ union {
+ struct scsi_mode_header hdr;
+ struct scsi_mode_header_big hdr_big;
+ } headers;
+ u_char pad[248]; /* To total length of 256 bytes. */
+};
+
/*
* SPI status information unit. See section 14.3.5 of SPI-3.
*/
diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c
index 9aebd2227af..2153cddbac3 100644
--- a/sys/scsi/scsi_base.c
+++ b/sys/scsi/scsi_base.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi_base.c,v 1.69 2005/05/22 01:12:47 krw Exp $ */
+/* $OpenBSD: scsi_base.c,v 1.70 2005/05/25 20:52:41 krw Exp $ */
/* $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $ */
/*
@@ -422,6 +422,114 @@ scsi_mode_sense_big(sc_link, byte2, page, data, len, flags, timeout)
return (error);
}
+void *
+scsi_mode_sense_page(hdr, page_len)
+ struct scsi_mode_header *hdr;
+ const int page_len;
+{
+ int total_length, header_length;
+
+ total_length = hdr->data_length + sizeof(hdr->data_length);
+ header_length = sizeof(*hdr) + hdr->blk_desc_len;
+
+ if ((total_length - header_length) < page_len)
+ return (NULL);
+
+ return ((u_char *)hdr + header_length);
+}
+
+void *
+scsi_mode_sense_big_page(hdr, page_len)
+ struct scsi_mode_header_big *hdr;
+ const int page_len;
+{
+ int total_length, header_length;
+
+ total_length = _2btol(hdr->data_length) + sizeof(hdr->data_length);
+ header_length = sizeof(*hdr) + _2btol(hdr->blk_desc_len);
+
+ if ((total_length - header_length) < page_len)
+ return (NULL);
+
+ return ((u_char *)hdr + header_length);
+}
+
+int
+scsi_do_mode_sense(sc_link, page, buf, page_data, density, block_count,
+ block_size, page_len, flags)
+ struct scsi_link *sc_link;
+ struct scsi_mode_sense_buf *buf;
+ int page, page_len, *density, *block_count, *block_size;
+ void **page_data;
+{
+ struct scsi_mode_blk_desc_big *desc_big;
+ struct scsi_mode_direct_blk_desc *desc;
+ struct scsi_mode_header_big *hdr_big;
+ struct scsi_mode_header *hdr;
+ u_char *cbuf = (u_char *)buf;
+ int error, blk_desc_len;
+
+ *page_data = NULL;
+
+ if (density)
+ *density = 0;
+ if (block_count)
+ /* XXX We don't do block_count at this time. */
+ *block_count = 0;
+ if (block_size)
+ *block_size = 0;
+
+ /* Try 10 byte mode sense request. Don't bother with SMS_DBD. */
+ error = scsi_mode_sense_big(sc_link, 0, page, &buf->headers.hdr_big,
+ sizeof(*buf), flags, 20000);
+ hdr_big = &buf->headers.hdr_big;
+ if (error == 0 && _2btol(hdr_big->data_length) > 0) {
+ cbuf += sizeof(struct scsi_mode_header_big);
+ *page_data = scsi_mode_sense_big_page(hdr_big, page_len);
+ blk_desc_len = _2btol(hdr_big->blk_desc_len);
+ if ((hdr_big->reserved & LONGLBA) == 0)
+ goto eight_byte;
+ /* 16 byte block descriptors. */
+ if (blk_desc_len < sizeof(struct scsi_mode_blk_desc_big))
+ return (0);
+ desc_big = (struct scsi_mode_blk_desc_big *)cbuf;
+ if (density)
+ *density = desc_big->density;
+ if (block_size)
+ *block_size = _4btol(desc_big->blklen);
+ return (0);
+ }
+
+ if (sc_link->flags & SDEV_ONLYBIG)
+ return (EIO);
+
+ /* Try 6 byte mode sense request. Don't bother with SMS_DBD. */
+ error = scsi_mode_sense(sc_link, 0, page, &buf->headers.hdr,
+ sizeof(*buf), flags, 20000);
+ if (error != 0)
+ return (error);
+
+ hdr = &buf->headers.hdr;
+ if (hdr->data_length == 0)
+ return (EIO);
+
+ cbuf += sizeof(struct scsi_mode_header);
+ *page_data = scsi_mode_sense_page(hdr, page_len);
+ blk_desc_len = hdr->blk_desc_len;
+
+eight_byte:
+ if (blk_desc_len < sizeof(struct scsi_mode_direct_blk_desc))
+ return (0);
+
+ desc = (struct scsi_mode_direct_blk_desc *)cbuf;
+ if (density)
+ *density = desc->density;
+ if (block_size)
+ *block_size = _3btol(desc->blklen);
+
+ return (0);
+}
+
int
scsi_mode_select(sc_link, byte2, data, len, flags, timeout)
struct scsi_link *sc_link;
diff --git a/sys/scsi/scsi_disk.h b/sys/scsi/scsi_disk.h
index cb93bcd8c30..71c32cfdc8a 100644
--- a/sys/scsi/scsi_disk.h
+++ b/sys/scsi/scsi_disk.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi_disk.h,v 1.14 2003/06/24 22:42:07 mickey Exp $ */
+/* $OpenBSD: scsi_disk.h,v 1.15 2005/05/25 20:52:41 krw Exp $ */
/* $NetBSD: scsi_disk.h,v 1.10 1996/07/05 16:19:05 christos Exp $ */
/*
@@ -236,12 +236,6 @@ struct scsi_reassign_blocks_data {
} defect_descriptor[1];
};
-struct scsi_disk_blk_desc {
- u_int8_t nblocks[4];
- u_int8_t density;
- u_int8_t blklen[3];
-};
-
union scsi_disk_pages {
#define DISK_PGCODE 0x3F /* only 6 bits valid */
struct page_disk_format {
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
index 52c09756127..87d1e270ff4 100644
--- a/sys/scsi/scsiconf.h
+++ b/sys/scsi/scsiconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.h,v 1.52 2005/05/14 00:20:43 krw Exp $ */
+/* $OpenBSD: scsiconf.h,v 1.53 2005/05/25 20:52:41 krw Exp $ */
/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */
/*
@@ -335,6 +335,11 @@ int scsi_mode_sense(struct scsi_link *, int, int, struct scsi_mode_header *,
size_t, int, int);
int scsi_mode_sense_big(struct scsi_link *, int, int,
struct scsi_mode_header_big *, size_t, int, int);
+void * scsi_mode_sense_page(struct scsi_mode_header *, int);
+void * scsi_mode_sense_big_page(struct scsi_mode_header_big *, int);
+int scsi_do_mode_sense(struct scsi_link *, int,
+ struct scsi_mode_sense_buf *, void **, int *, int *, int *, int,
+ int);
int scsi_mode_select(struct scsi_link *, int, struct scsi_mode_header *,
size_t, int, int);
int scsi_mode_select_big(struct scsi_link *, int,
diff --git a/sys/scsi/sd_scsi.c b/sys/scsi/sd_scsi.c
index 74b46567254..47785001fc4 100644
--- a/sys/scsi/sd_scsi.c
+++ b/sys/scsi/sd_scsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sd_scsi.c,v 1.11 2005/05/24 20:48:43 krw Exp $ */
+/* $OpenBSD: sd_scsi.c,v 1.12 2005/05/25 20:52:41 krw Exp $ */
/* $NetBSD: sd_scsi.c,v 1.8 1998/10/08 20:21:13 thorpej Exp $ */
/*-
@@ -138,9 +138,10 @@ sd_scsibus_get_parms(sd, dp, flags)
int flags;
{
struct sd_scsibus_mode_sense_data scsi_sense;
- union scsi_disk_pages *sense_pages;
- u_int16_t rpm;
- int page, error;
+ struct scsi_mode_sense_buf buf;
+ union scsi_disk_pages *sense_pages = NULL;
+ u_int16_t rpm = 0;
+ int page, error, blksize;
dp->rot_rate = 3600;
@@ -151,103 +152,98 @@ sd_scsibus_get_parms(sd, dp, flags)
if (sd->type == T_OPTICAL)
return (sd_scsibus_get_optparms(sd, dp, flags));
- error = scsi_mode_sense(sd->sc_link, 0, page = 4,
- (struct scsi_mode_header *)&scsi_sense, sizeof(scsi_sense),
- flags | SCSI_SILENT, 6000);
+ error = scsi_do_mode_sense(sd->sc_link, page = 4, &buf,
+ (void **)&sense_pages, NULL, NULL, &blksize,
+ sizeof(sense_pages->rigid_geometry), flags | SCSI_SILENT);
if (error == 0) {
- sense_pages = (union scsi_disk_pages *)
- ((char *)&scsi_sense.blk_desc +
- (size_t)scsi_sense.header.blk_desc_len);
- SC_DEBUG(sd->sc_link, SDEV_DB3,
- ("%d cyls, %d heads, %d precomp, %d red_write,"
- " %d land_zone\n",
- _3btol(sense_pages->rigid_geometry.ncyl),
- sense_pages->rigid_geometry.nheads,
- _2btol(sense_pages->rigid_geometry.st_cyl_wp),
- _2btol(sense_pages->rigid_geometry.st_cyl_rwc),
- _2btol(sense_pages->rigid_geometry.land_zone)));
-
- /*
- * KLUDGE!! (for zone recorded disks)
- * give a number of sectors so that sec * trks * cyls
- * is <= disk_size
- * can lead to wasted space! THINK ABOUT THIS !
- */
- dp->heads = sense_pages->rigid_geometry.nheads;
- dp->cyls = _3btol(sense_pages->rigid_geometry.ncyl);
- rpm = _2btol(scsi_sense.pages.rigid_geometry.rpm);
- if (rpm)
- dp->rot_rate = rpm;
- if (scsi_sense.header.blk_desc_len >= 8)
- dp->blksize = _3btol(scsi_sense.blk_desc.blklen);
- else
- dp->blksize = 0;
+ if (sense_pages) {
+ SC_DEBUG(sd->sc_link, SDEV_DB3,
+ ("%d cyls, %d heads, %d precomp, %d red_write,"
+ " %d land_zone\n",
+ _3btol(sense_pages->rigid_geometry.ncyl),
+ sense_pages->rigid_geometry.nheads,
+ _2btol(sense_pages->rigid_geometry.st_cyl_wp),
+ _2btol(sense_pages->rigid_geometry.st_cyl_rwc),
+ _2btol(sense_pages->rigid_geometry.land_zone)));
+ /*
+ * KLUDGE!! (for zone recorded disks)
+ * give a number of sectors so that sec * trks * cyls
+ * is <= disk_size
+ * can lead to wasted space! THINK ABOUT THIS !
+ */
+ dp->heads = sense_pages->rigid_geometry.nheads;
+ dp->cyls = _3btol(sense_pages->rigid_geometry.ncyl);
+ rpm = _2btol(sense_pages->rigid_geometry.rpm);
+ }
+ dp->disksize = scsi_size(sd->sc_link, flags);
- if (dp->heads == 0 || dp->cyls == 0)
+ if (dp->disksize == 0 || dp->heads == 0 || dp->cyls == 0)
goto fake_it;
- if (dp->blksize == 0)
- dp->blksize = 512;
-
- dp->disksize = scsi_size(sd->sc_link, flags);
- if (dp->disksize == 0)
- return (SDGP_RESULT_OFFLINE);
-
/* XXX dubious on SCSI */
dp->sectors = dp->disksize / (dp->heads * dp->cyls);
+ if (rpm)
+ dp->rot_rate = rpm;
+
+ dp->blksize = (blksize == 0) ? 512 : blksize;
+
return (SDGP_RESULT_OK);
}
- error = scsi_mode_sense(sd->sc_link, 0, page = 5,
- (struct scsi_mode_header *)&scsi_sense, sizeof(scsi_sense),
- flags | SCSI_SILENT, 6000);
+ error = scsi_do_mode_sense(sd->sc_link, page = 5, &buf,
+ (void **)&sense_pages, NULL, NULL, &blksize,
+ sizeof(sense_pages->flex_geometry), flags | SCSI_SILENT);
if (error == 0) {
- sense_pages = (union scsi_disk_pages *)
- ((char *)&scsi_sense.blk_desc +
- (size_t)scsi_sense.header.blk_desc_len);
- dp->heads = sense_pages->flex_geometry.nheads;
- dp->cyls = _2btol(sense_pages->flex_geometry.ncyl);
- rpm = _2btol(scsi_sense.pages.flex_geometry.rpm);
- if (rpm)
- dp->rot_rate = rpm;
- if (scsi_sense.header.blk_desc_len >= 8)
- dp->blksize = _3btol(scsi_sense.blk_desc.blklen);
- else
+ if (sense_pages) {
+ dp->heads = sense_pages->flex_geometry.nheads;
+ dp->cyls = _2btol(sense_pages->flex_geometry.ncyl);
+ dp->sectors = sense_pages->flex_geometry.ph_sec_tr;
dp->blksize =
_2btol(sense_pages->flex_geometry.bytes_s);
- dp->sectors = sense_pages->flex_geometry.ph_sec_tr;
- dp->disksize = dp->heads * dp->cyls * dp->sectors;
- if (dp->disksize == 0)
+ rpm = _2btol(scsi_sense.pages.flex_geometry.rpm);
+ }
+ if (dp->cyls == 0 || dp->heads == 0 || dp->cyls == 0)
goto fake_it;
- if (dp->blksize == 0)
+
+ dp->disksize = dp->heads * dp->cyls * dp->sectors;
+
+ if (rpm)
+ dp->rot_rate = rpm;
+
+ if (blksize)
+ dp->blksize = blksize;
+ else if (dp->blksize == 0)
dp->blksize = 512;
+
return (SDGP_RESULT_OK);
}
- /* T_RDIRECT define page 6. */
- error = scsi_mode_sense(sd->sc_link, 0, page = 6,
- (struct scsi_mode_header *)&scsi_sense, sizeof(scsi_sense),
- flags | SCSI_SILENT, 6000);
+ /* T_RDIRECT defines page 6. */
+ if (sd->type != T_RDIRECT)
+ goto fake_it;
+
+ error = scsi_do_mode_sense(sd->sc_link, page = 6, &buf,
+ (void **)&sense_pages, NULL, NULL, &blksize,
+ sizeof(sense_pages->reduced_geometry), flags | SCSI_SILENT);
if (error == 0) {
- sense_pages = (union scsi_disk_pages *)
- ((char *)&scsi_sense.blk_desc +
- (size_t)scsi_sense.header.blk_desc_len);
dp->heads = 64;
dp->sectors = 32;
- dp->disksize =
- _4btol(sense_pages->reduced_geometry.sectors+1);
- dp->cyls = dp->disksize / (64 * 32);
- if (scsi_sense.header.blk_desc_len >= 8)
- dp->blksize = _3btol(scsi_sense.blk_desc.blklen);
- else
+ if (sense_pages) {
+ dp->disksize =
+ _4btol(sense_pages->reduced_geometry.sectors+1);
dp->blksize =
_2btol(sense_pages->reduced_geometry.bytes_s);
-
- if (dp->disksize == 0 ||
- sense_pages->reduced_geometry.sectors[0] != 0)
+ dp->sectors = sense_pages->reduced_geometry.sectors[0];
+ }
+ if (dp->disksize == 0 || dp->sectors == 0)
goto fake_it;
+ dp->cyls = dp->disksize / (dp->heads * dp->sectors);
+
+ if (blksize)
+ dp->blksize = blksize;
+
if (dp->blksize == 0)
dp->blksize = 512;