From 0488fc5f77149361f1c61d1781683b42f3b7cd83 Mon Sep 17 00:00:00 2001 From: deraadt Date: Tue, 16 Jan 1996 01:20:31 +0000 Subject: [PATCH] from netbsd: Honor cache request and add the SCSI tape device configuration page. Fixes PRs 807, 1201, and 1705. From John Kohl . --- sys/scsi/scsi_tape.h | 35 +++++++++++++++ sys/scsi/st.c | 102 ++++++++++++++++++++++--------------------- 2 files changed, 88 insertions(+), 49 deletions(-) diff --git a/sys/scsi/scsi_tape.h b/sys/scsi/scsi_tape.h index f4e24102af6..25b8f2624d8 100644 --- a/sys/scsi/scsi_tape.h +++ b/sys/scsi/scsi_tape.h @@ -137,6 +137,41 @@ struct scsi_block_limits_data { u_char min_length_0; /* Least significant */ }; +/* See SCSI-II spec 9.3.3.1 */ +struct scsi_tape_dev_conf_page { + u_char pagecode; /* 0x10 */ + u_char pagelength; /* 0x0e */ + u_char byte2; +#define SMT_CAP 0x40 /* change active partition */ +#define SMT_CAF 0x20 /* change active format */ +#define SMT_AFMASK 0x1f /* active format mask */ + u_char active_partition; + u_char wb_full_ratio; + u_char rb_empty_ratio; + u_char wrdelay_time_1; /* MSB */ + u_char wrdelay_time_0; /* LSB */ + u_char byte8; +#define SMT_DBR 0x80 /* data buffer recovery */ +#define SMT_BIS 0x40 /* block identifiers supported */ +#define SMT_RSMK 0x20 /* report setmarks */ +#define SMT_AVC 0x10 /* automatic velocity control */ +#define SMT_SOCF_MASK 0xc0 /* stop on consecutive formats */ +#define SMT_RBO 0x20 /* recover buffer order */ +#define SMT_REW 0x10 /* report early warning */ + u_char gap_size; + u_char byte10; +#define SMT_EODDEFINED 0xe0 /* EOD defined */ +#define SMT_EEG 0x10 /* enable EOD generation */ +#define SMT_SEW 0x80 /* synchronize at early warning */ + u_char ew_bufsize_2; /* MSB */ + u_char ew_bufsize_1; /* ... */ + u_char ew_bufsize_0; /* LSB */ + u_char sel_comp_alg; +#define SMT_COMP_NONE 0x00 +#define SMT_COMP_DEFAULT 0x01 + u_char reserved; +}; + /* defines for the device specific byte in the mode select/sense header */ #define SMH_DSP_SPEED 0x0F #define SMH_DSP_BUFF_MODE 0x70 diff --git a/sys/scsi/st.c b/sys/scsi/st.c index a4c68ccf3c8..1fb0c986def 100644 --- a/sys/scsi/st.c +++ b/sys/scsi/st.c @@ -273,14 +273,14 @@ int st_touch_tape __P((struct st_softc *)); int st_write_filemarks __P((struct st_softc *, int number, int flags)); int st_load __P((struct st_softc *, u_int type, int flags)); int st_mode_select __P((struct st_softc *, int flags)); -void ststrategy(); -int st_check_eod(); -void ststart(); -void st_unmount(); -int st_mount_tape(); -void st_loadquirks(); -void st_identify_drive(); -int st_interpret_sense(); +void ststrategy __P((struct buf *)); +int st_check_eod __P((struct st_softc *, boolean, int *, int)); +void ststart __P((struct st_softc *)); +void st_unmount __P((struct st_softc *, boolean)); +int st_mount_tape __P((dev_t, int)); +void st_loadquirks __P((struct st_softc *)); +void st_identify_drive __P((struct st_softc *, struct scsi_inquiry_data *)); +int st_interpret_sense __P((struct scsi_xfer *)); struct scsi_device st_switch = { st_interpret_sense, @@ -305,6 +305,7 @@ struct scsi_device st_switch = { #define ST_BLANK_READ 0x0200 /* BLANK CHECK encountered already */ #define ST_2FM_AT_EOD 0x0400 /* write 2 file marks at EOD */ #define ST_MOUNTED 0x0800 /* Device is presently mounted */ +#define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */ #define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ) #define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \ @@ -1109,9 +1110,6 @@ stioctl(dev, cmd, arg, flag, p) if (!error) error = st_space(st, number, SP_BLKS, flags); break; - case MTERASE: /* erase */ - error = st_erase(st, FALSE, flags); - break; case MTREW: /* rewind */ error = st_rewind(st, 0, flags); break; @@ -1131,7 +1129,13 @@ stioctl(dev, cmd, arg, flag, p) error = st_space(st, 1, SP_EOM, flags); break; case MTCACHE: /* enable controller cache */ + st->flags &= ~ST_DONTBUFFER; + goto try_new_value; case MTNOCACHE: /* disable controller cache */ + st->flags |= ST_DONTBUFFER; + goto try_new_value; + case MTERASE: /* erase volume */ + error = st_erase(st, number, flags); break; case MTSETBSIZ: /* Set block size for device */ #ifdef NOTYET @@ -1157,9 +1161,10 @@ stioctl(dev, cmd, arg, flag, p) goto try_new_value; case MTSETDNSTY: /* Set density for device and mode */ - if (number > SCSI_2_MAX_DENSITY_CODE) + if (number > SCSI_2_MAX_DENSITY_CODE) { error = EINVAL; - else + break; + } else st->density = number; goto try_new_value; @@ -1388,8 +1393,12 @@ st_mode_select(st, flags) bzero(&scsi_select, scsi_select_len); scsi_select.header.blk_desc_len = sizeof(struct scsi_blk_desc); - scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON; + 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) @@ -1403,6 +1412,36 @@ st_mode_select(st, flags) ST_RETRIES, 5000, NULL, flags | SCSI_DATA_OUT); } +/* + * issue an erase command + */ +int +st_erase(st, full, flags) + struct st_softc *st; + int full, flags; +{ + struct scsi_erase cmd; + + /* + * Full erase means set LONG bit in erase command, which asks + * the drive to erase the entire unit. Without this bit, we're + * asking the drive to write an erase gap. + */ + bzero(&cmd, sizeof(cmd)); + cmd.opcode = ERASE; + if (full) + cmd.byte2 = SE_IMMED|SE_LONG; + else + cmd.byte2 = SE_IMMED; + + /* + * XXX We always do this asynchronously, for now. How long should + * we wait if we want to (eventually) to it synchronously? + */ + return (scsi_scsi_cmd(st->sc_link, (struct scsi_generic *)&cmd, + sizeof(cmd), 0, 0, ST_RETRIES, 5000, NULL, flags)); +} + /* * skip N blocks/filemarks/seq filemarks/eom */ @@ -1615,41 +1654,6 @@ st_rewind(st, immediate, flags) flags); } -/* - * Erase the tape - */ -int -st_erase(st, immediate, flags) - struct st_softc *st; - u_int immediate; - int flags; -{ - struct scsi_erase scsi_cmd; - int error; - int nmarks; - - error = st_check_eod(st, FALSE, &nmarks, flags); - if (error) - return (error); - /* - * Archive Viper 2525 technical manual 5.7 (ERASE 19h): - * tape has to be positioned to BOT first before erase command - * is issued or command is rejected. So we rewind the tape first - * and exit with an error, if the tape can't be rewinded. - */ - error = st_rewind(st, FALSE, SCSI_SILENT); - if (error) - return (error); - st->flags &= ~ST_PER_ACTION; - bzero(&scsi_cmd, sizeof(scsi_cmd)); - scsi_cmd.opcode = ERASE; - scsi_cmd.byte2 = SE_LONG | (immediate ? SE_IMMED : 0); - return (scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &scsi_cmd, - sizeof(scsi_cmd), 0, 0, ST_RETRIES, - immediate ? 5000 : 300000, /* 5 sec or 5 min */ - NULL, flags)); -} - /* * Look at the returned sense and act on the error and detirmine * The unix error number to pass back... (0 = report no error) -- 2.20.1