patch-1.3.22 linux/drivers/scsi/st.c
Next file: linux/drivers/scsi/st.h
Previous file: linux/drivers/scsi/eata_pio.c
Back to the patch index
Back to the overall index
- Lines: 1003
- Date:
Thu Aug 31 07:44:09 1995
- Orig file:
v1.3.21/linux/drivers/scsi/st.c
- Orig date:
Wed Aug 2 13:21:14 1995
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
@@ -11,7 +11,7 @@
Copyright 1992, 1993, 1994, 1995 Kai Makisara
email [email protected]
- Last modified: Sat Feb 18 10:51:25 1995 by [email protected]
+ Last modified: Thu Aug 31 00:04:12 1995 by [email protected]
*/
#ifdef MODULE
#include <linux/autoconf.h>
@@ -31,6 +31,10 @@
#include <asm/segment.h>
#include <asm/system.h>
+/* The driver prints some debugging information on the console if DEBUG
+ is defined and non-zero. */
+#define DEBUG 0
+
#define MAJOR_NR SCSI_TAPE_MAJOR
#include "../block/blk.h"
#include "scsi.h"
@@ -39,31 +43,11 @@
#include "st.h"
#include "constants.h"
-/* #define DEBUG */
-
-/* #define ST_NOWAIT */
-
-/* #define ST_IN_FILE_POS */
-
-/* #define ST_RECOVERED_WRITE_FATAL */
-
-#define ST_TWO_FM 0
-
-#define ST_FAST_MTEOM 0
-
-#define ST_BUFFER_WRITES 1
-
-#define ST_ASYNC_WRITES 1
-
-#define ST_READ_AHEAD 1
+/* The default definitions have been moved to st_options.h */
#define ST_BLOCK_SIZE 1024
-#define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS)
-
-#define ST_BUFFER_BLOCKS 32
-
-#define ST_WRITE_THRESHOLD_BLOCKS 30
+#include "st_options.h"
#define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_BLOCK_SIZE)
#define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_BLOCK_SIZE)
@@ -74,7 +58,7 @@
#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
#endif
-#ifdef DEBUG
+#if DEBUG
static int debugging = 1;
#endif
@@ -92,7 +76,7 @@
static int st_write_threshold = ST_WRITE_THRESHOLD;
static int st_max_buffers = ST_MAX_BUFFERS;
-static Scsi_Tape * scsi_tapes = NULL;
+Scsi_Tape * scsi_tapes = NULL;
static void st_init(void);
static int st_attach(Scsi_Device *);
@@ -121,7 +105,7 @@
if (!result /* && SCpnt->sense_buffer[0] == 0 */ )
return 0;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
printk("st%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n", dev, result,
SCpnt->data_cmnd[0], SCpnt->data_cmnd[1], SCpnt->data_cmnd[2],
@@ -148,7 +132,7 @@
if ((sense[0] & 0x70) == 0x70 &&
scode == RECOVERED_ERROR
-#ifdef ST_RECOVERED_WRITE_FATAL
+#if ST_RECOVERED_WRITE_FATAL
&& SCpnt->data_cmnd[0] != WRITE_6
&& SCpnt->data_cmnd[0] != WRITE_FILEMARKS
#endif
@@ -201,10 +185,11 @@
SCpnt->request.dev = -1;
else
SCpnt->request.dev = 0xffff;
- if ((STp->buffer)->writing <= 0)
+ if (!(STp->buffer)->writing || STp->write_pending)
wake_up( &(STp->waiting) );
+ STp->write_pending = 0;
}
-#ifdef DEBUG
+#if DEBUG
else if (debugging)
printk("st?: Illegal interrupt device %x\n", st_nbr);
#endif
@@ -224,11 +209,17 @@
save_flags(flags);
cli();
- if (STbuffer->last_result < 0) {
- STbuffer->writing = (- STbuffer->writing);
+ if (STp->write_pending) {
+#if DEBUG
+ STp->nbr_waits++;
+#endif
sleep_on( &(STp->waiting) );
- STbuffer->writing = (- STbuffer->writing);
+ STp->write_pending = 0;
}
+#if DEBUG
+ else
+ STp->nbr_finished++;
+#endif
restore_flags(flags);
if (STbuffer->writing < STbuffer->buffer_bytes)
@@ -302,7 +293,7 @@
if ((STp->buffer)->writing) {
write_behind_check(dev);
if ((STp->buffer)->last_result_fatal) {
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Async write error (flush) %x.\n", dev,
(STp->buffer)->last_result);
@@ -313,6 +304,9 @@
}
}
+ if (STp->block_size == 0)
+ return 0;
+
result = 0;
if (STp->dirty == 1) {
SCpnt = allocate_device(NULL, STp->device, 1);
@@ -320,7 +314,7 @@
offset = (STp->buffer)->buffer_bytes;
transfer = ((offset + STp->block_size - 1) /
STp->block_size) * STp->block_size;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Flushing %d bytes.\n", dev, transfer);
#endif
@@ -454,12 +448,16 @@
STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
STp->dirty = 0;
+ STp->write_pending = 0;
STp->rw = ST_IDLE;
STp->ready = ST_READY;
if (STp->eof != ST_EOD) /* Save EOD across opens */
STp->eof = ST_NOEOF;
STp->eof_hit = 0;
STp->recover_count = 0;
+#if DEBUG
+ STp->nbr_waits = STp->nbr_finished = 0;
+#endif
SCpnt = allocate_device(NULL, STp->device, 1);
if (!SCpnt) {
@@ -476,7 +474,6 @@
0, st_sleep_done, ST_LONG_TIMEOUT,
MAX_READY_RETRIES);
-
/* this must be done with interrupts off */
save_flags (processor_flags);
cli();
@@ -495,12 +492,11 @@
0, st_sleep_done, ST_LONG_TIMEOUT,
MAX_READY_RETRIES);
-
- /* this must be done with interrupts off */
- save_flags (processor_flags);
- cli();
- if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
- restore_flags(processor_flags);
+ /* this must be done with interrupts off */
+ save_flags (processor_flags);
+ cli();
+ if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
+ restore_flags(processor_flags);
(STp->mt_status)->mt_fileno = STp->drv_block = 0;
STp->eof = ST_NOEOF;
@@ -517,15 +513,15 @@
STp->ready = ST_NOT_READY;
}
SCpnt->request.dev = -1; /* Mark as not busy */
- (STp->buffer)->in_use = 0;
- STp->buffer = NULL;
STp->density = 0; /* Clear the erroneous "residue" */
STp->write_prot = 0;
STp->block_size = 0;
STp->eof = ST_NOEOF;
(STp->mt_status)->mt_fileno = STp->drv_block = 0;
+ STp->door_locked = ST_UNLOCKED;
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)++;
return 0;
}
@@ -537,7 +533,6 @@
(void *) cmd, (void *) (STp->buffer)->b_data,
6, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
-
/* this must be done with interrupts off */
save_flags (processor_flags);
cli();
@@ -549,7 +544,7 @@
((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];
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
STp->max_block);
@@ -557,7 +552,7 @@
}
else {
STp->min_block = STp->max_block = (-1);
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Can't read block limits.\n", dev);
#endif
@@ -572,7 +567,6 @@
(void *) cmd, (void *) (STp->buffer)->b_data,
12, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
-
/* this must be done with interrupts off */
save_flags (processor_flags);
cli();
@@ -580,34 +574,36 @@
restore_flags(processor_flags);
if ((STp->buffer)->last_result_fatal != 0) {
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: No Mode Sense.\n", dev);
#endif
- (STp->buffer)->b_data[2] =
- (STp->buffer)->b_data[3] = 0;
+ STp->block_size = ST_DEFAULT_BLOCK; /* Educated guess (?) */
+ (STp->buffer)->last_result_fatal = 0; /* Prevent error propagation */
}
- SCpnt->request.dev = -1; /* Mark as not busy */
+ else {
-#ifdef DEBUG
- if (debugging)
- printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
- (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
- (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]);
+#if DEBUG
+ if (debugging)
+ printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
+ (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
+ (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]);
#endif
- if ((STp->buffer)->b_data[3] >= 8) {
- STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
- STp->density = (STp->buffer)->b_data[4];
- STp->block_size = (STp->buffer)->b_data[9] * 65536 +
- (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
-#ifdef DEBUG
- if (debugging)
- printk("st%d: Density %x, tape length: %x, drv buffer: %d\n",
- dev, STp->density, (STp->buffer)->b_data[5] * 65536 +
- (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
- STp->drv_buffer);
+ if ((STp->buffer)->b_data[3] >= 8) {
+ STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
+ STp->density = (STp->buffer)->b_data[4];
+ STp->block_size = (STp->buffer)->b_data[9] * 65536 +
+ (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
+#if DEBUG
+ if (debugging)
+ printk("st%d: Density %x, tape length: %x, drv buffer: %d\n",
+ dev, STp->density, (STp->buffer)->b_data[5] * 65536 +
+ (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
+ STp->drv_buffer);
#endif
+ }
+
if (STp->block_size > st_buffer_size) {
printk("st%d: Blocksize %d too large for buffer.\n", dev,
STp->block_size);
@@ -615,10 +611,8 @@
STp->in_use = 0;
return (-EIO);
}
-
}
- else
- STp->block_size = 512; /* "Educated Guess" (?) */
+ SCpnt->request.dev = -1; /* Mark as not busy */
if (STp->block_size > 0) {
(STp->buffer)->buffer_blocks = st_buffer_size / STp->block_size;
@@ -631,7 +625,7 @@
}
(STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
STp->block_size, (STp->buffer)->buffer_size,
@@ -641,7 +635,7 @@
STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
if (STp->drv_write_prot) {
STp->write_prot = 1;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk( "st%d: Write protected\n", dev);
#endif
@@ -682,9 +676,12 @@
result = flush_write_buffer(dev);
-#ifdef DEBUG
- if (debugging)
+#if DEBUG
+ if (debugging) {
printk("st%d: File length %ld bytes.\n", dev, (long)(filp->f_pos));
+ printk("st%d: Async write waits %d, finished %d.\n", dev,
+ STp->nbr_waits, STp->nbr_finished);
+ }
#endif
if (result == 0 || result == (-ENOSPC)) {
@@ -699,14 +696,12 @@
(void *) cmd, (void *) (STp->buffer)->b_data,
0, st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
-
/* this must be done with interrupts off */
save_flags (flags);
cli();
if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
restore_flags(flags);
-
if ((STp->buffer)->last_result_fatal != 0) {
SCpnt->request.dev = -1; /* Mark as not busy */
printk("st%d: Error on write filemark.\n", dev);
@@ -722,23 +717,26 @@
}
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Buffer flushed, %d EOF(s) written\n", dev, cmd[4]);
#endif
}
else if (!rewind) {
-#ifndef ST_IN_FILE_POS
+#if ST_IN_FILE_POS
+ flush_buffer(inode, filp, 0);
+#else
if ((STp->eof == ST_FM) && !STp->eof_hit)
back_over_eof(dev);
-#else
- flush_buffer(inode, filp, 0);
#endif
}
if (rewind)
st_int_ioctl(inode, filp, MTREW, 1);
+ if (STp->door_locked == ST_LOCKED_AUTO)
+ st_int_ioctl(inode, filp, MTUNLOCK, 0);
+
if (STp->buffer != NULL)
(STp->buffer)->in_use = 0;
STp->in_use = 0;
@@ -769,7 +767,7 @@
STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY)
return (-EIO);
-#ifdef DEBUG
+#if DEBUG
if (!STp->in_use) {
printk("st%d: Incorrect device.\n", dev);
return (-EIO);
@@ -782,6 +780,10 @@
if (STp->block_size == 0 && count > st_buffer_size)
return (-EOVERFLOW);
+ if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
+ !st_int_ioctl(inode, filp, MTLOCK, 0))
+ STp->door_locked = ST_LOCKED_AUTO;
+
if (STp->rw == ST_READING) {
retval = flush_buffer(inode, filp, 0);
if (retval)
@@ -795,7 +797,7 @@
if ((STp->buffer)->writing) {
write_behind_check(dev);
if ((STp->buffer)->last_result_fatal) {
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Async write error (write) %x.\n", dev,
(STp->buffer)->last_result);
@@ -867,15 +869,14 @@
(void *) cmd, (STp->buffer)->b_data, transfer,
st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
-
- /* this must be done with interrupts off */
- save_flags (flags);
- cli();
- if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
- restore_flags(flags);
+ /* this must be done with interrupts off */
+ save_flags (flags);
+ cli();
+ if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
+ restore_flags(flags);
if ((STp->buffer)->last_result_fatal != 0) {
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Error on write:\n", dev);
#endif
@@ -903,7 +904,7 @@
}
STp->eof = ST_EOM_OK;
retval = (-ENOSPC); /* EOM within current request */
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: EOM with %d bytes unwritten.\n",
dev, transfer);
@@ -913,7 +914,7 @@
STp->eof = ST_EOM_ERROR;
STp->drv_block = (-1); /* Too cautious? */
retval = (-EIO); /* EOM for old data */
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: EOM with lost data.\n", dev);
#endif
@@ -977,9 +978,9 @@
cmd[2] = blks >> 16;
cmd[3] = blks >> 8;
cmd[4] = blks;
- SCpnt->result = (STp->buffer)->last_result = -1;
SCpnt->sense_buffer[0] = 0;
SCpnt->request.dev = dev;
+ STp->write_pending = 1;
scsi_do_cmd (SCpnt,
(void *) cmd, (STp->buffer)->b_data,
(STp->buffer)->writing,
@@ -1009,7 +1010,7 @@
STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY)
return (-EIO);
-#ifdef DEBUG
+#if DEBUG
if (!STp->in_use) {
printk("st%d: Incorrect device.\n", dev);
return (-EIO);
@@ -1023,6 +1024,10 @@
(count % STp->block_size) != 0)
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))
+ STp->door_locked = ST_LOCKED_AUTO;
+
if (STp->rw == ST_WRITING) {
transfer = flush_buffer(inode, filp, 0);
if (transfer)
@@ -1032,7 +1037,7 @@
if (STp->moves_after_eof < 255)
STp->moves_after_eof++;
-#ifdef DEBUG
+#if DEBUG
if (debugging && STp->eof != ST_NOEOF)
printk("st%d: EOF flag up. Bytes %d\n", dev,
(STp->buffer)->buffer_bytes);
@@ -1078,7 +1083,6 @@
(void *) cmd, (STp->buffer)->b_data,
bytes, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
-
/* this must be done with interrupts off */
save_flags (flags);
cli();
@@ -1090,7 +1094,7 @@
STp->at_sm = 0;
if ((STp->buffer)->last_result_fatal) {
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
@@ -1131,7 +1135,7 @@
else
(STp->buffer)->buffer_bytes =
bytes - transfer * STp->block_size;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: EOM detected (%d bytes read).\n", dev,
(STp->buffer)->buffer_bytes);
@@ -1144,7 +1148,7 @@
else
(STp->buffer)->buffer_bytes =
bytes - transfer * STp->block_size;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk(
"st%d: EOF detected (%d bytes read, transferred %d bytes).\n",
@@ -1153,7 +1157,7 @@
}
} /* end of EOF, EOM, ILI test */
else { /* nonzero sense key */
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Tape error while reading.\n", dev);
#endif
@@ -1163,7 +1167,7 @@
return total;
else if (STp->moves_after_eof == 1 &&
(SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK) {
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Zero returned for first BLANK CHECK after EOF.\n",
dev);
@@ -1195,7 +1199,7 @@
STp->eof == ST_NOEOF) */
if ((STp->buffer)->buffer_bytes > 0) {
-#ifdef DEBUG
+#if DEBUG
if (debugging && STp->eof != ST_NOEOF)
printk("st%d: EOF up. Left %d, needed %d.\n", dev,
(STp->buffer)->buffer_bytes, count - total);
@@ -1253,14 +1257,15 @@
STp->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;
-#ifdef DEBUG
+ STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
+#if DEBUG
debugging = (options & MT_ST_DEBUGGING) != 0;
printk(
"st%d: options: buffer writes: %d, async writes: %d, read ahead: %d\n",
dev, STp->do_buffer_writes, STp->do_async_writes,
STp->do_read_ahead);
- printk(" two FMs: %d, fast mteom: %d debugging: %d\n",
- STp->two_fm, STp->fast_mteom, debugging);
+ printk(" two FMs: %d, fast mteom: %d auto lock: %d, debugging: %d\n",
+ STp->two_fm, STp->fast_mteom, STp->do_auto_lock, debugging);
#endif
}
else if ((options & MT_ST_OPTIONS) == MT_ST_WRITE_THRESHOLD) {
@@ -1271,7 +1276,7 @@
return (-EIO);
}
STp->write_threshold = value;
-#ifdef DEBUG
+#if DEBUG
printk("st%d: Write threshold set to %d bytes.\n", dev,
STp->write_threshold);
#endif
@@ -1300,7 +1305,7 @@
dev = dev & 127;
STp = &(scsi_tapes[dev]);
- if (STp->ready != ST_READY)
+ if (STp->ready != ST_READY && cmd_in != MTLOAD)
return (-EIO);
fileno = (STp->mt_status)->mt_fileno ;
blkno = STp->drv_block;
@@ -1316,7 +1321,7 @@
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Spacing tape forward over %d filemarks.\n", dev,
cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
@@ -1334,7 +1339,7 @@
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
if (cmd[2] & 0x80)
ltmp = 0xff000000;
@@ -1353,7 +1358,7 @@
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Spacing tape forward %d blocks.\n", dev,
cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
@@ -1369,7 +1374,7 @@
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
if (cmd[2] & 0x80)
ltmp = 0xff000000;
@@ -1387,7 +1392,7 @@
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Spacing tape forward %d setmarks.\n", dev,
cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
@@ -1404,7 +1409,7 @@
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
if (cmd[2] & 0x80)
ltmp = 0xff000000;
@@ -1428,7 +1433,7 @@
cmd[3] = (arg >> 8);
cmd[4] = arg;
timeout = ST_TIMEOUT;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
if (cmd_in == MTWEOF)
printk("st%d: Writing %d filemarks.\n", dev,
@@ -1445,11 +1450,11 @@
break;
case MTREW:
cmd[0] = REZERO_UNIT;
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
timeout = ST_TIMEOUT;
#endif
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Rewinding tape.\n", dev);
#endif
@@ -1457,18 +1462,18 @@
break;
case MTOFFL:
cmd[0] = START_STOP;
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
timeout = ST_TIMEOUT;
#endif
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Unloading tape.\n", dev);
#endif
fileno = blkno = at_sm = 0 ;
break;
case MTNOP:
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: No op on tape.\n", dev);
#endif
@@ -1476,12 +1481,12 @@
break;
case MTRETEN:
cmd[0] = START_STOP;
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
timeout = ST_TIMEOUT;
#endif
cmd[4] = 3;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Retensioning tape.\n", dev);
#endif
@@ -1503,7 +1508,7 @@
fileno = (-1);
cmd[0] = SPACE;
cmd[1] = 3;
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Spacing to end of recorded medium.\n", dev);
#endif
@@ -1515,18 +1520,46 @@
return (-EACCES);
cmd[0] = ERASE;
cmd[1] = 1; /* To the end of tape */
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
cmd[1] |= 2; /* Don't wait for completion */
timeout = ST_TIMEOUT;
#else
timeout = ST_LONG_TIMEOUT * 8;
#endif
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Erasing tape.\n", dev);
#endif
fileno = blkno = at_sm = 0 ;
break;
+ case MTLOCK:
+ cmd[0] = ALLOW_MEDIUM_REMOVAL;
+ cmd[4] = SCSI_REMOVAL_PREVENT;
+#if DEBUG
+ if (debugging)
+ printk("st%d: Locking drive door.\n", dev);
+#endif;
+ break;
+ case MTUNLOCK:
+ cmd[0] = ALLOW_MEDIUM_REMOVAL;
+ cmd[4] = SCSI_REMOVAL_ALLOW;
+#if DEBUG
+ if (debugging)
+ printk("st%d: Unlocking drive door.\n", dev);
+#endif;
+ break;
+ case MTLOAD:
+ case MTUNLOAD:
+ cmd[0] = START_STOP;
+ if (cmd_in == MTLOAD)
+ cmd[4] |= 1;
+#if ST_NOWAIT
+ cmd[1] |= 2; /* Don't wait for completion */
+ timeout = ST_TIMEOUT;
+#else
+ timeout = ST_LONG_TIMEOUT * 8;
+#endif
+ break;
case MTSEEK:
if ((STp->device)->scsi_level < SCSI_2) {
cmd[0] = QFA_SEEK_BLOCK;
@@ -1543,11 +1576,11 @@
cmd[5] = (arg >> 8);
cmd[6] = arg;
}
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
cmd[1] |= 1; /* Don't wait for completion */
timeout = ST_TIMEOUT;
#endif
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Seeking tape to block %ld.\n", dev, arg);
#endif
@@ -1588,7 +1621,7 @@
(STp->buffer)->b_data[10] = (ltmp >> 8);
(STp->buffer)->b_data[11] = ltmp;
timeout = ST_TIMEOUT;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
if (cmd_in == MTSETBLK)
printk("st%d: Setting block size to %d bytes.\n", dev,
@@ -1616,13 +1649,11 @@
(void *) cmd, (void *) (STp->buffer)->b_data, datalen,
st_sleep_done, timeout, MAX_RETRIES);
-
- /* this must be done with interrupts off */
- save_flags (flags);
- cli();
- if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
- restore_flags(flags);
-
+ /* this must be done with interrupts off */
+ save_flags (flags);
+ cli();
+ if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
+ restore_flags(flags);
ioctl_result = (STp->buffer)->last_result_fatal;
@@ -1642,6 +1673,10 @@
STp->drv_block = (STp->mt_status)->mt_fileno = (-1);
STp->at_sm = 0;
}
+ 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);
else if (cmd_in == MTFSFM)
@@ -1728,6 +1763,8 @@
if (STp->eof == ST_NOEOF &&
(SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK)
STp->eof = ST_EOD;
+ if (cmd_in == MTLOCK)
+ STp->door_locked = ST_LOCK_FAILS;
}
return ioctl_result;
@@ -1751,7 +1788,7 @@
dev = dev & 127;
STp = &(scsi_tapes[dev]);
-#ifdef DEBUG
+#if DEBUG
if (debugging && !STp->in_use) {
printk("st%d: Incorrect device.\n", dev);
return (-EIO);
@@ -1764,7 +1801,7 @@
if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc))
return (-EINVAL);
- i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(mtc));
+ i = verify_area(VERIFY_READ, (void *)arg, sizeof(mtc));
if (i)
return i;
@@ -1772,7 +1809,8 @@
i = flush_buffer(inode, file, mtc.mt_op == MTSEEK ||
mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
- mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM);
+ mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
+ mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD);
if (i < 0)
return i;
if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
@@ -1780,6 +1818,9 @@
mtc.mt_op != MTSETDRVBUFFER)
STp->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! */
+
if (mtc.mt_op == MTSETDRVBUFFER &&
(mtc.mt_count & MT_ST_OPTIONS) != 0)
return st_set_options(inode, mtc.mt_count);
@@ -1842,7 +1883,7 @@
else if (cmd == (MTIOCPOS & IOCCMD_MASK)) {
if (STp->ready != ST_READY)
return (-EIO);
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: get tape position.\n", dev);
#endif
@@ -1875,17 +1916,15 @@
(void *) scmd, (void *) (STp->buffer)->b_data,
20, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
+ /* this must be done with interrupts off */
+ save_flags (flags);
+ cli();
+ if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
+ restore_flags(flags);
- /* this must be done with interrupts off */
- save_flags (flags);
- cli();
- if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
- restore_flags(flags);
-
-
if ((STp->buffer)->last_result_fatal != 0) {
mt_pos.mt_blkno = (-1);
-#ifdef DEBUG
+#if DEBUG
if (debugging)
printk("st%d: Can't read tape position.\n", dev);
#endif
@@ -1910,10 +1949,8 @@
memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
return result;
}
- else if (STp->ready == ST_READY)
- return scsi_ioctl(STp->device, cmd_in, (void *) arg);
else
- return (-EIO);
+ return scsi_ioctl(STp->device, cmd_in, (void *) arg);
}
@@ -1971,6 +2008,24 @@
else
scsi_tapes[i].mt_status->mt_type = MT_ISSCSI2;
+ tpnt->dirty = 0;
+ tpnt->rw = ST_IDLE;
+ tpnt->eof = ST_NOEOF;
+ tpnt->waiting = NULL;
+ tpnt->in_use = 0;
+ tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
+ tpnt->density = 0;
+ tpnt->do_buffer_writes = ST_BUFFER_WRITES;
+ tpnt->do_async_writes = ST_ASYNC_WRITES;
+ tpnt->do_read_ahead = ST_READ_AHEAD;
+ tpnt->do_auto_lock = ST_AUTO_LOCK;
+ tpnt->two_fm = ST_TWO_FM;
+ tpnt->fast_mteom = ST_FAST_MTEOM;
+ tpnt->write_threshold = st_write_threshold;
+ tpnt->drv_block = 0;
+ tpnt->moves_after_eof = 1;
+ tpnt->at_sm = 0;
+
st_template.nr_dev++;
return 0;
};
@@ -1986,17 +2041,18 @@
return 1;
}
+static int st_registered = 0;
+
/* Driver initialization */
static void st_init()
{
int i;
Scsi_Tape * STp;
- static int st_registered = 0;
if (st_template.dev_noticed == 0) return;
if(!st_registered) {
- if (register_chrdev(MAJOR_NR,"st",&st_fops)) {
+ if (register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops)) {
printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
return;
}
@@ -2009,7 +2065,7 @@
sizeof(Scsi_Tape), GFP_ATOMIC);
st_template.dev_max = st_template.dev_noticed + ST_EXTRA_DEVS;
-#ifdef DEBUG
+#if DEBUG
printk("st: Buffer size %d bytes, write threshold %d bytes.\n",
st_buffer_size, st_write_threshold);
#endif
@@ -2028,6 +2084,7 @@
STp->do_buffer_writes = ST_BUFFER_WRITES;
STp->do_async_writes = ST_ASYNC_WRITES;
STp->do_read_ahead = ST_READ_AHEAD;
+ STp->do_auto_lock = ST_AUTO_LOCK;
STp->two_fm = ST_TWO_FM;
STp->fast_mteom = ST_FAST_MTEOM;
STp->write_threshold = st_write_threshold;
@@ -2053,7 +2110,7 @@
for (i=0; i < st_nbr_buffers; i++) {
st_buffers[i] = (ST_buffer *) scsi_init_malloc(sizeof(ST_buffer) -
1 + st_buffer_size, GFP_ATOMIC | GFP_DMA);
-#ifdef DEBUG
+#if DEBUG
/* printk("st: Buffer address: %p\n", st_buffers[i]); */
#endif
st_buffers[i]->in_use = 0;
@@ -2096,7 +2153,8 @@
return;
}
scsi_unregister_module(MODULE_SCSI_DEV, &st_template);
- unregister_chrdev(SCSI_GENERIC_MAJOR, "st");
+ unregister_chrdev(SCSI_TAPE_MAJOR, "st");
+ st_registered--;
if(scsi_tapes != NULL) {
scsi_init_free((char *) scsi_tapes,
(st_template.dev_noticed + ST_EXTRA_DEVS)
FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen, [email protected]
with Sam's (original) version of this