patch-1.3.98 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
- Lines: 1390
- Date:
Fri May 3 10:12:16 1996
- Orig file:
v1.3.97/linux/drivers/scsi/st.c
- Orig date:
Wed Apr 24 17:00:41 1996
diff -u --recursive --new-file v1.3.97/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
@@ -5,13 +5,13 @@
History:
Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
Contribution and ideas from several people including (in alphabetical
- order) Klaus Ehrenfried, Steve Hirsch, Wolfgang Denk, Andreas Koppenh"ofer,
- J"org Weule, and Eric Youngdale.
+ order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
+ Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
Copyright 1992 - 1996 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Wed Apr 24 09:53:23 1996 by root@kai.makisara.fi
+ Last modified: Thu May 2 19:41:34 1996 by makisara@kai.makisara.fi
Some small formal changes - aeb, 950809
*/
@@ -43,7 +43,7 @@
#include <linux/blk.h>
#include "scsi.h"
#include "hosts.h"
-#include "scsi_ioctl.h"
+#include <scsi/scsi_ioctl.h>
#include "st.h"
#include "constants.h"
@@ -72,7 +72,7 @@
#define NO_TAPE NOT_READY
#define ST_TIMEOUT (900 * HZ)
-#define ST_LONG_TIMEOUT (2000 * HZ)
+#define ST_LONG_TIMEOUT (14000 * HZ)
#define TAPE_NR(x) (MINOR(x) & ~(128 | ST_MODE_MASK))
#define TAPE_MODE(x) ((MINOR(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
@@ -107,8 +107,11 @@
static int st_compression(Scsi_Tape *, int);
-static int st_int_ioctl(struct inode * inode,struct file * file,
- unsigned int cmd_in, unsigned long arg);
+static int find_partition(struct inode *);
+static int update_partition(struct inode *);
+
+static int st_int_ioctl(struct inode * inode, unsigned int cmd_in,
+ unsigned long arg);
@@ -424,11 +427,14 @@
if (STp->ready != ST_READY)
return 0;
- if (STp->rw == ST_WRITING) /* Writing */
+ if (STp->ps[STp->partition].rw == ST_WRITING) /* Writing */
return flush_write_buffer(STp);
- if (STp->block_size == 0)
+ if (STp->block_size == 0) {
+ STp->eof = ST_NOEOF;
+ STp->eof_hit = 0;
return 0;
+ }
backspace = ((STp->buffer)->buffer_bytes +
(STp->buffer)->read_pointer) / STp->block_size -
@@ -446,7 +452,7 @@
}
}
if (!result && backspace > 0)
- result = st_int_ioctl(inode, filp, MTBSR, backspace);
+ result = st_int_ioctl(inode, MTBSR, backspace);
}
else if ((STp->eof == ST_FM) && !STp->eof_hit) {
(STp->mt_status)->mt_fileno++;
@@ -457,14 +463,49 @@
}
+/* Set the mode parameters */
+ static int
+set_mode_densblk(struct inode * inode, Scsi_Tape *STp, ST_mode *STm)
+{
+ int set_it = FALSE;
+ unsigned long arg;
+ int dev = TAPE_NR(inode->i_rdev);
+
+ 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, 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);
+ }
+ return 0;
+}
+
/* Open the device */
static int
scsi_tape_open(struct inode * inode, struct file * filp)
{
unsigned short flags;
- int i, need_dma_buffer, new_session = FALSE, set_it;
- unsigned int arg;
+ int i, need_dma_buffer, new_session = FALSE;
unsigned char cmd[10];
Scsi_Cmnd * SCpnt;
Scsi_Tape * STp;
@@ -513,13 +554,13 @@
STp->buffer = st_buffers[i];
(STp->buffer)->in_use = 1;
(STp->buffer)->writing = 0;
- STp->in_use = 1;
flags = filp->f_flags;
STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
STp->dirty = 0;
- STp->rw = ST_IDLE;
+ for (i=0; i < ST_NBR_PARTITIONS; i++)
+ STp->ps[i].rw = ST_IDLE;
STp->ready = ST_READY;
if (STp->eof != ST_EOD) /* Save EOD across opens */
STp->eof = ST_NOEOF;
@@ -547,6 +588,15 @@
(STp->mt_status)->mt_fileno = STp->drv_block = 0;
STp->eof = ST_NOEOF;
(STp->device)->was_reset = 0;
+ STp->partition = STp->new_partition = 0;
+ if (STp->can_partitions)
+ STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
+ for (i=0; i < ST_NBR_PARTITIONS; i++) {
+ STp->ps[i].rw = ST_IDLE;
+ STp->ps[i].moves_after_eof = 1;
+ STp->ps[i].at_sm = 0;
+ STp->ps[i].last_block_valid = FALSE;
+ }
new_session = TRUE;
}
@@ -566,7 +616,9 @@
STp->block_size = 0;
STp->eof = ST_NOEOF;
(STp->mt_status)->mt_fileno = STp->drv_block = 0;
+ STp->partition = STp->new_partition = 0;
STp->door_locked = ST_UNLOCKED;
+ STp->in_use = 1;
if (scsi_tapes[dev].device->host->hostt->usage_count)
(*scsi_tapes[dev].device->host->hostt->usage_count)++;
if(st_template.usage_count) (*st_template.usage_count)++;
@@ -645,7 +697,7 @@
printk(KERN_NOTICE "st%d: Blocksize %d too large for buffer.\n", dev,
STp->block_size);
(STp->buffer)->in_use = 0;
- STp->in_use = 0;
+ STp->buffer = NULL;
return (-EIO);
}
STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
@@ -673,52 +725,45 @@
#endif
if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
(STp->buffer)->in_use = 0;
- STp->buffer = 0;
- STp->in_use = 0;
+ STp->buffer = NULL;
return (-EROFS);
}
}
- if (new_session) {
+ if (STp->can_partitions && STp->nbr_partitions < 1) {
+ /* This code is reached when the device is opened for the first time
+ after the driver has been initialized with tape in the drive and the
+ partition support has been enabled. */
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Updating partition number in status.\n", dev);
+#endif
+ if ((STp->partition = find_partition(inode)) < 0) {
+ (STp->buffer)->in_use = 0;
+ STp->buffer = NULL;
+ return STp->partition;
+ }
+ STp->new_partition = STp->partition;
+ STp->nbr_partitions = 1; /* This guess will be updated when necessary */
+ }
+
+ if (new_session) { /* Change the drive parameters for the new mode */
STp->density_changed = STp->blksize_changed = FALSE;
STp->compression_changed = FALSE;
- if (!(STm->defaults_for_writes)) {
- 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) {
- 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) {
- (STp->buffer)->in_use = 0;
- STp->buffer = 0;
- STp->in_use = 0;
- return (-EINVAL);
- }
- }
+ if (!(STm->defaults_for_writes) &&
+ (i = set_mode_densblk(inode, STp, STm)) < 0) {
+ (STp->buffer)->in_use = 0;
+ STp->buffer = NULL;
+ return i;
}
if (STp->default_drvbuffer != 0xff) {
- if (st_int_ioctl(inode, filp, MTSETDRVBUFFER, STp->default_drvbuffer))
+ if (st_int_ioctl(inode, MTSETDRVBUFFER, STp->default_drvbuffer))
printk(KERN_WARNING "st%d: Can't set default drive buffering to %d.\n",
dev, STp->default_drvbuffer);
}
}
+ STp->in_use = 1;
if (scsi_tapes[dev].device->host->hostt->usage_count)
(*scsi_tapes[dev].device->host->hostt->usage_count)++;
if(st_template.usage_count) (*st_template.usage_count)++;
@@ -741,7 +786,16 @@
dev = TAPE_NR(devt);
STp = &(scsi_tapes[dev]);
- if ( STp->rw == ST_WRITING && !(STp->device)->was_reset) {
+ if (STp->can_partitions &&
+ update_partition(inode) < 0) {
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: update_partition at close failed.\n", dev);
+#endif
+ goto out;
+ }
+
+ if ( STp->ps[STp->partition].rw == ST_WRITING && !(STp->device)->was_reset) {
result = flush_write_buffer(STp);
@@ -762,7 +816,7 @@
SCpnt = st_do_scsi(NULL, STp, cmd, 0, ST_TIMEOUT, MAX_WRITE_RETRIES);
if (!SCpnt)
- return;
+ goto out;
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
@@ -790,18 +844,19 @@
back_over_eof(STp);
}
+out:
if (STp->rew_at_close)
- st_int_ioctl(inode, filp, MTREW, 1);
+ st_int_ioctl(inode, MTREW, 1);
if (STp->door_locked == ST_LOCKED_AUTO)
- st_int_ioctl(inode, filp, MTUNLOCK, 0);
+ st_int_ioctl(inode, MTUNLOCK, 0);
if (STp->buffer != NULL) {
normalize_buffer(STp->buffer);
(STp->buffer)->in_use = 0;
}
- STp->in_use = 0;
+ STp->in_use = 0;
if (scsi_tapes[dev].device->host->hostt->usage_count)
(*scsi_tapes[dev].device->host->hostt->usage_count)--;
if(st_template.usage_count) (*st_template.usage_count)--;
@@ -816,13 +871,13 @@
{
int total, do_count, blks, retval, transfer;
int write_threshold;
- int doing_write = 0, set_it;
- unsigned int arg;
+ int doing_write = 0;
static unsigned char cmd[10];
const char *b_point;
Scsi_Cmnd * SCpnt = NULL;
Scsi_Tape * STp;
ST_mode * STm;
+ ST_partstat * STps;
int dev = TAPE_NR(inode->i_rdev);
STp = &(scsi_tapes[dev]);
@@ -846,6 +901,11 @@
}
#endif
+ if (STp->can_partitions &&
+ (retval = update_partition(inode)) < 0)
+ return retval;
+ STps = &(STp->ps[STp->partition]);
+
if (STp->write_prot)
return (-EACCES);
@@ -855,42 +915,19 @@
return (-EOVERFLOW);
if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
- !st_int_ioctl(inode, filp, MTLOCK, 0))
+ !st_int_ioctl(inode, MTLOCK, 0))
STp->door_locked = ST_LOCKED_AUTO;
- if (STp->rw == ST_READING) {
+ if (STps->rw == ST_READING) {
retval = flush_buffer(inode, filp, 0);
if (retval)
- return retval;
- STp->rw = ST_WRITING;
+ return retval;
+ STps->rw = ST_WRITING;
}
- else if (STp->rw != ST_WRITING &&
+ else if (STps->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 ((retval = set_mode_densblk(inode, STp, STm)) < 0)
+ return retval;
if (STm->default_compression != ST_DONT_TOUCH &&
!(STp->compression_changed)) {
if (st_compression(STp, (STm->default_compression == ST_YES))) {
@@ -902,8 +939,8 @@
}
}
- if (STp->moves_after_eof < 255)
- STp->moves_after_eof++;
+ if (STps->moves_after_eof < 255)
+ STps->moves_after_eof++;
if ((STp->buffer)->writing) {
write_behind_check(STp);
@@ -943,7 +980,7 @@
cmd[0] = WRITE_6;
cmd[1] = (STp->block_size != 0);
- STp->rw = ST_WRITING;
+ STps->rw = ST_WRITING;
b_point = buf;
while((STp->block_size == 0 && !STm->do_async_writes && count > 0) ||
@@ -1101,7 +1138,7 @@
else if (SCpnt != NULL)
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
- STp->at_sm &= (total != 0);
+ STps->at_sm &= (total == 0);
return( total);
}
@@ -1116,6 +1153,7 @@
Scsi_Cmnd * SCpnt = NULL;
Scsi_Tape * STp;
ST_mode * STm;
+ ST_partstat * STps;
int dev = TAPE_NR(inode->i_rdev);
STp = &(scsi_tapes[dev]);
@@ -1131,6 +1169,11 @@
}
#endif
+ if (STp->can_partitions &&
+ (total = update_partition(inode)) < 0)
+ return total;
+ STps = &(STp->ps[STp->partition]);
+
if (STp->block_size == 0 &&
count > (STp->buffer)->buffer_size &&
!enlarge_buffer(STp->buffer, count, STp->restr_dma))
@@ -1141,17 +1184,17 @@
return (-EIO); /* Read must be integral number of blocks */
if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
- !st_int_ioctl(inode, filp, MTLOCK, 0))
+ !st_int_ioctl(inode, MTLOCK, 0))
STp->door_locked = ST_LOCKED_AUTO;
- if (STp->rw == ST_WRITING) {
+ if (STps->rw == ST_WRITING) {
transfer = flush_buffer(inode, filp, 0);
if (transfer)
return transfer;
- STp->rw = ST_READING;
+ STps->rw = ST_READING;
}
- if (STp->moves_after_eof < 255)
- STp->moves_after_eof++;
+ if (STps->moves_after_eof < 255)
+ STps->moves_after_eof++;
#if DEBUG
if (debugging && STp->eof != ST_NOEOF)
@@ -1162,7 +1205,7 @@
(STp->eof == ST_EOM_OK || STp->eof == ST_EOD))
return (-EIO); /* EOM or Blank Check */
- STp->rw = ST_READING;
+ STps->rw = ST_READING;
for (total = 0; total < count; ) {
@@ -1197,7 +1240,7 @@
(STp->buffer)->read_pointer = 0;
STp->eof_hit = 0;
- STp->at_sm = 0;
+ STps->at_sm = 0;
if ((STp->buffer)->last_result_fatal) {
#if DEBUG
@@ -1235,7 +1278,7 @@
printk(KERN_NOTICE "st%d: Incorrect block size.\n", dev);
if (STp->drv_block >= 0)
STp->drv_block += blks - transfer + 1;
- st_int_ioctl(inode, filp, MTBSR, 1);
+ st_int_ioctl(inode, MTBSR, 1);
return (-EIO);
}
/* We have some data, deliver it */
@@ -1249,7 +1292,7 @@
count = total + (STp->buffer)->buffer_bytes;
if (STp->drv_block >= 0)
STp->drv_block += 1;
- if (st_int_ioctl(inode, filp, MTBSR, 1))
+ if (st_int_ioctl(inode, MTBSR, 1))
return (-EIO);
SCpnt = NULL;
}
@@ -1291,7 +1334,7 @@
STp->drv_block = (-1);
if (total)
return total;
- else if (STp->moves_after_eof == 1 &&
+ else if (STps->moves_after_eof == 1 &&
(SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK) {
#if DEBUG
if (debugging)
@@ -1348,8 +1391,8 @@
if (total == 0 && STp->eof == ST_FM) {
STp->eof = ST_NOEOF;
STp->drv_block = 0;
- if (STp->moves_after_eof > 1)
- STp->moves_after_eof = 0;
+ if (STps->moves_after_eof > 1)
+ STps->moves_after_eof = 0;
if ((STp->mt_status)->mt_fileno >= 0)
(STp->mt_status)->mt_fileno++;
}
@@ -1383,8 +1426,9 @@
"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: defs for wr: %d, no block limits: %d\n",
- dev, STm->defaults_for_writes, STp->omit_blklims);
+"st%d: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
+ dev, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
+ STp->scsi2_logical);
#if DEBUG
printk(KERN_INFO
"st%d: debugging: %d\n",
@@ -1425,6 +1469,9 @@
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 ((STp->device)->scsi_level >= SCSI_2)
+ STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
+ STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
#if DEBUG
debugging = (options & MT_ST_DEBUGGING) != 0;
#endif
@@ -1450,6 +1497,11 @@
STp->can_bsr = value;
if ((options & MT_ST_NO_BLKLIMS) != 0)
STp->omit_blklims = value;
+ if ((STp->device)->scsi_level >= SCSI_2 &&
+ (options & MT_ST_CAN_PARTITIONS) != 0)
+ STp->can_partitions = value;
+ if ((options & MT_ST_SCSI2LOGICAL) != 0)
+ STp->scsi2_logical = value;
#if DEBUG
if ((options & MT_ST_DEBUGGING) != 0)
debugging = value;
@@ -1541,6 +1593,9 @@
unsigned char cmd[10];
Scsi_Cmnd * SCpnt = NULL;
+ if (STp->ready != ST_READY)
+ return (-EIO);
+
/* Read the current page contents */
memset(cmd, 0, 10);
cmd[0] = MODE_SENSE;
@@ -1549,6 +1604,8 @@
cmd[4] = COMPRESSION_PAGE_LENGTH + MODE_HEADER_LENGTH;
SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], ST_TIMEOUT, 0);
+ if (SCpnt == NULL)
+ return (-EBUSY);
dev = TAPE_NR(SCpnt->request.rq_dev);
if ((STp->buffer)->last_result_fatal != 0) {
@@ -1614,24 +1671,26 @@
/* Internal ioctl function */
static int
-st_int_ioctl(struct inode * inode,struct file * file,
+st_int_ioctl(struct inode * inode,
unsigned int cmd_in, unsigned long arg)
{
int timeout = ST_LONG_TIMEOUT;
long ltmp;
- int ioctl_result;
+ int i, ioctl_result;
unsigned char cmd[10];
Scsi_Cmnd * SCpnt;
Scsi_Tape * STp;
+ ST_partstat * STps;
int fileno, blkno, at_sm, undone, datalen;
int dev = TAPE_NR(inode->i_rdev);
STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY && cmd_in != MTLOAD)
return (-EIO);
+ STps = &(STp->ps[STp->partition]);
fileno = (STp->mt_status)->mt_fileno ;
blkno = STp->drv_block;
- at_sm = STp->at_sm;
+ at_sm = STps->at_sm;
memset(cmd, 0, 10);
datalen = 0;
@@ -1651,7 +1710,7 @@
if (fileno >= 0)
fileno += arg;
blkno = 0;
- at_sm &= (arg != 0);
+ at_sm &= (arg == 0);
break;
case MTBSF:
case MTBSFM:
@@ -1673,7 +1732,7 @@
if (fileno >= 0)
fileno -= arg;
blkno = (-1); /* We can't know the block number */
- at_sm &= (arg != 0);
+ at_sm &= (arg == 0);
break;
case MTFSR:
cmd[0] = SPACE;
@@ -1688,7 +1747,7 @@
#endif
if (blkno >= 0)
blkno += arg;
- at_sm &= (arg != 0);
+ at_sm &= (arg == 0);
break;
case MTBSR:
cmd[0] = SPACE;
@@ -1707,7 +1766,7 @@
#endif
if (blkno >= 0)
blkno -= arg;
- at_sm &= (arg != 0);
+ at_sm &= (arg == 0);
break;
case MTFSS:
cmd[0] = SPACE;
@@ -1829,7 +1888,7 @@
case MTEOM:
if (!STp->fast_mteom) {
/* space to the end of tape */
- ioctl_result = st_int_ioctl(inode, file, MTFSF, 0x3fff);
+ ioctl_result = st_int_ioctl(inode, MTFSF, 0x3fff);
fileno = (STp->mt_status)->mt_fileno ;
if (STp->eof == ST_EOD || STp->eof == ST_EOM_OK)
return 0;
@@ -1882,33 +1941,6 @@
printk(ST_DEB_MSG "st%d: Unlocking drive door.\n", dev);
#endif;
break;
- case MTSEEK:
- if ((STp->device)->scsi_level < SCSI_2) {
- cmd[0] = QFA_SEEK_BLOCK;
- cmd[2] = (arg >> 16);
- cmd[3] = (arg >> 8);
- cmd[4] = arg;
- cmd[5] = 0;
- }
- else {
- cmd[0] = SEEK_10;
- cmd[1] = 4;
- cmd[3] = (arg >> 24);
- cmd[4] = (arg >> 16);
- cmd[5] = (arg >> 8);
- cmd[6] = arg;
- }
-#if ST_NOWAIT
- cmd[1] |= 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
-#endif
-#if DEBUG
- if (debugging)
- printk(ST_DEB_MSG "st%d: Seeking tape to block %ld.\n", dev, arg);
-#endif
- fileno = blkno = (-1);
- at_sm = 0;
- break;
case MTSETBLK: /* Set block length */
case MTSETDENSITY: /* Set tape density */
case MTSETDRVBUFFER: /* Set drive buffering */
@@ -1981,27 +2013,21 @@
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
if (cmd_in == MTFSF)
- STp->moves_after_eof = 0;
- else
- STp->moves_after_eof = 1;
+ STps->moves_after_eof = 0;
+ else if (cmd_in != MTLOAD)
+ STps->moves_after_eof = 1;
if (!ioctl_result) { /* SCSI command successful */
- if (cmd_in != MTSEEK) {
- STp->drv_block = blkno;
- (STp->mt_status)->mt_fileno = fileno;
- STp->at_sm = at_sm;
- }
- else {
- STp->drv_block = (STp->mt_status)->mt_fileno = (-1);
- STp->at_sm = 0;
- }
+ STp->drv_block = blkno;
+ (STp->mt_status)->mt_fileno = fileno;
+ STps->at_sm = at_sm;
if (cmd_in == MTLOCK)
STp->door_locked = ST_LOCKED_EXPLICIT;
else if (cmd_in == MTUNLOCK)
STp->door_locked = ST_UNLOCKED;
if (cmd_in == MTBSFM)
- ioctl_result = st_int_ioctl(inode, file, MTFSF, 1);
+ ioctl_result = st_int_ioctl(inode, MTFSF, 1);
else if (cmd_in == MTFSFM)
- ioctl_result = st_int_ioctl(inode, file, MTBSF, 1);
+ ioctl_result = st_int_ioctl(inode, MTBSF, 1);
else if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
STp->block_size = arg & MT_ST_BLKSIZE_MASK;
if (STp->block_size != 0)
@@ -2025,8 +2051,15 @@
STp->density = arg >> MT_ST_DENSITY_SHIFT;
if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
STp->rew_at_close = 0;
- else if (cmd_in == MTLOAD)
+ else if (cmd_in == MTLOAD) {
STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+ for (i=0; i < ST_NBR_PARTITIONS; i++) {
+ STp->ps[i].rw = ST_IDLE;
+ STp->ps[i].moves_after_eof = 1;
+ STp->ps[i].last_block_valid = FALSE;
+ }
+ STp->partition = 0;
+ }
} else { /* SCSI command was not completely successful */
if (SCpnt->sense_buffer[2] & 0x40) {
if (cmd_in != MTBSF && cmd_in != MTBSFM &&
@@ -2075,7 +2108,7 @@
STp->drv_block = (-1);
}
}
- else if (cmd_in == MTEOM || cmd_in == MTSEEK) {
+ else if (cmd_in == MTEOM) {
(STp->mt_status)->mt_fileno = (-1);
STp->drv_block = (-1);
}
@@ -2090,19 +2123,351 @@
}
+/* Get the tape position. If bt == 2, arg points into a kernel space mt_loc
+ structure. */
+
+ static int
+get_location(struct inode * inode, unsigned int *block, int *partition,
+ int logical)
+{
+ Scsi_Tape *STp;
+ int dev = TAPE_NR(inode->i_rdev);
+ int result;
+ unsigned char scmd[10];
+ Scsi_Cmnd *SCpnt;
+
+ STp = &(scsi_tapes[dev]);
+ if (STp->ready != ST_READY)
+ return (-EIO);
+
+ memset (scmd, 0, 10);
+ if ((STp->device)->scsi_level < SCSI_2) {
+ scmd[0] = QFA_REQUEST_BLOCK;
+ scmd[4] = 3;
+ }
+ else {
+ scmd[0] = READ_POSITION;
+ if (!logical && !STp->scsi2_logical)
+ scmd[1] = 1;
+ }
+ SCpnt = st_do_scsi(NULL, STp, scmd, 20, ST_TIMEOUT, MAX_READY_RETRIES);
+ if (!SCpnt)
+ return (-EBUSY);
+
+ if ((STp->buffer)->last_result_fatal != 0 ||
+ ((STp->buffer)->b_data[0] & 4)) {
+ *block = *partition = 0;
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Can't read tape position.\n", dev);
+#endif
+ result = (-EIO);
+ }
+ else {
+ result = 0;
+ if ((STp->device)->scsi_level < SCSI_2) {
+ *block = ((STp->buffer)->b_data[0] << 16)
+ + ((STp->buffer)->b_data[1] << 8)
+ + (STp->buffer)->b_data[2];
+ *partition = 0;
+ }
+ else {
+ *block = ((STp->buffer)->b_data[4] << 24)
+ + ((STp->buffer)->b_data[5] << 16)
+ + ((STp->buffer)->b_data[6] << 8)
+ + (STp->buffer)->b_data[7];
+ *partition = (STp->buffer)->b_data[1];
+ if (((STp->buffer)->b_data[0] & 0x80) &&
+ (STp->buffer)->b_data[1] == 0) /* BOP of partition 0 */
+ STp->drv_block = (STp->mt_status)->mt_fileno = 0;
+ }
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Got tape pos. blk %d part %d.\n", dev,
+ *block, *partition);
+#endif
+
+ }
+ SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
+
+ return result;
+}
+
+
+/* Set the tape block and partition. Negative partition means that only the
+ block should be set in vendor specific way. */
+ static int
+set_location(struct inode * inode, unsigned int block, int partition,
+ int logical)
+{
+ Scsi_Tape *STp;
+ ST_partstat *STps;
+ int dev = TAPE_NR(inode->i_rdev);
+ int result, p;
+ unsigned int blk;
+ int timeout = ST_LONG_TIMEOUT;
+ unsigned char scmd[10];
+ Scsi_Cmnd *SCpnt;
+
+ STp = &(scsi_tapes[dev]);
+ if (STp->ready != ST_READY)
+ return (-EIO);
+ STps = &(STp->ps[STp->partition]);
+
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Setting block to %d and partition to %d.\n",
+ dev, block, partition);
+ if (partition < 0)
+ return (-EIO);
+#endif
+
+ /* Update the location at the partition we are leaving */
+ if ((!STp->can_partitions && partition != 0) ||
+ partition >= ST_NBR_PARTITIONS)
+ return (-EINVAL);
+ if (partition != STp->partition) {
+ if (get_location(inode, &blk, &p, 1))
+ STps->last_block_valid = FALSE;
+ else {
+ STps->last_block_valid = TRUE;
+ STps->last_block_visited = blk;
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Visited block %d for partition %d saved.\n",
+ dev, blk, STp->partition);
+#endif
+ }
+ }
+
+ memset (scmd, 0, 10);
+ if ((STp->device)->scsi_level < SCSI_2) {
+ scmd[0] = QFA_SEEK_BLOCK;
+ scmd[2] = (block >> 16);
+ scmd[3] = (block >> 8);
+ scmd[4] = block;
+ scmd[5] = 0;
+ }
+ else {
+ scmd[0] = SEEK_10;
+ scmd[3] = (block >> 24);
+ scmd[4] = (block >> 16);
+ scmd[5] = (block >> 8);
+ scmd[6] = block;
+ if (!logical && !STp->scsi2_logical)
+ scmd[1] = 4;
+ if (STp->partition != partition) {
+ scmd[1] |= 2;
+ scmd[8] = partition;
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Trying to change partition from %d to %d\n",
+ dev, STp->partition, partition);
+#endif
+ }
+ }
+#if ST_NOWAIT
+ scmd[1] |= 1; /* Don't wait for completion */
+ timeout = ST_TIMEOUT;
+#endif
+
+ SCpnt = st_do_scsi(NULL, STp, scmd, 20, timeout, MAX_READY_RETRIES);
+ if (!SCpnt)
+ return (-EBUSY);
+
+ STp->drv_block = (STp->mt_status)->mt_fileno = (-1);
+ if ((STp->buffer)->last_result_fatal != 0) {
+ result = (-EIO);
+ if (STp->can_partitions &&
+ (STp->device)->scsi_level >= SCSI_2 &&
+ (p = find_partition(inode)) >= 0)
+ STp->partition = p;
+ }
+ else {
+ if (STp->can_partitions) {
+ STp->partition = partition;
+ STps = &(STp->ps[partition]);
+ if (!STps->last_block_valid ||
+ STps->last_block_visited != block) {
+ STps->moves_after_eof = 1;
+ STps->at_sm = 0;
+ STps->rw = ST_IDLE;
+ }
+ }
+ else
+ STps->at_sm = 0;
+ if (block == 0)
+ STp->drv_block = (STp->mt_status)->mt_fileno = 0;
+ result = 0;
+ }
+ SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
+
+ return result;
+}
+
+
+/* Find the current partition number for the drive status. Called from open and
+ returns either partition number of negative error code. */
+ static int
+find_partition(struct inode *inode)
+{
+ int i, partition;
+ unsigned int block;
+
+ if ((i = get_location(inode, &block, &partition, 1)) < 0)
+ return i;
+ if (partition >= ST_NBR_PARTITIONS)
+ return (-EIO);
+ return partition;
+}
+
+
+/* Change the partition if necessary */
+ static int
+update_partition(struct inode * inode)
+{
+ int dev = TAPE_NR(inode->i_rdev);
+ Scsi_Tape *STp;
+ ST_partstat *STps;
+
+ STp = &(scsi_tapes[dev]);
+ if (STp->partition == STp->new_partition)
+ return 0;
+ STps = &(STp->ps[STp->new_partition]);
+ if (!STps->last_block_valid)
+ STps->last_block_visited = 0;
+ return set_location(inode, STps->last_block_visited, STp->new_partition, 1);
+}
+
+/* Functions for reading and writing the medium partition mode page. These
+ seem to work with Wangtek 6200HS and HP C1533A. */
+
+#define PART_PAGE 0x11
+#define PART_PAGE_LENGTH 10
+
+/* Get the number of partitions on the tape. As a side effect reads the
+ mode page into the tape buffer. */
+ static int
+nbr_partitions(struct inode * inode)
+{
+ int dev = TAPE_NR(inode->i_rdev), result;
+ Scsi_Tape *STp;
+ Scsi_Cmnd * SCpnt = NULL;
+ unsigned char cmd[10];
+
+ STp = &(scsi_tapes[dev]);
+ if (STp->ready != ST_READY)
+ return (-EIO);
+
+ memset ((void *) &cmd[0], 0, 10);
+ cmd[0] = MODE_SENSE;
+ cmd[1] = 8; /* Page format */
+ cmd[2] = PART_PAGE;
+ cmd[4] = 200;
+
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, 200, ST_TIMEOUT, MAX_READY_RETRIES);
+ if (SCpnt == NULL)
+ return (-EBUSY);
+ SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
+
+ if ((STp->buffer)->last_result_fatal != 0) {
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Can't read medium partition page.\n", dev);
+#endif
+ result = (-EIO);
+ }
+ else {
+ result = (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] + 1;
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Number of partitions %d.\n", dev, result);
+#endif
+ }
+
+ return result;
+}
+
+
+/* Partition the tape into two partitions if size > 0 or one partition if
+ size == 0 */
+ static int
+partition_tape(struct inode * inode, int size)
+{
+ int dev = TAPE_NR(inode->i_rdev), result;
+ int length;
+ Scsi_Tape *STp;
+ Scsi_Cmnd * SCpnt = NULL;
+ unsigned char cmd[10], *bp;
+
+ if ((result = nbr_partitions(inode)) < 0)
+ return result;
+ STp = &(scsi_tapes[dev]);
+
+ /* The mode page is in the buffer. Let's modify it and write it. */
+ bp = &((STp->buffer)->b_data[0]);
+ if (size <= 0) {
+ length = 8;
+ bp[MODE_HEADER_LENGTH + 3] = 0;
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Formatting tape with one partition.\n", dev);
+#endif
+ }
+ else {
+ length = 10;
+ bp[MODE_HEADER_LENGTH + 3] = 1;
+ bp[MODE_HEADER_LENGTH + 8] = (size >> 8) & 0xff;
+ bp[MODE_HEADER_LENGTH + 9] = size & 0xff;
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Formatting tape with two partition (1 = %d MB).\n",
+ dev, size);
+#endif
+ }
+ bp[MODE_HEADER_LENGTH + 6] = 0;
+ bp[MODE_HEADER_LENGTH + 7] = 0;
+ bp[MODE_HEADER_LENGTH + 4] = 0x30; /* IDP | PSUM = MB */
+
+ bp[0] = 0;
+ bp[1] = 0;
+ bp[MODE_HEADER_LENGTH] &= 0x3f;
+ bp[MODE_HEADER_LENGTH + 1] = length - 2;
+
+ memset(cmd, 0, 10);
+ cmd[0] = MODE_SELECT;
+ cmd[1] = 0x10;
+ cmd[4] = length + MODE_HEADER_LENGTH;
+
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], ST_LONG_TIMEOUT, MAX_READY_RETRIES);
+ if (SCpnt == NULL)
+ return (-EBUSY);
+ SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
+
+ if ((STp->buffer)->last_result_fatal != 0) {
+ printk(KERN_INFO "st%d: Partitioning of tape failed.\n", dev);
+ result = (-EIO);
+ }
+ else
+ result = 0;
+
+ return result;
+}
+
+
/* The ioctl command */
static int
st_ioctl(struct inode * inode,struct file * file,
unsigned int cmd_in, unsigned long arg)
{
- int i, cmd_nr, cmd_type, result;
+ int i, cmd_nr, cmd_type, bt;
+ unsigned int blk;
struct mtop mtc;
struct mtpos mt_pos;
- unsigned char scmd[10];
- Scsi_Cmnd *SCpnt;
Scsi_Tape *STp;
ST_mode *STm;
+ ST_partstat *STps;
int dev = TAPE_NR(inode->i_rdev);
STp = &(scsi_tapes[dev]);
@@ -2113,18 +2478,11 @@
}
#endif
STm = &(STp->modes[STp->current_mode]);
+ STps = &(STp->ps[STp->partition]);
- /*
- * If this is something intended for the lower layer, just pass it
- * through.
- */
- if( cmd_in == SCSI_IOCTL_GET_IDLUN || cmd_in == SCSI_IOCTL_PROBE_HOST )
- {
- return scsi_ioctl(STp->device, cmd_in, (void *) arg);
- }
-
cmd_type = _IOC_TYPE(cmd_in);
cmd_nr = _IOC_NR(cmd_in);
+
if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
if (_IOC_SIZE(cmd_in) != sizeof(mtc))
return (-EINVAL);
@@ -2180,7 +2538,7 @@
STp->device->was_reset = 0;
if (STp->door_locked != ST_UNLOCKED &&
STp->door_locked != ST_LOCK_FAILS) {
- if (st_int_ioctl(inode, file, MTLOCK, 0)) {
+ if (st_int_ioctl(inode, MTLOCK, 0)) {
printk(KERN_NOTICE "st%d: Could not relock door after bus reset.\n",
dev);
STp->door_locked = ST_UNLOCKED;
@@ -2190,24 +2548,69 @@
if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTWSM &&
- mtc.mt_op != MTSETDRVBUFFER)
- STp->rw = ST_IDLE; /* Prevent automatic WEOF */
+ mtc.mt_op != MTSETDRVBUFFER && mtc.mt_op != MTSEEK &&
+ mtc.mt_op != MTSETPART)
+ STps->rw = ST_IDLE; /* Prevent automatic WEOF */
if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
- st_int_ioctl(inode, file, MTUNLOCK, 0); /* Ignore result! */
+ st_int_ioctl(inode, MTUNLOCK, 0); /* Ignore result! */
if (mtc.mt_op == MTSETDRVBUFFER &&
(mtc.mt_count & MT_ST_OPTIONS) != 0)
return st_set_options(inode, mtc.mt_count);
- else if (mtc.mt_op == MTCOMPRESSION)
+ if (mtc.mt_op == MTSETPART) {
+ if (!STp->can_partitions ||
+ mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS)
+ return (-EINVAL);
+ if (mtc.mt_count >= STp->nbr_partitions &&
+ (STp->nbr_partitions = nbr_partitions(inode)) < 0)
+ return (-EIO);
+ if (mtc.mt_count >= STp->nbr_partitions)
+ return (-EINVAL);
+ STp->new_partition = mtc.mt_count;
+ return 0;
+ }
+ if (mtc.mt_op == MTMKPART) {
+ if (!STp->can_partitions)
+ return (-EINVAL);
+ if ((i = st_int_ioctl(inode, MTREW, 0)) < 0 ||
+ (i = partition_tape(inode, mtc.mt_count)) < 0)
+ return i;
+ for (i=0; i < ST_NBR_PARTITIONS; i++) {
+ STp->ps[i].rw = ST_IDLE;
+ STp->ps[i].moves_after_eof = 1;
+ STp->ps[i].at_sm = 0;
+ STp->ps[i].last_block_valid = FALSE;
+ }
+ STp->partition = STp->new_partition = 0;
+ STp->nbr_partitions = 1; /* Bad guess ?-) */
+ STp->drv_block = (STp->mt_status)->mt_fileno = 0;
+ return 0;
+ }
+ if (mtc.mt_op == MTSEEK) {
+ i = set_location(inode, mtc.mt_count, STp->new_partition, 0);
+ if (!STp->can_partitions)
+ STp->ps[0].rw = ST_IDLE;
+ return i;
+ }
+ if (STp->can_partitions && STp->ready == ST_READY &&
+ (i = update_partition(inode)) < 0)
+ return i;
+ if (mtc.mt_op == MTCOMPRESSION)
return st_compression(STp, (mtc.mt_count & 1));
else
- return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count);
+ return st_int_ioctl(inode, mtc.mt_op, mtc.mt_count);
}
if (!STm->defined)
return (-ENXIO);
+ if ((i = flush_buffer(inode, file, FALSE)) < 0)
+ return i;
+ if (STp->can_partitions &&
+ (i = update_partition(inode)) < 0)
+ return i;
+
if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
if (_IOC_SIZE(cmd_in) != sizeof(struct mtget))
@@ -2216,19 +2619,15 @@
if (i)
return i;
- i = flush_buffer(inode, file, FALSE);
- if (i < 0)
- return i;
-
(STp->mt_status)->mt_dsreg =
((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
(STp->mt_status)->mt_blkno = STp->drv_block;
if (STp->block_size != 0) {
- if (STp->rw == ST_WRITING)
+ if (STps->rw == ST_WRITING)
(STp->mt_status)->mt_blkno +=
(STp->buffer)->buffer_bytes / STp->block_size;
- else if (STp->rw == ST_READING)
+ else if (STps->rw == ST_READING)
(STp->mt_status)->mt_blkno -= ((STp->buffer)->buffer_bytes +
STp->block_size - 1) / STp->block_size;
}
@@ -2242,6 +2641,7 @@
else
(STp->mt_status)->mt_gstat |= GMT_EOF(0xffffffff);
}
+ (STp->mt_status)->mt_resid = STp->partition;
if (STp->eof == ST_EOM_OK || STp->eof == ST_EOM_ERROR)
(STp->mt_status)->mt_gstat |= GMT_EOT(0xffffffff);
else if (STp->eof == ST_EOD)
@@ -2256,7 +2656,7 @@
(STp->mt_status)->mt_gstat |= GMT_ONLINE(0xffffffff);
if (STp->ready == ST_NO_TAPE)
(STp->mt_status)->mt_gstat |= GMT_DR_OPEN(0xffffffff);
- if (STp->at_sm)
+ if (STps->at_sm)
(STp->mt_status)->mt_gstat |= GMT_SM(0xffffffff);
memcpy_tofs((char *)arg, (char *)(STp->mt_status),
@@ -2264,67 +2664,22 @@
(STp->mt_status)->mt_erreg = 0; /* Clear after read */
return 0;
- }
- else if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
- if (STp->ready != ST_READY)
- return (-EIO);
-#if DEBUG
- if (debugging)
- printk(ST_DEB_MSG "st%d: get tape position.\n", dev);
-#endif
+ } /* End of MTIOCGET */
+
+ if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos))
return (-EINVAL);
-
- i = flush_buffer(inode, file, 0);
- if (i < 0)
+ if ((i = get_location(inode, &blk, &bt, 0)) < 0)
return i;
-
- i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mtpos));
+ i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(mt_pos));
if (i)
- return i;
-
- memset (scmd, 0, 10);
- if ((STp->device)->scsi_level < SCSI_2) {
- scmd[0] = QFA_REQUEST_BLOCK;
- scmd[4] = 3;
- }
- else {
- scmd[0] = READ_POSITION;
- scmd[1] = 1;
- }
- SCpnt = st_do_scsi(NULL, STp, scmd, 20, ST_TIMEOUT, MAX_READY_RETRIES);
- if (!SCpnt)
- return (-EBUSY);
-
- if ((STp->buffer)->last_result_fatal != 0) {
- mt_pos.mt_blkno = (-1);
-#if DEBUG
- if (debugging)
- printk(ST_DEB_MSG "st%d: Can't read tape position.\n", dev);
-#endif
- result = (-EIO);
- }
- else {
- result = 0;
- if ((STp->device)->scsi_level < SCSI_2)
- mt_pos.mt_blkno = ((STp->buffer)->b_data[0] << 16)
- + ((STp->buffer)->b_data[1] << 8)
- + (STp->buffer)->b_data[2];
- else
- mt_pos.mt_blkno = ((STp->buffer)->b_data[4] << 24)
- + ((STp->buffer)->b_data[5] << 16)
- + ((STp->buffer)->b_data[6] << 8)
- + (STp->buffer)->b_data[7];
-
- }
-
- SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
-
+ return i;
+ mt_pos.mt_blkno = blk;
memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
- return result;
+ return 0;
}
- else
- return scsi_ioctl(STp->device, cmd_in, (void *) arg);
+
+ return scsi_ioctl(STp->device, cmd_in, (void *) arg);
}
@@ -2464,6 +2819,8 @@
static int st_attach(Scsi_Device * SDp){
Scsi_Tape * tpnt;
+ ST_mode * STm;
+ ST_partstat * STps;
int i;
if(SDp->type != TYPE_TAPE) return 1;
@@ -2487,7 +2844,6 @@
tpnt->devt = MKDEV(SCSI_TAPE_MAJOR, i);
tpnt->dirty = 0;
- tpnt->rw = ST_IDLE;
tpnt->eof = ST_NOEOF;
tpnt->waiting = NULL;
tpnt->in_use = 0;
@@ -2496,25 +2852,38 @@
tpnt->density = 0;
tpnt->do_auto_lock = ST_AUTO_LOCK;
tpnt->can_bsr = ST_IN_FILE_POS;
+ tpnt->can_partitions = 0;
tpnt->two_fm = ST_TWO_FM;
tpnt->fast_mteom = ST_FAST_MTEOM;
+ tpnt->scsi2_logical = 0;
tpnt->write_threshold = st_write_threshold;
tpnt->default_drvbuffer = 0xff; /* No forced buffering */
+ tpnt->partition = 0;
+ tpnt->new_partition = 0;
+ tpnt->nbr_partitions = 0;
tpnt->drv_block = (-1);
- tpnt->moves_after_eof = 1;
- tpnt->at_sm = 0;
(tpnt->mt_status)->mt_fileno = (tpnt->mt_status)->mt_blkno = (-1);
for (i=0; i < ST_NBR_MODES; i++) {
- tpnt->modes[i].defined = FALSE;
- 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 */
+ STm = &(tpnt->modes[i]);
+ STm->defined = FALSE;
+ STm->defaults_for_writes = 0;
+ STm->do_async_writes = ST_ASYNC_WRITES;
+ STm->do_buffer_writes = ST_BUFFER_WRITES;
+ STm->do_read_ahead = ST_READ_AHEAD;
+ STm->default_compression = ST_DONT_TOUCH;
+ STm->default_blksize = (-1); /* No forced size */
+ STm->default_density = (-1); /* No forced density */
}
+
+ for (i=0; i < ST_NBR_PARTITIONS; i++) {
+ STps = &(tpnt->ps[i]);
+ STps->rw = ST_IDLE;
+ STps->moves_after_eof = 1;
+ STps->at_sm = 0;
+ STps->last_block_valid = FALSE;
+ }
+
tpnt->current_mode = 0;
tpnt->modes[0].defined = TRUE;
@@ -2529,7 +2898,8 @@
{
if(SDp->type != TYPE_TAPE) return 0;
- printk("Detected scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n",
+ printk(KERN_INFO
+ "Detected scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n",
st_template.dev_noticed++,
SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
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