vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| The latest snapshots (dated today or later) include an uncommitted diff (included below for those doing the -current thing) that updates how st.c detects and sets the mode of tape drives. cd's and disk's have been using the new code for a while but tape drives make more extensive use of the MODE SENSE/SELECT mechanism. If anyone has tape drives they want to work on 3.8, now is the time to test a snapshot and ensure their drive works, so that problems can be addressed asap. In particular any of the following tape drives: TANDBERG TDC 3600 ARCHIVE VIPER 150 ARCHIVE VIPER 150 EXABYTE EXB-8200 are particularly likely to be affected since they use MODE SENSE page 0 information. Please report success or failure to me, including a dmesg and what your test consisted of. If you experience a failure, a capture of the output from a kernel compiled with the options option SCSIDEBUG option SCSIDEBUG_LEVEL=0xf0 option SCSIDEBUG_BUSES=0x.. option SCSIDEBUG_TARGETS=0x.. option SCSIDEBUG_LUNS=0xff (where the ..'s are replaced with the appropriate bit value indicating the bus and target ids of the tape drive. See options(8) for details.) would be needed for diagnosis. A perfect failure report would include such a trace before and after the diff below. ..... Ken Index: st.c ================================================== ================= RCS file: /cvs/src/sys/scsi/st.c,v retrieving revision 1.47 diff -u -r1.47 st.c --- st.c 5 Jun 2005 21:27:07 -0000 1.47 +++ st.c 12 Jun 2005 22:32:46 -0000 @@ -107,8 +107,6 @@ #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 @@ 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 @@ * 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 @@ * 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 @@ }}}, #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 @@ }}}, #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 @@ 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 @@ 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 @@ #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->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 @@ 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; + 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 (vendor specific) mode sense data. + */ + 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; - scsi_sense_len = 12 + st->page_0_size; - - /* - * Ask for page 0 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; - - 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 @@ 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 @@ if (sc_link->flags & SDEV_ATAPI) return 0; - /* - * Set up for a mode select. Remember that data_length is the - * size less the size of the data_length field. - */ - 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; + bzero(&outbuf, sizeof(outbuf)); + bzero(&general, sizeof(general)); + + general.density = st->density; 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); + _lto3b(st->blksize, general.blklen); /* - * do the command + * Ask for page 0 (vendor specific) mode sense data. */ - return (scsi_mode_select(st->sc_link, 0, - (struct scsi_mode_header *)&scsi_select, flags, ST_CTL_TIME)); + 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); + } + + /* + * Set up for a mode select. + */ + 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)); } /* |