Subject: kern/807: scsi tape code doesn't honor cache request, doesn't implement erase
To: None <gnats-admin@NetBSD.ORG>
From: John Kohl <jtk@kolvir.blrc.ma.us>
List: netbsd-bugs
Date: 02/19/1995 12:20:04
>Number: 807
>Category: kern
>Synopsis: scsi tape code doesn't honor cache request, doesn't implement erase
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sun Feb 19 12:20:03 1995
>Originator: John Kohl
>Organization:
NetBSD Kernel Hackers `R` Us
>Release: -current, 1995 Feb 19
>Environment:
System: NetBSD kolvir 1.0A NetBSD 1.0A (KOLVIR) #85: Sun Feb 19 14:10:26 EST 1995 jtk@kolvir:/u1/NetBSD-current/src/sys/arch/i386/compile/KOLVIR i386
>Description:
The SCSI code in -current doesn't honor the cache/nocache requests, and
doesn't implement the MTERASE operation.
The control flow is also wrong on a bad density setting.
>How-To-Repeat:
try 'mt erase', or read code.
>Fix:
See the comments about whether we should wait for erase, and/or how long
we should wait. Any suggestions?
===================================================================
RCS file: RCS/st.c,v
retrieving revision 1.1
diff -ubw -r1.1 st.c
--- 1.1 1995/02/17 23:58:02
+++ st.c 1995/02/19 19:47:41
@@ -230,10 +230,12 @@
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_erase __P((struct st_softc *, int full, int flags));
int st_mode_select __P((struct st_softc *, int flags));
void ststrategy();
void stminphys();
-int st_check_eod();
+int st_check_eod __P((struct st_softc *st, boolean position, int *nmarks,
+ int flags));
void ststart();
void st_unmount();
int st_mount_tape();
@@ -264,6 +266,7 @@
#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 | \
@@ -1080,7 +1083,13 @@
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
@@ -1106,9 +1115,10 @@
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;
@@ -1337,6 +1347,10 @@
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;
+ 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;
scsi_select.blk_desc.density = st->density;
if (st->flags & ST_FIXEDBLOCKS)
@@ -1535,6 +1549,36 @@
return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
sizeof(cmd), 0, 0, ST_RETRIES, 300000, NULL, flags);
+}
+
+/*
+ * erase
+ */
+int
+st_erase(st, full, flags)
+ struct st_softc *st;
+ int full;
+ int flags;
+{
+ struct scsi_erase cmd;
+
+ /* full erase means set LONG bit in erase command (ask the drive
+ * to zap everything.
+ * non-full means don't set LONG bit (ask the drive to write an
+ * erase gap)
+ */
+ bzero(&cmd, sizeof(cmd));
+ cmd.opcode = ERASE;
+ if (full)
+ cmd.byte2 = SE_IMMEDIATE|SE_LONG;
+ else
+ cmd.byte2 = SE_IMMEDIATE;
+
+ /* We always do it asynchronously, for now.
+ How long should we wait if we want (eventually) to do it
+ synchronously? */
+ return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+ sizeof(cmd), 0, 0, ST_RETRIES, 5000, NULL, flags);
}
/*
===================================================================
RCS file: RCS/scsi_tape.h,v
retrieving revision 1.1
diff -ubw -r1.1 scsi_tape.h
--- 1.1 1995/02/18 00:24:28
+++ scsi_tape.h 1995/02/19 19:04:07
@@ -110,12 +110,54 @@
u_char control;
};
+#define ERASE 0x19
+struct scsi_erase {
+ u_char opcode;
+ u_char byte2;
+#define SE_LONG 0x01
+#define SE_IMMED 0x02
+ u_char unused[3];
+ u_char control;
+};
+
#define READ_BLOCK_LIMITS 0x05
struct scsi_block_limits {
u_char opcode;
u_char byte2;
u_char unused[3];
u_char control;
+};
+
+/* 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 */
+ u_char active_partition;
+ u_char wb_full_ratio;
+ u_char rb_empty_ratio;
+ u_char wrdelay_time[2];
+ 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_bufsiz[3];
+ u_char sel_comp_alg; /* select compression algorithm */
+#define SMT_COMP_NONE 0x00
+#define SMT_COMP_DEFAULT 0x01
+ u_char reserved;
};
struct scsi_block_limits_data {
>Audit-Trail:
>Unformatted: