patch-2.1.41 linux/drivers/scsi/st.c
Next file: linux/drivers/scsi/st.h
Previous file: linux/drivers/scsi/README.st
Back to the patch index
Back to the overall index
- Lines: 524
- Date:
Tue May 27 13:20:09 1997
- Orig file:
v2.1.40/linux/drivers/scsi/st.c
- Orig date:
Fri Apr 4 08:52:23 1997
diff -u --recursive --new-file v2.1.40/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
@@ -11,7 +11,7 @@
Copyright 1992 - 1997 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Wed Jan 1 15:26:54 1997 by makisara@kai.makisara.fi
+ Last modified: Tue May 27 22:29:00 1997 by makisara@home
Some small formal changes - aeb, 950809
*/
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/init.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/mtio.h>
@@ -48,14 +49,23 @@
#include "st.h"
#include "constants.h"
+#ifdef MODULE
+MODULE_PARM(buffer_kbs, "i");
+MODULE_PARM(write_threshold_kbs, "i");
+MODULE_PARM(max_buffers, "i");
+static int buffer_kbs = 0;
+static int write_threshold_kbs = 0;
+static int max_buffers = 0;
+#endif
+
/* The default definitions have been moved to st_options.h */
-#define ST_BLOCK_SIZE 1024
+#define ST_KILOBYTE 1024
#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)
+#define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_KILOBYTE)
+#define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
/* The buffer size should fit into the 24 bits for length in the
6-byte SCSI read and write commands. */
@@ -220,6 +230,7 @@
}
else
(STp->buffer)->last_result = SCpnt->result;
+#if 0
if ((STp->buffer)->writing) {
/* Process errors before releasing request */
(STp->buffer)->last_result_fatal = st_chk_result(SCpnt);
@@ -227,6 +238,10 @@
}
else
SCpnt->request.rq_status = RQ_SCSI_DONE;
+#else
+ SCpnt->request.rq_status = RQ_SCSI_DONE;
+ (STp->buffer)->last_SCpnt = SCpnt;
+#endif
#if DEBUG
STp->write_pending = 0;
@@ -286,6 +301,9 @@
down(&(STp->sem));
+ (STp->buffer)->last_result_fatal = st_chk_result((STp->buffer)->last_SCpnt);
+ ((STp->buffer)->last_SCpnt)->request.rq_status = RQ_INACTIVE;
+
if (STbuffer->writing < STbuffer->buffer_bytes)
memcpy(STbuffer->b_data,
STbuffer->b_data + STbuffer->writing,
@@ -327,7 +345,7 @@
TAPE_NR(STp->devt), forward ? "forward" : "backward");
#endif
- SCpnt = st_do_scsi(NULL, STp, cmd, 0, ST_TIMEOUT, MAX_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_RETRIES);
if (!SCpnt)
return (-EBUSY);
@@ -387,7 +405,7 @@
cmd[3] = blks >> 8;
cmd[4] = blks;
- SCpnt = st_do_scsi(NULL, STp, cmd, transfer, ST_TIMEOUT, MAX_WRITE_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES);
if (!SCpnt)
return (-EBUSY);
@@ -594,7 +612,7 @@
memset ((void *) &cmd[0], 0, 10);
cmd[0] = TEST_UNIT_READY;
- SCpnt = st_do_scsi(NULL, STp, cmd, 0, ST_LONG_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->long_timeout, MAX_READY_RETRIES);
if (!SCpnt) {
if (scsi_tapes[dev].device->host->hostt->module)
__MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
@@ -608,7 +626,7 @@
memset ((void *) &cmd[0], 0, 10);
cmd[0] = TEST_UNIT_READY;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, 0, ST_LONG_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, 0, STp->long_timeout, MAX_READY_RETRIES);
(STp->device)->was_reset = 0;
STp->partition = STp->new_partition = 0;
@@ -649,7 +667,7 @@
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, STp->timeout, MAX_READY_RETRIES);
if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
STp->max_block = ((STp->buffer)->b_data[1] << 16) |
@@ -675,7 +693,7 @@
cmd[0] = MODE_SENSE;
cmd[4] = 12;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, 12, ST_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, 12, STp->timeout, MAX_READY_RETRIES);
if ((STp->buffer)->last_result_fatal != 0) {
#if DEBUG
@@ -807,7 +825,7 @@
static int
scsi_tape_close(struct inode * inode, struct file * filp)
{
- int result;
+ int result = 0, result2;
static unsigned char cmd[10];
Scsi_Cmnd * SCpnt;
Scsi_Tape * STp;
@@ -823,7 +841,7 @@
STps = &(STp->ps[STp->partition]);
if (STp->can_partitions &&
- update_partition(inode) < 0) {
+ (result = update_partition(inode)) < 0) {
#if DEBUG
if (debugging)
printk(ST_DEB_MSG "st%d: update_partition at close failed.\n", dev);
@@ -850,7 +868,7 @@
cmd[0] = WRITE_FILEMARKS;
cmd[4] = 1 + STp->two_fm;
- SCpnt = st_do_scsi(NULL, STp, cmd, 0, ST_TIMEOUT, MAX_WRITE_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_WRITE_RETRIES);
if (!SCpnt)
goto out;
@@ -862,8 +880,12 @@
((SCpnt->sense_buffer[0] & 0x80) != 0 &&
(SCpnt->sense_buffer[3] | SCpnt->sense_buffer[4] |
SCpnt->sense_buffer[5] |
- SCpnt->sense_buffer[6]) == 0))) /* Filter out successful write at EOM */
- printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
+ SCpnt->sense_buffer[6]) == 0))) {
+ /* Filter out successful write at EOM */
+ printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
+ if (result == 0)
+ result = (-EIO);
+ }
else {
if (STps->drv_file >= 0)
STps->drv_file++ ;
@@ -884,9 +906,10 @@
STps = &(STp->ps[STp->partition]);
if (!STm->sysv || STps->rw != ST_READING) {
if (STp->can_bsr)
- flush_buffer(inode, filp, 0);
+ result = flush_buffer(inode, filp, 0);
else if (STps->eof == ST_FM_HIT) {
- if (cross_eof(STp, FALSE)) {
+ result = cross_eof(STp, FALSE);
+ if (result) {
if (STps->drv_file >= 0)
STps->drv_file++;
STps->drv_block = 0;
@@ -896,7 +919,8 @@
STps->eof = ST_NOEOF;
}
}
- else if ((STps->eof == ST_NOEOF && !cross_eof(STp, TRUE)) ||
+ else if ((STps->eof == ST_NOEOF &&
+ !(result = cross_eof(STp, TRUE))) ||
STps->eof == ST_FM_HIT) {
if (STps->drv_file >= 0)
STps->drv_file++;
@@ -906,8 +930,11 @@
}
out:
- if (STp->rew_at_close)
- st_int_ioctl(inode, MTREW, 1);
+ if (STp->rew_at_close) {
+ result2 = st_int_ioctl(inode, MTREW, 1);
+ if (result == 0)
+ result = result2;
+ }
if (STp->door_locked == ST_LOCKED_AUTO)
st_int_ioctl(inode, MTUNLOCK, 0);
@@ -923,7 +950,7 @@
if(st_template.module)
__MOD_DEC_USE_COUNT(st_template.module);
- return 0;
+ return result;
}
@@ -1083,7 +1110,7 @@
cmd[3] = blks >> 8;
cmd[4] = blks;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, transfer, ST_TIMEOUT, MAX_WRITE_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES);
if (!SCpnt)
return (-EBUSY);
@@ -1177,7 +1204,8 @@
}
if (STm->do_async_writes &&
- ((STp->buffer)->buffer_bytes >= STp->write_threshold ||
+ (((STp->buffer)->buffer_bytes >= STp->write_threshold &&
+ (STp->buffer)->buffer_bytes >= STp->block_size) ||
STp->block_size == 0) ) {
/* Schedule an asynchronous write */
if (!SCpnt) {
@@ -1211,7 +1239,7 @@
scsi_do_cmd (SCpnt,
(void *) cmd, (STp->buffer)->b_data,
(STp->buffer)->writing,
- st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
+ st_sleep_done, STp->timeout, MAX_WRITE_RETRIES);
}
else if (SCpnt != NULL)
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
@@ -1270,7 +1298,7 @@
cmd[4] = blks;
SCpnt = *aSCpnt;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, bytes, ST_TIMEOUT, MAX_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, bytes, STp->timeout, MAX_RETRIES);
*aSCpnt = SCpnt;
if (!SCpnt)
return (-EBUSY);
@@ -1572,6 +1600,8 @@
"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);
+ printk(KERN_INFO
+"st%d: sysv: %d\n", dev, STm->sysv);
#if DEBUG
printk(KERN_INFO
"st%d: debugging: %d\n",
@@ -1615,6 +1645,7 @@
if ((STp->device)->scsi_level >= SCSI_2)
STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
+ STm->sysv = (options & MT_ST_SYSV) != 0;
#if DEBUG
debugging = (options & MT_ST_DEBUGGING) != 0;
#endif
@@ -1645,6 +1676,8 @@
STp->can_partitions = value;
if ((options & MT_ST_SCSI2LOGICAL) != 0)
STp->scsi2_logical = value;
+ if ((options & MT_ST_SYSV) != 0)
+ STm->sysv = value;
#if DEBUG
if ((options & MT_ST_DEBUGGING) != 0)
debugging = value;
@@ -1652,7 +1685,7 @@
st_log_options(STp, STm, dev);
}
else if (code == MT_ST_WRITE_THRESHOLD) {
- value = (options & ~MT_ST_OPTIONS) * ST_BLOCK_SIZE;
+ value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
if (value < 1 || value > st_buffer_size) {
printk(KERN_WARNING "st%d: Write threshold %d too small or too large.\n",
dev, value);
@@ -1674,6 +1707,19 @@
dev, STm->default_blksize);
}
}
+ else if (code == MT_ST_TIMEOUTS) {
+ value = (options & ~MT_ST_OPTIONS);
+ if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
+ STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
+ printk(KERN_INFO "st%d: Long timeout set to %d seconds.\n", dev,
+ (value & ~MT_ST_SET_LONG_TIMEOUT));
+ }
+ else {
+ STp->timeout = value * HZ;
+ printk(KERN_INFO "st%d: Normal timeout set to %d seconds.\n", dev,
+ value);
+ }
+ }
else if (code == MT_ST_DEF_OPTIONS) {
code = (options & ~MT_ST_CLEAR_DEFAULT);
value = (options & MT_ST_CLEAR_DEFAULT);
@@ -1746,7 +1792,7 @@
cmd[2] = COMPRESSION_PAGE;
cmd[4] = COMPRESSION_PAGE_LENGTH + MODE_HEADER_LENGTH;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], ST_TIMEOUT, 0);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0);
if (SCpnt == NULL)
return (-EBUSY);
dev = TAPE_NR(SCpnt->request.rq_dev);
@@ -1789,7 +1835,7 @@
(STp->buffer)->b_data[0] = 0; /* Reserved data length */
(STp->buffer)->b_data[1] = 0; /* Reserved media type byte */
(STp->buffer)->b_data[MODE_HEADER_LENGTH] &= 0x3f;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], ST_TIMEOUT, 0);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0);
if ((STp->buffer)->last_result_fatal != 0) {
#if DEBUG
@@ -1817,7 +1863,7 @@
st_int_ioctl(struct inode * inode,
unsigned int cmd_in, unsigned long arg)
{
- int timeout = ST_LONG_TIMEOUT;
+ int timeout;
long ltmp;
int i, ioctl_result;
int chg_eof = TRUE;
@@ -1831,6 +1877,7 @@
STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY && cmd_in != MTLOAD)
return (-EIO);
+ timeout = STp->long_timeout;
STps = &(STp->ps[STp->partition]);
fileno = STps->drv_file;
blkno = STps->drv_block;
@@ -1961,7 +2008,7 @@
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#if DEBUG
if (debugging) {
if (cmd_in == MTWEOF)
@@ -1981,7 +2028,7 @@
cmd[0] = REZERO_UNIT;
#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#endif
#if DEBUG
if (debugging)
@@ -2012,9 +2059,9 @@
}
#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#else
- timeout = ST_LONG_TIMEOUT * 8;
+ timeout = STp->long_timeout;
#endif
#if DEBUG
if (debugging) {
@@ -2037,7 +2084,7 @@
cmd[0] = START_STOP;
#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#endif
cmd[4] = 3;
#if DEBUG
@@ -2076,9 +2123,9 @@
cmd[1] = 1; /* To the end of tape */
#if ST_NOWAIT
cmd[1] |= 2; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#else
- timeout = ST_LONG_TIMEOUT * 8;
+ timeout = STp->long_timeout * 8;
#endif
#if DEBUG
if (debugging)
@@ -2147,7 +2194,7 @@
(STp->buffer)->b_data[9] = (ltmp >> 16);
(STp->buffer)->b_data[10] = (ltmp >> 8);
(STp->buffer)->b_data[11] = ltmp;
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#if DEBUG
if (debugging) {
if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
@@ -2338,7 +2385,7 @@
if (!logical && !STp->scsi2_logical)
scmd[1] = 1;
}
- SCpnt = st_do_scsi(NULL, STp, scmd, 20, ST_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, scmd, 20, STp->timeout, MAX_READY_RETRIES);
if (!SCpnt)
return (-EBUSY);
@@ -2394,13 +2441,14 @@
int dev = TAPE_NR(inode->i_rdev);
int result, p;
unsigned int blk;
- int timeout = ST_LONG_TIMEOUT;
+ int timeout;
unsigned char scmd[10];
Scsi_Cmnd *SCpnt;
STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY)
return (-EIO);
+ timeout = STp->long_timeout;
STps = &(STp->ps[STp->partition]);
#if DEBUG
@@ -2457,7 +2505,7 @@
}
#if ST_NOWAIT
scmd[1] |= 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#endif
SCpnt = st_do_scsi(NULL, STp, scmd, 20, timeout, MAX_READY_RETRIES);
@@ -2554,7 +2602,7 @@
cmd[2] = PART_PAGE;
cmd[4] = 200;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, 200, ST_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, 200, STp->timeout, MAX_READY_RETRIES);
if (SCpnt == NULL)
return (-EBUSY);
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
@@ -2628,7 +2676,7 @@
cmd[1] = 0x10;
cmd[4] = length + MODE_HEADER_LENGTH;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], ST_LONG_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->long_timeout, MAX_READY_RETRIES);
if (SCpnt == NULL)
return (-EBUSY);
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
@@ -2979,13 +3027,13 @@
/* Set the boot options. Syntax: st=xxx,yyy
where xxx is buffer size in 1024 byte blocks and yyy is write threshold
in 1024 byte blocks. */
- void
-st_setup(char *str, int *ints)
+ __initfunc( void
+st_setup(char *str, int *ints))
{
if (ints[0] > 0 && ints[1] > 0)
- st_buffer_size = ints[1] * ST_BLOCK_SIZE;
+ st_buffer_size = ints[1] * ST_KILOBYTE;
if (ints[0] > 1 && ints[2] > 0) {
- st_write_threshold = ints[2] * ST_BLOCK_SIZE;
+ st_write_threshold = ints[2] * ST_KILOBYTE;
if (st_write_threshold > st_buffer_size)
st_write_threshold = st_buffer_size;
}
@@ -3045,12 +3093,14 @@
tpnt->can_partitions = 0;
tpnt->two_fm = ST_TWO_FM;
tpnt->fast_mteom = ST_FAST_MTEOM;
- tpnt->scsi2_logical = 0;
+ tpnt->scsi2_logical = ST_SCSI2LOGICAL;
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->timeout = ST_TIMEOUT;
+ tpnt->long_timeout = ST_LONG_TIMEOUT;
for (i=0; i < ST_NBR_MODES; i++) {
STm = &(tpnt->modes[i]);
@@ -3099,7 +3149,7 @@
static int st_registered = 0;
-/* Driver initialization */
+/* Driver initialization (not __initfunc because may be called later) */
static int st_init()
{
int i;
@@ -3213,8 +3263,25 @@
#ifdef MODULE
int init_module(void) {
+ int result;
+
st_template.module = &__this_module;
- return scsi_register_module(MODULE_SCSI_DEV, &st_template);
+ result = scsi_register_module(MODULE_SCSI_DEV, &st_template);
+ if (result)
+ return result;
+
+ if (buffer_kbs > 0)
+ st_buffer_size = buffer_kbs * ST_KILOBYTE;
+ if (write_threshold_kbs > 0)
+ st_write_threshold = write_threshold_kbs * ST_KILOBYTE;
+ if (st_write_threshold > st_buffer_size)
+ st_write_threshold = st_buffer_size;
+ if (max_buffers > 0)
+ st_max_buffers = max_buffers;
+printk(KERN_INFO "st: bufsize %d, wrt %d, max buffers %d.\n",
+st_buffer_size, st_write_threshold, st_max_buffers);
+
+ return 0;
}
void cleanup_module( void)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov