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: