diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2005-06-24 20:48:26 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2005-06-24 20:48:26 +0000 |
commit | 88a9d1540b8ba6caa65a80963783b38fe390fdcb (patch) | |
tree | ef58d565547c108bdeea7804fcc5e6b914024a37 /sys | |
parent | f1425ac7851f760b4d876aac487905e9304ea453 (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.c | 189 |
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)); } /* |