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

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

diff -u --recursive --new-file v1.3.93/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
@@ -11,7 +11,7 @@
   Copyright 1992 - 1996 Kai Makisara
 		 email Kai.Makisara@metla.fi
 
-  Last modified: Sun Apr  7 20:33:27 1996 by root@kai.makisara.fi
+  Last modified: Sun Apr 21 22:03:50 1996 by root@kai.makisara.fi
   Some small formal changes - aeb, 950809
 */
 
@@ -77,6 +77,10 @@
 #define TAPE_NR(x) (MINOR(x) & ~(128 | ST_MODE_MASK))
 #define TAPE_MODE(x) ((MINOR(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
 
+/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
+   24 bits) */
+#define SET_DENS_AND_BLK 0x10001
+
 static int st_nbr_buffers;
 static ST_buffer **st_buffers;
 static int st_buffer_size = ST_BUFFER_SIZE;
@@ -459,7 +463,8 @@
 scsi_tape_open(struct inode * inode, struct file * filp)
 {
     unsigned short flags;
-    int i, need_dma_buffer, new_session = FALSE, setting_failed;
+    int i, need_dma_buffer, new_session = FALSE, set_it;
+    unsigned int arg;
     unsigned char cmd[10];
     Scsi_Cmnd * SCpnt;
     Scsi_Tape * STp;
@@ -568,28 +573,32 @@
       return 0;
     }
 
-    memset ((void *) &cmd[0], 0, 10);
-    cmd[0] = READ_BLOCK_LIMITS;
+    if (STp->omit_blklims)
+      STp->min_block = STp->max_block = (-1);
+    else {
+      memset ((void *) &cmd[0], 0, 10);
+      cmd[0] = READ_BLOCK_LIMITS;
 
-    SCpnt = st_do_scsi(SCpnt, STp, cmd, 6, ST_TIMEOUT, MAX_READY_RETRIES);
+      SCpnt = st_do_scsi(SCpnt, STp, cmd, 6, ST_TIMEOUT, MAX_READY_RETRIES);
 
-    if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
-      STp->max_block = ((STp->buffer)->b_data[1] << 16) |
-	((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
-      STp->min_block = ((STp->buffer)->b_data[4] << 8) |
-	(STp->buffer)->b_data[5];
+      if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
+	STp->max_block = ((STp->buffer)->b_data[1] << 16) |
+	  ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
+	STp->min_block = ((STp->buffer)->b_data[4] << 8) |
+	  (STp->buffer)->b_data[5];
 #if DEBUG
-      if (debugging)
-	printk(ST_DEB_MSG "st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
-	       STp->max_block);
+	if (debugging)
+	  printk(ST_DEB_MSG "st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
+		 STp->max_block);
 #endif
-    }
-    else {
-      STp->min_block = STp->max_block = (-1);
+      }
+      else {
+	STp->min_block = STp->max_block = (-1);
 #if DEBUG
-      if (debugging)
-	printk(ST_DEB_MSG "st%d: Can't read block limits.\n", dev);
+	if (debugging)
+	  printk(ST_DEB_MSG "st%d: Can't read block limits.\n", dev);
 #endif
+      }
     }
 
     memset ((void *) &cmd[0], 0, 10);
@@ -674,34 +683,34 @@
       STp->density_changed = STp->blksize_changed = FALSE;
       STp->compression_changed = FALSE;
       if (!(STm->defaults_for_writes)) {
-	setting_failed = FALSE;
+	set_it = FALSE;
+	if (STm->default_density >= 0 &&
+	    STm->default_density != STp->density) {
+	  arg = STm->default_density;
+	  set_it = TRUE;
+	}
+	else
+	  arg = STp->density;
+	arg <<= MT_ST_DENSITY_SHIFT;
 	if (STm->default_blksize >= 0 &&
 	    STm->default_blksize != STp->block_size) {
-	  if (STm->default_density >= 0 &&
-	      STm->default_density != STp->density)
-	    STp->density = STm->default_density;  /* Dirty trick! */
-	  if (st_int_ioctl(inode, filp, MTSETBLK, STm->default_blksize)) {
-	    printk(KERN_WARNING "st%d: Can't set default block size to %d bytes.\n",
-		   dev, STm->default_blksize);
-	    if (modes_defined)
-	      setting_failed = TRUE;
-	  }
+	  arg |= STm->default_blksize;
+	  set_it = TRUE;
 	}
-	if (STm->default_density >= 0 &&
-	    STm->default_density != STp->density) {
-	  if (st_int_ioctl(inode, filp, MTSETDENSITY, STm->default_density)) {
-	    printk(KERN_WARNING "st%d: Can't set default density to %x.\n",
-		   dev, STm->default_density);
-	    if (modes_defined)
-	      setting_failed = TRUE;
+	else
+	  arg |= STp->block_size;
+	if (set_it &&
+	    st_int_ioctl(inode, filp, SET_DENS_AND_BLK, arg)) {
+	  printk(KERN_WARNING
+		 "st%d: Can't set default block size to %d bytes and density %x.\n",
+		 dev, STm->default_blksize, STm->default_density);
+	  if (modes_defined) {
+	    (STp->buffer)->in_use = 0;
+	    STp->buffer = 0;
+	    STp->in_use = 0;
+	    return (-EINVAL);
 	  }
 	}
-	if (setting_failed) {
-	  (STp->buffer)->in_use = 0;
-	  STp->buffer = 0;
-	  STp->in_use = 0;
-	  return (-EINVAL);
-	}
       }
       if (STp->default_drvbuffer != 0xff) {
 	if (st_int_ioctl(inode, filp, MTSETDRVBUFFER, STp->default_drvbuffer))
@@ -807,7 +816,8 @@
 {
     int total, do_count, blks, retval, transfer;
     int write_threshold;
-    int doing_write = 0;
+    int doing_write = 0, set_it;
+    unsigned int arg;
     static unsigned char cmd[10];
     const char *b_point;
     Scsi_Cmnd * SCpnt = NULL;
@@ -854,32 +864,33 @@
        return retval;
       STp->rw = ST_WRITING;
     }
-    else if (STp->rw != ST_WRITING) {
-      if (STm->defaults_for_writes &&
-	  (STp->mt_status)->mt_fileno == 0 && STp->drv_block == 0) {
-	/* Force unless explicitly changed by the user */
-	if (!(STp->blksize_changed) && STm->default_blksize >= 0 &&
-	    STp->block_size != STm->default_blksize) {
-	  if (STm->default_density >= 0 &&
-	      STm->default_density != STp->density)
-	    STp->density = STm->default_density;  /* Dirty trick! */
-	  if (st_int_ioctl(inode, filp, MTSETBLK, STm->default_blksize)) {
-	    printk(KERN_WARNING "st%d: Can't set default block size to %d bytes.\n",
-		   dev, STm->default_blksize);
-	    if (modes_defined)
-	      return (-EINVAL);
-	  }
-	}
-	if (!(STp->density_changed) && STm->default_density >= 0 &&
-	    STm->default_density != STp->density) {
-	  if (st_int_ioctl(inode, filp, MTSETDENSITY, STm->default_density)) {
-	    printk(KERN_WARNING "st%d: Can't set default density %x.\n",
-		   dev, STm->default_density);
-	    if (modes_defined)
-	      return (-EINVAL);
-	  }
-	}
+    else if (STp->rw != ST_WRITING &&
+	     (STp->mt_status)->mt_fileno == 0 && STp->drv_block == 0) {
+      set_it = FALSE;
+      if (!STp->density_changed && STm->default_density >= 0 &&
+	  STm->default_density != STp->density) {
+	  arg = STm->default_density;
+	  set_it = TRUE;
+      }
+      else
+	arg = STp->density;
+      arg <<= MT_ST_DENSITY_SHIFT;
+      if (!STp->blksize_changed && STm->default_blksize >= 0 &&
+	  STm->default_blksize != STp->block_size) {
+	arg |= STm->default_blksize;
+	set_it = TRUE;
       }
+      else
+	arg |= STp->block_size;
+      if (set_it &&
+	  st_int_ioctl(inode, filp, SET_DENS_AND_BLK, arg)) {
+	printk(KERN_WARNING
+	       "st%d: Can't set default block size to %d bytes and density %x.\n",
+	       dev, STm->default_blksize, STm->default_density);
+	if (modes_defined)
+	  return (-EINVAL);
+      }
+
       if (STm->default_compression != ST_DONT_TOUCH &&
 	  !(STp->compression_changed)) {
 	if (st_compression(STp, (STm->default_compression == ST_YES))) {
@@ -1104,12 +1115,14 @@
     static unsigned char cmd[10];
     Scsi_Cmnd * SCpnt = NULL;
     Scsi_Tape * STp;
+    ST_mode * STm;
     int dev = TAPE_NR(inode->i_rdev);
 
     STp = &(scsi_tapes[dev]);
     if (STp->ready != ST_READY)
       return (-EIO);
-    if (!STp->modes[STp->current_mode].defined)
+    STm = &(STp->modes[STp->current_mode]);
+    if (!STm->defined)
       return (-ENXIO);
 #if DEBUG
     if (!STp->in_use) {
@@ -1123,7 +1136,7 @@
 	!enlarge_buffer(STp->buffer, count, STp->restr_dma))
       return (-EOVERFLOW);
 
-    if (!(STp->do_read_ahead) && STp->block_size != 0 &&
+    if (!(STm->do_read_ahead) && STp->block_size != 0 &&
 	(count % STp->block_size) != 0)
       return (-EIO);	/* Read must be integral number of blocks */
 
@@ -1162,12 +1175,12 @@
 	if (STp->block_size == 0)
 	  blks = bytes = count;
 	else {
-	  if (STp->do_read_ahead) {
+	  if (STm->do_read_ahead) {
 	    blks = (STp->buffer)->buffer_blocks;
 	    bytes = blks * STp->block_size;
 	  }
 	  else {
-	    bytes = count;
+	    bytes = count - total;
 	    if (bytes > (STp->buffer)->buffer_size)
 	      bytes = (STp->buffer)->buffer_size;
 	    blks = bytes / STp->block_size;
@@ -1346,11 +1359,13 @@
   printk(KERN_INFO
 "st%d: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
 	 dev, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
-	 STp->do_read_ahead);
+	 STm->do_read_ahead);
+  printk(KERN_INFO
+"st%d:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
+	 dev, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
   printk(KERN_INFO
-"st%d:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d, defs for wr: %d \n",
-	 dev, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock,
-	 STm->defaults_for_writes);
+"st%d:    defs for wr: %d, no block limits: %d\n",
+	 dev, STm->defaults_for_writes, STp->omit_blklims);
 #if DEBUG
   printk(KERN_INFO
 	 "st%d:    debugging: %d\n",
@@ -1385,11 +1400,12 @@
     STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
     STm->do_async_writes  = (options & MT_ST_ASYNC_WRITES) != 0;
     STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
-    STp->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
+    STm->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
     STp->two_fm		  = (options & MT_ST_TWO_FM) != 0;
     STp->fast_mteom	  = (options & MT_ST_FAST_MTEOM) != 0;
     STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
     STp->can_bsr          = (options & MT_ST_CAN_BSR) != 0;
+    STp->omit_blklims	  = (options & MT_ST_NO_BLKLIMS) != 0;
 #if DEBUG
     debugging = (options & MT_ST_DEBUGGING) != 0;
 #endif
@@ -1404,7 +1420,7 @@
     if ((options & MT_ST_DEF_WRITES) != 0)
       STm->defaults_for_writes = value;
     if ((options & MT_ST_READ_AHEAD) != 0)
-      STp->do_read_ahead = value;
+      STm->do_read_ahead = value;
     if ((options & MT_ST_TWO_FM) != 0)
       STp->two_fm = value;
     if ((options & MT_ST_FAST_MTEOM) != 0)
@@ -1413,6 +1429,8 @@
       STp->do_auto_lock = value;
     if ((options & MT_ST_CAN_BSR) != 0)
       STp->can_bsr = value;
+    if ((options & MT_ST_NO_BLKLIMS) != 0)
+      STp->omit_blklims = value;
 #if DEBUG
     if ((options & MT_ST_DEBUGGING) != 0)
       debugging = value;
@@ -1875,12 +1893,14 @@
      case MTSETBLK:  /* Set block length */
      case MTSETDENSITY: /* Set tape density */
      case MTSETDRVBUFFER: /* Set drive buffering */
+     case SET_DENS_AND_BLK: /* Set density and block size */
        if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
 	 return (-EIO);   /* Not allowed if data in buffer */
-       if (cmd_in == MTSETBLK &&
-	   arg != 0 &&
-	   (arg < STp->min_block || arg > STp->max_block ||
-	    arg > st_buffer_size)) {
+       if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
+	   (arg & MT_ST_BLKSIZE_MASK) != 0 &&
+	   ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block ||
+	    (arg & MT_ST_BLKSIZE_MASK) > STp->max_block ||
+	    (arg & MT_ST_BLKSIZE_MASK) > st_buffer_size)) {
 	 printk(KERN_WARNING "st%d: Illegal block size.\n", dev);
 	 return (-EINVAL);
        }
@@ -1898,11 +1918,14 @@
 	 (STp->buffer)->b_data[4] = arg;
 	 STp->density_changed = TRUE;  /* At least we tried ;-) */
        }
+       else if (cmd_in == SET_DENS_AND_BLK)
+	 (STp->buffer)->b_data[4] = arg >> 24;
        else
 	 (STp->buffer)->b_data[4] = STp->density;
-       if (cmd_in == MTSETBLK) {
-	 ltmp = arg;
-	 STp->blksize_changed = TRUE;  /* At least we tried ;-) */
+       if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
+	 ltmp = arg & MT_ST_BLKSIZE_MASK;
+	 if (cmd_in == MTSETBLK)
+	   STp->blksize_changed = TRUE;  /* At least we tried ;-) */
        }
        else
 	 ltmp = STp->block_size;
@@ -1912,15 +1935,15 @@
        timeout = ST_TIMEOUT;
 #if DEBUG
        if (debugging) {
-	 if (cmd_in == MTSETBLK)
+	 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
 	   printk(ST_DEB_MSG "st%d: Setting block size to %d bytes.\n", dev,
 		  (STp->buffer)->b_data[9] * 65536 +
 		  (STp->buffer)->b_data[10] * 256 +
 		  (STp->buffer)->b_data[11]);
-	 else if (cmd_in == MTSETDENSITY)
+	 if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK)
 	   printk(ST_DEB_MSG "st%d: Setting density code to %x.\n", dev,
 		  (STp->buffer)->b_data[4]);
-	 else
+	 if (cmd_in == MTSETDRVBUFFER)
 	   printk(ST_DEB_MSG "st%d: Setting drive buffer code to %d.\n", dev,
 		  ((STp->buffer)->b_data[2] >> 4) & 7);
        }
@@ -1960,9 +1983,9 @@
        ioctl_result = st_int_ioctl(inode, file, MTFSF, 1);
      else if (cmd_in == MTFSFM)
        ioctl_result = st_int_ioctl(inode, file, MTBSF, 1);
-     else if (cmd_in == MTSETBLK) {
-       STp->block_size = arg;
-       if (arg != 0)
+     else if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
+       STp->block_size = arg & MT_ST_BLKSIZE_MASK;
+       if (STp->block_size != 0)
 	 (STp->buffer)->buffer_blocks =
 	   (STp->buffer)->buffer_size / STp->block_size;
        (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
@@ -1979,6 +2002,8 @@
        STp->eof = ST_NOEOF;
        STp->eof_hit = 0;
      }
+     if (cmd_in == SET_DENS_AND_BLK)
+       STp->density = arg >> MT_ST_DENSITY_SHIFT;
      if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
        STp->rew_at_close = 0;
      else if (cmd_in == MTLOAD)
@@ -2450,7 +2475,6 @@
    tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
    tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
    tpnt->density = 0;
-   tpnt->do_read_ahead = ST_READ_AHEAD;
    tpnt->do_auto_lock = ST_AUTO_LOCK;
    tpnt->can_bsr = ST_IN_FILE_POS;
    tpnt->two_fm = ST_TWO_FM;
@@ -2467,6 +2491,7 @@
      tpnt->modes[i].defaults_for_writes = 0;
      tpnt->modes[i].do_async_writes = ST_ASYNC_WRITES;
      tpnt->modes[i].do_buffer_writes = ST_BUFFER_WRITES;
+     tpnt->modes[i].do_read_ahead = ST_READ_AHEAD;
      tpnt->modes[i].default_compression = ST_DONT_TOUCH;
      tpnt->modes[i].default_blksize = (-1);  /* No forced size */
      tpnt->modes[i].default_density = (-1);  /* No forced density */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this