patch-2.4.9 linux/drivers/scsi/st.c

Next file: linux/drivers/scsi/st.h
Previous file: linux/drivers/scsi/sr_ioctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.8/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
@@ -5,14 +5,14 @@
    History:
    Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
    Contribution and ideas from several people including (in alphabetical
-   order) Klaus Ehrenfried, Eric Lee Green, Wolfgang Denk, Steve Hirsch,
-   Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, Michael Schaefer,
-   J"org Weule, and Eric Youngdale.
+   order) Klaus Ehrenfried, Eugene Exarevsky, Eric Lee Green, Wolfgang Denk,
+   Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
+   Michael Schaefer, J"org Weule, and Eric Youngdale.
 
-   Copyright 1992 - 2000 Kai Makisara
+   Copyright 1992 - 2001 Kai Makisara
    email Kai.Makisara@metla.fi
 
-   Last modified: Mon Nov 13 21:01:09 2000 by makisara@kai.makisara.local
+   Last modified: Sun Aug 12 12:34:28 2001 by makisara@kai.makisara.local
    Some small formal changes - aeb, 950809
 
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
@@ -21,6 +21,8 @@
    error handling will be discarded.
  */
 
+static char *verstr = "20010812";
+
 #include <linux/module.h>
 
 #include <linux/fs.h>
@@ -77,9 +79,13 @@
 MODULE_AUTHOR("Kai Makisara");
 MODULE_DESCRIPTION("SCSI Tape Driver");
 MODULE_PARM(buffer_kbs, "i");
+MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size (KB; 32)");
 MODULE_PARM(write_threshold_kbs, "i");
+MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 30)");
 MODULE_PARM(max_buffers, "i");
+MODULE_PARM_DESC(max_buffers, "Maximum number of buffer allocated at initialisation (4)");
 MODULE_PARM(max_sg_segs, "i");
+MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (32)");
 
 #ifndef MODULE
 static struct st_dev_parm {
@@ -302,38 +308,33 @@
 	int remainder;
 	Scsi_Tape *STp;
 
-	if ((st_nbr = TAPE_NR(SCpnt->request.rq_dev)) < st_template.nr_dev) {
-		read_lock(&st_dev_arr_lock);
-		STp = scsi_tapes[st_nbr];
-		read_unlock(&st_dev_arr_lock);
-		if ((STp->buffer)->writing &&
-		    (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
-		    (SCpnt->sense_buffer[2] & 0x40)) {
-			/* EOM at write-behind, has all been written? */
-			if ((SCpnt->sense_buffer[0] & 0x80) != 0)
-				remainder = (SCpnt->sense_buffer[3] << 24) |
-                                    (SCpnt->sense_buffer[4] << 16) |
-				    (SCpnt->sense_buffer[5] << 8) |
-                                    SCpnt->sense_buffer[6];
-			else
-				remainder = 0;
-			if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW ||
-			    remainder > 0)
-				(STp->buffer)->midlevel_result = SCpnt->result; /* Error */
-			else
-				(STp->buffer)->midlevel_result = INT_MAX;	/* OK */
-		} else
-			(STp->buffer)->midlevel_result = SCpnt->result;
-		SCpnt->request.rq_status = RQ_SCSI_DONE;
-		(STp->buffer)->last_SRpnt = SCpnt->sc_request;
-		DEB( STp->write_pending = 0; )
+	st_nbr = TAPE_NR(SCpnt->request.rq_dev);
+	read_lock(&st_dev_arr_lock);
+	STp = scsi_tapes[st_nbr];
+	read_unlock(&st_dev_arr_lock);
+	if ((STp->buffer)->writing &&
+	    (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
+	    (SCpnt->sense_buffer[2] & 0x40)) {
+		/* EOM at write-behind, has all been written? */
+		if ((SCpnt->sense_buffer[0] & 0x80) != 0)
+			remainder = (SCpnt->sense_buffer[3] << 24) |
+				(SCpnt->sense_buffer[4] << 16) |
+				(SCpnt->sense_buffer[5] << 8) |
+				SCpnt->sense_buffer[6];
+		else
+			remainder = 0;
+		if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW ||
+		    remainder > 0)
+			(STp->buffer)->midlevel_result = SCpnt->result; /* Error */
+		else
+			(STp->buffer)->midlevel_result = INT_MAX;	/* OK */
+	} else
+		(STp->buffer)->midlevel_result = SCpnt->result;
+	SCpnt->request.rq_status = RQ_SCSI_DONE;
+	(STp->buffer)->last_SRpnt = SCpnt->sc_request;
+	DEB( STp->write_pending = 0; )
 
-		complete(SCpnt->request.waiting);
-	}
-        DEB(
-	else if (debugging)
-		printk(KERN_ERR "st?: Illegal interrupt device %x\n", st_nbr);
-	) /* end DEB */
+	complete(SCpnt->request.waiting);
 }
 
 
@@ -1302,8 +1303,7 @@
                         DEBC(printk(ST_DEB_MSG "st%d: Error on write:\n", dev));
 			if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
 			    (SRpnt->sr_sense_buffer[2] & 0x40)) {
-				if (STp->block_size != 0 &&
-                                    (SRpnt->sr_sense_buffer[0] & 0x80) != 0)
+				if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)
 					transfer = (SRpnt->sr_sense_buffer[3] << 24) |
 					    (SRpnt->sr_sense_buffer[4] << 16) |
 					    (SRpnt->sr_sense_buffer[5] << 8) |
@@ -2302,7 +2302,7 @@
 	case MTEOM:
 		if (!STp->fast_mteom) {
 			/* space to the end of tape */
-			ioctl_result = st_int_ioctl(STp, MTFSF, 0x3fff);
+			ioctl_result = st_int_ioctl(STp, MTFSF, 0x7fffff);
 			fileno = STps->drv_file;
 			if (STps->eof >= ST_EOD_1)
 				return 0;
@@ -2361,6 +2361,8 @@
 			return (-EINVAL);
 		}
 		cmd[0] = MODE_SELECT;
+		if ((STp->use_pf & USE_PF))
+			cmd[1] = MODE_SELECT_PAGE_FORMAT;
 		cmd[4] = datalen = 12;
 		direction = SCSI_DATA_WRITE;
 
@@ -2474,11 +2476,11 @@
 			STps->drv_block = 0;
 		}
 
-		undone = (
-				 (SRpnt->sr_sense_buffer[3] << 24) +
-				 (SRpnt->sr_sense_buffer[4] << 16) +
-				 (SRpnt->sr_sense_buffer[5] << 8) +
-				 SRpnt->sr_sense_buffer[6]);
+		undone = ((SRpnt->sr_sense_buffer[3] << 24) +
+			  (SRpnt->sr_sense_buffer[4] << 16) +
+			  (SRpnt->sr_sense_buffer[5] << 8) +
+			  SRpnt->sr_sense_buffer[6]);
+
 		if (cmd_in == MTWEOF &&
 		    (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
 		    (SRpnt->sr_sense_buffer[2] & 0x4f) == 0x40 &&
@@ -2496,6 +2498,8 @@
 			STps->drv_block = 0;
 			STps->eof = ST_NOEOF;
 		} else if ((cmd_in == MTBSF) || (cmd_in == MTBSFM)) {
+			if (arg > 0 && undone < 0)  /* Some drives get this wrong */
+				undone = (-undone);
 			if (STps->drv_file >= 0)
 				STps->drv_file = fileno + undone;
 			STps->drv_block = 0;
@@ -2518,6 +2522,8 @@
 				STps->drv_file--;
 				STps->drv_block = (-1);
 			} else {
+				if (arg > 0 && undone < 0)  /* Some drives get this wrong */
+					undone = (-undone);
 				if (STps->drv_block >= 0)
 					STps->drv_block = blkno + undone;
 			}
@@ -2526,6 +2532,19 @@
 			STps->drv_file = (-1);
 			STps->drv_block = (-1);
 			STps->eof = ST_EOD;
+		} else if (cmd_in == MTSETBLK ||
+			   cmd_in == MTSETDENSITY ||
+			   cmd_in == MTSETDRVBUFFER ||
+			   cmd_in == SET_DENS_AND_BLK) {
+			if ((SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST &&
+			    !(STp->use_pf & PF_TESTED)) {
+				/* Try the other possible state of Page Format if not
+				   already tried */
+				STp->use_pf = !STp->use_pf | PF_TESTED;
+				scsi_release_request(SRpnt);
+				SRpnt = NULL;
+				return st_int_ioctl(STp, cmd_in, arg);
+			}
 		} else if (chg_eof)
 			STps->eof = ST_NOEOF;
 
@@ -3608,6 +3627,7 @@
 	tpnt->in_use = 0;
 	tpnt->drv_buffer = 1;	/* Try buffering if no mode sense */
 	tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
+	tpnt->use_pf = (SDp->scsi_level >= SCSI_2);
 	tpnt->density = 0;
 	tpnt->do_auto_lock = ST_AUTO_LOCK;
 	tpnt->can_bsr = ST_IN_FILE_POS;
@@ -3692,8 +3712,9 @@
 	if (st_template.dev_noticed == 0 || st_registered)
 		return 0;
 
-	printk(KERN_INFO "st: bufsize %d, wrt %d, max init. buffers %d, s/g segs %d.\n",
-	       st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs);
+	printk(KERN_INFO
+	       "st: Version %s, bufsize %d, wrt %d, max init. bufs %d, s/g segs %d\n",
+	       verstr, st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs);
 
 	write_lock_irqsave(&st_dev_arr_lock, flags);
 	if (!st_registered) {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)