order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
- Copyright 1992 - 2002 Kai Makisara / Willem Riede
- email Kai.Makisara@metla.fi / osst@riede.org
+ Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
+ email osst@riede.org
- $Header: /cvsroot/osst/Driver/osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $
+ $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
Microscopic alterations - Rik Ling, 2000/12/21
Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
Some small formal changes - aeb, 950809
*/
-static const char * cvsid = "$Id: osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $";
-const char * osst_version = "0.99.1";
+static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
+static const char * osst_version = "0.99.4";
/* The "failure to reconnect" firmware bug */
#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
#include <asm/system.h>
in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
#define OSST_DEB_MSG KERN_NOTICE
-#include "scsi.h"
-#include <scsi/scsi_host.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#define ST_KILOBYTE 1024
MODULE_AUTHOR("Willem Riede");
MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
-MODULE_PARM(max_dev, "i");
+module_param(max_dev, int, 0444);
MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
-MODULE_PARM(write_threshold_kbs, "i");
+module_param(write_threshold_kbs, int, 0644);
MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
-MODULE_PARM(max_sg_segs, "i");
+module_param(max_sg_segs, int, 0644);
MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
#else
static struct osst_dev_parm {
};
#endif
-static char *osst_formats[ST_NBR_MODES] ={"", "l", "m", "a"};
-
/* Some default definitions have been moved to osst_options.h */
#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
// #define OSST_INJECT_ERRORS 1
#endif
-#define MAX_RETRIES 2
-#define MAX_READ_RETRIES 0
-#define MAX_WRITE_RETRIES 0
-#define MAX_READY_RETRIES 0
+/* Do not retry! The drive firmware already retries when appropriate,
+ and when it tries to tell us something, we had better listen... */
+#define MAX_RETRIES 0
+
#define NO_TAPE NOT_READY
#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
static int osst_max_dev = OSST_MAX_TAPES;
static int osst_nr_dev;
-static OS_Scsi_Tape **os_scsi_tapes = NULL;
-static rwlock_t os_scsi_tapes_lock = RW_LOCK_UNLOCKED;
+static struct osst_tape **os_scsi_tapes = NULL;
+static DEFINE_RWLOCK(os_scsi_tapes_lock);
-static int modes_defined = FALSE;
+static int modes_defined = 0;
-static OSST_buffer *new_tape_buffer(int, int, int);
-static int enlarge_buffer(OSST_buffer *, int);
-static void normalize_buffer(OSST_buffer *);
-static int append_to_buffer(const char __user *, OSST_buffer *, int);
-static int from_buffer(OSST_buffer *, char __user *, int);
-static int osst_zero_buffer_tail(OSST_buffer *);
-static int osst_copy_to_buffer(OSST_buffer *, unsigned char *);
-static int osst_copy_from_buffer(OSST_buffer *, unsigned char *);
+static struct osst_buffer *new_tape_buffer(int, int, int);
+static int enlarge_buffer(struct osst_buffer *, int);
+static void normalize_buffer(struct osst_buffer *);
+static int append_to_buffer(const char __user *, struct osst_buffer *, int);
+static int from_buffer(struct osst_buffer *, char __user *, int);
+static int osst_zero_buffer_tail(struct osst_buffer *);
+static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
+static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
static int osst_probe(struct device *);
static int osst_remove(struct device *);
-struct scsi_driver osst_template = {
+static struct scsi_driver osst_template = {
.owner = THIS_MODULE,
.gendrv = {
.name = "osst",
}
};
-static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
+static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
+ unsigned int cmd_in, unsigned long arg);
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int frame, int skip);
+static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
-static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
+static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
+static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
-static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending);
+static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
-static inline char *tape_name(OS_Scsi_Tape *tape)
+static inline char *tape_name(struct osst_tape *tape)
{
return tape->drive->disk_name;
}
\f
/* Routines that handle the interaction with mid-layer SCSI routines */
+
+/* Normalize Sense */
+static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
+{
+ const u8 *ucp;
+ const u8 *sense = SRpnt->sense;
+
+ s->have_sense = scsi_normalize_sense(SRpnt->sense,
+ SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
+ s->flags = 0;
+
+ if (s->have_sense) {
+ s->deferred = 0;
+ s->remainder_valid =
+ scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
+ switch (sense[0] & 0x7f) {
+ case 0x71:
+ s->deferred = 1;
+ case 0x70:
+ s->fixed_format = 1;
+ s->flags = sense[2] & 0xe0;
+ break;
+ case 0x73:
+ s->deferred = 1;
+ case 0x72:
+ s->fixed_format = 0;
+ ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
+ s->flags = ucp ? (ucp[3] & 0xe0) : 0;
+ break;
+ }
+ }
+}
+
/* Convert the result to success code */
-static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
+static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
{
char *name = tape_name(STp);
- int result = SRpnt->sr_result;
- unsigned char * sense = SRpnt->sr_sense_buffer, scode;
+ int result = SRpnt->result;
+ u8 * sense = SRpnt->sense, scode;
#if DEBUG
const char *stp;
#endif
+ struct st_cmdstatus *cmdstatp;
- if (!result) {
- sense[0] = 0; /* We don't have sense data if this byte is zero */
+ if (!result)
return 0;
- }
- if ((driver_byte(result) & DRIVER_MASK) == DRIVER_SENSE)
- scode = sense[2] & 0x0f;
- else {
- sense[0] = 0; /* We don't have sense data if this byte is zero */
+
+ cmdstatp = &STp->buffer->cmdstat;
+ osst_analyze_sense(SRpnt, cmdstatp);
+
+ if (cmdstatp->have_sense)
+ scode = STp->buffer->cmdstat.sense_hdr.sense_key;
+ else
scode = 0;
- }
#if DEBUG
if (debugging) {
- printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
+ printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
name, result,
- SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
- SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
- SRpnt->sr_bufflen);
+ SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
+ SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
name, scode, sense[12], sense[13]);
- if (driver_byte(result) & DRIVER_SENSE)
- print_req_sense("osst ", SRpnt);
+ if (cmdstatp->have_sense)
+ __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
}
-// else
+ else
#endif
- if (!(driver_byte(result) & DRIVER_SENSE) ||
- ((sense[0] & 0x70) == 0x70 &&
+ if (cmdstatp->have_sense && (
scode != NO_SENSE &&
scode != RECOVERED_ERROR &&
/* scode != UNIT_ATTENTION && */
scode != BLANK_CHECK &&
scode != VOLUME_OVERFLOW &&
- SRpnt->sr_cmnd[0] != MODE_SENSE &&
- SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
- if (driver_byte(result) & DRIVER_SENSE) {
- printk(KERN_WARNING "%s:W: Command with sense data: ", name);
- print_req_sense("osst:", SRpnt);
+ SRpnt->cmd[0] != MODE_SENSE &&
+ SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
+ if (cmdstatp->have_sense) {
+ printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
+ __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
}
else {
static int notyetprinted = 1;
}
STp->pos_unknown |= STp->device->was_reset;
- if ((sense[0] & 0x70) == 0x70 &&
- scode == RECOVERED_ERROR) {
+ if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
STp->recover_count++;
STp->recover_erreg++;
#if DEBUG
if (debugging) {
- if (SRpnt->sr_cmnd[0] == READ_6)
+ if (SRpnt->cmd[0] == READ_6)
stp = "read";
- else if (SRpnt->sr_cmnd[0] == WRITE_6)
+ else if (SRpnt->cmd[0] == WRITE_6)
stp = "write";
else
stp = "ioctl";
/* Wakeup from interrupt */
-static void osst_sleep_done (Scsi_Cmnd * SCpnt)
+static void osst_sleep_done(void *data, char *sense, int result, int resid)
{
- OS_Scsi_Tape * STp = container_of(SCpnt->request->rq_disk->private_data, OS_Scsi_Tape, driver);
-
- 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[2] & 0x0f) == VOLUME_OVERFLOW)
- 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;
+ struct osst_request *SRpnt = data;
+ struct osst_tape *STp = SRpnt->stp;
+ memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
+ STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
#if DEBUG
STp->write_pending = 0;
#endif
- complete(SCpnt->request->waiting);
+ if (SRpnt->waiting)
+ complete(SRpnt->waiting);
+}
+
+/* osst_request memory management */
+static struct osst_request *osst_allocate_request(void)
+{
+ return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
}
+static void osst_release_request(struct osst_request *streq)
+{
+ kfree(streq);
+}
/* Do the scsi command. Waits until command performed if do_wait is true.
Otherwise osst_write_behind_check() is used to check that the command
has finished. */
-static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
+static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
{
unsigned char *bp;
+ unsigned short use_sg;
#ifdef OSST_INJECT_ERRORS
static int inject = 0;
static int repeat = 0;
#endif
+ struct completion *waiting;
+
+ /* if async, make sure there's no command outstanding */
+ if (!do_wait && ((STp->buffer)->last_SRpnt)) {
+ printk(KERN_ERR "%s: Async command already active.\n",
+ tape_name(STp));
+ if (signal_pending(current))
+ (STp->buffer)->syscall_result = (-EINTR);
+ else
+ (STp->buffer)->syscall_result = (-EBUSY);
+ return NULL;
+ }
+
if (SRpnt == NULL) {
- if ((SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC)) == NULL) {
- printk(KERN_ERR "%s:E: Can't get SCSI request.\n", tape_name(STp));
+ SRpnt = osst_allocate_request();
+ if (SRpnt == NULL) {
+ printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
+ tape_name(STp));
if (signal_pending(current))
(STp->buffer)->syscall_result = (-EINTR);
else
(STp->buffer)->syscall_result = (-EBUSY);
return NULL;
}
+ SRpnt->stp = STp;
}
- init_completion(&STp->wait);
- SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ?
- (STp->buffer)->use_sg : 0;
- if (SRpnt->sr_use_sg) {
+ /* If async IO, set last_SRpnt. This ptr tells write_behind_check
+ which IO is outstanding. It's nulled out when the IO completes. */
+ if (!do_wait)
+ (STp->buffer)->last_SRpnt = SRpnt;
+
+ waiting = &STp->wait;
+ init_completion(waiting);
+ SRpnt->waiting = waiting;
+
+ use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
+ if (use_sg) {
bp = (char *)&(STp->buffer->sg[0]);
- if (STp->buffer->sg_segs < SRpnt->sr_use_sg)
- SRpnt->sr_use_sg = STp->buffer->sg_segs;
+ if (STp->buffer->sg_segs < use_sg)
+ use_sg = STp->buffer->sg_segs;
}
else
bp = (STp->buffer)->b_data;
- SRpnt->sr_data_direction = direction;
- SRpnt->sr_cmd_len = 0;
- SRpnt->sr_request->waiting = &(STp->wait);
- SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
- SRpnt->sr_request->rq_disk = STp->drive;
- scsi_do_req(SRpnt, (void *)cmd, bp, bytes, osst_sleep_done, timeout, retries);
+ memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
+ STp->buffer->cmdstat.have_sense = 0;
+ STp->buffer->syscall_result = 0;
- if (do_wait) {
- wait_for_completion(SRpnt->sr_request->waiting);
- SRpnt->sr_request->waiting = NULL;
+ if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
+ use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL))
+ /* could not allocate the buffer or request was too large */
+ (STp->buffer)->syscall_result = (-EBUSY);
+ else if (do_wait) {
+ wait_for_completion(waiting);
+ SRpnt->waiting = NULL;
STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
#ifdef OSST_INJECT_ERRORS
if (STp->buffer->syscall_result == 0 &&
/* Handle the write-behind checking (downs the semaphore) */
-static void osst_write_behind_check(OS_Scsi_Tape *STp)
+static void osst_write_behind_check(struct osst_tape *STp)
{
- OSST_buffer * STbuffer;
+ struct osst_buffer * STbuffer;
STbuffer = STp->buffer;
STp->nbr_finished++;
#endif
wait_for_completion(&(STp->wait));
- (STp->buffer)->last_SRpnt->sr_request->waiting = NULL;
+ STp->buffer->last_SRpnt->waiting = NULL;
STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
- if ((STp->buffer)->syscall_result)
- (STp->buffer)->syscall_result =
- osst_write_error_recovery(STp, &((STp->buffer)->last_SRpnt), 1);
+ if (STp->buffer->syscall_result)
+ STp->buffer->syscall_result =
+ osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
else
STp->first_frame_position++;
- scsi_release_request((STp->buffer)->last_SRpnt);
+ osst_release_request(STp->buffer->last_SRpnt);
if (STbuffer->writing < STbuffer->buffer_bytes)
printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
+ STbuffer->last_SRpnt = NULL;
STbuffer->buffer_bytes -= STbuffer->writing;
STbuffer->writing = 0;
/*
* Initialize the OnStream AUX
*/
-static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number,
+static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
int logical_blk_num, int blk_sz, int blk_cnt)
{
os_aux_t *aux = STp->buffer->aux;
/*
* Verify that we have the correct tape frame
*/
-static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet)
+static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
{
- char * name = tape_name(STp);
- os_aux_t * aux = STp->buffer->aux;
- os_partition_t * par = &(aux->partition);
- ST_partstat * STps = &(STp->ps[STp->partition]);
- int blk_cnt, blk_sz, i;
+ char * name = tape_name(STp);
+ os_aux_t * aux = STp->buffer->aux;
+ os_partition_t * par = &(aux->partition);
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ int blk_cnt, blk_sz, i;
if (STp->raw) {
if (STp->buffer->syscall_result) {
/*
* Wait for the unit to become Ready
*/
-static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout, int initial_delay)
+static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
+ unsigned timeout, int initial_delay)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
- char * name = tape_name(STp);
+ int dbg = debugging;
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
#endif
- if (initial_delay > 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(initial_delay);
- }
+ if (initial_delay > 0)
+ msleep(jiffies_to_msecs(initial_delay));
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
- (( SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
- (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) ||
- ( SRpnt->sr_sense_buffer[2] == 6 && SRpnt->sr_sense_buffer[12] == 0x28 &&
- SRpnt->sr_sense_buffer[13] == 0 ) )) {
+ (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
+ (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
+ ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
+ SRpnt->sense[13] == 0 ) )) {
#if DEBUG
if (debugging) {
printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
debugging = 0;
}
#endif
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
+ msleep(100);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
}
*aSRpnt = SRpnt;
#if DEBUG
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
- STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
- SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
+ STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
+ SRpnt->sense[12], SRpnt->sense[13]);
#endif
return (-EIO);
}
/*
* Wait for a tape to be inserted in the unit
*/
-static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
+static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
- char * name = tape_name(STp);
+ int dbg = debugging;
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
#endif
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
- SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 0x3a &&
- SRpnt->sr_sense_buffer[13] == 0 ) {
+ SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
#if DEBUG
if (debugging) {
printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
debugging = 0;
}
#endif
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
+ msleep(100);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
}
*aSRpnt = SRpnt;
#if DEBUG
debugging = dbg;
#endif
- if ( STp->buffer->syscall_result && SRpnt->sr_sense_buffer[2] != 2 &&
- SRpnt->sr_sense_buffer[12] != 4 && SRpnt->sr_sense_buffer[13] == 1) {
+ if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
+ SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
- STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
- SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
+ STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
+ SRpnt->sense[12], SRpnt->sense[13]);
#endif
return 0;
}
return 1;
}
-static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame)
+static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
{
int retval;
/*
* Wait for write(s) to complete
*/
-static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
-
- int result = 0;
- int delay = OSST_WAIT_WRITE_COMPLETE;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt;
+ int result = 0;
+ int delay = OSST_WAIT_WRITE_COMPLETE;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
#endif
cmd[0] = WRITE_FILEMARKS;
cmd[1] = 1;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
if (STp->buffer->syscall_result) {
- if ((SRpnt->sr_sense_buffer[2] & 0x0f) == 2 && SRpnt->sr_sense_buffer[12] == 4) {
- if (SRpnt->sr_sense_buffer[13] == 8) {
+ if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
+ if (SRpnt->sense[13] == 8) {
delay = OSST_WAIT_LONG_WRITE_COMPLETE;
}
} else
}
#define OSST_POLL_PER_SEC 10
-static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to)
+static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
{
- unsigned long startwait = jiffies;
- char * name = tape_name(STp);
+ unsigned long startwait = jiffies;
+ char * name = tape_name(STp);
#if DEBUG
- char notyetprinted = 1;
+ char notyetprinted = 1;
#endif
if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
while (time_before (jiffies, startwait + to*HZ))
{
int result;
- result = osst_get_frame_position (STp, aSRpnt);
+ result = osst_get_frame_position(STp, aSRpnt);
if (result == -EIO)
if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
return 0; /* successful recovery leaves drive ready for frame */
) && result >= 0)
{
#if DEBUG
- if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC)
+ if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
printk (OSST_DEB_MSG
"%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
name, curr, curr+minlast, STp->first_frame_position,
return 0;
}
#if DEBUG
- if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted)
+ if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
{
printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
name, curr, curr+minlast, STp->first_frame_position,
notyetprinted--;
}
#endif
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout (HZ / OSST_POLL_PER_SEC);
+ msleep(1000 / OSST_POLL_PER_SEC);
}
#if DEBUG
printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
return -EBUSY;
}
+static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
+{
+ struct osst_request * SRpnt;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ unsigned long startwait = jiffies;
+ int retval = 1;
+ char * name = tape_name(STp);
+
+ if (writing) {
+ char mybuf[24];
+ char * olddata = STp->buffer->b_data;
+ int oldsize = STp->buffer->buffer_size;
+
+ /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
+
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = WRITE_FILEMARKS;
+ cmd[1] = 1;
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
+ MAX_RETRIES, 1);
+
+ while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
+
+ if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
+
+ /* some failure - not just not-ready */
+ retval = osst_write_error_recovery(STp, aSRpnt, 0);
+ break;
+ }
+ schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
+
+ STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = READ_POSITION;
+
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
+ MAX_RETRIES, 1);
+
+ retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
+ STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
+ }
+ if (retval)
+ printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
+ } else
+ /* TODO - figure out which error conditions can be handled */
+ if (STp->buffer->syscall_result)
+ printk(KERN_WARNING
+ "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
+ (*aSRpnt)->sense[ 2] & 0x0f,
+ (*aSRpnt)->sense[12],
+ (*aSRpnt)->sense[13]);
+
+ return retval;
+}
+
/*
* Read the next OnStream tape frame at the current location
*/
-static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout)
+static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int retval = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt;
+ int retval = 0;
#if DEBUG
- os_aux_t * aux = STp->buffer->aux;
- char * name = tape_name(STp);
+ os_aux_t * aux = STp->buffer->aux;
+ char * name = tape_name(STp);
#endif
- /* TODO: Error handling */
if (STp->poll)
- retval = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout);
-
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
+ retval = osst_recover_wait_frame(STp, aSRpnt, 0);
+
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = READ_6;
cmd[1] = 1;
#if DEBUG
if (debugging)
- printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
+ printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
#endif
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
- STp->timeout, MAX_READ_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
+ STp->timeout, MAX_RETRIES, 1);
*aSRpnt = SRpnt;
if (!SRpnt)
- return (-EBUSY);
+ return (-EBUSY);
if ((STp->buffer)->syscall_result) {
retval = 1;
if (debugging)
printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
name,
- SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],
- SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
- SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
- SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]);
+ SRpnt->sense[0], SRpnt->sense[1],
+ SRpnt->sense[2], SRpnt->sense[3],
+ SRpnt->sense[4], SRpnt->sense[5],
+ SRpnt->sense[6], SRpnt->sense[7]);
#endif
}
else
return (retval);
}
-static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
{
- ST_partstat * STps = &(STp->ps[STp->partition]);
- Scsi_Request * SRpnt ;
- unsigned char cmd[MAX_COMMAND_SIZE];
- int retval = 0;
-#if DEBUG
- char * name = tape_name(STp);
-#endif
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ struct osst_request * SRpnt ;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ int retval = 0;
+ char * name = tape_name(STp);
if (STps->rw != ST_READING) { /* Initialize read operation */
if (STps->rw == ST_WRITING || STp->dirty) {
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
#endif
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READ_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
*aSRpnt = SRpnt;
- retval = STp->buffer->syscall_result;
+ if ((retval = STp->buffer->syscall_result))
+ printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
}
return retval;
}
-static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet)
+static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
+ int frame_seq_number, int quiet)
{
- ST_partstat * STps = &(STp->ps[STp->partition]);
- char * name = tape_name(STp);
- int cnt = 0,
- bad = 0,
- past = 0,
- x,
- position;
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ char * name = tape_name(STp);
+ int cnt = 0,
+ bad = 0,
+ past = 0,
+ x,
+ position;
/*
* If we want just any frame (-1) and there is a frame in the buffer, return it
name, STp->read_error_frame);
#endif
STp->read_error_frame = 0;
+ STp->abort_count++;
}
return (-EIO);
}
position = 0xbb8;
else if (position > STp->eod_frame_ppos || ++bad == 10) {
position = STp->read_error_frame - 1;
+ bad = 0;
}
else {
- position += 39;
- cnt += 20;
+ position += 29;
+ cnt += 19;
}
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
"%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
name, frame_seq_number, STp->frame_seq_number, STps->eof);
#endif
- STp->fast_open = FALSE;
+ STp->fast_open = 0;
STp->read_error_frame = 0;
return (STps->eof);
}
-static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num)
+static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
{
- ST_partstat * STps = &(STp->ps[STp->partition]);
- char * name = tape_name(STp);
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ char * name = tape_name(STp);
int retries = 0;
int frame_seq_estimate, ppos_estimate, move;
#define OSST_SECTOR_SHIFT 9
#define OSST_SECTOR_MASK 0x03F
-static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
{
int sector;
#if DEBUG
return sector;
}
-static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector)
+static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
{
- ST_partstat * STps = &(STp->ps[STp->partition]);
- int frame = sector >> OSST_FRAME_SHIFT,
- offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
- r;
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ int frame = sector >> OSST_FRAME_SHIFT,
+ offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
+ r;
#if DEBUG
char * name = tape_name(STp);
* Precondition for this function to work: all frames in the
* drive's buffer must be of one type (DATA, MARK or EOD)!
*/
-static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
- unsigned int frame, unsigned int skip, int pending)
+static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
+ unsigned int frame, unsigned int skip, int pending)
{
- Scsi_Request * SRpnt = * aSRpnt;
- unsigned char * buffer, * p;
- unsigned char cmd[MAX_COMMAND_SIZE];
- int flag, new_frame, i;
- int nframes = STp->cur_frames;
- int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
- int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
+ struct osst_request * SRpnt = * aSRpnt;
+ unsigned char * buffer, * p;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ int flag, new_frame, i;
+ int nframes = STp->cur_frames;
+ int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+ int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
- (nframes + pending - 1);
- int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
+ int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
- (nframes + pending - 1) * blks_per_frame;
- char * name = tape_name(STp);
- unsigned long startwait = jiffies;
+ char * name = tape_name(STp);
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
+ int dbg = debugging;
#endif
if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
cmd[7] = 32768 >> 8;
cmd[8] = 32768 & 0xff;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
- STp->timeout, MAX_READ_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
+ STp->timeout, MAX_RETRIES, 1);
if ((STp->buffer)->syscall_result || !SRpnt) {
printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
*aSRpnt = SRpnt;
return (-EIO);
}
if (new_frame > frame + 1000) {
printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
return (-EIO);
}
- flag = 0;
if ( i >= nframes + pending ) break;
+ flag = 0;
}
osst_copy_to_buffer(STp->buffer, p);
/*
name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
p[0], p[1], p[2], p[3]);
#endif
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
+ STp->timeout, MAX_RETRIES, 1);
if (STp->buffer->syscall_result)
flag = 1;
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = WRITE_FILEMARKS;
cmd[1] = 1;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
+ STp->timeout, MAX_RETRIES, 1);
#if DEBUG
if (debugging) {
printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
- MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
+ MAX_RETRIES, 1);
- if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
- (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {
+ if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
+ (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
/* in the process of becoming ready */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
+ msleep(100);
continue;
}
if (STp->buffer->syscall_result)
}
*aSRpnt = SRpnt;
if (flag) {
- if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&
- SRpnt->sr_sense_buffer[12] == 0 &&
- SRpnt->sr_sense_buffer[13] == 2) {
+ if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
+ SRpnt->sense[12] == 0 &&
+ SRpnt->sense[13] == 2) {
printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
return (-EIO); /* hit end of tape = fail */
}
- i = ((SRpnt->sr_sense_buffer[3] << 24) |
- (SRpnt->sr_sense_buffer[4] << 16) |
- (SRpnt->sr_sense_buffer[5] << 8) |
- SRpnt->sr_sense_buffer[6] ) - new_frame;
+ i = ((SRpnt->sense[3] << 24) |
+ (SRpnt->sense[4] << 16) |
+ (SRpnt->sense[5] << 8) |
+ SRpnt->sense[6] ) - new_frame;
p = &buffer[i * OS_DATA_SIZE];
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
#endif
osst_get_frame_position(STp, aSRpnt);
#if DEBUG
- printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
- name, STp->first_frame_position, STp->last_frame_position);
+ printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
+ name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
#endif
}
- }
+ }
+ if (flag) {
+ /* error recovery did not successfully complete */
+ printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
+ STp->write_type == OS_WRITE_HEADER?"header":"body");
+ }
if (!pending)
osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
- vfree((void *)buffer);
+ vfree(buffer);
return 0;
}
-static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
unsigned int frame, unsigned int skip, int pending)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- char * name = tape_name(STp);
- int expected = 0;
- int attempts = 1000 / skip;
- int flag = 1;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt;
+ char * name = tape_name(STp);
+ int expected = 0;
+ int attempts = 1000 / skip;
+ int flag = 1;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
+ int dbg = debugging;
#endif
while (attempts && time_before(jiffies, startwait + 60*HZ)) {
osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
flag = 0;
attempts--;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
}
if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
#if DEBUG
printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
name, STp->frame_seq_number-1, STp->first_frame_position);
#endif
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
+ STp->timeout, MAX_RETRIES, 1);
*aSRpnt = SRpnt;
if (STp->buffer->syscall_result) { /* additional write error */
- if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&
- SRpnt->sr_sense_buffer[12] == 0 &&
- SRpnt->sr_sense_buffer[13] == 2) {
+ if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
+ SRpnt->sense[12] == 0 &&
+ SRpnt->sense[13] == 2) {
printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n",
name);
debugging = 0;
}
#endif
- schedule_timeout(HZ / 10);
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
}
printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
#if DEBUG
* Error recovery algorithm for the OnStream tape.
*/
-static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending)
+static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
{
- Scsi_Request * SRpnt = * aSRpnt;
- ST_partstat * STps = & STp->ps[STp->partition];
- char * name = tape_name(STp);
- int retval = 0;
- int rw_state;
- unsigned int frame, skip;
+ struct osst_request * SRpnt = * aSRpnt;
+ struct st_partstat * STps = & STp->ps[STp->partition];
+ char * name = tape_name(STp);
+ int retval = 0;
+ int rw_state;
+ unsigned int frame, skip;
rw_state = STps->rw;
- if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) != 3
- || SRpnt->sr_sense_buffer[12] != 12
- || SRpnt->sr_sense_buffer[13] != 0) {
+ if ((SRpnt->sense[ 2] & 0x0f) != 3
+ || SRpnt->sense[12] != 12
+ || SRpnt->sense[13] != 0) {
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
- SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
+ SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
#endif
return (-EIO);
}
- frame = (SRpnt->sr_sense_buffer[3] << 24) |
- (SRpnt->sr_sense_buffer[4] << 16) |
- (SRpnt->sr_sense_buffer[5] << 8) |
- SRpnt->sr_sense_buffer[6];
- skip = SRpnt->sr_sense_buffer[9];
+ frame = (SRpnt->sense[3] << 24) |
+ (SRpnt->sense[4] << 16) |
+ (SRpnt->sense[5] << 8) |
+ SRpnt->sense[6];
+ skip = SRpnt->sense[9];
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
if (retval == 0) {
STp->recover_count++;
STp->recover_erreg++;
- }
+ } else
+ STp->abort_count++;
+
STps->rw = rw_state;
return retval;
}
-static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
int mt_op, int mt_count)
{
char * name = tape_name(STp);
*
* Just scans for the filemark sequentially.
*/
-static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
int mt_op, int mt_count)
{
int cnt = 0;
/*
* Fast linux specific version of OnStream FSF
*/
-static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
int mt_op, int mt_count)
{
char * name = tape_name(STp);
* to test the error recovery mechanism.
*/
#if DEBUG
-static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int retries)
+static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = * aSRpnt;
- char * name = tape_name(STp);
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt = * aSRpnt;
+ char * name = tape_name(STp);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SELECT;
if (debugging)
printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
*aSRpnt = SRpnt;
if ((STp->buffer)->syscall_result)
#endif
-static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
{
int result;
int this_mark_ppos = STp->first_frame_position;
return result;
}
-static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
{
int result;
#if DEBUG
return result;
}
-static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
+static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
{
char * name = tape_name(STp);
return osst_flush_drive_buffer(STp, aSRpnt);
}
-static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
+static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
{
char * name = tape_name(STp);
int result;
return result;
}
-static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int locate_eod)
+static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
{
os_header_t * header;
int result;
return result;
}
-static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
{
if (STp->header_cache != NULL)
memset(STp->header_cache, 0, sizeof(os_header_t));
return osst_write_header(STp, aSRpnt, 1);
}
-static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ppos)
+static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
{
char * name = tape_name(STp);
os_header_t * header;
return 1;
}
-static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
{
int position, ppos;
int first, last;
return 1;
}
-static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
{
int frame_position = STp->first_frame_position;
int frame_seq_numbr = STp->frame_seq_number;
/*
* Configure the OnStream SCII tape drive for default operation
*/
-static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
{
unsigned char cmd[MAX_COMMAND_SIZE];
char * name = tape_name(STp);
- Scsi_Request * SRpnt = * aSRpnt;
+ struct osst_request * SRpnt = * aSRpnt;
osst_mode_parameter_header_t * header;
osst_block_size_page_t * bs;
osst_capabilities_page_t * cp;
cmd[2] = BLOCK_SIZE_PAGE;
cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
if (SRpnt == NULL) {
#if DEBUG
printk(OSST_DEB_MSG "osst :D: Busy\n");
cmd[1] = 0x10;
cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
*aSRpnt = SRpnt;
if ((STp->buffer)->syscall_result != 0) {
printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
(STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
(STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
*aSRpnt = SRpnt;
if ((STp->buffer)->syscall_result != 0) {
cmd[2] = CAPABILITIES_PAGE;
cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
*aSRpnt = SRpnt;
if ((STp->buffer)->syscall_result != 0) {
cmd[2] = TAPE_PARAMTR_PAGE;
cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
*aSRpnt = SRpnt;
if ((STp->buffer)->syscall_result != 0) {
/* Step over EOF if it has been inadvertently crossed (ioctl not used because
it messes up the block number). */
-static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
+static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
{
int result;
char * name = tape_name(STp);
/* Get the tape position. */
-static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
{
- unsigned char scmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int result = 0;
+ unsigned char scmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt;
+ int result = 0;
+ char * name = tape_name(STp);
/* KG: We want to be able to use it for checking Write Buffer availability
* and thus don't want to risk to overwrite anything. Exchange buffers ... */
char mybuf[24];
char * olddata = STp->buffer->b_data;
int oldsize = STp->buffer->buffer_size;
- char * name = tape_name(STp);
if (STp->ready != ST_READY) return (-EIO);
scmd[0] = READ_POSITION;
STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
- SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, SCSI_DATA_READ,
- STp->timeout, MAX_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
+ STp->timeout, MAX_RETRIES, 1);
if (!SRpnt) {
STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
return (-EBUSY);
*aSRpnt = SRpnt;
if (STp->buffer->syscall_result)
- result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;
+ result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
if (result == -EINVAL)
printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
else {
-
- if (result == -EIO) { /* re-read position */
+ if (result == -EIO) { /* re-read position - this needs to preserve media errors */
unsigned char mysense[16];
- memcpy (mysense, SRpnt->sr_sense_buffer, 16);
+ memcpy (mysense, SRpnt->sense, 16);
memset (scmd, 0, MAX_COMMAND_SIZE);
scmd[0] = READ_POSITION;
STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
- SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, SCSI_DATA_READ,
- STp->timeout, MAX_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
+ STp->timeout, MAX_RETRIES, 1);
+#if DEBUG
+ printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
+ name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
+ SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
+#endif
if (!STp->buffer->syscall_result)
- memcpy (SRpnt->sr_sense_buffer, mysense, 16);
+ memcpy (SRpnt->sense, mysense, 16);
+ else
+ printk(KERN_WARNING "%s:W: Double error in get position\n", name);
}
STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
+ ((STp->buffer)->b_data[5] << 16)
#endif
if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
#if DEBUG
- printk(KERN_WARNING "%s:D: Correcting read position %d, %d, %d\n", name,
+ printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
#endif
STp->first_frame_position = STp->last_frame_position;
/* Set the tape block */
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int ppos, int skip)
+static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
{
- unsigned char scmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- ST_partstat * STps;
- int result = 0;
- int pp = (ppos == 3000 && !skip)? 0 : ppos;
- char * name = tape_name(STp);
+ unsigned char scmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt;
+ struct st_partstat * STps;
+ int result = 0;
+ int pp = (ppos == 3000 && !skip)? 0 : ppos;
+ char * name = tape_name(STp);
if (STp->ready != ST_READY) return (-EIO);
if (skip)
scmd[9] = 0x80;
- SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, SCSI_DATA_NONE, STp->long_timeout,
- MAX_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
+ MAX_RETRIES, 1);
if (!SRpnt)
return (-EBUSY);
*aSRpnt = SRpnt;
return result;
}
-static int osst_write_trailer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int leave_at_EOT)
+static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
{
- ST_partstat * STps = &(STp->ps[STp->partition]);
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
int result = 0;
if (STp->write_type != OS_WRITE_NEW_MARK) {
/* osst versions of st functions - augmented and stripped to suit OnStream only */
/* Flush the write buffer (never need to write if variable blocksize). */
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
{
- int offset, transfer, blks = 0;
- int result = 0;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = *aSRpnt;
- ST_partstat * STps;
- char * name = tape_name(STp);
+ int offset, transfer, blks = 0;
+ int result = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt = *aSRpnt;
+ struct st_partstat * STps;
+ char * name = tape_name(STp);
if ((STp->buffer)->writing) {
if (SRpnt == (STp->buffer)->last_SRpnt)
#if DEBUG
{ printk(OSST_DEB_MSG
- "%s:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", name);
+ "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
#endif
*aSRpnt = SRpnt = NULL;
#if DEBUG
} else if (SRpnt)
printk(OSST_DEB_MSG
- "%s:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", name);
+ "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
#endif
osst_write_behind_check(STp);
if ((STp->buffer)->syscall_result) {
if (offset < OS_DATA_SIZE)
osst_zero_buffer_tail(STp->buffer);
- /* TODO: Error handling! */
if (STp->poll)
- result = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120);
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
+ result = osst_recover_wait_frame(STp, aSRpnt, 1);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = WRITE_6;
name, offset, transfer, blks);
#endif
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
+ STp->timeout, MAX_RETRIES, 1);
*aSRpnt = SRpnt;
if (!SRpnt)
return (-EBUSY);
#if DEBUG
printk(OSST_DEB_MSG
"%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
- name, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
- SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
+ name, SRpnt->sense[0], SRpnt->sense[2],
+ SRpnt->sense[12], SRpnt->sense[13]);
#endif
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
- (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) {
+ if ((SRpnt->sense[0] & 0x70) == 0x70 &&
+ (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
+ (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
STp->dirty = 0;
(STp->buffer)->buffer_bytes = 0;
result = (-ENOSPC);
/* Flush the tape buffer. The tape will be positioned correctly unless
seek_next is true. */
-static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next)
+static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
{
- ST_partstat * STps;
- int backspace = 0, result = 0;
+ struct st_partstat * STps;
+ int backspace = 0, result = 0;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
#endif
/*
if (!seek_next) {
if (STps->eof == ST_FM_HIT) {
- result = cross_eof(STp, aSRpnt, FALSE); /* Back over the EOF hit */
+ result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
if (!result)
STps->eof = ST_NOEOF;
else {
return result;
}
-static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int synchronous)
+static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int blks;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt;
+ int blks;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
#endif
if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
}
if (STp->poll)
- osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 60);
- /* TODO: Check for an error ! */
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
+ if (osst_recover_wait_frame(STp, aSRpnt, 1))
+ return (-EIO);
// osst_build_stats(STp, &SRpnt);
if (!synchronous)
STp->write_pending = 1;
#endif
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout,
- MAX_WRITE_RETRIES, synchronous);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
+ MAX_RETRIES, synchronous);
if (!SRpnt)
return (-EBUSY);
*aSRpnt = SRpnt;
if (debugging)
printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
#endif
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x40)) {
- if ((SRpnt->sr_sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
+ if ((SRpnt->sense[0] & 0x70) == 0x70 &&
+ (SRpnt->sense[2] & 0x40)) {
+ if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
return (-ENOSPC);
}
else {
return 0;
}
-/* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */
-static int do_door_lock(OS_Scsi_Tape * STp, int do_lock)
+/* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
+static int do_door_lock(struct osst_tape * STp, int do_lock)
{
int retval, cmd;
}
/* Set the internal state after reset */
-static void reset_state(OS_Scsi_Tape *STp)
+static void reset_state(struct osst_tape *STp)
{
int i;
- ST_partstat *STps;
+ struct st_partstat *STps;
STp->pos_unknown = 0;
for (i = 0; i < ST_NBR_PARTITIONS; i++) {
STps->rw = ST_IDLE;
STps->eof = ST_NOEOF;
STps->at_sm = 0;
- STps->last_block_valid = FALSE;
+ STps->last_block_valid = 0;
STps->drv_block = -1;
STps->drv_file = -1;
}
/* Write command */
static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
{
- ssize_t total, retval = 0;
- ssize_t i, do_count, blks, transfer;
- int write_threshold;
- int doing_write = 0;
+ ssize_t total, retval = 0;
+ ssize_t i, do_count, blks, transfer;
+ int write_threshold;
+ int doing_write = 0;
const char __user * b_point;
- Scsi_Request * SRpnt = NULL;
- ST_mode * STm;
- ST_partstat * STps;
- OS_Scsi_Tape * STp = filp->private_data;
- char * name = tape_name(STp);
+ struct osst_request * SRpnt = NULL;
+ struct st_modedef * STm;
+ struct st_partstat * STps;
+ struct osst_tape * STp = filp->private_data;
+ char * name = tape_name(STp);
if (down_interruptible(&STp->lock))
#endif
}
}
- STp->fast_open = FALSE;
+ STp->fast_open = 0;
}
if (!STp->header_ok) {
#if DEBUG
#if DEBUG
if (debugging)
printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
- name, count, STps->drv_file, STps->drv_block,
+ name, (int) count, STps->drv_file, STps->drv_block,
STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
#endif
b_point = buf;
blks = do_count / STp->block_size;
STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
- i = osst_write_frame(STp, &SRpnt, TRUE);
+ i = osst_write_frame(STp, &SRpnt, 1);
if (i == (-ENOSPC)) {
transfer = STp->buffer->writing; /* FIXME -- check this logic */
#if DEBUG
if (debugging)
printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
- name, transfer);
+ name, (int) transfer);
#endif
}
else {
if (retval < 0) {
if (SRpnt != NULL) {
- scsi_release_request(SRpnt);
+ osst_release_request(SRpnt);
SRpnt = NULL;
}
STp->buffer->buffer_bytes = 0;
STp->dirty = !((STp->buffer)->writing ==
(STp->buffer)->buffer_bytes);
- i = osst_write_frame(STp, &SRpnt, FALSE);
+ i = osst_write_frame(STp, &SRpnt, 0);
if (i < 0) {
retval = (-EIO);
goto out;
retval = total;
out:
- if (SRpnt != NULL) scsi_release_request(SRpnt);
+ if (SRpnt != NULL) osst_release_request(SRpnt);
up(&STp->lock);
/* Read command */
static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
{
- ssize_t total, retval = 0;
- ssize_t i, transfer;
- int special;
- ST_mode * STm;
- ST_partstat * STps;
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp = filp->private_data;
- char * name = tape_name(STp);
+ ssize_t total, retval = 0;
+ ssize_t i, transfer;
+ int special;
+ struct st_modedef * STm;
+ struct st_partstat * STps;
+ struct osst_request * SRpnt = NULL;
+ struct osst_tape * STp = filp->private_data;
+ char * name = tape_name(STp);
if (down_interruptible(&STp->lock))
#if DEBUG
if (debugging && STps->eof != ST_NOEOF)
printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
- STps->eof, (STp->buffer)->buffer_bytes, count - total);
+ STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
#endif
/* force multiple of block size, note block_size may have been adjusted */
transfer = (((STp->buffer)->buffer_bytes < count - total ?
retval = total;
out:
- if (SRpnt != NULL) scsi_release_request(SRpnt);
+ if (SRpnt != NULL) osst_release_request(SRpnt);
up(&STp->lock);
/* Set the driver options */
-static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, char *name)
+static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
{
printk(KERN_INFO
"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
}
-static int osst_set_options(OS_Scsi_Tape *STp, long options)
+static int osst_set_options(struct osst_tape *STp, long options)
{
- int value;
- long code;
- ST_mode * STm;
- char * name = tape_name(STp);
+ int value;
+ long code;
+ struct st_modedef * STm;
+ char * name = tape_name(STp);
STm = &(STp->modes[STp->current_mode]);
if (!STm->defined) {
- memcpy(STm, &(STp->modes[0]), sizeof(ST_mode));
- modes_defined = TRUE;
+ memcpy(STm, &(STp->modes[0]), sizeof(*STm));
+ modes_defined = 1;
#if DEBUG
if (debugging)
printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
/* Internal ioctl function */
-static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
+static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
+ unsigned int cmd_in, unsigned long arg)
{
- int timeout;
- long ltmp;
- int i, ioctl_result;
- int chg_eof = TRUE;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = * aSRpnt;
- ST_partstat * STps;
- int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
- int datalen = 0, direction = SCSI_DATA_NONE;
- char * name = tape_name(STp);
+ int timeout;
+ long ltmp;
+ int i, ioctl_result;
+ int chg_eof = 1;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt = * aSRpnt;
+ struct st_partstat * STps;
+ int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
+ int datalen = 0, direction = DMA_NONE;
+ char * name = tape_name(STp);
if (STp->ready != ST_READY && cmd_in != MTLOAD) {
if (STp->ready == ST_NO_TAPE)
memset(cmd, 0, MAX_COMMAND_SIZE);
switch (cmd_in) {
case MTFSFM:
- chg_eof = FALSE; /* Changed from the FSF after this */
+ chg_eof = 0; /* Changed from the FSF after this */
case MTFSF:
if (STp->raw)
return (-EIO);
goto os_bypass;
case MTBSF:
- chg_eof = FALSE; /* Changed from the FSF after this */
+ chg_eof = 0; /* Changed from the FSF after this */
case MTBSFM:
if (STp->raw)
return (-EIO);
case MTSETDENSITY: /* Set tape density */
case MTSETDRVBUFFER: /* Set drive buffering */
case SET_DENS_AND_BLK: /* Set density and block size */
- chg_eof = FALSE;
+ chg_eof = 0;
if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
return (-EIO); /* Not allowed if data in buffer */
if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
return (-ENOSYS);
}
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
ioctl_result = (STp->buffer)->syscall_result;
else if (cmd_in == MTLOAD) {
for (i=0; i < ST_NBR_PARTITIONS; i++) {
STp->ps[i].rw = ST_IDLE;
- STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */
+ STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
}
STp->partition = 0;
}
} else if (cmd_in == MTERASE) {
STp->header_ok = 0;
} else if (SRpnt) { /* SCSI command was not completely successful. */
- if (SRpnt->sr_sense_buffer[2] & 0x40) {
+ if (SRpnt->sense[2] & 0x40) {
STps->eof = ST_EOM_OK;
STps->drv_block = 0;
}
if (chg_eof)
STps->eof = ST_NOEOF;
- if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
+ if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
STps->eof = ST_EOD;
if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
/* Open the device */
static int os_scsi_tape_open(struct inode * inode, struct file * filp)
{
- unsigned short flags;
- int i, b_size, new_session = FALSE, retval = 0;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp;
- ST_mode * STm;
- ST_partstat * STps;
- char * name;
- int dev = TAPE_NR(inode);
- int mode = TAPE_MODE(inode);
-
- nonseekable_open(inode, filp);
+ unsigned short flags;
+ int i, b_size, new_session = 0, retval = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct osst_request * SRpnt = NULL;
+ struct osst_tape * STp;
+ struct st_modedef * STm;
+ struct st_partstat * STps;
+ char * name;
+ int dev = TAPE_NR(inode);
+ int mode = TAPE_MODE(inode);
+
+ /*
+ * We really want to do nonseekable_open(inode, filp); here, but some
+ * versions of tar incorrectly call lseek on tapes and bail out if that
+ * fails. So we disallow pread() and pwrite(), but permit lseeks.
+ */
+ filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+
write_lock(&os_scsi_tapes_lock);
if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
(STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
name, STp->current_mode, mode);
#endif
- new_session = TRUE;
+ new_session = 1;
STp->current_mode = mode;
}
STm = &(STp->modes[STp->current_mode]);
memset (cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
if (!SRpnt) {
- retval = (STp->buffer)->syscall_result;
+ retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
goto err_out;
}
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
- SRpnt->sr_sense_buffer[12] == 4 ) {
+ if ((SRpnt->sense[0] & 0x70) == 0x70 &&
+ (SRpnt->sense[2] & 0x0f) == NOT_READY &&
+ SRpnt->sense[12] == 4 ) {
#if DEBUG
- printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sr_sense_buffer[13]);
+ printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
#endif
if (filp->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
goto err_out;
}
- if (SRpnt->sr_sense_buffer[13] == 2) { /* initialize command required (LOAD) */
+ if (SRpnt->sense[13] == 2) { /* initialize command required (LOAD) */
memset (cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = START_STOP;
cmd[1] = 1;
cmd[4] = 1;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
+ STp->timeout, MAX_RETRIES, 1);
}
- osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
+ osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
}
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
+ if ((SRpnt->sense[0] & 0x70) == 0x70 &&
+ (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
#endif
memset (cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
- if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
- (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
+ STp->timeout, MAX_RETRIES, 1);
+ if ((SRpnt->sense[0] & 0x70) != 0x70 ||
+ (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
break;
}
STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
STps->eof = ST_NOEOF;
STps->at_sm = 0;
- STps->last_block_valid = FALSE;
+ STps->last_block_valid = 0;
STps->drv_block = 0;
STps->drv_file = 0 ;
}
- new_session = TRUE;
+ new_session = 1;
STp->recover_count = 0;
+ STp->abort_count = 0;
}
/*
* if we have valid headers from before, and the drive/tape seem untouched,
* open without reconfiguring and re-reading the headers
*/
if (!STp->buffer->syscall_result && STp->header_ok &&
- !SRpnt->sr_result && SRpnt->sr_sense_buffer[0] == 0) {
+ !SRpnt->result && SRpnt->sense[0] == 0) {
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SENSE;
cmd[2] = VENDOR_IDENT_PAGE;
cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
if (STp->buffer->syscall_result ||
STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
}
STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
- STp->fast_open = TRUE;
- scsi_release_request(SRpnt);
+ STp->fast_open = 1;
+ osst_release_request(SRpnt);
return 0;
}
#if DEBUG
#endif
STp->header_ok = 0;
}
- STp->fast_open = FALSE;
+ STp->fast_open = 0;
if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
- (SRpnt->sr_sense_buffer[2] != 2 || SRpnt->sr_sense_buffer[12] != 0x3A) ) {
+ (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SELECT;
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
#endif
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
STp->header_ok = 0;
memset (cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
- if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
- (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
+ STp->timeout, MAX_RETRIES, 1);
+ if ((SRpnt->sense[0] & 0x70) != 0x70 ||
+ (SRpnt->sense[2] & 0x0f) == NOT_READY)
break;
- if ((SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {
+ if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
STp->pos_unknown = 0;
STp->partition = STp->new_partition = 0;
if (STp->can_partitions)
STps->rw = ST_IDLE;
STps->eof = ST_NOEOF;
STps->at_sm = 0;
- STps->last_block_valid = FALSE;
+ STps->last_block_valid = 0;
STps->drv_block = 0;
STps->drv_file = 0 ;
}
- new_session = TRUE;
+ new_session = 1;
}
}
}
if ((STp->buffer)->syscall_result != 0) {
if ((STp->device)->scsi_level >= SCSI_2 &&
- (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
- SRpnt->sr_sense_buffer[12] == 0x3a) { /* Check ASC */
+ (SRpnt->sense[0] & 0x70) == 0x70 &&
+ (SRpnt->sense[2] & 0x0f) == NOT_READY &&
+ SRpnt->sense[12] == 0x3a) { /* Check ASC */
STp->ready = ST_NO_TAPE;
} else
STp->ready = ST_NOT_READY;
- scsi_release_request(SRpnt);
+ osst_release_request(SRpnt);
SRpnt = NULL;
STp->density = 0; /* Clear the erroneous "residue" */
STp->write_prot = 0;
if (debugging)
printk(OSST_DEB_MSG "%s:D: New Session\n", name);
#endif
- STp->density_changed = STp->blksize_changed = FALSE;
- STp->compression_changed = FALSE;
+ STp->density_changed = STp->blksize_changed = 0;
+ STp->compression_changed = 0;
}
/*
osst_analyze_headers(STp, &SRpnt);
- scsi_release_request(SRpnt);
+ osst_release_request(SRpnt);
SRpnt = NULL;
return 0;
err_out:
if (SRpnt != NULL)
- scsi_release_request(SRpnt);
+ osst_release_request(SRpnt);
normalize_buffer(STp->buffer);
STp->header_ok = 0;
STp->in_use = 0;
/* Flush the tape buffer before close */
-static int os_scsi_tape_flush(struct file * filp)
+static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
{
- int result = 0, result2;
- OS_Scsi_Tape * STp = filp->private_data;
- ST_mode * STm = &(STp->modes[STp->current_mode]);
- ST_partstat * STps = &(STp->ps[STp->partition]);
- Scsi_Request * SRpnt = NULL;
- char * name = tape_name(STp);
+ int result = 0, result2;
+ struct osst_tape * STp = filp->private_data;
+ struct st_modedef * STm = &(STp->modes[STp->current_mode]);
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ struct osst_request * SRpnt = NULL;
+ char * name = tape_name(STp);
if (file_count(filp) > 1)
return 0;
if (STp->can_bsr)
result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
else if (STps->eof == ST_FM_HIT) {
- result = cross_eof(STp, &SRpnt, FALSE);
+ result = cross_eof(STp, &SRpnt, 0);
if (result) {
if (STps->drv_file >= 0)
STps->drv_file++;
}
}
else if ((STps->eof == ST_NOEOF &&
- !(result = cross_eof(STp, &SRpnt, TRUE))) ||
+ !(result = cross_eof(STp, &SRpnt, 1))) ||
STps->eof == ST_FM_HIT) {
if (STps->drv_file >= 0)
STps->drv_file++;
if (result == 0 && result2 < 0)
result = result2;
}
- if (SRpnt) scsi_release_request(SRpnt);
+ if (SRpnt) osst_release_request(SRpnt);
- if (STp->recover_count) {
- printk(KERN_INFO "%s:I: %d recovered errors in", name, STp->recover_count);
+ if (STp->abort_count || STp->recover_count) {
+ printk(KERN_INFO "%s:I:", name);
+ if (STp->abort_count)
+ printk(" %d unrecovered errors", STp->abort_count);
+ if (STp->recover_count)
+ printk(" %d recovered errors", STp->recover_count);
if (STp->write_count)
- printk(" %d frames written", STp->write_count);
+ printk(" in %d frames written", STp->write_count);
if (STp->read_count)
- printk(" %d frames read", STp->read_count);
+ printk(" in %d frames read", STp->read_count);
printk("\n");
STp->recover_count = 0;
+ STp->abort_count = 0;
}
STp->write_count = 0;
STp->read_count = 0;
/* Close the device and release it */
static int os_scsi_tape_close(struct inode * inode, struct file * filp)
{
- int result = 0;
- OS_Scsi_Tape * STp = filp->private_data;
- Scsi_Request * SRpnt = NULL;
-
- if (SRpnt) scsi_release_request(SRpnt);
+ int result = 0;
+ struct osst_tape * STp = filp->private_data;
if (STp->door_locked == ST_LOCKED_AUTO)
do_door_lock(STp, 0);
static int osst_ioctl(struct inode * inode,struct file * file,
unsigned int cmd_in, unsigned long arg)
{
- int i, cmd_nr, cmd_type, retval = 0;
- unsigned int blk;
- ST_mode * STm;
- ST_partstat * STps;
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp = file->private_data;
- char * name = tape_name(STp);
- void __user *p = (void __user *)arg;
+ int i, cmd_nr, cmd_type, blk, retval = 0;
+ struct st_modedef * STm;
+ struct st_partstat * STps;
+ struct osst_request * SRpnt = NULL;
+ struct osst_tape * STp = file->private_data;
+ char * name = tape_name(STp);
+ void __user * p = (void __user *)arg;
if (down_interruptible(&STp->lock))
return -ERESTARTSYS;
for (i=0; i < ST_NBR_PARTITIONS; i++) {
STp->ps[i].rw = ST_IDLE;
STp->ps[i].at_sm = 0;
- STp->ps[i].last_block_valid = FALSE;
+ STp->ps[i].last_block_valid = 0;
}
STp->partition = STp->new_partition = 0;
STp->nbr_partitions = 1; /* Bad guess ?-) */
}
if (auto_weof)
- cross_eof(STp, &SRpnt, FALSE);
+ cross_eof(STp, &SRpnt, 0);
if (mtc.mt_op == MTCOMPRESSION)
retval = -EINVAL; /* OnStream drives don't have compression hardware */
goto out;
}
- if ((i = osst_flush_buffer(STp, &SRpnt, FALSE)) < 0) {
+ if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
retval = i;
goto out;
}
retval = -EFAULT;
goto out;
}
- if (SRpnt) scsi_release_request(SRpnt);
+ if (SRpnt) osst_release_request(SRpnt);
up(&STp->lock);
return scsi_ioctl(STp->device, cmd_in, p);
out:
- if (SRpnt) scsi_release_request(SRpnt);
+ if (SRpnt) osst_release_request(SRpnt);
up(&STp->lock);
return retval;
}
+#ifdef CONFIG_COMPAT
+static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
+{
+ struct osst_tape *STp = file->private_data;
+ struct scsi_device *sdev = STp->device;
+ int ret = -ENOIOCTLCMD;
+ if (sdev->host->hostt->compat_ioctl) {
+
+ ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
+
+ }
+ return ret;
+}
+#endif
+
+
\f
/* Memory handling routines */
/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
-static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
+static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
{
- int i, priority;
- OSST_buffer *tb;
+ int i;
+ gfp_t priority;
+ struct osst_buffer *tb;
if (from_initialization)
priority = GFP_ATOMIC;
else
priority = GFP_KERNEL;
- i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
- tb = (OSST_buffer *)kmalloc(i, priority);
+ i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
+ tb = kzalloc(i, priority);
if (!tb) {
printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
return NULL;
}
- memset(tb, 0, i);
+
tb->sg_segs = tb->orig_sg_segs = 0;
tb->use_sg = max_sg;
- tb->in_use = TRUE;
+ tb->in_use = 1;
tb->dma = need_dma;
tb->buffer_size = 0;
#if DEBUG
}
/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
-static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
+static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
{
- int segs, nbr, max_segs, b_size, priority, order, got;
+ int segs, nbr, max_segs, b_size, order, got;
+ gfp_t priority;
if (STbuffer->buffer_size >= OS_FRAME_SIZE)
- return TRUE;
+ return 1;
if (STbuffer->sg_segs) {
printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
/* See how many segments we can use -- need at least two */
nbr = max_segs = STbuffer->use_sg;
if (nbr <= 2)
- return FALSE;
+ return 0;
- priority = GFP_KERNEL;
+ priority = GFP_KERNEL /* | __GFP_NOWARN */;
if (need_dma)
priority |= GFP_DMA;
- priority |= __GFP_NOWARN;
-
/* Try to allocate the first segment up to OS_DATA_SIZE and the others
big enough to reach the goal (code assumes no segments in place) */
for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
}
if (STbuffer->sg[0].page == NULL) {
printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
- return FALSE;
+ return 0;
}
/* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
for (segs=STbuffer->sg_segs=1, got=b_size;
STbuffer->buffer_size = got;
#endif
normalize_buffer(STbuffer);
- return FALSE;
+ return 0;
}
STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size;
got += STbuffer->sg[segs].length;
}
#endif
- return TRUE;
+ return 1;
}
/* Release the segments */
-static void normalize_buffer(OSST_buffer *STbuffer)
+static void normalize_buffer(struct osst_buffer *STbuffer)
{
int i, order, b_size;
/* Move data from the user buffer to the tape buffer. Returns zero (success) or
negative error code. */
-static int append_to_buffer(const char __user *ubp, OSST_buffer *st_bp, int do_count)
+static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
{
int i, cnt, res, offset;
/* Move data from the tape buffer to the user buffer. Returns zero (success) or
negative error code. */
-static int from_buffer(OSST_buffer *st_bp, char __user *ubp, int do_count)
+static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
{
int i, cnt, res, offset;
/* Sets the tail of the buffer after fill point to zero.
Returns zero (success) or negative error code. */
-static int osst_zero_buffer_tail(OSST_buffer *st_bp)
+static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
{
int i, offset, do_count, cnt;
/* Copy a osst 32K chunk of memory into the buffer.
Returns zero (success) or negative error code. */
-static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
+static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
{
int i, cnt, do_count = OS_DATA_SIZE;
/* Copy a osst 32K chunk of memory from the buffer.
Returns zero (success) or negative error code. */
-static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
+static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
{
int i, cnt, do_count = OS_DATA_SIZE;
char *stp;
stp = get_options(str, ARRAY_SIZE(ints), ints);
-
+
if (ints[0] > 0) {
for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
*parms[i].val = ints[i + 1];
break;
}
}
- if (i >= sizeof(parms) / sizeof(struct osst_dev_parm))
+ if (i >= ARRAY_SIZE(parms))
printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
stp);
stp = strchr(stp, ',');
.read = osst_read,
.write = osst_write,
.ioctl = osst_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = osst_compat_ioctl,
+#endif
.open = os_scsi_tape_open,
.flush = os_scsi_tape_flush,
.release = os_scsi_tape_close,
};
-static int osst_supports(Scsi_Device * SDp)
+static int osst_supports(struct scsi_device * SDp)
{
struct osst_support_data {
char *vendor;
return 0;
}
+/*
+ * sysfs support for osst driver parameter information
+ */
+
+static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
+}
+
+static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
+
+static int osst_create_driverfs_files(struct device_driver *driverfs)
+{
+ return driver_create_file(driverfs, &driver_attr_version);
+}
+
+static void osst_remove_driverfs_files(struct device_driver *driverfs)
+{
+ driver_remove_file(driverfs, &driver_attr_version);
+}
+
+/*
+ * sysfs support for accessing ADR header information
+ */
+
+static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
+
+static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
+
+static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
+
+static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
+
+static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
+
+static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
+
+static struct class *osst_sysfs_class;
+
+static int osst_sysfs_init(void)
+{
+ osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
+ if (IS_ERR(osst_sysfs_class)) {
+ printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
+ return PTR_ERR(osst_sysfs_class);
+ }
+
+ return 0;
+}
+
+static void osst_sysfs_destroy(dev_t dev)
+{
+ class_device_destroy(osst_sysfs_class, dev);
+}
+
+static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
+{
+ struct class_device *osst_class_member;
+ int err;
+
+ osst_class_member = class_device_create(osst_sysfs_class, NULL, dev,
+ device, "%s", name);
+ if (IS_ERR(osst_class_member)) {
+ printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
+ return PTR_ERR(osst_class_member);
+ }
+
+ class_set_devdata(osst_class_member, STp);
+ err = class_device_create_file(osst_class_member,
+ &class_device_attr_ADR_rev);
+ if (err)
+ goto err_out;
+ err = class_device_create_file(osst_class_member,
+ &class_device_attr_media_version);
+ if (err)
+ goto err_out;
+ err = class_device_create_file(osst_class_member,
+ &class_device_attr_capacity);
+ if (err)
+ goto err_out;
+ err = class_device_create_file(osst_class_member,
+ &class_device_attr_BOT_frame);
+ if (err)
+ goto err_out;
+ err = class_device_create_file(osst_class_member,
+ &class_device_attr_EOD_frame);
+ if (err)
+ goto err_out;
+ err = class_device_create_file(osst_class_member,
+ &class_device_attr_file_count);
+ if (err)
+ goto err_out;
+
+ return 0;
+
+err_out:
+ osst_sysfs_destroy(dev);
+ return err;
+}
+
+static void osst_sysfs_cleanup(void)
+{
+ class_destroy(osst_sysfs_class);
+}
+
/*
* osst startup / cleanup code
*/
static int osst_probe(struct device *dev)
{
- Scsi_Device * SDp = to_scsi_device(dev);
- OS_Scsi_Tape * tpnt;
- ST_mode * STm;
- ST_partstat * STps;
- OSST_buffer * buffer;
- struct gendisk * drive;
- int i, mode, dev_num;
+ struct scsi_device * SDp = to_scsi_device(dev);
+ struct osst_tape * tpnt;
+ struct st_modedef * STm;
+ struct st_partstat * STps;
+ struct osst_buffer * buffer;
+ struct gendisk * drive;
+ int i, dev_num, err = -ENODEV;
if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
return -ENODEV;
write_lock(&os_scsi_tapes_lock);
if (os_scsi_tapes == NULL) {
os_scsi_tapes =
- (OS_Scsi_Tape **)kmalloc(osst_max_dev * sizeof(OS_Scsi_Tape *),
+ (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
GFP_ATOMIC);
if (os_scsi_tapes == NULL) {
write_unlock(&os_scsi_tapes_lock);
if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
dev_num = i;
- /* allocate a OS_Scsi_Tape for this device */
- tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
+ /* allocate a struct osst_tape for this device */
+ tpnt = kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
if (tpnt == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
goto out_put_disk;
}
- memset(tpnt, 0, sizeof(OS_Scsi_Tape));
+ memset(tpnt, 0, sizeof(struct osst_tape));
/* allocate a buffer for this device */
i = SDp->host->sg_tablesize;
if (osst_max_sg_segs < i)
i = osst_max_sg_segs;
- buffer = new_tape_buffer(TRUE, SDp->host->unchecked_isa_dma, i);
+ buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
if (buffer == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
for (i=0; i < ST_NBR_MODES; i++) {
STm = &(tpnt->modes[i]);
- STm->defined = FALSE;
+ STm->defined = 0;
STm->sysv = OSST_SYSV;
STm->defaults_for_writes = 0;
STm->do_async_writes = OSST_ASYNC_WRITES;
STps->rw = ST_IDLE;
STps->eof = ST_NOEOF;
STps->at_sm = 0;
- STps->last_block_valid = FALSE;
+ STps->last_block_valid = 0;
STps->drv_block = (-1);
STps->drv_file = (-1);
}
tpnt->current_mode = 0;
- tpnt->modes[0].defined = TRUE;
- tpnt->modes[2].defined = TRUE;
- tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = FALSE;
+ tpnt->modes[0].defined = 1;
+ tpnt->modes[2].defined = 1;
+ tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
init_MUTEX(&tpnt->lock);
osst_nr_dev++;
write_unlock(&os_scsi_tapes_lock);
- for (mode = 0; mode < ST_NBR_MODES; ++mode) {
+ {
+ char name[8];
+
/* Rewind entry */
- devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
- S_IFCHR | S_IRUGO | S_IWUGO,
- "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
+ err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
+ if (err)
+ goto out_free_buffer;
/* No-rewind entry */
- devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128),
- S_IFCHR | S_IRUGO | S_IWUGO,
- "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
+ snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
+ err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
+ if (err)
+ goto out_free_sysfs1;
}
- drive->number = devfs_register_tape(SDp->devfs_name);
- printk(KERN_INFO
- "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n",
- SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt));
+ sdev_printk(KERN_INFO, SDp,
+ "osst :I: Attached OnStream %.5s tape as %s\n",
+ SDp->model, tape_name(tpnt));
return 0;
+out_free_sysfs1:
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
+out_free_buffer:
+ kfree(buffer);
out_put_disk:
put_disk(drive);
- return -ENODEV;
+ return err;
};
static int osst_remove(struct device *dev)
{
- Scsi_Device * SDp = to_scsi_device(dev);
- OS_Scsi_Tape * tpnt;
- int i, mode;
+ struct scsi_device * SDp = to_scsi_device(dev);
+ struct osst_tape * tpnt;
+ int i;
if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
return 0;
write_lock(&os_scsi_tapes_lock);
for(i=0; i < osst_max_dev; i++) {
if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
tpnt->device = NULL;
- for (mode = 0; mode < ST_NBR_MODES; ++mode) {
- devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
- devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
- }
- devfs_unregister_tape(tpnt->drive->number);
put_disk(tpnt->drive);
os_scsi_tapes[i] = NULL;
osst_nr_dev--;
write_unlock(&os_scsi_tapes_lock);
- if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
+ vfree(tpnt->header_cache);
if (tpnt->buffer) {
normalize_buffer(tpnt->buffer);
kfree(tpnt->buffer);
static int __init init_osst(void)
{
+ int err;
+
printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
validate_options();
-
- if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
+
+ err = osst_sysfs_init();
+ if (err)
+ return err;
+
+ err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
+ if (err < 0) {
printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
- return 1;
+ goto err_out;
}
+ err = scsi_register_driver(&osst_template.gendrv);
+ if (err)
+ goto err_out_chrdev;
+
+ err = osst_create_driverfs_files(&osst_template.gendrv);
+ if (err)
+ goto err_out_scsidrv;
+
return 0;
+
+err_out_scsidrv:
+ scsi_unregister_driver(&osst_template.gendrv);
+err_out_chrdev:
+ unregister_chrdev(OSST_MAJOR, "osst");
+err_out:
+ osst_sysfs_cleanup();
+ return err;
}
static void __exit exit_osst (void)
{
int i;
- OS_Scsi_Tape * STp;
+ struct osst_tape * STp;
+ osst_remove_driverfs_files(&osst_template.gendrv);
scsi_unregister_driver(&osst_template.gendrv);
unregister_chrdev(OSST_MAJOR, "osst");
+ osst_sysfs_cleanup();
if (os_scsi_tapes) {
for (i=0; i < osst_max_dev; ++i) {
if (!(STp = os_scsi_tapes[i])) continue;
/* This is defensive, supposed to happen during detach */
- if (STp->header_cache)
- vfree(STp->header_cache);
+ vfree(STp->header_cache);
if (STp->buffer) {
normalize_buffer(STp->buffer);
kfree(STp->buffer);