summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2005-06-24 20:48:26 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2005-06-24 20:48:26 +0000
commit88a9d1540b8ba6caa65a80963783b38fe390fdcb (patch)
treeef58d565547c108bdeea7804fcc5e6b914024a37 /sys
parentf1425ac7851f760b4d876aac487905e9304ea453 (diff)
Move st.c to new mode sense mechanism. Don't save page0 data (if any), just
ask for it when needed. Eliminate the page_0_size quirk. Tested on various tape drives by myself, hshoexer@ and henning@.
Diffstat (limited to 'sys')
-rw-r--r--sys/scsi/st.c189
1 files changed, 109 insertions, 80 deletions
diff --git a/sys/scsi/st.c b/sys/scsi/st.c
index 0cc920021de..2d0c2accc2d 100644
--- a/sys/scsi/st.c
+++ b/sys/scsi/st.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: st.c,v 1.47 2005/06/05 21:27:07 krw Exp $ */
+/* $OpenBSD: st.c,v 1.48 2005/06/24 20:48:25 krw Exp $ */
/* $NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $ */
/*
@@ -107,8 +107,6 @@ struct quirkdata {
#define ST_Q_IGNORE_LOADS 0x0004
#define ST_Q_BLKSIZE 0x0008 /* variable-block media_blksize > 0 */
#define ST_Q_UNIMODAL 0x0010 /* unimode drive rejects mode select */
- u_int page_0_size;
-#define MAX_PAGE_0_SIZE 64
struct modes modes[4];
};
@@ -119,21 +117,21 @@ struct st_quirk_inquiry_pattern {
const struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
{{T_SEQUENTIAL, T_REMOV,
- " ", " ", " "}, {0, 0, {
+ " ", " ", " "}, {0, {
{ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
{ST_Q_FORCE_BLKSIZE, 512, QIC_24}, /* minor 4-7 */
{ST_Q_FORCE_BLKSIZE, 0, HALFINCH_1600}, /* minor 8-11 */
{ST_Q_FORCE_BLKSIZE, 0, HALFINCH_6250} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "TANDBERG", " TDC 3600 ", ""}, {0, 12, {
+ "TANDBERG", " TDC 3600 ", ""}, {0, {
{0, 0, 0}, /* minor 0-3 */
{ST_Q_FORCE_BLKSIZE, 0, QIC_525}, /* minor 4-7 */
{0, 0, QIC_150}, /* minor 8-11 */
{0, 0, QIC_120} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "TANDBERG", " TDC 3800 ", ""}, {0, 0, {
+ "TANDBERG", " TDC 3800 ", ""}, {0, {
{ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
{0, 0, QIC_525}, /* minor 4-7 */
{0, 0, QIC_150}, /* minor 8-11 */
@@ -144,7 +142,7 @@ const struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
* hear otherwise. - mycroft, 31MAR1994
*/
{{T_SEQUENTIAL, T_REMOV,
- "ARCHIVE ", "VIPER 2525 25462", ""}, {0, 0, {
+ "ARCHIVE ", "VIPER 2525 25462", ""}, {0, {
{ST_Q_SENSE_HELP, 0, 0}, /* minor 0-3 */
{ST_Q_SENSE_HELP, 0, QIC_525}, /* minor 4-7 */
{0, 0, QIC_150}, /* minor 8-11 */
@@ -155,70 +153,70 @@ const struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
* needs more work. - mycroft, 09APR1994
*/
{{T_SEQUENTIAL, T_REMOV,
- "SANKYO ", "CP525 ", ""}, {0, 0, {
+ "SANKYO ", "CP525 ", ""}, {0, {
{ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
{ST_Q_FORCE_BLKSIZE, 512, QIC_525}, /* minor 4-7 */
{0, 0, QIC_150}, /* minor 8-11 */
{0, 0, QIC_120} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "ANRITSU ", "DMT780 ", ""}, {0, 0, {
+ "ANRITSU ", "DMT780 ", ""}, {0, {
{ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
{ST_Q_FORCE_BLKSIZE, 512, QIC_525}, /* minor 4-7 */
{0, 0, QIC_150}, /* minor 8-11 */
{0, 0, QIC_120} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "ARCHIVE ", "VIPER 150 21247", ""}, {0, 12, {
+ "ARCHIVE ", "VIPER 150 21247", ""}, {0, {
{0, 0, 0}, /* minor 0-3 */
{0, 0, QIC_150}, /* minor 4-7 */
{0, 0, QIC_120}, /* minor 8-11 */
{0, 0, QIC_24} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "ARCHIVE ", "VIPER 150 21531", ""}, {0, 12, {
+ "ARCHIVE ", "VIPER 150 21531", ""}, {0, {
{ST_Q_SENSE_HELP, 0, 0}, /* minor 0-3 */
{0, 0, QIC_150}, /* minor 4-7 */
{0, 0, QIC_120}, /* minor 8-11 */
{0, 0, QIC_24} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "WANGTEK ", "5099ES SCSI", ""}, {0, 0, {
+ "WANGTEK ", "5099ES SCSI", ""}, {0, {
{ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
{0, 0, QIC_11}, /* minor 4-7 */
{0, 0, QIC_24}, /* minor 8-11 */
{0, 0, QIC_24} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "WANGTEK ", "5150ES SCSI", ""}, {0, 0, {
+ "WANGTEK ", "5150ES SCSI", ""}, {0, {
{ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
{0, 0, QIC_24}, /* minor 4-7 */
{0, 0, QIC_120}, /* minor 8-11 */
{0, 0, QIC_150} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "WANGTEK ", "5525ES SCSI REV7", ""}, {0, 0, {
+ "WANGTEK ", "5525ES SCSI REV7", ""}, {0, {
{0, 0, 0}, /* minor 0-3 */
{ST_Q_BLKSIZE, 0, QIC_525}, /* minor 4-7 */
{0, 0, QIC_150}, /* minor 8-11 */
{0, 0, QIC_120} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "WangDAT ", "Model 1300 ", ""}, {0, 0, {
+ "WangDAT ", "Model 1300 ", ""}, {0, {
{0, 0, 0}, /* minor 0-3 */
{ST_Q_FORCE_BLKSIZE, 512, DDS}, /* minor 4-7 */
{ST_Q_FORCE_BLKSIZE, 1024, DDS}, /* minor 8-11 */
{ST_Q_FORCE_BLKSIZE, 0, DDS} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "EXABYTE ", "EXB-8200 ", "263H"}, {0, 5, {
+ "EXABYTE ", "EXB-8200 ", "263H"}, {0, {
{0, 0, 0}, /* minor 0-3 */
{0, 0, 0}, /* minor 4-7 */
{0, 0, 0}, /* minor 8-11 */
{0, 0, 0} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "HP ", "T4000s ", ""}, {ST_Q_UNIMODAL, 0, {
+ "HP ", "T4000s ", ""}, {ST_Q_UNIMODAL, {
{0, 0, QIC_3095}, /* minor 0-3 */
{0, 0, QIC_3095}, /* minor 4-7 */
{0, 0, QIC_3095}, /* minor 8-11 */
@@ -226,7 +224,7 @@ const struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
}}},
#if 0
{{T_SEQUENTIAL, T_REMOV,
- "EXABYTE ", "EXB-8200 ", ""}, {0, 12, {
+ "EXABYTE ", "EXB-8200 ", ""}, {0, {
{0, 0, 0}, /* minor 0-3 */
{0, 0, 0}, /* minor 4-7 */
{0, 0, 0}, /* minor 8-11 */
@@ -234,14 +232,14 @@ const struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
}}},
#endif
{{T_SEQUENTIAL, T_REMOV,
- "WANGTEK ", "5150ES SCSI FA15\0""01 A", "????"}, {0, 0, {
+ "WANGTEK ", "5150ES SCSI FA15\0""01 A", "????"}, {0, {
{0, ST_Q_IGNORE_LOADS, 0}, /* minor 0-3 */
{0, 0, 0}, /* minor 4-7 */
{0, 0, 0}, /* minor 8-11 */
{0, 0, 0} /* minor 12-15 */
}}},
{{T_SEQUENTIAL, T_REMOV,
- "TEAC ", "MT-2ST/N50 ", ""}, {ST_Q_IGNORE_LOADS, 0, {
+ "TEAC ", "MT-2ST/N50 ", ""}, {ST_Q_IGNORE_LOADS, {
{0, 0, 0}, /* minor 0-3 */
{0, 0, 0}, /* minor 4-7 */
{0, 0, 0}, /* minor 8-11 */
@@ -263,7 +261,6 @@ struct st_softc {
u_int quirks; /* quirks for the open mode */
int blksize; /* blksize we are using */
u_int8_t density; /* present density */
- u_int page_0_size; /* size of page 0 data */
u_int last_dsty; /* last density opened */
short mt_resid; /* last (short) resid */
short mt_erreg; /* last error (sense key) seen */
@@ -274,9 +271,9 @@ struct st_softc {
int blkmax; /* max blk size */
const struct quirkdata *quirkdata; /* if we have a rogue entry */
/*--------------------parameters reported by the device for this media--------*/
- u_long numblks; /* nominal blocks capacity */
- int media_blksize; /* 0 if not ST_FIXEDBLOCKS */
- u_int8_t media_density; /* this is what it said when asked */
+ u_int64_t numblks; /* nominal blocks capacity */
+ u_int32_t media_blksize; /* 0 if not ST_FIXEDBLOCKS */
+ u_int32_t media_density; /* this is what it said when asked */
/*--------------------quirks for the whole drive------------------------------*/
u_int drive_quirks; /* quirks of this drive */
/*--------------------How we should set up when opening each minor device----*/
@@ -287,10 +284,6 @@ struct st_softc {
#define BLKSIZE_SET_BY_USER 0x04
#define BLKSIZE_SET_BY_QUIRK 0x08
/*--------------------storage for sense data returned by the drive------------*/
- u_char sense_data[MAX_PAGE_0_SIZE]; /*
- * additional sense data needed
- * for mode sense/select.
- */
struct buf buf_queue; /* the queue of pending IO operations */
};
@@ -459,7 +452,6 @@ st_identify_drive(st, inqbuf)
st->quirkdata = &finger->quirkdata;
st->drive_quirks = finger->quirkdata.quirks;
st->quirks = finger->quirkdata.quirks; /* start value */
- st->page_0_size = finger->quirkdata.page_0_size;
st_loadquirks(st);
}
}
@@ -1429,44 +1421,47 @@ st_mode_sense(st, flags)
struct st_softc *st;
int flags;
{
- size_t scsi_sense_len;
- int error;
- struct scsi_sense {
- struct scsi_mode_header header;
- struct scsi_blk_desc blk_desc;
- u_char sense_data[MAX_PAGE_0_SIZE];
- } scsi_sense;
+ struct scsi_mode_sense_buf data;
struct scsi_link *sc_link = st->sc_link;
-
- scsi_sense_len = 12 + st->page_0_size;
+ u_int64_t block_count;
+ u_int32_t density, block_size;
+ u_char *page0 = NULL;
+ u_int8_t dev_spec;
+ int error, big;
/*
- * Ask for page 0 mode sense data.
+ * Ask for page 0 (vendor specific) mode sense data.
*/
- bzero(&scsi_sense, sizeof(scsi_sense));
- error = scsi_mode_sense(sc_link, 0, 0,
- (struct scsi_mode_header *)&scsi_sense, scsi_sense_len, flags,
- ST_CTL_TIME);
- if (error)
- return error;
+ error = scsi_do_mode_sense(sc_link, 0, &data, (void **)&page0,
+ &density, &block_count, &block_size, 1, flags | SCSI_SILENT, &big);
+ if (error != 0)
+ return (error);
+
+ /* It is valid for no page0 to be available. */
+
+ if (big)
+ dev_spec = data.headers.hdr_big.dev_spec;
+ else
+ dev_spec = data.headers.hdr.dev_spec;
- st->numblks = _3btol(scsi_sense.blk_desc.nblocks);
- st->media_blksize = _3btol(scsi_sense.blk_desc.blklen);
- st->media_density = scsi_sense.blk_desc.density;
- if (scsi_sense.header.dev_spec & SMH_DSP_WRITE_PROT)
+ if (dev_spec & SMH_DSP_WRITE_PROT)
st->flags |= ST_READONLY;
else
st->flags &= ~ST_READONLY;
+
+ st->numblks = block_count;
+ st->media_blksize = block_size;
+ st->media_density = density;
+
SC_DEBUG(sc_link, SDEV_DB3,
("density code 0x%x, %d-byte blocks, write-%s, ",
st->media_density, st->media_blksize,
st->flags & ST_READONLY ? "protected" : "enabled"));
SC_DEBUGN(sc_link, SDEV_DB3,
- ("%sbuffered\n",
- scsi_sense.header.dev_spec & SMH_DSP_BUFF_MODE ? "" : "un"));
- if (st->page_0_size)
- bcopy(scsi_sense.sense_data, st->sense_data, st->page_0_size);
+ ("%sbuffered\n", dev_spec & SMH_DSP_BUFF_MODE ? "" : "un"));
+
sc_link->flags |= SDEV_MEDIA_LOADED;
+
return 0;
}
@@ -1479,17 +1474,16 @@ st_mode_select(st, flags)
struct st_softc *st;
int flags;
{
- struct scsi_select {
- struct scsi_mode_header header;
- struct scsi_blk_desc blk_desc;
- u_char sense_data[MAX_PAGE_0_SIZE];
- } scsi_select;
+ struct scsi_mode_sense_buf inbuf, outbuf;
+ struct scsi_blk_desc general;
struct scsi_link *sc_link = st->sc_link;
+ u_int8_t *page0 = NULL;
+ int error, big, page0_size;
/*
- * This quirk deals with drives that have only one valid mode
- * and think this gives them license to reject all mode selects,
- * even if the selected mode is the one that is supported.
+ * This quirk deals with drives that have only one valid mode and think
+ * this gives them license to reject all mode selects, even if the
+ * selected mode is the one that is supported.
*/
if (st->quirks & ST_Q_UNIMODAL) {
SC_DEBUG(sc_link, SDEV_DB3,
@@ -1501,30 +1495,65 @@ st_mode_select(st, flags)
if (sc_link->flags & SDEV_ATAPI)
return 0;
+ bzero(&outbuf, sizeof(outbuf));
+ bzero(&general, sizeof(general));
+
+ general.density = st->density;
+ if (st->flags & ST_FIXEDBLOCKS)
+ _lto3b(st->blksize, general.blklen);
+
/*
- * Set up for a mode select. Remember that data_length is the
- * size less the size of the data_length field.
+ * Ask for page 0 (vendor specific) mode sense data.
*/
- bzero(&scsi_select, sizeof(scsi_select));
- scsi_select.header.data_length = sizeof(scsi_select.header) +
- sizeof(scsi_select.blk_desc) + st->page_0_size - 1;
- scsi_select.header.blk_desc_len = sizeof(struct scsi_blk_desc);
- scsi_select.header.dev_spec &= ~SMH_DSP_BUFF_MODE;
- scsi_select.blk_desc.density = st->density;
- if (st->flags & ST_DONTBUFFER)
- scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_OFF;
- else
- scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
- if (st->flags & ST_FIXEDBLOCKS)
- _lto3b(st->blksize, scsi_select.blk_desc.blklen);
- if (st->page_0_size)
- bcopy(st->sense_data, scsi_select.sense_data, st->page_0_size);
+ error = scsi_do_mode_sense(sc_link, 0, &inbuf, (void **)&page0, NULL,
+ NULL, NULL, 1, flags | SCSI_SILENT, &big);
+ if (error != 0)
+ return (error);
+
+ if (page0 == NULL) {
+ page0_size = 0;
+ } else if (big == 0) {
+ page0_size = inbuf.headers.hdr.data_length +
+ sizeof(inbuf.headers.hdr.data_length) -
+ sizeof(inbuf.headers.hdr) - inbuf.headers.hdr.blk_desc_len;
+ memcpy(&outbuf.headers.buf[sizeof(outbuf.headers.hdr)+
+ sizeof(general)], page0, page0_size);
+ } else {
+ page0_size = _2btol(inbuf.headers.hdr_big.data_length) +
+ sizeof(inbuf.headers.hdr_big.data_length) -
+ sizeof(inbuf.headers.hdr_big) -
+ _2btol(inbuf.headers.hdr_big.blk_desc_len);
+ memcpy(&outbuf.headers.buf[sizeof(outbuf.headers.hdr_big) +
+ sizeof(general)], page0, page0_size);
+ }
/*
- * do the command
+ * Set up for a mode select.
*/
- return (scsi_mode_select(st->sc_link, 0,
- (struct scsi_mode_header *)&scsi_select, flags, ST_CTL_TIME));
+ if (big == 0) {
+ outbuf.headers.hdr.data_length = sizeof(outbuf.headers.hdr) +
+ sizeof(general) + page0_size -
+ sizeof(outbuf.headers.hdr.data_length);
+ if ((st->flags & ST_DONTBUFFER) == 0)
+ outbuf.headers.hdr.dev_spec = SMH_DSP_BUFF_MODE_ON;
+ outbuf.headers.hdr.blk_desc_len = sizeof(general);
+ memcpy(&outbuf.headers.buf[sizeof(outbuf.headers.hdr)],
+ &general, sizeof(general));
+ return (scsi_mode_select(st->sc_link, 0, &outbuf.headers.hdr,
+ flags, ST_CTL_TIME));
+ }
+
+ /* MODE SENSE (10) header was returned, so use MODE SELECT (10). */
+ _lto2b((sizeof(outbuf.headers.hdr_big) + sizeof(general) + page0_size -
+ sizeof(outbuf.headers.hdr_big.data_length)),
+ outbuf.headers.hdr_big.data_length);
+ if ((st->flags & ST_DONTBUFFER) == 0)
+ outbuf.headers.hdr_big.dev_spec = SMH_DSP_BUFF_MODE_ON;
+ _lto2b(sizeof(general), outbuf.headers.hdr_big.blk_desc_len);
+ memcpy(&outbuf.headers.buf[sizeof(outbuf.headers.hdr_big)], &general,
+ sizeof(general));
+ return (scsi_mode_select_big(st->sc_link, 0, &outbuf.headers.hdr_big,
+ flags, ST_CTL_TIME));
}
/*