from netbsd:
authorderaadt <deraadt@openbsd.org>
Tue, 16 Jan 1996 01:20:31 +0000 (01:20 +0000)
committerderaadt <deraadt@openbsd.org>
Tue, 16 Jan 1996 01:20:31 +0000 (01:20 +0000)
Honor cache request and add the SCSI tape device configuration page.
Fixes PRs 807, 1201, and 1705. From John Kohl <jtk@kolvir.blrc.ma.us>.

sys/scsi/scsi_tape.h
sys/scsi/st.c

index f4e2410..25b8f26 100644 (file)
@@ -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
index a4c68cc..1fb0c98 100644 (file)
@@ -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)