Linux Audio

Check our new training course

Loading...
v3.1
   1/*
   2  SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
   3  file Documentation/scsi/st.txt for more information.
   4
   5  History:
   6
   7  OnStream SCSI Tape support (osst) cloned from st.c by
   8  Willem Riede (osst@riede.org) Feb 2000
   9  Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
  10
  11  Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
  12  Contribution and ideas from several people including (in alphabetical
  13  order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
  14  Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
  15
  16  Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
  17	 email osst@riede.org
  18
  19  $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
  20
  21  Microscopic alterations - Rik Ling, 2000/12/21
  22  Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
  23  Some small formal changes - aeb, 950809
  24*/
  25
  26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
  27static const char * osst_version = "0.99.4";
  28
  29/* The "failure to reconnect" firmware bug */
  30#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
  31#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
  32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
  33
  34#include <linux/module.h>
  35
  36#include <linux/fs.h>
  37#include <linux/kernel.h>
  38#include <linux/sched.h>
  39#include <linux/proc_fs.h>
  40#include <linux/mm.h>
  41#include <linux/slab.h>
  42#include <linux/init.h>
  43#include <linux/string.h>
  44#include <linux/errno.h>
  45#include <linux/mtio.h>
  46#include <linux/ioctl.h>
  47#include <linux/fcntl.h>
  48#include <linux/spinlock.h>
  49#include <linux/vmalloc.h>
  50#include <linux/blkdev.h>
  51#include <linux/moduleparam.h>
  52#include <linux/delay.h>
  53#include <linux/jiffies.h>
  54#include <linux/mutex.h>
  55#include <asm/uaccess.h>
  56#include <asm/dma.h>
  57#include <asm/system.h>
  58
  59/* The driver prints some debugging information on the console if DEBUG
  60   is defined and non-zero. */
  61#define DEBUG 0
  62
  63/* The message level for the debug messages is currently set to KERN_NOTICE
  64   so that people can easily see the messages. Later when the debugging messages
  65   in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
  66#define OSST_DEB_MSG  KERN_NOTICE
  67
  68#include <scsi/scsi.h>
  69#include <scsi/scsi_dbg.h>
  70#include <scsi/scsi_device.h>
  71#include <scsi/scsi_driver.h>
  72#include <scsi/scsi_eh.h>
  73#include <scsi/scsi_host.h>
  74#include <scsi/scsi_ioctl.h>
  75
  76#define ST_KILOBYTE 1024
  77
  78#include "st.h"
  79#include "osst.h"
  80#include "osst_options.h"
  81#include "osst_detect.h"
  82
  83static DEFINE_MUTEX(osst_int_mutex);
  84static int max_dev = 0;
  85static int write_threshold_kbs = 0;
  86static int max_sg_segs = 0;
  87
  88#ifdef MODULE
  89MODULE_AUTHOR("Willem Riede");
  90MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
  91MODULE_LICENSE("GPL");
  92MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
  93MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
  94
  95module_param(max_dev, int, 0444);
  96MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
  97
  98module_param(write_threshold_kbs, int, 0644);
  99MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
 100
 101module_param(max_sg_segs, int, 0644);
 102MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
 103#else
 104static struct osst_dev_parm {
 105       char   *name;
 106       int    *val;
 107} parms[] __initdata = {
 108       { "max_dev",             &max_dev             },
 109       { "write_threshold_kbs", &write_threshold_kbs },
 110       { "max_sg_segs",         &max_sg_segs         }
 111};
 112#endif
 113
 114/* Some default definitions have been moved to osst_options.h */
 115#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
 116#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
 117
 118/* The buffer size should fit into the 24 bits for length in the
 119   6-byte SCSI read and write commands. */
 120#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
 121#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
 122#endif
 123
 124#if DEBUG
 125static int debugging = 1;
 126/* uncomment define below to test error recovery */
 127// #define OSST_INJECT_ERRORS 1 
 128#endif
 129
 130/* Do not retry! The drive firmware already retries when appropriate,
 131   and when it tries to tell us something, we had better listen... */
 132#define MAX_RETRIES 0
 133
 134#define NO_TAPE  NOT_READY
 135
 136#define OSST_WAIT_POSITION_COMPLETE   (HZ > 200 ? HZ / 200 : 1)
 137#define OSST_WAIT_WRITE_COMPLETE      (HZ / 12)
 138#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
 139	
 140#define OSST_TIMEOUT (200 * HZ)
 141#define OSST_LONG_TIMEOUT (1800 * HZ)
 142
 143#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
 144#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
 145#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
 146#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
 147
 148/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
 149   24 bits) */
 150#define SET_DENS_AND_BLK 0x10001
 151
 152static int osst_buffer_size       = OSST_BUFFER_SIZE;
 153static int osst_write_threshold   = OSST_WRITE_THRESHOLD;
 154static int osst_max_sg_segs       = OSST_MAX_SG;
 155static int osst_max_dev           = OSST_MAX_TAPES;
 156static int osst_nr_dev;
 157
 158static struct osst_tape **os_scsi_tapes = NULL;
 159static DEFINE_RWLOCK(os_scsi_tapes_lock);
 160
 161static int modes_defined = 0;
 162
 163static struct osst_buffer *new_tape_buffer(int, int, int);
 164static int enlarge_buffer(struct osst_buffer *, int);
 165static void normalize_buffer(struct osst_buffer *);
 166static int append_to_buffer(const char __user *, struct osst_buffer *, int);
 167static int from_buffer(struct osst_buffer *, char __user *, int);
 168static int osst_zero_buffer_tail(struct osst_buffer *);
 169static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
 170static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
 171
 172static int osst_probe(struct device *);
 173static int osst_remove(struct device *);
 174
 175static struct scsi_driver osst_template = {
 176	.owner			= THIS_MODULE,
 177	.gendrv = {
 178		.name		=  "osst",
 179		.probe		= osst_probe,
 180		.remove		= osst_remove,
 181	}
 182};
 183
 184static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
 185			    unsigned int cmd_in, unsigned long arg);
 186
 187static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
 188
 189static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
 190
 191static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
 192
 193static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
 194
 195static inline char *tape_name(struct osst_tape *tape)
 196{
 197	return tape->drive->disk_name;
 198}
 199
 200/* Routines that handle the interaction with mid-layer SCSI routines */
 201
 202
 203/* Normalize Sense */
 204static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
 205{
 206	const u8 *ucp;
 207	const u8 *sense = SRpnt->sense;
 208
 209	s->have_sense = scsi_normalize_sense(SRpnt->sense,
 210				SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
 211	s->flags = 0;
 212
 213	if (s->have_sense) {
 214		s->deferred = 0;
 215		s->remainder_valid =
 216			scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
 217		switch (sense[0] & 0x7f) {
 218		case 0x71:
 219			s->deferred = 1;
 220		case 0x70:
 221			s->fixed_format = 1;
 222			s->flags = sense[2] & 0xe0;
 223			break;
 224		case 0x73:
 225			s->deferred = 1;
 226		case 0x72:
 227			s->fixed_format = 0;
 228			ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
 229			s->flags = ucp ? (ucp[3] & 0xe0) : 0;
 230			break;
 231		}
 232	}
 233}
 234
 235/* Convert the result to success code */
 236static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
 237{
 238	char *name = tape_name(STp);
 239	int result = SRpnt->result;
 240	u8 * sense = SRpnt->sense, scode;
 241#if DEBUG
 242	const char *stp;
 243#endif
 244	struct st_cmdstatus *cmdstatp;
 245
 246	if (!result)
 247		return 0;
 248
 249	cmdstatp = &STp->buffer->cmdstat;
 250	osst_analyze_sense(SRpnt, cmdstatp);
 251
 252	if (cmdstatp->have_sense)
 253		scode = STp->buffer->cmdstat.sense_hdr.sense_key;
 254	else
 255		scode = 0;
 256#if DEBUG
 257	if (debugging) {
 258		printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
 259		   name, result,
 260		   SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
 261		   SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
 262		if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
 263			       	name, scode, sense[12], sense[13]);
 264		if (cmdstatp->have_sense)
 265			__scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 266	}
 267	else
 268#endif
 269	if (cmdstatp->have_sense && (
 270		 scode != NO_SENSE &&
 271		 scode != RECOVERED_ERROR &&
 272/*      	 scode != UNIT_ATTENTION && */
 273		 scode != BLANK_CHECK &&
 274		 scode != VOLUME_OVERFLOW &&
 275		 SRpnt->cmd[0] != MODE_SENSE &&
 276		 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
 277		if (cmdstatp->have_sense) {
 278			printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
 279			__scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 280		}
 281		else {
 282			static	int	notyetprinted = 1;
 283
 284			printk(KERN_WARNING
 285			     "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
 286			     name, result, driver_byte(result),
 287			     host_byte(result));
 288			if (notyetprinted) {
 289				notyetprinted = 0;
 290				printk(KERN_INFO
 291					"%s:I: This warning may be caused by your scsi controller,\n", name);
 292				printk(KERN_INFO
 293					"%s:I: it has been reported with some Buslogic cards.\n", name);
 294			}
 295		}
 296	}
 297	STp->pos_unknown |= STp->device->was_reset;
 298
 299	if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
 300		STp->recover_count++;
 301		STp->recover_erreg++;
 302#if DEBUG
 303		if (debugging) {
 304			if (SRpnt->cmd[0] == READ_6)
 305				stp = "read";
 306			else if (SRpnt->cmd[0] == WRITE_6)
 307				stp = "write";
 308			else
 309				stp = "ioctl";
 310			printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
 311					     STp->recover_count);
 312		}
 313#endif
 314		if ((sense[2] & 0xe0) == 0)
 315			return 0;
 316	}
 317	return (-EIO);
 318}
 319
 320
 321/* Wakeup from interrupt */
 322static void osst_end_async(struct request *req, int update)
 323{
 324	struct osst_request *SRpnt = req->end_io_data;
 325	struct osst_tape *STp = SRpnt->stp;
 326	struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
 327
 328	STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
 329#if DEBUG
 330	STp->write_pending = 0;
 331#endif
 332	if (SRpnt->waiting)
 333		complete(SRpnt->waiting);
 334
 335	if (SRpnt->bio) {
 336		kfree(mdata->pages);
 337		blk_rq_unmap_user(SRpnt->bio);
 338	}
 339
 340	__blk_put_request(req->q, req);
 341}
 342
 343/* osst_request memory management */
 344static struct osst_request *osst_allocate_request(void)
 345{
 346	return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
 347}
 348
 349static void osst_release_request(struct osst_request *streq)
 350{
 351	kfree(streq);
 352}
 353
 354static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
 355			int cmd_len, int data_direction, void *buffer, unsigned bufflen,
 356			int use_sg, int timeout, int retries)
 357{
 358	struct request *req;
 359	struct page **pages = NULL;
 360	struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
 361
 362	int err = 0;
 363	int write = (data_direction == DMA_TO_DEVICE);
 364
 365	req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
 366	if (!req)
 367		return DRIVER_ERROR << 24;
 368
 369	req->cmd_type = REQ_TYPE_BLOCK_PC;
 370	req->cmd_flags |= REQ_QUIET;
 371
 372	SRpnt->bio = NULL;
 373
 374	if (use_sg) {
 375		struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
 376		int i;
 377
 378		pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
 379		if (!pages)
 380			goto free_req;
 381
 382		for_each_sg(sgl, sg, use_sg, i)
 383			pages[i] = sg_page(sg);
 384
 385		mdata->null_mapped = 1;
 386
 387		mdata->page_order = get_order(sgl[0].length);
 388		mdata->nr_entries =
 389			DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
 390		mdata->offset = 0;
 391
 392		err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
 393		if (err) {
 394			kfree(pages);
 395			goto free_req;
 396		}
 397		SRpnt->bio = req->bio;
 398		mdata->pages = pages;
 399
 400	} else if (bufflen) {
 401		err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
 402		if (err)
 403			goto free_req;
 404	}
 405
 406	req->cmd_len = cmd_len;
 407	memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
 408	memcpy(req->cmd, cmd, req->cmd_len);
 409	req->sense = SRpnt->sense;
 410	req->sense_len = 0;
 411	req->timeout = timeout;
 412	req->retries = retries;
 413	req->end_io_data = SRpnt;
 414
 415	blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
 416	return 0;
 417free_req:
 418	blk_put_request(req);
 419	return DRIVER_ERROR << 24;
 420}
 421
 422/* Do the scsi command. Waits until command performed if do_wait is true.
 423   Otherwise osst_write_behind_check() is used to check that the command
 424   has finished. */
 425static	struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp, 
 426	unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
 427{
 428	unsigned char *bp;
 429	unsigned short use_sg;
 430#ifdef OSST_INJECT_ERRORS
 431	static   int   inject = 0;
 432	static   int   repeat = 0;
 433#endif
 434	struct completion *waiting;
 435
 436	/* if async, make sure there's no command outstanding */
 437	if (!do_wait && ((STp->buffer)->last_SRpnt)) {
 438		printk(KERN_ERR "%s: Async command already active.\n",
 439		       tape_name(STp));
 440		if (signal_pending(current))
 441			(STp->buffer)->syscall_result = (-EINTR);
 442		else
 443			(STp->buffer)->syscall_result = (-EBUSY);
 444		return NULL;
 445	}
 446
 447	if (SRpnt == NULL) {
 448		SRpnt = osst_allocate_request();
 449		if (SRpnt == NULL) {
 450			printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
 451				     tape_name(STp));
 452			if (signal_pending(current))
 453				(STp->buffer)->syscall_result = (-EINTR);
 454			else
 455				(STp->buffer)->syscall_result = (-EBUSY);
 456			return NULL;
 457		}
 458		SRpnt->stp = STp;
 459	}
 460
 461	/* If async IO, set last_SRpnt. This ptr tells write_behind_check
 462	   which IO is outstanding. It's nulled out when the IO completes. */
 463	if (!do_wait)
 464		(STp->buffer)->last_SRpnt = SRpnt;
 465
 466	waiting = &STp->wait;
 467	init_completion(waiting);
 468	SRpnt->waiting = waiting;
 469
 470	use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
 471	if (use_sg) {
 472		bp = (char *)&(STp->buffer->sg[0]);
 473		if (STp->buffer->sg_segs < use_sg)
 474			use_sg = STp->buffer->sg_segs;
 475	}
 476	else
 477		bp = (STp->buffer)->b_data;
 478
 479	memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
 480	STp->buffer->cmdstat.have_sense = 0;
 481	STp->buffer->syscall_result = 0;
 482
 483	if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
 484			 use_sg, timeout, retries))
 485		/* could not allocate the buffer or request was too large */
 486		(STp->buffer)->syscall_result = (-EBUSY);
 487	else if (do_wait) {
 488		wait_for_completion(waiting);
 489		SRpnt->waiting = NULL;
 490		STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
 491#ifdef OSST_INJECT_ERRORS
 492		if (STp->buffer->syscall_result == 0 &&
 493		    cmd[0] == READ_6 &&
 494		    cmd[4] && 
 495		    ( (++ inject % 83) == 29  ||
 496		      (STp->first_frame_position == 240 
 497			         /* or STp->read_error_frame to fail again on the block calculated above */ &&
 498				 ++repeat < 3))) {
 499			printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
 500			STp->buffer->last_result_fatal = 1;
 501		}
 502#endif
 503	}
 504	return SRpnt;
 505}
 506
 507
 508/* Handle the write-behind checking (downs the semaphore) */
 509static void osst_write_behind_check(struct osst_tape *STp)
 510{
 511	struct osst_buffer * STbuffer;
 512
 513	STbuffer = STp->buffer;
 514
 515#if DEBUG
 516	if (STp->write_pending)
 517		STp->nbr_waits++;
 518	else
 519		STp->nbr_finished++;
 520#endif
 521	wait_for_completion(&(STp->wait));
 522	STp->buffer->last_SRpnt->waiting = NULL;
 523
 524	STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
 525
 526	if (STp->buffer->syscall_result)
 527		STp->buffer->syscall_result =
 528			osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
 529	else
 530		STp->first_frame_position++;
 531
 532	osst_release_request(STp->buffer->last_SRpnt);
 533
 534	if (STbuffer->writing < STbuffer->buffer_bytes)
 535		printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
 536
 537	STbuffer->last_SRpnt = NULL;
 538	STbuffer->buffer_bytes -= STbuffer->writing;
 539	STbuffer->writing = 0;
 540
 541	return;
 542}
 543
 544
 545
 546/* Onstream specific Routines */
 547/*
 548 * Initialize the OnStream AUX
 549 */
 550static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
 551					 int logical_blk_num, int blk_sz, int blk_cnt)
 552{
 553	os_aux_t       *aux = STp->buffer->aux;
 554	os_partition_t *par = &aux->partition;
 555	os_dat_t       *dat = &aux->dat;
 556
 557	if (STp->raw) return;
 558
 559	memset(aux, 0, sizeof(*aux));
 560	aux->format_id = htonl(0);
 561	memcpy(aux->application_sig, "LIN4", 4);
 562	aux->hdwr = htonl(0);
 563	aux->frame_type = frame_type;
 564
 565	switch (frame_type) {
 566	  case	OS_FRAME_TYPE_HEADER:
 567		aux->update_frame_cntr    = htonl(STp->update_frame_cntr);
 568		par->partition_num        = OS_CONFIG_PARTITION;
 569		par->par_desc_ver         = OS_PARTITION_VERSION;
 570		par->wrt_pass_cntr        = htons(0xffff);
 571		/* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
 572		par->first_frame_ppos     = htonl(0);
 573		par->last_frame_ppos      = htonl(0xbb7);
 574		aux->frame_seq_num        = htonl(0);
 575		aux->logical_blk_num_high = htonl(0);
 576		aux->logical_blk_num      = htonl(0);
 577		aux->next_mark_ppos       = htonl(STp->first_mark_ppos);
 578		break;
 579	  case	OS_FRAME_TYPE_DATA:
 580	  case	OS_FRAME_TYPE_MARKER:
 581		dat->dat_sz = 8;
 582		dat->reserved1 = 0;
 583		dat->entry_cnt = 1;
 584		dat->reserved3 = 0;
 585		dat->dat_list[0].blk_sz   = htonl(blk_sz);
 586		dat->dat_list[0].blk_cnt  = htons(blk_cnt);
 587		dat->dat_list[0].flags    = frame_type==OS_FRAME_TYPE_MARKER?
 588							OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
 589		dat->dat_list[0].reserved = 0;
 590	  case	OS_FRAME_TYPE_EOD:
 591		aux->update_frame_cntr    = htonl(0);
 592		par->partition_num        = OS_DATA_PARTITION;
 593		par->par_desc_ver         = OS_PARTITION_VERSION;
 594		par->wrt_pass_cntr        = htons(STp->wrt_pass_cntr);
 595		par->first_frame_ppos     = htonl(STp->first_data_ppos);
 596		par->last_frame_ppos      = htonl(STp->capacity);
 597		aux->frame_seq_num        = htonl(frame_seq_number);
 598		aux->logical_blk_num_high = htonl(0);
 599		aux->logical_blk_num      = htonl(logical_blk_num);
 600		break;
 601	  default: ; /* probably FILL */
 602	}
 603	aux->filemark_cnt = htonl(STp->filemark_cnt);
 604	aux->phys_fm = htonl(0xffffffff);
 605	aux->last_mark_ppos = htonl(STp->last_mark_ppos);
 606	aux->last_mark_lbn  = htonl(STp->last_mark_lbn);
 607}
 608
 609/*
 610 * Verify that we have the correct tape frame
 611 */
 612static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
 613{
 614	char               * name = tape_name(STp);
 615	os_aux_t           * aux  = STp->buffer->aux;
 616	os_partition_t     * par  = &(aux->partition);
 617	struct st_partstat * STps = &(STp->ps[STp->partition]);
 618	int		     blk_cnt, blk_sz, i;
 619
 620	if (STp->raw) {
 621		if (STp->buffer->syscall_result) {
 622			for (i=0; i < STp->buffer->sg_segs; i++)
 623				memset(page_address(sg_page(&STp->buffer->sg[i])),
 624				       0, STp->buffer->sg[i].length);
 625			strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
 626                } else
 627			STp->buffer->buffer_bytes = OS_FRAME_SIZE;
 628		return 1;
 629	}
 630	if (STp->buffer->syscall_result) {
 631#if DEBUG
 632		printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
 633#endif
 634		return 0;
 635	}
 636	if (ntohl(aux->format_id) != 0) {
 637#if DEBUG
 638		printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
 639#endif
 640		goto err_out;
 641	}
 642	if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
 643	    (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
 644#if DEBUG
 645		printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
 646#endif
 647		goto err_out;
 648	}
 649	if (par->partition_num != OS_DATA_PARTITION) {
 650		if (!STp->linux_media || STp->linux_media_version != 2) {
 651#if DEBUG
 652			printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
 653					    name, par->partition_num);
 654#endif
 655			goto err_out;
 656		}
 657	}
 658	if (par->par_desc_ver != OS_PARTITION_VERSION) {
 659#if DEBUG
 660		printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
 661#endif
 662		goto err_out;
 663	}
 664	if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
 665#if DEBUG
 666		printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", 
 667				    name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
 668#endif
 669		goto err_out;
 670	}
 671	if (aux->frame_type != OS_FRAME_TYPE_DATA &&
 672	    aux->frame_type != OS_FRAME_TYPE_EOD &&
 673	    aux->frame_type != OS_FRAME_TYPE_MARKER) {
 674		if (!quiet) {
 675#if DEBUG
 676			printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
 677#endif
 678		}
 679		goto err_out;
 680	}
 681	if (aux->frame_type == OS_FRAME_TYPE_EOD &&
 682	    STp->first_frame_position < STp->eod_frame_ppos) {
 683		printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
 684				 STp->first_frame_position);
 685		goto err_out;
 686	}
 687        if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
 688		if (!quiet) {
 689#if DEBUG
 690			printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n", 
 691					    name, ntohl(aux->frame_seq_num), frame_seq_number);
 692#endif
 693		}
 694		goto err_out;
 695	}
 696	if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
 697		STps->eof = ST_FM_HIT;
 698
 699		i = ntohl(aux->filemark_cnt);
 700		if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
 701		    STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
 702#if DEBUG
 703			printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
 704				  STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
 705				  i, STp->first_frame_position - 1);
 706#endif
 707			STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
 708			if (i >= STp->filemark_cnt)
 709				 STp->filemark_cnt = i+1;
 710		}
 711	}
 712	if (aux->frame_type == OS_FRAME_TYPE_EOD) {
 713		STps->eof = ST_EOD_1;
 714		STp->frame_in_buffer = 1;
 715	}
 716	if (aux->frame_type == OS_FRAME_TYPE_DATA) {
 717                blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
 718		blk_sz  = ntohl(aux->dat.dat_list[0].blk_sz);
 719		STp->buffer->buffer_bytes = blk_cnt * blk_sz;
 720		STp->buffer->read_pointer = 0;
 721		STp->frame_in_buffer = 1;
 722
 723		/* See what block size was used to write file */
 724		if (STp->block_size != blk_sz && blk_sz > 0) {
 725			printk(KERN_INFO
 726	    	"%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
 727       				name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
 728				STp->block_size<1024?STp->block_size:STp->block_size/1024,
 729				STp->block_size<1024?'b':'k');
 730			STp->block_size            = blk_sz;
 731			STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
 732		}
 733		STps->eof = ST_NOEOF;
 734	}
 735        STp->frame_seq_number = ntohl(aux->frame_seq_num);
 736	STp->logical_blk_num  = ntohl(aux->logical_blk_num);
 737	return 1;
 738
 739err_out:
 740	if (STp->read_error_frame == 0)
 741		STp->read_error_frame = STp->first_frame_position - 1;
 742	return 0;
 743}
 744
 745/*
 746 * Wait for the unit to become Ready
 747 */
 748static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
 749				 unsigned timeout, int initial_delay)
 750{
 751	unsigned char		cmd[MAX_COMMAND_SIZE];
 752	struct osst_request   * SRpnt;
 753	unsigned long		startwait = jiffies;
 754#if DEBUG
 755	int			dbg  = debugging;
 756	char    	      * name = tape_name(STp);
 757
 758	printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
 759#endif
 760
 761	if (initial_delay > 0)
 762		msleep(jiffies_to_msecs(initial_delay));
 763
 764	memset(cmd, 0, MAX_COMMAND_SIZE);
 765	cmd[0] = TEST_UNIT_READY;
 766
 767	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 768	*aSRpnt = SRpnt;
 769	if (!SRpnt) return (-EBUSY);
 770
 771	while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 772	       (( SRpnt->sense[2]  == 2 && SRpnt->sense[12] == 4    &&
 773		 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)    ) ||
 774		( SRpnt->sense[2]  == 6 && SRpnt->sense[12] == 0x28 &&
 775		  SRpnt->sense[13] == 0                                        )  )) {
 776#if DEBUG
 777	    if (debugging) {
 778		printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
 779		printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 780		debugging = 0;
 781	    }
 782#endif
 783	    msleep(100);
 784
 785	    memset(cmd, 0, MAX_COMMAND_SIZE);
 786	    cmd[0] = TEST_UNIT_READY;
 787
 788	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 789	}
 790	*aSRpnt = SRpnt;
 791#if DEBUG
 792	debugging = dbg;
 793#endif
 794	if ( STp->buffer->syscall_result &&
 795	     osst_write_error_recovery(STp, aSRpnt, 0) ) {
 796#if DEBUG
 797	    printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
 798	    printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 799			STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 800			SRpnt->sense[12], SRpnt->sense[13]);
 801#endif
 802	    return (-EIO);
 803	}
 804#if DEBUG
 805	printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
 806#endif
 807	return 0;
 808}
 809
 810/*
 811 * Wait for a tape to be inserted in the unit
 812 */
 813static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
 814{
 815	unsigned char		cmd[MAX_COMMAND_SIZE];
 816	struct osst_request   * SRpnt;
 817	unsigned long		startwait = jiffies;
 818#if DEBUG
 819	int			dbg = debugging;
 820	char    	      * name = tape_name(STp);
 821
 822	printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
 823#endif
 824
 825	memset(cmd, 0, MAX_COMMAND_SIZE);
 826	cmd[0] = TEST_UNIT_READY;
 827
 828	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 829	*aSRpnt = SRpnt;
 830	if (!SRpnt) return (-EBUSY);
 831
 832	while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 833		SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0  ) {
 834#if DEBUG
 835	    if (debugging) {
 836		printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
 837		printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 838		debugging = 0;
 839	    }
 840#endif
 841	    msleep(100);
 842
 843	    memset(cmd, 0, MAX_COMMAND_SIZE);
 844	    cmd[0] = TEST_UNIT_READY;
 845
 846	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 847	}
 848	*aSRpnt = SRpnt;
 849#if DEBUG
 850	debugging = dbg;
 851#endif
 852	if ( STp->buffer->syscall_result     && SRpnt->sense[2]  != 2 &&
 853	     SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
 854#if DEBUG
 855	    printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
 856	    printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 857			STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 858			SRpnt->sense[12], SRpnt->sense[13]);
 859#endif
 860	    return 0;
 861	}
 862#if DEBUG
 863	printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
 864#endif
 865	return 1;
 866}
 867
 868static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
 869{
 870	int	retval;
 871
 872	osst_wait_ready(STp, aSRpnt, 15 * 60, 0);			/* TODO - can this catch a write error? */
 873	retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
 874	if (retval) return (retval);
 875	osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
 876	return (osst_get_frame_position(STp, aSRpnt));
 877}
 878
 879/*
 880 * Wait for write(s) to complete
 881 */
 882static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
 883{
 884	unsigned char		cmd[MAX_COMMAND_SIZE];
 885	struct osst_request   * SRpnt;
 886	int			result = 0;
 887	int			delay  = OSST_WAIT_WRITE_COMPLETE;
 888#if DEBUG
 889	char		      * name = tape_name(STp);
 890
 891	printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
 892#endif
 893
 894	memset(cmd, 0, MAX_COMMAND_SIZE);
 895	cmd[0] = WRITE_FILEMARKS;
 896	cmd[1] = 1;
 897
 898	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 899	*aSRpnt = SRpnt;
 900	if (!SRpnt) return (-EBUSY);
 901	if (STp->buffer->syscall_result) {
 902		if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
 903			if (SRpnt->sense[13] == 8) {
 904				delay = OSST_WAIT_LONG_WRITE_COMPLETE;
 905			}
 906		} else
 907			result = osst_write_error_recovery(STp, aSRpnt, 0);
 908	}
 909	result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
 910	STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
 911
 912	return (result);
 913}
 914
 915#define OSST_POLL_PER_SEC 10
 916static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
 917{
 918	unsigned long	startwait = jiffies;
 919	char	      * name      = tape_name(STp);
 920#if DEBUG
 921	char	   notyetprinted  = 1;
 922#endif
 923	if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
 924		printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
 925
 926	while (time_before (jiffies, startwait + to*HZ))
 927	{ 
 928		int result;
 929		result = osst_get_frame_position(STp, aSRpnt);
 930		if (result == -EIO)
 931			if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
 932				return 0;	/* successful recovery leaves drive ready for frame */
 933		if (result < 0) break;
 934		if (STp->first_frame_position == curr &&
 935		    ((minlast < 0 &&
 936		      (signed)STp->last_frame_position > (signed)curr + minlast) ||
 937		     (minlast >= 0 && STp->cur_frames > minlast)
 938		    ) && result >= 0)
 939		{
 940#if DEBUG			
 941			if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
 942				printk (OSST_DEB_MSG
 943					"%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
 944					name, curr, curr+minlast, STp->first_frame_position,
 945					STp->last_frame_position, STp->cur_frames,
 946					result, (jiffies-startwait)/HZ, 
 947					(((jiffies-startwait)%HZ)*10)/HZ);
 948#endif
 949			return 0;
 950		}
 951#if DEBUG
 952		if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
 953		{
 954			printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
 955				name, curr, curr+minlast, STp->first_frame_position,
 956				STp->last_frame_position, STp->cur_frames, result);
 957			notyetprinted--;
 958		}
 959#endif
 960		msleep(1000 / OSST_POLL_PER_SEC);
 961	}
 962#if DEBUG
 963	printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
 964		name, curr, curr+minlast, STp->first_frame_position,
 965		STp->last_frame_position, STp->cur_frames,
 966		(jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
 967#endif	
 968	return -EBUSY;
 969}
 970
 971static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
 972{
 973	struct osst_request   * SRpnt;
 974	unsigned char		cmd[MAX_COMMAND_SIZE];
 975	unsigned long   	startwait = jiffies;
 976	int			retval    = 1;
 977        char		      * name      = tape_name(STp);
 978                                                                                                                                
 979	if (writing) {
 980		char	mybuf[24];
 981		char  * olddata = STp->buffer->b_data;
 982		int	oldsize = STp->buffer->buffer_size;
 983
 984		/* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
 985
 986		memset(cmd, 0, MAX_COMMAND_SIZE);
 987		cmd[0] = WRITE_FILEMARKS;
 988		cmd[1] = 1;
 989		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
 990								MAX_RETRIES, 1);
 991
 992		while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
 993
 994			if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
 995
 996				/* some failure - not just not-ready */
 997				retval = osst_write_error_recovery(STp, aSRpnt, 0);
 998				break;
 999			}
1000			schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
1001
1002			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1003			memset(cmd, 0, MAX_COMMAND_SIZE);
1004			cmd[0] = READ_POSITION;
1005
1006			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1007										MAX_RETRIES, 1);
1008
1009			retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1010			STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1011		}
1012		if (retval)
1013			printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1014	} else
1015		/* TODO - figure out which error conditions can be handled */
1016		if (STp->buffer->syscall_result)
1017			printk(KERN_WARNING
1018				"%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1019					(*aSRpnt)->sense[ 2] & 0x0f,
1020					(*aSRpnt)->sense[12],
1021					(*aSRpnt)->sense[13]);
1022
1023	return retval;
1024}
1025
1026/*
1027 * Read the next OnStream tape frame at the current location
1028 */
1029static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1030{
1031	unsigned char		cmd[MAX_COMMAND_SIZE];
1032	struct osst_request   * SRpnt;
1033	int			retval = 0;
1034#if DEBUG
1035	os_aux_t	      * aux    = STp->buffer->aux;
1036	char		      * name   = tape_name(STp);
1037#endif
1038
1039	if (STp->poll)
1040		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1041			retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1042
1043	memset(cmd, 0, MAX_COMMAND_SIZE);
1044	cmd[0] = READ_6;
1045	cmd[1] = 1;
1046	cmd[4] = 1;
1047
1048#if DEBUG
1049	if (debugging)
1050		printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1051#endif
1052	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1053				      STp->timeout, MAX_RETRIES, 1);
1054	*aSRpnt = SRpnt;
1055	if (!SRpnt)
1056		return (-EBUSY);
1057
1058	if ((STp->buffer)->syscall_result) {
1059	    retval = 1;
1060	    if (STp->read_error_frame == 0) {
1061		STp->read_error_frame = STp->first_frame_position;
1062#if DEBUG
1063		printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1064#endif
1065	    }
1066#if DEBUG
1067	    if (debugging)
1068		printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1069		   name,
1070		   SRpnt->sense[0], SRpnt->sense[1],
1071		   SRpnt->sense[2], SRpnt->sense[3],
1072		   SRpnt->sense[4], SRpnt->sense[5],
1073		   SRpnt->sense[6], SRpnt->sense[7]);
1074#endif
1075	}
1076	else
1077	    STp->first_frame_position++;
1078#if DEBUG
1079	if (debugging) {
1080	   char sig[8]; int i;
1081	   for (i=0;i<4;i++)
1082		   sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1083	   sig[4] = '\0';
1084	   printk(OSST_DEB_MSG 
1085		"%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1086			ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1087			aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1088			aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", 
1089			ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1090			ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1091	   if (aux->frame_type==2)
1092		printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1093			ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1094	   printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1095	}
1096#endif
1097	return (retval);
1098}
1099
1100static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1101{
1102	struct st_partstat    * STps   = &(STp->ps[STp->partition]);
1103	struct osst_request   * SRpnt  ;
1104	unsigned char		cmd[MAX_COMMAND_SIZE];
1105	int			retval = 0;
1106	char		      * name   = tape_name(STp);
1107
1108	if (STps->rw != ST_READING) {         /* Initialize read operation */
1109		if (STps->rw == ST_WRITING || STp->dirty) {
1110			STp->write_type = OS_WRITE_DATA;
1111                        osst_flush_write_buffer(STp, aSRpnt);
1112			osst_flush_drive_buffer(STp, aSRpnt);
1113		}
1114		STps->rw = ST_READING;
1115		STp->frame_in_buffer = 0;
1116
1117		/*
1118		 *      Issue a read 0 command to get the OnStream drive
1119                 *      read frames into its buffer.
1120		 */
1121		memset(cmd, 0, MAX_COMMAND_SIZE);
1122		cmd[0] = READ_6;
1123		cmd[1] = 1;
1124
1125#if DEBUG
1126		printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1127#endif
1128		SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1129		*aSRpnt = SRpnt;
1130		if ((retval = STp->buffer->syscall_result))
1131			printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1132	}
1133
1134	return retval;
1135}
1136
1137static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1138						int frame_seq_number, int quiet)
1139{
1140	struct st_partstat * STps  = &(STp->ps[STp->partition]);
1141	char		   * name  = tape_name(STp);
1142	int		     cnt   = 0,
1143			     bad   = 0,
1144			     past  = 0,
1145			     x,
1146			     position;
1147
1148	/*
1149	 * If we want just any frame (-1) and there is a frame in the buffer, return it
1150	 */
1151	if (frame_seq_number == -1 && STp->frame_in_buffer) {
1152#if DEBUG
1153		printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1154#endif
1155		return (STps->eof);
1156	}
1157	/*
1158         * Search and wait for the next logical tape frame
1159	 */
1160	while (1) {
1161		if (cnt++ > 400) {
1162                        printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1163					    name, frame_seq_number);
1164			if (STp->read_error_frame) {
1165				osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1166#if DEBUG
1167                        	printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1168						    name, STp->read_error_frame);
1169#endif
1170				STp->read_error_frame = 0;
1171				STp->abort_count++;
1172			}
1173			return (-EIO);
1174		}
1175#if DEBUG
1176		if (debugging)
1177			printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1178					  name, frame_seq_number, cnt);
1179#endif
1180		if ( osst_initiate_read(STp, aSRpnt)
1181                || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1182			if (STp->raw)
1183				return (-EIO);
1184			position = osst_get_frame_position(STp, aSRpnt);
1185			if (position >= 0xbae && position < 0xbb8)
1186				position = 0xbb8;
1187			else if (position > STp->eod_frame_ppos || ++bad == 10) {
1188				position = STp->read_error_frame - 1;
1189				bad = 0;
1190			}
1191			else {
1192				position += 29;
1193				cnt      += 19;
1194			}
1195#if DEBUG
1196			printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1197					 name, position);
1198#endif
1199			osst_set_frame_position(STp, aSRpnt, position, 0);
1200			continue;
1201		}
1202		if (osst_verify_frame(STp, frame_seq_number, quiet))
1203			break;
1204		if (osst_verify_frame(STp, -1, quiet)) {
1205			x = ntohl(STp->buffer->aux->frame_seq_num);
1206			if (STp->fast_open) {
1207				printk(KERN_WARNING
1208				       "%s:W: Found logical frame %d instead of %d after fast open\n",
1209				       name, x, frame_seq_number);
1210				STp->header_ok = 0;
1211				STp->read_error_frame = 0;
1212				return (-EIO);
1213			}
1214			if (x > frame_seq_number) {
1215				if (++past > 3) {
1216					/* positioning backwards did not bring us to the desired frame */
1217					position = STp->read_error_frame - 1;
1218				}
1219				else {
1220			        	position = osst_get_frame_position(STp, aSRpnt)
1221					         + frame_seq_number - x - 1;
1222
1223					if (STp->first_frame_position >= 3000 && position < 3000)
1224						position -= 10;
1225				}
1226#if DEBUG
1227                                printk(OSST_DEB_MSG
1228				       "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1229						name, x, frame_seq_number,
1230					       	STp->first_frame_position - position);
1231#endif
1232                        	osst_set_frame_position(STp, aSRpnt, position, 0);
1233				cnt += 10;
1234			}
1235			else
1236				past = 0;
1237		}
1238		if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1239#if DEBUG
1240			printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1241#endif
1242			osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1243			cnt--;
1244		}
1245		STp->frame_in_buffer = 0;
1246	}
1247	if (cnt > 1) {
1248		STp->recover_count++;
1249		STp->recover_erreg++;
1250		printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n", 
1251					name, STp->read_error_frame);
1252 	}
1253	STp->read_count++;
1254
1255#if DEBUG
1256	if (debugging || STps->eof)
1257		printk(OSST_DEB_MSG
1258			"%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1259			name, frame_seq_number, STp->frame_seq_number, STps->eof);
1260#endif
1261	STp->fast_open = 0;
1262	STp->read_error_frame = 0;
1263	return (STps->eof);
1264}
1265
1266static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1267{
1268        struct st_partstat * STps = &(STp->ps[STp->partition]);
1269	char		   * name = tape_name(STp);
1270	int	retries    = 0;
1271	int	frame_seq_estimate, ppos_estimate, move;
1272	
1273	if (logical_blk_num < 0) logical_blk_num = 0;
1274#if DEBUG
1275	printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1276				name, logical_blk_num, STp->logical_blk_num, 
1277				STp->block_size<1024?STp->block_size:STp->block_size/1024,
1278				STp->block_size<1024?'b':'k');
1279#endif
1280	/* Do we know where we are? */
1281	if (STps->drv_block >= 0) {
1282		move                = logical_blk_num - STp->logical_blk_num;
1283		if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1284		move               /= (OS_DATA_SIZE / STp->block_size);
1285		frame_seq_estimate  = STp->frame_seq_number + move;
1286	} else
1287		frame_seq_estimate  = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1288
1289	if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1290	else			       ppos_estimate = frame_seq_estimate + 20;
1291	while (++retries < 10) {
1292	   if (ppos_estimate > STp->eod_frame_ppos-2) {
1293	       frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1294	       ppos_estimate       = STp->eod_frame_ppos - 2;
1295	   }
1296	   if (frame_seq_estimate < 0) {
1297	       frame_seq_estimate = 0;
1298	       ppos_estimate      = 10;
1299	   }
1300	   osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1301	   if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1302	      /* we've located the estimated frame, now does it have our block? */
1303	      if (logical_blk_num <  STp->logical_blk_num ||
1304	          logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1305		 if (STps->eof == ST_FM_HIT)
1306		    move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1307		 else {
1308		    move                = logical_blk_num - STp->logical_blk_num;
1309		    if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1310		    move               /= (OS_DATA_SIZE / STp->block_size);
1311		 }
1312		 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1313#if DEBUG
1314		 printk(OSST_DEB_MSG
1315			"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1316				name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1317				STp->logical_blk_num, logical_blk_num, move);
1318#endif
1319		 frame_seq_estimate += move;
1320		 ppos_estimate      += move;
1321		 continue;
1322	      } else {
1323		 STp->buffer->read_pointer  = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1324		 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1325		 STp->logical_blk_num       =  logical_blk_num;
1326#if DEBUG
1327		 printk(OSST_DEB_MSG 
1328			"%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1329				name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer, 
1330				STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size, 
1331				STp->block_size);
1332#endif
1333		 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1334		 if (STps->eof == ST_FM_HIT) {
1335		     STps->drv_file++;
1336		     STps->drv_block = 0;
1337		 } else {
1338		     STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1339					  STp->logical_blk_num -
1340					     (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1341					-1;
1342		 }
1343		 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1344		 return 0;
1345	      }
1346	   }
1347	   if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1348	      goto error;
1349	   /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1350#if DEBUG
1351	   printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n", 
1352			   name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1353			   STp->logical_blk_num, logical_blk_num);
1354#endif
1355	   if (frame_seq_estimate != STp->frame_seq_number)
1356	      ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1357	   else
1358	      break;
1359	}
1360error:
1361	printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n", 
1362			    name, logical_blk_num, STp->logical_blk_num, retries);
1363	return (-EIO);
1364}
1365
1366/* The values below are based on the OnStream frame payload size of 32K == 2**15,
1367 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1368 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1369 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1370 */
1371#define OSST_FRAME_SHIFT  6
1372#define OSST_SECTOR_SHIFT 9
1373#define OSST_SECTOR_MASK  0x03F
1374
1375static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1376{
1377	int	sector;
1378#if DEBUG
1379	char  * name = tape_name(STp);
1380	
1381	printk(OSST_DEB_MSG 
1382		"%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1383		name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1384		STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block, 
1385		STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1386		STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1387		STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1388#endif
1389	/* do we know where we are inside a file? */
1390	if (STp->ps[STp->partition].drv_block >= 0) {
1391		sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1392				STp->first_frame_position) << OSST_FRAME_SHIFT;
1393		if (STp->ps[STp->partition].rw == ST_WRITING)
1394		       	sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1395		else
1396	       		sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1397	} else {
1398		sector = osst_get_frame_position(STp, aSRpnt);
1399		if (sector > 0)
1400			sector <<= OSST_FRAME_SHIFT;
1401	}
1402	return sector;
1403}
1404
1405static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1406{
1407        struct st_partstat * STps   = &(STp->ps[STp->partition]);
1408	int		     frame  = sector >> OSST_FRAME_SHIFT,
1409			     offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
1410			     r;
1411#if DEBUG
1412	char          * name = tape_name(STp);
1413
1414	printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1415				name, sector, frame, offset);
1416#endif
1417	if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1418
1419	if (frame <= STp->first_data_ppos) {
1420		STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1421		return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1422	}
1423	r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1424	if (r < 0) return r;
1425
1426	r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1427	if (r < 0) return r;
1428
1429	if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1430
1431	if (offset) {
1432		STp->logical_blk_num      += offset / STp->block_size;
1433		STp->buffer->read_pointer  = offset;
1434		STp->buffer->buffer_bytes -= offset;
1435	} else {
1436		STp->frame_seq_number++;
1437		STp->frame_in_buffer       = 0;
1438		STp->logical_blk_num      += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1439		STp->buffer->buffer_bytes  = STp->buffer->read_pointer = 0;
1440	}
1441	STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1442	if (STps->eof == ST_FM_HIT) {
1443		STps->drv_file++;
1444		STps->drv_block = 0;
1445	} else {
1446		STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1447				    STp->logical_blk_num -
1448					(STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1449				  -1;
1450	}
1451	STps->eof       = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1452#if DEBUG
1453	printk(OSST_DEB_MSG 
1454		"%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1455		name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1456		STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1457#endif
1458	return 0;
1459}
1460
1461/*
1462 * Read back the drive's internal buffer contents, as a part
1463 * of the write error recovery mechanism for old OnStream
1464 * firmware revisions.
1465 * Precondition for this function to work: all frames in the
1466 * drive's buffer must be of one type (DATA, MARK or EOD)!
1467 */
1468static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1469						unsigned int frame, unsigned int skip, int pending)
1470{
1471	struct osst_request   * SRpnt = * aSRpnt;
1472	unsigned char	      * buffer, * p;
1473	unsigned char		cmd[MAX_COMMAND_SIZE];
1474	int			flag, new_frame, i;
1475	int			nframes          = STp->cur_frames;
1476	int			blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1477	int			frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1478						- (nframes + pending - 1);
1479	int			logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
1480						- (nframes + pending - 1) * blks_per_frame;
1481	char		      * name             = tape_name(STp);
1482	unsigned long		startwait        = jiffies;
1483#if DEBUG
1484	int			dbg              = debugging;
1485#endif
1486
1487	if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1488		return (-EIO);
1489
1490	printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1491			 name, nframes, pending?" and one that was pending":"");
1492
1493	osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1494#if DEBUG
1495	if (pending && debugging)
1496		printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1497				name, frame_seq_number + nframes,
1498			       	logical_blk_num + nframes * blks_per_frame,
1499			       	p[0], p[1], p[2], p[3]);
1500#endif
1501	for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1502
1503		memset(cmd, 0, MAX_COMMAND_SIZE);
1504		cmd[0] = 0x3C;		/* Buffer Read           */
1505		cmd[1] = 6;		/* Retrieve Faulty Block */
1506		cmd[7] = 32768 >> 8;
1507		cmd[8] = 32768 & 0xff;
1508
1509		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1510					    STp->timeout, MAX_RETRIES, 1);
1511	
1512		if ((STp->buffer)->syscall_result || !SRpnt) {
1513			printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1514			vfree(buffer);
1515			*aSRpnt = SRpnt;
1516			return (-EIO);
1517		}
1518		osst_copy_from_buffer(STp->buffer, p);
1519#if DEBUG
1520		if (debugging)
1521			printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1522					  name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1523#endif
1524	}
1525	*aSRpnt = SRpnt;
1526	osst_get_frame_position(STp, aSRpnt);
1527
1528#if DEBUG
1529	printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1530#endif
1531	/* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1532	/* In the header we don't actually re-write the frames that fail, just the ones after them */
1533
1534	for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1535
1536		if (flag) {
1537			if (STp->write_type == OS_WRITE_HEADER) {
1538				i += skip;
1539				p += skip * OS_DATA_SIZE;
1540			}
1541			else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1542				new_frame = 3000-i;
1543			else
1544				new_frame += skip;
1545#if DEBUG
1546			printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1547						name, new_frame+i, frame_seq_number+i);
1548#endif
1549			osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1550			osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1551			osst_get_frame_position(STp, aSRpnt);
1552			SRpnt = * aSRpnt;
1553
1554			if (new_frame > frame + 1000) {
1555				printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1556				vfree(buffer);
1557				return (-EIO);
1558			}
1559			if ( i >= nframes + pending ) break;
1560			flag = 0;
1561		}
1562		osst_copy_to_buffer(STp->buffer, p);
1563		/*
1564		 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1565		 */
1566		osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1567			       	logical_blk_num + i*blks_per_frame,
1568			       	ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1569		memset(cmd, 0, MAX_COMMAND_SIZE);
1570		cmd[0] = WRITE_6;
1571		cmd[1] = 1;
1572		cmd[4] = 1;
1573
1574#if DEBUG
1575		if (debugging)
1576			printk(OSST_DEB_MSG
1577				"%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1578				name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1579				p[0], p[1], p[2], p[3]);
1580#endif
1581		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1582					    STp->timeout, MAX_RETRIES, 1);
1583
1584		if (STp->buffer->syscall_result)
1585			flag = 1;
1586		else {
1587			p += OS_DATA_SIZE; i++;
1588
1589			/* if we just sent the last frame, wait till all successfully written */
1590			if ( i == nframes + pending ) {
1591#if DEBUG
1592				printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1593#endif
1594				memset(cmd, 0, MAX_COMMAND_SIZE);
1595				cmd[0] = WRITE_FILEMARKS;
1596				cmd[1] = 1;
1597				SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1598							    STp->timeout, MAX_RETRIES, 1);
1599#if DEBUG
1600				if (debugging) {
1601					printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1602					printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1603					debugging = 0;
1604				}
1605#endif
1606				flag = STp->buffer->syscall_result;
1607				while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1608
1609					memset(cmd, 0, MAX_COMMAND_SIZE);
1610					cmd[0] = TEST_UNIT_READY;
1611
1612					SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1613												MAX_RETRIES, 1);
1614
1615					if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1616					    (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1617						/* in the process of becoming ready */
1618						msleep(100);
1619						continue;
1620					}
1621					if (STp->buffer->syscall_result)
1622						flag = 1;
1623					break;
1624				}
1625#if DEBUG
1626				debugging = dbg;
1627				printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1628#endif
1629			}
1630		}
1631		*aSRpnt = SRpnt;
1632		if (flag) {
1633			if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1634			     SRpnt->sense[12]         ==  0 &&
1635			     SRpnt->sense[13]         ==  2) {
1636				printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1637				vfree(buffer);
1638				return (-EIO);			/* hit end of tape = fail */
1639			}
1640			i = ((SRpnt->sense[3] << 24) |
1641			     (SRpnt->sense[4] << 16) |
1642			     (SRpnt->sense[5] <<  8) |
1643			      SRpnt->sense[6]        ) - new_frame;
1644			p = &buffer[i * OS_DATA_SIZE];
1645#if DEBUG
1646			printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1647#endif
1648			osst_get_frame_position(STp, aSRpnt);
1649#if DEBUG
1650			printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1651					  name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1652#endif
1653		}
1654	}
1655	if (flag) {
1656		/* error recovery did not successfully complete */
1657		printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1658				STp->write_type == OS_WRITE_HEADER?"header":"body");
1659	}
1660	if (!pending)
1661		osst_copy_to_buffer(STp->buffer, p);	/* so buffer content == at entry in all cases */
1662	vfree(buffer);
1663	return 0;
1664}
1665
1666static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1667					unsigned int frame, unsigned int skip, int pending)
1668{
1669	unsigned char		cmd[MAX_COMMAND_SIZE];
1670	struct osst_request   * SRpnt;
1671	char		      * name      = tape_name(STp);
1672	int			expected  = 0;
1673	int			attempts  = 1000 / skip;
1674	int			flag      = 1;
1675	unsigned long		startwait = jiffies;
1676#if DEBUG
1677	int			dbg       = debugging;
1678#endif
1679
1680	while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1681		if (flag) {
1682#if DEBUG
1683			debugging = dbg;
1684#endif
1685			if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1686				frame = 3000-skip;
1687			expected = frame+skip+STp->cur_frames+pending;
1688#if DEBUG
1689			printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1690					  name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1691#endif
1692			osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1693			flag = 0;
1694			attempts--;
1695			schedule_timeout_interruptible(msecs_to_jiffies(100));
1696		}
1697		if (osst_get_frame_position(STp, aSRpnt) < 0) {		/* additional write error */
1698#if DEBUG
1699			printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1700					  name, STp->first_frame_position,
1701					  STp->last_frame_position, STp->cur_frames);
1702#endif
1703			frame = STp->last_frame_position;
1704			flag = 1;
1705			continue;
1706		}
1707		if (pending && STp->cur_frames < 50) {
1708
1709			memset(cmd, 0, MAX_COMMAND_SIZE);
1710			cmd[0] = WRITE_6;
1711			cmd[1] = 1;
1712			cmd[4] = 1;
1713#if DEBUG
1714			printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1715					  name, STp->frame_seq_number-1, STp->first_frame_position);
1716#endif
1717			SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1718						      STp->timeout, MAX_RETRIES, 1);
1719			*aSRpnt = SRpnt;
1720
1721			if (STp->buffer->syscall_result) {		/* additional write error */
1722				if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1723				     SRpnt->sense[12]         ==  0 &&
1724				     SRpnt->sense[13]         ==  2) {
1725					printk(KERN_ERR
1726					       "%s:E: Volume overflow in write error recovery\n",
1727					       name);
1728					break;				/* hit end of tape = fail */
1729				}
1730				flag = 1;
1731			}
1732			else
1733				pending = 0;
1734
1735			continue;
1736		}
1737		if (STp->cur_frames == 0) {
1738#if DEBUG
1739			debugging = dbg;
1740			printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1741#endif
1742			if (STp->first_frame_position != expected) {
1743				printk(KERN_ERR "%s:A: Actual position %d - expected %d\n", 
1744						name, STp->first_frame_position, expected);
1745				return (-EIO);
1746			}
1747			return 0;
1748		}
1749#if DEBUG
1750		if (debugging) {
1751			printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1752			printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1753			debugging = 0;
1754		}
1755#endif
1756		schedule_timeout_interruptible(msecs_to_jiffies(100));
1757	}
1758	printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1759#if DEBUG
1760	debugging = dbg;
1761#endif
1762	return (-EIO);
1763}
1764
1765/*
1766 * Error recovery algorithm for the OnStream tape.
1767 */
1768
1769static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1770{
1771	struct osst_request * SRpnt  = * aSRpnt;
1772	struct st_partstat  * STps   = & STp->ps[STp->partition];
1773	char		    * name   = tape_name(STp);
1774	int		      retval = 0;
1775	int		      rw_state;
1776	unsigned int	      frame, skip;
1777
1778	rw_state = STps->rw;
1779
1780	if ((SRpnt->sense[ 2] & 0x0f) != 3
1781	  || SRpnt->sense[12]         != 12
1782	  || SRpnt->sense[13]         != 0) {
1783#if DEBUG
1784		printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1785			SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1786#endif
1787		return (-EIO);
1788	}
1789	frame =	(SRpnt->sense[3] << 24) |
1790		(SRpnt->sense[4] << 16) |
1791		(SRpnt->sense[5] <<  8) |
1792		 SRpnt->sense[6];
1793	skip  =  SRpnt->sense[9];
1794 
1795#if DEBUG
1796	printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1797#endif
1798	osst_get_frame_position(STp, aSRpnt);
1799#if DEBUG
1800	printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1801			name, STp->first_frame_position, STp->last_frame_position);
1802#endif
1803	switch (STp->write_type) {
1804	   case OS_WRITE_DATA:
1805	   case OS_WRITE_EOD:
1806	   case OS_WRITE_NEW_MARK:
1807		printk(KERN_WARNING 
1808			"%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1809			name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1810		if (STp->os_fw_rev >= 10600)
1811			retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1812		else
1813			retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1814		printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1815			       	retval?"E"    :"I",
1816			       	retval?""     :"Don't worry, ",
1817			       	retval?" not ":" ");
1818		break;
1819	   case OS_WRITE_LAST_MARK:
1820		printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1821		osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1822		retval = -EIO;
1823		break;
1824	   case OS_WRITE_HEADER:
1825		printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1826		retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1827		break;
1828	   default:
1829		printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1830		osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1831	}
1832	osst_get_frame_position(STp, aSRpnt);
1833#if DEBUG
1834	printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", 
1835			name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1836	printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1837#endif
1838	if (retval == 0) {
1839		STp->recover_count++;
1840		STp->recover_erreg++;
1841	} else
1842		STp->abort_count++;
1843
1844	STps->rw = rw_state;
1845	return retval;
1846}
1847
1848static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1849								 int mt_op, int mt_count)
1850{
1851	char  * name = tape_name(STp);
1852	int     cnt;
1853	int     last_mark_ppos = -1;
1854
1855#if DEBUG
1856	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1857#endif
1858	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1859#if DEBUG
1860		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1861#endif
1862		return -EIO;
1863	}
1864	if (STp->linux_media_version >= 4) {
1865		/*
1866		 * direct lookup in header filemark list
1867		 */
1868		cnt = ntohl(STp->buffer->aux->filemark_cnt);
1869		if (STp->header_ok                         && 
1870		    STp->header_cache != NULL              &&
1871		    (cnt - mt_count)  >= 0                 &&
1872		    (cnt - mt_count)   < OS_FM_TAB_MAX     &&
1873		    (cnt - mt_count)   < STp->filemark_cnt &&
1874		    STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1875
1876			last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1877#if DEBUG
1878		if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1879			printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1880			       STp->header_cache == NULL?"lack of header cache":"count out of range");
1881		else
1882			printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1883				name, cnt,
1884				((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1885				 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1886					 STp->buffer->aux->last_mark_ppos))?"match":"error",
1887			       mt_count, last_mark_ppos);
1888#endif
1889		if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1890			osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1891			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1892#if DEBUG
1893				printk(OSST_DEB_MSG 
1894					"%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1895#endif
1896				return (-EIO);
1897			}
1898			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1899				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1900						 name, last_mark_ppos);
1901				return (-EIO);
1902			}
1903			goto found;
1904		}
1905#if DEBUG
1906		printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1907#endif
1908	}
1909	cnt = 0;
1910	while (cnt != mt_count) {
1911		last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1912		if (last_mark_ppos == -1)
1913			return (-EIO);
1914#if DEBUG
1915		printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1916#endif
1917		osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1918		cnt++;
1919		if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1920#if DEBUG
1921			printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1922#endif
1923			return (-EIO);
1924		}
1925		if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1926			printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1927					 name, last_mark_ppos);
1928			return (-EIO);
1929		}
1930	}
1931found:
1932	if (mt_op == MTBSFM) {
1933		STp->frame_seq_number++;
1934		STp->frame_in_buffer      = 0;
1935		STp->buffer->buffer_bytes = 0;
1936		STp->buffer->read_pointer = 0;
1937		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1938	}
1939	return 0;
1940}
1941
1942/*
1943 * ADRL 1.1 compatible "slow" space filemarks fwd version
1944 *
1945 * Just scans for the filemark sequentially.
1946 */
1947static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1948								     int mt_op, int mt_count)
1949{
1950	int	cnt = 0;
1951#if DEBUG
1952	char  * name = tape_name(STp);
1953
1954	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1955#endif
1956	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1957#if DEBUG
1958		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1959#endif
1960		return (-EIO);
1961	}
1962	while (1) {
1963		if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1964#if DEBUG
1965			printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1966#endif
1967			return (-EIO);
1968		}
1969		if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1970			cnt++;
1971		if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1972#if DEBUG
1973			printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1974#endif
1975			if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1976#if DEBUG
1977				printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1978					       	name, STp->eod_frame_ppos, STp->first_frame_position-1);
1979#endif
1980				STp->eod_frame_ppos = STp->first_frame_position-1;
1981			}
1982			return (-EIO);
1983		}
1984		if (cnt == mt_count)
1985			break;
1986		STp->frame_in_buffer = 0;
1987	}
1988	if (mt_op == MTFSF) {
1989		STp->frame_seq_number++;
1990		STp->frame_in_buffer      = 0;
1991		STp->buffer->buffer_bytes = 0;
1992		STp->buffer->read_pointer = 0;
1993		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1994	}
1995	return 0;
1996}
1997
1998/*
1999 * Fast linux specific version of OnStream FSF
2000 */
2001static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
2002								     int mt_op, int mt_count)
2003{
2004	char  * name = tape_name(STp);
2005	int	cnt  = 0,
2006		next_mark_ppos = -1;
2007
2008#if DEBUG
2009	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
2010#endif
2011	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2012#if DEBUG
2013		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
2014#endif
2015		return (-EIO);
2016	}
2017
2018	if (STp->linux_media_version >= 4) {
2019		/*
2020		 * direct lookup in header filemark list
2021		 */
2022		cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
2023		if (STp->header_ok                         && 
2024		    STp->header_cache != NULL              &&
2025		    (cnt + mt_count)   < OS_FM_TAB_MAX     &&
2026		    (cnt + mt_count)   < STp->filemark_cnt &&
2027		    ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2028		     (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
2029
2030			next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
2031#if DEBUG
2032		if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
2033			printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
2034			       STp->header_cache == NULL?"lack of header cache":"count out of range");
2035		else
2036			printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2037			       name, cnt,
2038			       ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2039				(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
2040					 STp->buffer->aux->last_mark_ppos))?"match":"error",
2041			       mt_count, next_mark_ppos);
2042#endif
2043		if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
2044#if DEBUG
2045			printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2046#endif
2047			return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2048		} else {
2049			osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2050			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2051#if DEBUG
2052				printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2053						 name);
2054#endif
2055				return (-EIO);
2056			}
2057			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2058				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2059						 name, next_mark_ppos);
2060				return (-EIO);
2061			}
2062			if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
2063				printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
2064						 name, cnt+mt_count, next_mark_ppos,
2065						 ntohl(STp->buffer->aux->filemark_cnt));
2066       				return (-EIO);
2067			}
2068		}
2069	} else {
2070		/*
2071		 * Find nearest (usually previous) marker, then jump from marker to marker
2072		 */
2073		while (1) {
2074			if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
2075				break;
2076			if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2077#if DEBUG
2078				printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2079#endif
2080				return (-EIO);
2081			}
2082			if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2083				if (STp->first_mark_ppos == -1) {
2084#if DEBUG
2085					printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2086#endif
2087					return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2088				}
2089				osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2090				if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2091#if DEBUG
2092					printk(OSST_DEB_MSG
2093					       "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2094					       name);
2095#endif
2096					return (-EIO);
2097				}
2098				if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2099					printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2100							 name, STp->first_mark_ppos);
2101					return (-EIO);
2102				}
2103			} else {
2104				if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2105					return (-EIO);
2106				mt_count++;
2107			}
2108		}
2109		cnt++;
2110		while (cnt != mt_count) {
2111			next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2112			if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2113#if DEBUG
2114				printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2115#endif
2116				return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2117			}
2118#if DEBUG
2119			else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2120#endif
2121			osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2122			cnt++;
2123			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2124#if DEBUG
2125				printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2126						 name);
2127#endif
2128				return (-EIO);
2129			}
2130			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2131				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2132						 name, next_mark_ppos);
2133				return (-EIO);
2134			}
2135		}
2136	}
2137	if (mt_op == MTFSF) {
2138		STp->frame_seq_number++;
2139		STp->frame_in_buffer      = 0;
2140		STp->buffer->buffer_bytes = 0;
2141		STp->buffer->read_pointer = 0;
2142		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2143	}
2144	return 0;
2145}
2146
2147/*
2148 * In debug mode, we want to see as many errors as possible
2149 * to test the error recovery mechanism.
2150 */
2151#if DEBUG
2152static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2153{
2154	unsigned char		cmd[MAX_COMMAND_SIZE];
2155	struct osst_request   * SRpnt  = * aSRpnt;
2156	char		      * name   = tape_name(STp);
2157
2158	memset(cmd, 0, MAX_COMMAND_SIZE);
2159	cmd[0] = MODE_SELECT;
2160	cmd[1] = 0x10;
2161	cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2162
2163	(STp->buffer)->b_data[0] = cmd[4] - 1;
2164	(STp->buffer)->b_data[1] = 0;			/* Medium Type - ignoring */
2165	(STp->buffer)->b_data[2] = 0;			/* Reserved */
2166	(STp->buffer)->b_data[3] = 0;			/* Block Descriptor Length */
2167	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2168	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2169	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2170	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2171
2172	if (debugging)
2173	    printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2174
2175	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2176	*aSRpnt = SRpnt;
2177
2178	if ((STp->buffer)->syscall_result)
2179	    printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2180}
2181#endif
2182
2183
2184static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2185{
2186	int	result;
2187	int	this_mark_ppos = STp->first_frame_position;
2188	int	this_mark_lbn  = STp->logical_blk_num;
2189#if DEBUG
2190	char  * name = tape_name(STp);
2191#endif
2192
2193	if (STp->raw) return 0;
2194
2195	STp->write_type = OS_WRITE_NEW_MARK;
2196#if DEBUG
2197	printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n", 
2198	       name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2199#endif
2200	STp->dirty = 1;
2201	result  = osst_flush_write_buffer(STp, aSRpnt);
2202	result |= osst_flush_drive_buffer(STp, aSRpnt);
2203	STp->last_mark_ppos = this_mark_ppos;
2204	STp->last_mark_lbn  = this_mark_lbn;
2205	if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2206		STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2207	if (STp->filemark_cnt++ == 0)
2208		STp->first_mark_ppos = this_mark_ppos;
2209	return result;
2210}
2211
2212static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2213{
2214	int	result;
2215#if DEBUG
2216	char  * name = tape_name(STp);
2217#endif
2218
2219	if (STp->raw) return 0;
2220
2221	STp->write_type = OS_WRITE_EOD;
2222	STp->eod_frame_ppos = STp->first_frame_position;
2223#if DEBUG
2224	printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2225			STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2226#endif
2227	STp->dirty = 1;
2228
2229	result  = osst_flush_write_buffer(STp, aSRpnt);	
2230	result |= osst_flush_drive_buffer(STp, aSRpnt);
2231	STp->eod_frame_lfa = --(STp->frame_seq_number);
2232	return result;
2233}
2234
2235static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2236{
2237	char * name = tape_name(STp);
2238
2239#if DEBUG
2240	printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2241#endif
2242	osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2243	osst_set_frame_position(STp, aSRpnt, where, 0);
2244	STp->write_type = OS_WRITE_FILLER;
2245	while (count--) {
2246		memcpy(STp->buffer->b_data, "Filler", 6);
2247		STp->buffer->buffer_bytes = 6;
2248		STp->dirty = 1;
2249		if (osst_flush_write_buffer(STp, aSRpnt)) {
2250			printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2251			return (-EIO);
2252		}
2253	}
2254#if DEBUG
2255	printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2256#endif
2257	return osst_flush_drive_buffer(STp, aSRpnt);
2258}
2259
2260static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2261{
2262	char * name = tape_name(STp);
2263	int     result;
2264
2265#if DEBUG
2266	printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2267#endif
2268	osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2269	osst_set_frame_position(STp, aSRpnt, where, 0);
2270	STp->write_type = OS_WRITE_HEADER;
2271	while (count--) {
2272		osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2273		STp->buffer->buffer_bytes = sizeof(os_header_t);
2274		STp->dirty = 1;
2275		if (osst_flush_write_buffer(STp, aSRpnt)) {
2276			printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2277			return (-EIO);
2278		}
2279	}
2280	result = osst_flush_drive_buffer(STp, aSRpnt);
2281#if DEBUG
2282	printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2283#endif
2284	return result;
2285}
2286
2287static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2288{
2289	os_header_t * header;
2290	int	      result;
2291	char        * name = tape_name(STp);
2292
2293#if DEBUG
2294	printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2295#endif
2296	if (STp->raw) return 0;
2297
2298	if (STp->header_cache == NULL) {
2299		if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2300			printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2301			return (-ENOMEM);
2302		}
2303		memset(STp->header_cache, 0, sizeof(os_header_t));
2304#if DEBUG
2305		printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2306#endif
2307	}
2308	if (STp->header_ok) STp->update_frame_cntr++;
2309	else                STp->update_frame_cntr = 0;
2310
2311	header = STp->header_cache;
2312	strcpy(header->ident_str, "ADR_SEQ");
2313	header->major_rev      = 1;
2314	header->minor_rev      = 4;
2315	header->ext_trk_tb_off = htons(17192);
2316	header->pt_par_num     = 1;
2317	header->partition[0].partition_num              = OS_DATA_PARTITION;
2318	header->partition[0].par_desc_ver               = OS_PARTITION_VERSION;
2319	header->partition[0].wrt_pass_cntr              = htons(STp->wrt_pass_cntr);
2320	header->partition[0].first_frame_ppos           = htonl(STp->first_data_ppos);
2321	header->partition[0].last_frame_ppos            = htonl(STp->capacity);
2322	header->partition[0].eod_frame_ppos             = htonl(STp->eod_frame_ppos);
2323	header->cfg_col_width                           = htonl(20);
2324	header->dat_col_width                           = htonl(1500);
2325	header->qfa_col_width                           = htonl(0);
2326	header->ext_track_tb.nr_stream_part             = 1;
2327	header->ext_track_tb.et_ent_sz                  = 32;
2328	header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2329	header->ext_track_tb.dat_ext_trk_ey.fmt         = 1;
2330	header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  = htons(17736);
2331	header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2332	header->ext_track_tb.dat_ext_trk_ey.last_hlb    = htonl(STp->eod_frame_lfa);
2333	header->ext_track_tb.dat_ext_trk_ey.last_pp	= htonl(STp->eod_frame_ppos);
2334	header->dat_fm_tab.fm_part_num                  = 0;
2335	header->dat_fm_tab.fm_tab_ent_sz                = 4;
2336	header->dat_fm_tab.fm_tab_ent_cnt               = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2337								STp->filemark_cnt:OS_FM_TAB_MAX);
2338
2339	result  = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2340	if (STp->update_frame_cntr == 0)
2341		    osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2342	result &= __osst_write_header(STp, aSRpnt,     5, 5);
2343
2344	if (locate_eod) {
2345#if DEBUG
2346		printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2347#endif
2348		osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2349	}
2350	if (result)
2351		printk(KERN_ERR "%s:E: Write header failed\n", name);
2352	else {
2353		memcpy(STp->application_sig, "LIN4", 4);
2354		STp->linux_media         = 1;
2355		STp->linux_media_version = 4;
2356		STp->header_ok           = 1;
2357	}
2358	return result;
2359}
2360
2361static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2362{
2363	if (STp->header_cache != NULL)
2364		memset(STp->header_cache, 0, sizeof(os_header_t));
2365
2366	STp->logical_blk_num = STp->frame_seq_number = 0;
2367	STp->frame_in_buffer = 0;
2368	STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2369	STp->filemark_cnt = 0;
2370	STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2371	return osst_write_header(STp, aSRpnt, 1);
2372}
2373
2374static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2375{
2376	char        * name = tape_name(STp);
2377	os_header_t * header;
2378	os_aux_t    * aux;
2379	char          id_string[8];
2380	int	      linux_media_version,
2381		      update_frame_cntr;
2382
2383	if (STp->raw)
2384		return 1;
2385
2386	if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2387		if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2388			printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2389		osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2390		if (osst_initiate_read (STp, aSRpnt)) {
2391			printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2392			return 0;
2393		}
2394	}
2395	if (osst_read_frame(STp, aSRpnt, 180)) {
2396#if DEBUG
2397		printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2398#endif
2399		return 0;
2400	}
2401	header = (os_header_t *) STp->buffer->b_data;	/* warning: only first segment addressable */
2402	aux = STp->buffer->aux;
2403	if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2404#if DEBUG
2405		printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2406#endif
2407		return 0;
2408	}
2409	if (ntohl(aux->frame_seq_num)              != 0                   ||
2410	    ntohl(aux->logical_blk_num)            != 0                   ||
2411	          aux->partition.partition_num     != OS_CONFIG_PARTITION ||
2412	    ntohl(aux->partition.first_frame_ppos) != 0                   ||
2413	    ntohl(aux->partition.last_frame_ppos)  != 0xbb7               ) {
2414#if DEBUG
2415		printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2416				ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2417			       	aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2418			       	ntohl(aux->partition.last_frame_ppos));
2419#endif
2420		return 0;
2421	}
2422	if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2423	    strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2424		strlcpy(id_string, header->ident_str, 8);
2425#if DEBUG
2426		printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2427#endif
2428		return 0;
2429	}
2430	update_frame_cntr = ntohl(aux->update_frame_cntr);
2431	if (update_frame_cntr < STp->update_frame_cntr) {
2432#if DEBUG
2433		printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2434				   name, ppos, update_frame_cntr, STp->update_frame_cntr);
2435#endif
2436		return 0;
2437	}
2438	if (header->major_rev != 1 || header->minor_rev != 4 ) {
2439#if DEBUG
2440		printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n", 
2441				 name, (header->major_rev != 1 || header->minor_rev < 2 || 
2442				       header->minor_rev  > 4 )? "Invalid" : "Warning:",
2443				 header->major_rev, header->minor_rev);
2444#endif
2445		if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2446			return 0;
2447	}
2448#if DEBUG
2449	if (header->pt_par_num != 1)
2450		printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n", 
2451				 name, header->pt_par_num);
2452#endif
2453	memcpy(id_string, aux->application_sig, 4);
2454	id_string[4] = 0;
2455	if (memcmp(id_string, "LIN", 3) == 0) {
2456		STp->linux_media = 1;
2457		linux_media_version = id_string[3] - '0';
2458		if (linux_media_version != 4)
2459			printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2460					 name, linux_media_version);
2461	} else {
2462		printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2463		return 0;
2464	}
2465	if (linux_media_version < STp->linux_media_version) {
2466#if DEBUG
2467		printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2468				  name, ppos, linux_media_version);
2469#endif
2470		return 0;
2471	}
2472	if (linux_media_version > STp->linux_media_version) {
2473#if DEBUG
2474		printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2475				   name, ppos, linux_media_version);
2476#endif
2477		memcpy(STp->application_sig, id_string, 5);
2478		STp->linux_media_version = linux_media_version;
2479		STp->update_frame_cntr = -1;
2480	}
2481	if (update_frame_cntr > STp->update_frame_cntr) {
2482#if DEBUG
2483		printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2484				   name, ppos, update_frame_cntr);
2485#endif
2486		if (STp->header_cache == NULL) {
2487			if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2488				printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2489				return 0;
2490			}
2491#if DEBUG
2492			printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2493#endif
2494		}
2495		osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2496		header = STp->header_cache;	/* further accesses from cached (full) copy */
2497
2498		STp->wrt_pass_cntr     = ntohs(header->partition[0].wrt_pass_cntr);
2499		STp->first_data_ppos   = ntohl(header->partition[0].first_frame_ppos);
2500		STp->eod_frame_ppos    = ntohl(header->partition[0].eod_frame_ppos);
2501		STp->eod_frame_lfa     = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2502		STp->filemark_cnt      = ntohl(aux->filemark_cnt);
2503		STp->first_mark_ppos   = ntohl(aux->next_mark_ppos);
2504		STp->last_mark_ppos    = ntohl(aux->last_mark_ppos);
2505		STp->last_mark_lbn     = ntohl(aux->last_mark_lbn);
2506		STp->update_frame_cntr = update_frame_cntr;
2507#if DEBUG
2508	printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2509			  name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2510	printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2511			  STp->first_data_ppos,
2512			  ntohl(header->partition[0].last_frame_ppos),
2513			  ntohl(header->partition[0].eod_frame_ppos));
2514	printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n", 
2515			  name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2516#endif
2517		if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2518#if DEBUG
2519			printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2520#endif
2521			memcpy((void *)header->dat_fm_tab.fm_tab_ent, 
2522			       (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2523			memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2524		}
2525		if (header->minor_rev == 4   &&
2526		    (header->ext_trk_tb_off                          != htons(17192)               ||
2527		     header->partition[0].partition_num              != OS_DATA_PARTITION          ||
2528		     header->partition[0].par_desc_ver               != OS_PARTITION_VERSION       ||
2529		     header->partition[0].last_frame_ppos            != htonl(STp->capacity)       ||
2530		     header->cfg_col_width                           != htonl(20)                  ||
2531		     header->dat_col_width                           != htonl(1500)                ||
2532		     header->qfa_col_width                           != htonl(0)                   ||
2533		     header->ext_track_tb.nr_stream_part             != 1                          ||
2534		     header->ext_track_tb.et_ent_sz                  != 32                         ||
2535		     header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION          ||
2536		     header->ext_track_tb.dat_ext_trk_ey.fmt         != 1                          ||
2537		     header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  != htons(17736)               ||
2538		     header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0                          ||
2539		     header->ext_track_tb.dat_ext_trk_ey.last_pp     != htonl(STp->eod_frame_ppos) ||
2540		     header->dat_fm_tab.fm_part_num                  != OS_DATA_PARTITION          ||
2541		     header->dat_fm_tab.fm_tab_ent_sz                != 4                          ||
2542		     header->dat_fm_tab.fm_tab_ent_cnt               !=
2543			     htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2544			printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2545
2546	}
2547
2548	return 1;
2549}
2550
2551static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2552{
2553	int	position, ppos;
2554	int	first, last;
2555	int	valid = 0;
2556	char  * name  = tape_name(STp);
2557
2558	position = osst_get_frame_position(STp, aSRpnt);
2559
2560	if (STp->raw) {
2561		STp->header_ok = STp->linux_media = 1;
2562		STp->linux_media_version = 0;
2563		return 1;
2564	}
2565	STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2566	STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2567	STp->eod_frame_ppos = STp->first_data_ppos = -1;
2568	STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2569#if DEBUG
2570	printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2571#endif
2572
2573	/* optimization for speed - if we are positioned at ppos 10, read second group first  */	
2574	/* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2575
2576	first = position==10?0xbae: 5;
2577	last  = position==10?0xbb3:10;
2578
2579	for (ppos = first; ppos < last; ppos++)
2580		if (__osst_analyze_headers(STp, aSRpnt, ppos))
2581			valid = 1;
2582
2583	first = position==10? 5:0xbae;
2584	last  = position==10?10:0xbb3;
2585
2586	for (ppos = first; ppos < last; ppos++)
2587		if (__osst_analyze_headers(STp, aSRpnt, ppos))
2588			valid = 1;
2589
2590	if (!valid) {
2591		printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2592		STp->eod_frame_ppos = STp->first_data_ppos = 0;
2593		osst_set_frame_position(STp, aSRpnt, 10, 0);
2594		return 0;
2595	}
2596	if (position <= STp->first_data_ppos) {
2597		position = STp->first_data_ppos;
2598		STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2599	}
2600	osst_set_frame_position(STp, aSRpnt, position, 0);
2601	STp->header_ok = 1;
2602
2603	return 1;
2604}
2605
2606static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2607{
2608	int	frame_position  = STp->first_frame_position;
2609	int	frame_seq_numbr = STp->frame_seq_number;
2610	int	logical_blk_num = STp->logical_blk_num;
2611       	int	halfway_frame   = STp->frame_in_buffer;
2612	int	read_pointer    = STp->buffer->read_pointer;
2613	int	prev_mark_ppos  = -1;
2614	int	actual_mark_ppos, i, n;
2615#if DEBUG
2616	char  * name = tape_name(STp);
2617
2618	printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2619#endif
2620	osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2621	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2622#if DEBUG
2623		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2624#endif
2625		return (-EIO);
2626	}
2627	if (STp->linux_media_version >= 4) {
2628		for (i=0; i<STp->filemark_cnt; i++)
2629			if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2630				prev_mark_ppos = n;
2631	} else
2632		prev_mark_ppos = frame_position - 1;  /* usually - we don't really know */
2633	actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2634				frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2635	if (frame_position  != STp->first_frame_position                   ||
2636	    frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2637	    prev_mark_ppos  != actual_mark_ppos                            ) {
2638#if DEBUG
2639		printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2640				  STp->first_frame_position, frame_position, 
2641				  STp->frame_seq_number + (halfway_frame?0:1),
2642				  frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2643#endif
2644		return (-EIO);
2645	}
2646	if (halfway_frame) {
2647		/* prepare buffer for append and rewrite on top of original */
2648		osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2649		STp->buffer->buffer_bytes  = read_pointer;
2650		STp->ps[STp->partition].rw = ST_WRITING;
2651		STp->dirty                 = 1;
2652	}
2653	STp->frame_in_buffer  = halfway_frame;
2654	STp->frame_seq_number = frame_seq_numbr;
2655	STp->logical_blk_num  = logical_blk_num;
2656	return 0;
2657}
2658
2659/* Acc. to OnStream, the vers. numbering is the following:
2660 * X.XX for released versions (X=digit), 
2661 * XXXY for unreleased versions (Y=letter)
2662 * Ordering 1.05 < 106A < 106B < ...  < 106a < ... < 1.06
2663 * This fn makes monoton numbers out of this scheme ...
2664 */
2665static unsigned int osst_parse_firmware_rev (const char * str)
2666{
2667	if (str[1] == '.') {
2668		return (str[0]-'0')*10000
2669			+(str[2]-'0')*1000
2670			+(str[3]-'0')*100;
2671	} else {
2672		return (str[0]-'0')*10000
2673			+(str[1]-'0')*1000
2674			+(str[2]-'0')*100 - 100
2675			+(str[3]-'@');
2676	}
2677}
2678
2679/*
2680 * Configure the OnStream SCII tape drive for default operation
2681 */
2682static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2683{
2684	unsigned char                  cmd[MAX_COMMAND_SIZE];
2685	char                         * name = tape_name(STp);
2686	struct osst_request          * SRpnt = * aSRpnt;
2687	osst_mode_parameter_header_t * header;
2688	osst_block_size_page_t       * bs;
2689	osst_capabilities_page_t     * cp;
2690	osst_tape_paramtr_page_t     * prm;
2691	int                            drive_buffer_size;
2692
2693	if (STp->ready != ST_READY) {
2694#if DEBUG
2695	    printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2696#endif
2697	    return (-EIO);
2698	}
2699	
2700	if (STp->os_fw_rev < 10600) {
2701	    printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2702	    printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2703	}
2704
2705	/*
2706	 * Configure 32.5KB (data+aux) frame size.
2707         * Get the current frame size from the block size mode page
2708	 */
2709	memset(cmd, 0, MAX_COMMAND_SIZE);
2710	cmd[0] = MODE_SENSE;
2711	cmd[1] = 8;
2712	cmd[2] = BLOCK_SIZE_PAGE;
2713	cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2714
2715	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2716	if (SRpnt == NULL) {
2717#if DEBUG
2718 	    printk(OSST_DEB_MSG "osst :D: Busy\n");
2719#endif
2720	    return (-EBUSY);
2721	}
2722	*aSRpnt = SRpnt;
2723	if ((STp->buffer)->syscall_result != 0) {
2724	    printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2725	    return (-EIO);
2726	}
2727
2728	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2729	bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2730
2731#if DEBUG
2732	printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n",   name, bs->play32     ? "Yes" : "No");
2733	printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5   ? "Yes" : "No");
2734	printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n",      name, bs->record32   ? "Yes" : "No");
2735	printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n",    name, bs->record32_5 ? "Yes" : "No");
2736#endif
2737
2738	/*
2739	 * Configure default auto columns mode, 32.5KB transfer mode
2740	 */ 
2741	bs->one = 1;
2742	bs->play32 = 0;
2743	bs->play32_5 = 1;
2744	bs->record32 = 0;
2745	bs->record32_5 = 1;
2746
2747	memset(cmd, 0, MAX_COMMAND_SIZE);
2748	cmd[0] = MODE_SELECT;
2749	cmd[1] = 0x10;
2750	cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2751
2752	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2753	*aSRpnt = SRpnt;
2754	if ((STp->buffer)->syscall_result != 0) {
2755	    printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2756	    return (-EIO);
2757	}
2758
2759#if DEBUG
2760	printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2761	 /*
2762	 * In debug mode, we want to see as many errors as possible
2763	 * to test the error recovery mechanism.
2764	 */
2765	osst_set_retries(STp, aSRpnt, 0);
2766	SRpnt = * aSRpnt;
2767#endif
2768
2769	/*
2770	 * Set vendor name to 'LIN4' for "Linux support version 4".
2771	 */
2772
2773	memset(cmd, 0, MAX_COMMAND_SIZE);
2774	cmd[0] = MODE_SELECT;
2775	cmd[1] = 0x10;
2776	cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2777
2778	header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2779	header->medium_type      = 0;	/* Medium Type - ignoring */
2780	header->dsp              = 0;	/* Reserved */
2781	header->bdl              = 0;	/* Block Descriptor Length */
2782	
2783	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2784	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2785	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2786	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2787	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2788	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2789	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2790	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2791
2792	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2793	*aSRpnt = SRpnt;
2794
2795	if ((STp->buffer)->syscall_result != 0) {
2796	    printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name, 
2797			(char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2798	    return (-EIO);
2799	}
2800
2801	memset(cmd, 0, MAX_COMMAND_SIZE);
2802	cmd[0] = MODE_SENSE;
2803	cmd[1] = 8;
2804	cmd[2] = CAPABILITIES_PAGE;
2805	cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2806
2807	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2808	*aSRpnt = SRpnt;
2809
2810	if ((STp->buffer)->syscall_result != 0) {
2811	    printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2812	    return (-EIO);
2813	}
2814
2815	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2816	cp     = (osst_capabilities_page_t    *) ((STp->buffer)->b_data +
2817		 sizeof(osst_mode_parameter_header_t) + header->bdl);
2818
2819	drive_buffer_size = ntohs(cp->buffer_size) / 2;
2820
2821	memset(cmd, 0, MAX_COMMAND_SIZE);
2822	cmd[0] = MODE_SENSE;
2823	cmd[1] = 8;
2824	cmd[2] = TAPE_PARAMTR_PAGE;
2825	cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2826
2827	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2828	*aSRpnt = SRpnt;
2829
2830	if ((STp->buffer)->syscall_result != 0) {
2831	    printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2832	    return (-EIO);
2833	}
2834
2835	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2836	prm    = (osst_tape_paramtr_page_t    *) ((STp->buffer)->b_data +
2837		 sizeof(osst_mode_parameter_header_t) + header->bdl);
2838
2839	STp->density  = prm->density;
2840	STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2841#if DEBUG
2842	printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2843			  name, STp->density, STp->capacity / 32, drive_buffer_size);
2844#endif
2845
2846	return 0;
2847	
2848}
2849
2850
2851/* Step over EOF if it has been inadvertently crossed (ioctl not used because
2852   it messes up the block number). */
2853static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2854{
2855	int	result;
2856	char  * name = tape_name(STp);
2857
2858#if DEBUG
2859	if (debugging)
2860		printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2861	   			  name, forward ? "forward" : "backward");
2862#endif
2863
2864	if (forward) {
2865	   /* assumes that the filemark is already read by the drive, so this is low cost */
2866	   result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2867	}
2868	else
2869	   /* assumes this is only called if we just read the filemark! */
2870	   result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2871
2872	if (result < 0)
2873	   printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2874				name, forward ? "forward" : "backward");
2875
2876	return result;
2877}
2878
2879
2880/* Get the tape position. */
2881
2882static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2883{
2884	unsigned char		scmd[MAX_COMMAND_SIZE];
2885	struct osst_request   * SRpnt;
2886	int			result = 0;
2887	char    	      * name   = tape_name(STp);
2888
2889	/* KG: We want to be able to use it for checking Write Buffer availability
2890	 *  and thus don't want to risk to overwrite anything. Exchange buffers ... */
2891	char		mybuf[24];
2892	char	      * olddata = STp->buffer->b_data;
2893	int		oldsize = STp->buffer->buffer_size;
2894
2895	if (STp->ready != ST_READY) return (-EIO);
2896
2897	memset (scmd, 0, MAX_COMMAND_SIZE);
2898	scmd[0] = READ_POSITION;
2899
2900	STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2901	SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2902				      STp->timeout, MAX_RETRIES, 1);
2903	if (!SRpnt) {
2904		STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2905		return (-EBUSY);
2906	}
2907	*aSRpnt = SRpnt;
2908
2909	if (STp->buffer->syscall_result)
2910		result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL;	/* 3: Write Error */
2911
2912	if (result == -EINVAL)
2913		printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2914	else {
2915		if (result == -EIO) {	/* re-read position - this needs to preserve media errors */
2916			unsigned char mysense[16];
2917			memcpy (mysense, SRpnt->sense, 16);
2918			memset (scmd, 0, MAX_COMMAND_SIZE);
2919			scmd[0] = READ_POSITION;
2920			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2921			SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2922						    STp->timeout, MAX_RETRIES, 1);
2923#if DEBUG
2924			printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2925					name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2926					SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2927#endif
2928			if (!STp->buffer->syscall_result)
2929				memcpy (SRpnt->sense, mysense, 16);
2930			else
2931				printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2932		}
2933		STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2934					  + ((STp->buffer)->b_data[5] << 16)
2935					  + ((STp->buffer)->b_data[6] << 8)
2936					  +  (STp->buffer)->b_data[7];
2937		STp->last_frame_position  = ((STp->buffer)->b_data[ 8] << 24)
2938					  + ((STp->buffer)->b_data[ 9] << 16)
2939					  + ((STp->buffer)->b_data[10] <<  8)
2940					  +  (STp->buffer)->b_data[11];
2941		STp->cur_frames           =  (STp->buffer)->b_data[15];
2942#if DEBUG
2943		if (debugging) {
2944			printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2945					    STp->first_frame_position, STp->last_frame_position,
2946					    ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2947					    ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2948					    STp->cur_frames);
2949		}
2950#endif
2951		if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2952#if DEBUG
2953			printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2954					STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2955#endif
2956			STp->first_frame_position = STp->last_frame_position;
2957		}
2958	}
2959	STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2960
2961	return (result == 0 ? STp->first_frame_position : result);
2962}
2963
2964
2965/* Set the tape block */
2966static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2967{
2968	unsigned char		scmd[MAX_COMMAND_SIZE];
2969	struct osst_request   * SRpnt;
2970	struct st_partstat    * STps;
2971	int			result = 0;
2972	int			pp     = (ppos == 3000 && !skip)? 0 : ppos;
2973	char		      * name   = tape_name(STp);
2974
2975	if (STp->ready != ST_READY) return (-EIO);
2976
2977	STps = &(STp->ps[STp->partition]);
2978
2979	if (ppos < 0 || ppos > STp->capacity) {
2980		printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2981		pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2982		result = (-EINVAL);
2983	}
2984
2985	do {
2986#if DEBUG
2987		if (debugging)
2988			printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2989#endif
2990		memset (scmd, 0, MAX_COMMAND_SIZE);
2991		scmd[0] = SEEK_10;
2992		scmd[1] = 1;
2993		scmd[3] = (pp >> 24);
2994		scmd[4] = (pp >> 16);
2995		scmd[5] = (pp >> 8);
2996		scmd[6] =  pp;
2997		if (skip)
2998			scmd[9] = 0x80;
2999
3000		SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
3001								MAX_RETRIES, 1);
3002		if (!SRpnt)
3003			return (-EBUSY);
3004		*aSRpnt  = SRpnt;
3005
3006		if ((STp->buffer)->syscall_result != 0) {
3007#if DEBUG
3008			printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
3009					name, STp->first_frame_position, pp);
3010#endif
3011			result = (-EIO);
3012		}
3013		if (pp != ppos)
3014			osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
3015	} while ((pp != ppos) && (pp = ppos));
3016	STp->first_frame_position = STp->last_frame_position = ppos;
3017	STps->eof = ST_NOEOF;
3018	STps->at_sm = 0;
3019	STps->rw = ST_IDLE;
3020	STp->frame_in_buffer = 0;
3021	return result;
3022}
3023
3024static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
3025{
3026	struct st_partstat * STps = &(STp->ps[STp->partition]);
3027	int result = 0;
3028
3029	if (STp->write_type != OS_WRITE_NEW_MARK) {
3030		/* true unless the user wrote the filemark for us */
3031		result = osst_flush_drive_buffer(STp, aSRpnt);
3032		if (result < 0) goto out;
3033		result = osst_write_filemark(STp, aSRpnt);
3034		if (result < 0) goto out;
3035
3036		if (STps->drv_file >= 0)
3037			STps->drv_file++ ;
3038		STps->drv_block = 0;
3039	}
3040	result = osst_write_eod(STp, aSRpnt);
3041	osst_write_header(STp, aSRpnt, leave_at_EOT);
3042
3043	STps->eof = ST_FM;
3044out:
3045	return result;
3046}
3047
3048/* osst versions of st functions - augmented and stripped to suit OnStream only */
3049
3050/* Flush the write buffer (never need to write if variable blocksize). */
3051static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
3052{
3053	int			offset, transfer, blks = 0;
3054	int			result = 0;
3055	unsigned char		cmd[MAX_COMMAND_SIZE];
3056	struct osst_request   * SRpnt = *aSRpnt;
3057	struct st_partstat    * STps;
3058	char		      * name = tape_name(STp);
3059
3060	if ((STp->buffer)->writing) {
3061		if (SRpnt == (STp->buffer)->last_SRpnt)
3062#if DEBUG
3063			{ printk(OSST_DEB_MSG
3064	 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
3065#endif
3066			*aSRpnt = SRpnt = NULL;
3067#if DEBUG
3068			} else if (SRpnt)
3069				printk(OSST_DEB_MSG
3070	 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
3071#endif	
3072		osst_write_behind_check(STp);
3073		if ((STp->buffer)->syscall_result) {
3074#if DEBUG
3075			if (debugging)
3076				printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3077				       name, (STp->buffer)->midlevel_result);
3078#endif
3079			if ((STp->buffer)->midlevel_result == INT_MAX)
3080				return (-ENOSPC);
3081			return (-EIO);
3082		}
3083	}
3084
3085	result = 0;
3086	if (STp->dirty == 1) {
3087
3088		STp->write_count++;
3089		STps     = &(STp->ps[STp->partition]);
3090		STps->rw = ST_WRITING;
3091		offset   = STp->buffer->buffer_bytes;
3092		blks     = (offset + STp->block_size - 1) / STp->block_size;
3093		transfer = OS_FRAME_SIZE;
3094		
3095		if (offset < OS_DATA_SIZE)
3096			osst_zero_buffer_tail(STp->buffer);
3097
3098		if (STp->poll)
3099			if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3100				result = osst_recover_wait_frame(STp, aSRpnt, 1);
3101
3102		memset(cmd, 0, MAX_COMMAND_SIZE);
3103		cmd[0] = WRITE_6;
3104		cmd[1] = 1;
3105		cmd[4] = 1;
3106
3107		switch	(STp->write_type) {
3108		   case OS_WRITE_DATA:
3109#if DEBUG
3110   			if (debugging)
3111				printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3112					name, blks, STp->frame_seq_number, 
3113					STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3114#endif
3115			osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3116				      STp->logical_blk_num - blks, STp->block_size, blks);
3117			break;
3118		   case OS_WRITE_EOD:
3119			osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3120				      STp->logical_blk_num, 0, 0);
3121			break;
3122		   case OS_WRITE_NEW_MARK:
3123			osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3124				      STp->logical_blk_num++, 0, blks=1);
3125			break;
3126		   case OS_WRITE_HEADER:
3127			osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3128			break;
3129		default: /* probably FILLER */
3130			osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3131		}
3132#if DEBUG
3133		if (debugging)
3134			printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3135			  			 name, offset, transfer, blks);
3136#endif
3137
3138		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3139					      STp->timeout, MAX_RETRIES, 1);
3140		*aSRpnt = SRpnt;
3141		if (!SRpnt)
3142			return (-EBUSY);
3143
3144		if ((STp->buffer)->syscall_result != 0) {
3145#if DEBUG
3146			printk(OSST_DEB_MSG
3147				"%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3148				name, SRpnt->sense[0], SRpnt->sense[2],
3149				SRpnt->sense[12], SRpnt->sense[13]);
3150#endif
3151			if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3152			    (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3153			    (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3154				STp->dirty = 0;
3155				(STp->buffer)->buffer_bytes = 0;
3156				result = (-ENOSPC);
3157			}
3158			else {
3159				if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3160					printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3161					result = (-EIO);
3162				}
3163			}
3164			STps->drv_block = (-1);		/* FIXME - even if write recovery succeeds? */
3165		}
3166		else {
3167			STp->first_frame_position++;
3168			STp->dirty = 0;
3169			(STp->buffer)->buffer_bytes = 0;
3170		}
3171	}
3172#if DEBUG
3173	printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3174#endif
3175	return result;
3176}
3177
3178
3179/* Flush the tape buffer. The tape will be positioned correctly unless
3180   seek_next is true. */
3181static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3182{
3183	struct st_partstat * STps;
3184	int    backspace = 0, result = 0;
3185#if DEBUG
3186	char * name = tape_name(STp);
3187#endif
3188
3189	/*
3190	 * If there was a bus reset, block further access
3191	 * to this device.
3192	 */
3193	if( STp->pos_unknown)
3194		return (-EIO);
3195
3196	if (STp->ready != ST_READY)
3197		return 0;
3198
3199	STps = &(STp->ps[STp->partition]);
3200	if (STps->rw == ST_WRITING || STp->dirty) {	/* Writing */
3201		STp->write_type = OS_WRITE_DATA;
3202		return osst_flush_write_buffer(STp, aSRpnt);
3203	}
3204	if (STp->block_size == 0)
3205		return 0;
3206
3207#if DEBUG
3208	printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3209#endif
3210
3211	if (!STp->can_bsr) {
3212		backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3213			    ((STp->buffer)->read_pointer + STp->block_size - 1        ) / STp->block_size ;
3214		(STp->buffer)->buffer_bytes = 0;
3215		(STp->buffer)->read_pointer = 0;
3216		STp->frame_in_buffer = 0;		/* FIXME is this relevant w. OSST? */
3217	}
3218
3219	if (!seek_next) {
3220		if (STps->eof == ST_FM_HIT) {
3221			result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3222			if (!result)
3223				STps->eof = ST_NOEOF;
3224			else {
3225				if (STps->drv_file >= 0)
3226					STps->drv_file++;
3227				STps->drv_block = 0;
3228			}
3229		}
3230		if (!result && backspace > 0)	/* TODO -- design and run a test case for this */
3231			result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3232	}
3233	else if (STps->eof == ST_FM_HIT) {
3234		if (STps->drv_file >= 0)
3235			STps->drv_file++;
3236		STps->drv_block = 0;
3237		STps->eof = ST_NOEOF;
3238	}
3239
3240	return result;
3241}
3242
3243static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3244{
3245	unsigned char		cmd[MAX_COMMAND_SIZE];
3246	struct osst_request   * SRpnt;
3247	int			blks;
3248#if DEBUG
3249	char		      * name = tape_name(STp);
3250#endif
3251
3252	if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3253#if DEBUG
3254		printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3255#endif
3256		if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3257			return (-EIO);
3258		}
3259		/* error recovery may have bumped us past the header partition */
3260		if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3261#if DEBUG
3262			printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3263#endif
3264		osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3265		}
3266	}
3267
3268	if (STp->poll)
3269		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3270			if (osst_recover_wait_frame(STp, aSRpnt, 1))
3271				return (-EIO);
3272
3273//	osst_build_stats(STp, &SRpnt);
3274
3275	STp->ps[STp->partition].rw = ST_WRITING;
3276	STp->write_type            = OS_WRITE_DATA;
3277			
3278	memset(cmd, 0, MAX_COMMAND_SIZE);
3279	cmd[0]   = WRITE_6;
3280	cmd[1]   = 1;
3281	cmd[4]   = 1;						/* one frame at a time... */
3282	blks     = STp->buffer->buffer_bytes / STp->block_size;
3283#if DEBUG
3284	if (debugging)
3285		printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks, 
3286			STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3287#endif
3288	osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3289		      STp->logical_blk_num - blks, STp->block_size, blks);
3290
3291#if DEBUG
3292	if (!synchronous)
3293		STp->write_pending = 1;
3294#endif
3295	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3296									MAX_RETRIES, synchronous);
3297	if (!SRpnt)
3298		return (-EBUSY);
3299	*aSRpnt = SRpnt;
3300
3301	if (synchronous) {
3302		if (STp->buffer->syscall_result != 0) {
3303#if DEBUG
3304			if (debugging)
3305				printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3306#endif
3307			if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3308			    (SRpnt->sense[2] & 0x40)) {
3309				if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3310					return (-ENOSPC);
3311			}
3312			else {
3313				if (osst_write_error_recovery(STp, aSRpnt, 1))
3314					return (-EIO);
3315			}
3316		}
3317		else
3318			STp->first_frame_position++;
3319	}
3320
3321	STp->write_count++;
3322
3323	return 0;
3324}
3325
3326/* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3327static int do_door_lock(struct osst_tape * STp, int do_lock)
3328{
3329	int retval, cmd;
3330
3331	cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3332#if DEBUG
3333	printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3334#endif
3335	retval = scsi_ioctl(STp->device, cmd, NULL);
3336	if (!retval) {
3337		STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3338	}
3339	else {
3340		STp->door_locked = ST_LOCK_FAILS;
3341	}
3342	return retval;
3343}
3344
3345/* Set the internal state after reset */
3346static void reset_state(struct osst_tape *STp)
3347{
3348	int i;
3349	struct st_partstat *STps;
3350
3351	STp->pos_unknown = 0;
3352	for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3353		STps = &(STp->ps[i]);
3354		STps->rw = ST_IDLE;
3355		STps->eof = ST_NOEOF;
3356		STps->at_sm = 0;
3357		STps->last_block_valid = 0;
3358		STps->drv_block = -1;
3359		STps->drv_file = -1;
3360	}
3361}
3362				
3363
3364/* Entry points to osst */
3365
3366/* Write command */
3367static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3368{
3369	ssize_t		      total, retval = 0;
3370	ssize_t		      i, do_count, blks, transfer;
3371	int		      write_threshold;
3372	int		      doing_write = 0;
3373	const char   __user * b_point;
3374	struct osst_request * SRpnt = NULL;
3375	struct st_modedef   * STm;
3376	struct st_partstat  * STps;
3377	struct osst_tape    * STp  = filp->private_data;
3378	char		    * name = tape_name(STp);
3379
3380
3381	if (mutex_lock_interruptible(&STp->lock))
3382		return (-ERESTARTSYS);
3383
3384	/*
3385	 * If we are in the middle of error recovery, don't let anyone
3386	 * else try and use this device.  Also, if error recovery fails, it
3387	 * may try and take the device offline, in which case all further
3388	 * access to the device is prohibited.
3389	 */
3390	if( !scsi_block_when_processing_errors(STp->device) ) {
3391		retval = (-ENXIO);
3392		goto out;
3393	}
3394	
3395	if (STp->ready != ST_READY) {
3396		if (STp->ready == ST_NO_TAPE)
3397			retval = (-ENOMEDIUM);
3398		else
3399			retval = (-EIO);
3400		goto out;
3401	}
3402	STm = &(STp->modes[STp->current_mode]);
3403	if (!STm->defined) {
3404		retval = (-ENXIO);
3405		goto out;
3406	}
3407	if (count == 0)
3408		goto out;
3409
3410	/*
3411	 * If there was a bus reset, block further access
3412	 * to this device.
3413	 */
3414	if (STp->pos_unknown) {
3415		retval = (-EIO);
3416		goto out;
3417	}
3418
3419#if DEBUG
3420	if (!STp->in_use) {
3421		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3422		retval = (-EIO);
3423		goto out;
3424	}
3425#endif
3426
3427	if (STp->write_prot) {
3428		retval = (-EACCES);
3429		goto out;
3430	}
3431
3432	/* Write must be integral number of blocks */
3433	if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3434		printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3435				       name, count, STp->block_size<1024?
3436				       STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3437		retval = (-EINVAL);
3438		goto out;
3439	}
3440
3441	if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3442		printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3443				       name, STp->first_frame_position);
3444		retval = (-ENOSPC);
3445		goto out;
3446	}
3447
3448	if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3449		STp->door_locked = ST_LOCKED_AUTO;
3450
3451	STps = &(STp->ps[STp->partition]);
3452
3453	if (STps->rw == ST_READING) {
3454#if DEBUG
3455		printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name, 
3456					STps->drv_file, STps->drv_block);
3457#endif
3458		retval = osst_flush_buffer(STp, &SRpnt, 0);
3459		if (retval)
3460			goto out;
3461		STps->rw = ST_IDLE;
3462	}
3463	if (STps->rw != ST_WRITING) {
3464		/* Are we totally rewriting this tape? */
3465		if (!STp->header_ok ||
3466		    (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3467		    (STps->drv_file == 0 && STps->drv_block == 0)) {
3468			STp->wrt_pass_cntr++;
3469#if DEBUG
3470			printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3471						  name, STp->wrt_pass_cntr);
3472#endif
3473			osst_reset_header(STp, &SRpnt);
3474			STps->drv_file = STps->drv_block = 0;
3475		}
3476		/* Do we know where we'll be writing on the tape? */
3477		else {
3478			if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3479			  		STps->drv_file < 0 || STps->drv_block < 0) {
3480				if (STp->first_frame_position == STp->eod_frame_ppos) {	/* at EOD */
3481			  		STps->drv_file = STp->filemark_cnt;
3482			  		STps->drv_block = 0;
3483				}
3484				else {
3485					/* We have no idea where the tape is positioned - give up */
3486#if DEBUG
3487					printk(OSST_DEB_MSG
3488						"%s:D: Cannot write at indeterminate position.\n", name);
3489#endif
3490					retval = (-EIO);
3491					goto out;
3492				}
3493      			}	  
3494			if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3495				STp->filemark_cnt = STps->drv_file;
3496				STp->last_mark_ppos =
3497				       	ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3498				printk(KERN_WARNING
3499					"%s:W: Overwriting file %d with old write pass counter %d\n",
3500						name, STps->drv_file, STp->wrt_pass_cntr);
3501				printk(KERN_WARNING
3502					"%s:W: may lead to stale data being accepted on reading back!\n",
3503						name);
3504#if DEBUG
3505				printk(OSST_DEB_MSG
3506				  "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3507					name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3508#endif
3509			}
3510		}
3511		STp->fast_open = 0;
3512	}
3513	if (!STp->header_ok) {
3514#if DEBUG
3515		printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3516#endif
3517		retval = (-EIO);
3518		goto out;
3519	}
3520
3521	if ((STp->buffer)->writing) {
3522if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3523		osst_write_behind_check(STp);
3524		if ((STp->buffer)->syscall_result) {
3525#if DEBUG
3526		if (debugging)
3527			printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3528						 (STp->buffer)->midlevel_result);
3529#endif
3530		if ((STp->buffer)->midlevel_result == INT_MAX)
3531			STps->eof = ST_EOM_OK;
3532		else
3533			STps->eof = ST_EOM_ERROR;
3534		}
3535	}
3536	if (STps->eof == ST_EOM_OK) {
3537		retval = (-ENOSPC);
3538		goto out;
3539	}
3540	else if (STps->eof == ST_EOM_ERROR) {
3541		retval = (-EIO);
3542		goto out;
3543	}
3544
3545	/* Check the buffer readability in cases where copy_user might catch
3546		 the problems after some tape movement. */
3547	if ((copy_from_user(&i, buf, 1) != 0 ||
3548	     copy_from_user(&i, buf + count - 1, 1) != 0)) {
3549		retval = (-EFAULT);
3550		goto out;
3551	}
3552
3553	if (!STm->do_buffer_writes) {
3554		write_threshold = 1;
3555	}
3556	else
3557		write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3558	if (!STm->do_async_writes)
3559		write_threshold--;
3560
3561	total = count;
3562#if DEBUG
3563	if (debugging)
3564		printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3565				name, (int) count, STps->drv_file, STps->drv_block,
3566				STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3567#endif
3568	b_point = buf;
3569	while ((STp->buffer)->buffer_bytes + count > write_threshold)
3570	{
3571		doing_write = 1;
3572		do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3573			   (STp->buffer)->buffer_bytes;
3574		if (do_count > count)
3575			do_count = count;
3576
3577		i = append_to_buffer(b_point, STp->buffer, do_count);
3578		if (i) {
3579			retval = i;
3580			goto out;
3581		}
3582
3583		blks = do_count / STp->block_size;
3584		STp->logical_blk_num += blks;  /* logical_blk_num is incremented as data is moved from user */
3585  
3586		i = osst_write_frame(STp, &SRpnt, 1);
3587
3588		if (i == (-ENOSPC)) {
3589			transfer = STp->buffer->writing;	/* FIXME -- check this logic */
3590			if (transfer <= do_count) {
3591				*ppos += do_count - transfer;
3592				count -= do_count - transfer;
3593				if (STps->drv_block >= 0) {
3594					STps->drv_block += (do_count - transfer) / STp->block_size;
3595				}
3596				STps->eof = ST_EOM_OK;
3597				retval = (-ENOSPC);		/* EOM within current request */
3598#if DEBUG
3599				if (debugging)
3600				      printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3601							     name, (int) transfer);
3602#endif
3603			}
3604			else {
3605				STps->eof = ST_EOM_ERROR;
3606				STps->drv_block = (-1);		/* Too cautious? */
3607				retval = (-EIO);		/* EOM for old data */
3608#if DEBUG
3609				if (debugging)
3610				      printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3611#endif
3612			}
3613		}
3614		else
3615			retval = i;
3616			
3617		if (retval < 0) {
3618			if (SRpnt != NULL) {
3619				osst_release_request(SRpnt);
3620				SRpnt = NULL;
3621			}
3622			STp->buffer->buffer_bytes = 0;
3623			STp->dirty = 0;
3624			if (count < total)
3625				retval = total - count;
3626			goto out;
3627		}
3628
3629		*ppos += do_count;
3630		b_point += do_count;
3631		count -= do_count;
3632		if (STps->drv_block >= 0) {
3633			STps->drv_block += blks;
3634		}
3635		STp->buffer->buffer_bytes = 0;
3636		STp->dirty = 0;
3637	}  /* end while write threshold exceeded */
3638
3639	if (count != 0) {
3640		STp->dirty = 1;
3641		i = append_to_buffer(b_point, STp->buffer, count);
3642		if (i) {
3643			retval = i;
3644			goto out;
3645		}
3646		blks = count / STp->block_size;
3647		STp->logical_blk_num += blks;
3648		if (STps->drv_block >= 0) {
3649			STps->drv_block += blks;
3650		}
3651		*ppos += count;
3652		count = 0;
3653	}
3654
3655	if (doing_write && (STp->buffer)->syscall_result != 0) {
3656		retval = (STp->buffer)->syscall_result;
3657		goto out;
3658	}
3659
3660	if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) { 
3661		/* Schedule an asynchronous write */
3662		(STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3663					   STp->block_size) * STp->block_size;
3664		STp->dirty = !((STp->buffer)->writing ==
3665				          (STp->buffer)->buffer_bytes);
3666
3667		i = osst_write_frame(STp, &SRpnt, 0);
3668		if (i < 0) {
3669			retval = (-EIO);
3670			goto out;
3671		}
3672		SRpnt = NULL;			/* Prevent releasing this request! */
3673	}
3674	STps->at_sm &= (total == 0);
3675	if (total > 0)
3676		STps->eof = ST_NOEOF;
3677
3678	retval = total;
3679
3680out:
3681	if (SRpnt != NULL) osst_release_request(SRpnt);
3682
3683	mutex_unlock(&STp->lock);
3684
3685	return retval;
3686}
3687
3688
3689/* Read command */
3690static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3691{
3692	ssize_t		      total, retval = 0;
3693	ssize_t		      i, transfer;
3694	int		      special;
3695	struct st_modedef   * STm;
3696	struct st_partstat  * STps;
3697	struct osst_request * SRpnt = NULL;
3698	struct osst_tape    * STp   = filp->private_data;
3699	char		    * name  = tape_name(STp);
3700
3701
3702	if (mutex_lock_interruptible(&STp->lock))
3703		return (-ERESTARTSYS);
3704
3705	/*
3706	 * If we are in the middle of error recovery, don't let anyone
3707	 * else try and use this device.  Also, if error recovery fails, it
3708	 * may try and take the device offline, in which case all further
3709	 * access to the device is prohibited.
3710	 */
3711	if( !scsi_block_when_processing_errors(STp->device) ) {
3712		retval = (-ENXIO);
3713		goto out;
3714	}
3715	
3716	if (STp->ready != ST_READY) {
3717		if (STp->ready == ST_NO_TAPE)
3718			retval = (-ENOMEDIUM);
3719		else
3720			retval = (-EIO);
3721		goto out;
3722	}
3723	STm = &(STp->modes[STp->current_mode]);
3724	if (!STm->defined) {
3725		retval = (-ENXIO);
3726		goto out;
3727	}
3728#if DEBUG
3729	if (!STp->in_use) {
3730		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3731		retval = (-EIO);
3732		goto out;
3733	}
3734#endif
3735	/* Must have initialized medium */
3736	if (!STp->header_ok) {
3737		retval = (-EIO);
3738		goto out;
3739	}
3740
3741	if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3742		STp->door_locked = ST_LOCKED_AUTO;
3743
3744	STps = &(STp->ps[STp->partition]);
3745	if (STps->rw == ST_WRITING) {
3746		retval = osst_flush_buffer(STp, &SRpnt, 0);
3747		if (retval)
3748			goto out;
3749		STps->rw = ST_IDLE;
3750		/* FIXME -- this may leave the tape without EOD and up2date headers */
3751	}
3752
3753	if ((count % STp->block_size) != 0) {
3754		printk(KERN_WARNING
3755		    "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3756		    STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3757	}
3758
3759#if DEBUG
3760	if (debugging && STps->eof != ST_NOEOF)
3761		printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3762				     STps->eof, (STp->buffer)->buffer_bytes);
3763#endif
3764	if ((STp->buffer)->buffer_bytes == 0 &&
3765	     STps->eof >= ST_EOD_1) {
3766		if (STps->eof < ST_EOD) {
3767			STps->eof += 1;
3768			retval = 0;
3769			goto out;
3770		}
3771		retval = (-EIO);  /* EOM or Blank Check */
3772		goto out;
3773	}
3774
3775	/* Check the buffer writability before any tape movement. Don't alter
3776		 buffer data. */
3777	if (copy_from_user(&i, buf, 1)             != 0 ||
3778	    copy_to_user  (buf, &i, 1)             != 0 ||
3779	    copy_from_user(&i, buf + count - 1, 1) != 0 ||
3780	    copy_to_user  (buf + count - 1, &i, 1) != 0) {
3781		retval = (-EFAULT);
3782		goto out;
3783	}
3784
3785	/* Loop until enough data in buffer or a special condition found */
3786	for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3787
3788		/* Get new data if the buffer is empty */
3789		if ((STp->buffer)->buffer_bytes == 0) {
3790			if (STps->eof == ST_FM_HIT)
3791				break;
3792			special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3793			if (special < 0) { 			/* No need to continue read */
3794				STp->frame_in_buffer = 0;
3795				retval = special;
3796				goto out;
3797			}
3798		}
3799
3800		/* Move the data from driver buffer to user buffer */
3801		if ((STp->buffer)->buffer_bytes > 0) {
3802#if DEBUG
3803			if (debugging && STps->eof != ST_NOEOF)
3804			    printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3805						 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3806#endif
3807		       	/* force multiple of block size, note block_size may have been adjusted */
3808			transfer = (((STp->buffer)->buffer_bytes < count - total ?
3809				     (STp->buffer)->buffer_bytes : count - total)/
3810					STp->block_size) * STp->block_size;
3811
3812			if (transfer == 0) {
3813				printk(KERN_WARNING
3814				  "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n",
3815			   		name, count, STp->block_size < 1024?
3816					STp->block_size:STp->block_size/1024,
3817				       	STp->block_size<1024?'b':'k');
3818				break;
3819			}
3820			i = from_buffer(STp->buffer, buf, transfer);
3821			if (i)  {
3822				retval = i;
3823				goto out;
3824			}
3825			STp->logical_blk_num += transfer / STp->block_size;
3826			STps->drv_block      += transfer / STp->block_size;
3827			*ppos          += transfer;
3828			buf                  += transfer;
3829			total                += transfer;
3830		}
3831 
3832		if ((STp->buffer)->buffer_bytes == 0) {
3833#if DEBUG
3834			if (debugging)
3835				printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3836					       	name, STp->frame_seq_number);
3837#endif
3838			STp->frame_in_buffer = 0;
3839			STp->frame_seq_number++;              /* frame to look for next time */
3840		}
3841	} /* for (total = 0, special = 0; total < count && !special; ) */
3842
3843	/* Change the eof state if no data from tape or buffer */
3844	if (total == 0) {
3845		if (STps->eof == ST_FM_HIT) {
3846			STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3847			STps->drv_block = 0;
3848			if (STps->drv_file >= 0)
3849				STps->drv_file++;
3850		}
3851		else if (STps->eof == ST_EOD_1) {
3852			STps->eof = ST_EOD_2;
3853			if (STps->drv_block > 0 && STps->drv_file >= 0)
3854				STps->drv_file++;
3855			STps->drv_block = 0;
3856		}
3857		else if (STps->eof == ST_EOD_2)
3858			STps->eof = ST_EOD;
3859	}
3860	else if (STps->eof == ST_FM)
3861		STps->eof = ST_NOEOF;
3862
3863	retval = total;
3864
3865out:
3866	if (SRpnt != NULL) osst_release_request(SRpnt);
3867
3868	mutex_unlock(&STp->lock);
3869
3870	return retval;
3871}
3872
3873
3874/* Set the driver options */
3875static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3876{
3877  printk(KERN_INFO
3878"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3879	 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3880	 STm->do_read_ahead);
3881  printk(KERN_INFO
3882"%s:I:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3883	 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3884  printk(KERN_INFO
3885"%s:I:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3886	 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3887	 STp->scsi2_logical);
3888  printk(KERN_INFO
3889"%s:I:    sysv: %d\n", name, STm->sysv);
3890#if DEBUG
3891  printk(KERN_INFO
3892	 "%s:D:    debugging: %d\n",
3893	 name, debugging);
3894#endif
3895}
3896
3897
3898static int osst_set_options(struct osst_tape *STp, long options)
3899{
3900	int		    value;
3901	long		    code;
3902	struct st_modedef * STm;
3903	char		  * name = tape_name(STp);
3904
3905	STm = &(STp->modes[STp->current_mode]);
3906	if (!STm->defined) {
3907		memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3908		modes_defined = 1;
3909#if DEBUG
3910		if (debugging)
3911			printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3912					     name, STp->current_mode);
3913#endif
3914	}
3915
3916	code = options & MT_ST_OPTIONS;
3917	if (code == MT_ST_BOOLEANS) {
3918		STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3919		STm->do_async_writes  = (options & MT_ST_ASYNC_WRITES) != 0;
3920		STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3921		STm->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
3922		STp->two_fm	      = (options & MT_ST_TWO_FM) != 0;
3923		STp->fast_mteom	      = (options & MT_ST_FAST_MTEOM) != 0;
3924		STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
3925		STp->can_bsr          = (options & MT_ST_CAN_BSR) != 0;
3926		STp->omit_blklims     = (options & MT_ST_NO_BLKLIMS) != 0;
3927		if ((STp->device)->scsi_level >= SCSI_2)
3928			STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3929		STp->scsi2_logical    = (options & MT_ST_SCSI2LOGICAL) != 0;
3930		STm->sysv	      = (options & MT_ST_SYSV) != 0;
3931#if DEBUG
3932		debugging = (options & MT_ST_DEBUGGING) != 0;
3933#endif
3934		osst_log_options(STp, STm, name);
3935	}
3936	else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3937		value = (code == MT_ST_SETBOOLEANS);
3938		if ((options & MT_ST_BUFFER_WRITES) != 0)
3939			STm->do_buffer_writes = value;
3940		if ((options & MT_ST_ASYNC_WRITES) != 0)
3941			STm->do_async_writes = value;
3942		if ((options & MT_ST_DEF_WRITES) != 0)
3943			STm->defaults_for_writes = value;
3944		if ((options & MT_ST_READ_AHEAD) != 0)
3945			STm->do_read_ahead = value;
3946		if ((options & MT_ST_TWO_FM) != 0)
3947			STp->two_fm = value;
3948		if ((options & MT_ST_FAST_MTEOM) != 0)
3949			STp->fast_mteom = value;
3950		if ((options & MT_ST_AUTO_LOCK) != 0)
3951			STp->do_auto_lock = value;
3952		if ((options & MT_ST_CAN_BSR) != 0)
3953			STp->can_bsr = value;
3954		if ((options & MT_ST_NO_BLKLIMS) != 0)
3955			STp->omit_blklims = value;
3956		if ((STp->device)->scsi_level >= SCSI_2 &&
3957		    (options & MT_ST_CAN_PARTITIONS) != 0)
3958			STp->can_partitions = value;
3959		if ((options & MT_ST_SCSI2LOGICAL) != 0)
3960			STp->scsi2_logical = value;
3961		if ((options & MT_ST_SYSV) != 0)
3962			STm->sysv = value;
3963#if DEBUG
3964		if ((options & MT_ST_DEBUGGING) != 0)
3965			debugging = value;
3966#endif
3967		osst_log_options(STp, STm, name);
3968	}
3969	else if (code == MT_ST_WRITE_THRESHOLD) {
3970		value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3971		if (value < 1 || value > osst_buffer_size) {
3972			printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3973					     name, value);
3974			return (-EIO);
3975		}
3976		STp->write_threshold = value;
3977		printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3978				  name, value);
3979	}
3980	else if (code == MT_ST_DEF_BLKSIZE) {
3981		value = (options & ~MT_ST_OPTIONS);
3982		if (value == ~MT_ST_OPTIONS) {
3983			STm->default_blksize = (-1);
3984			printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3985		}
3986		else {
3987			if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3988				printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3989							 name, value);
3990				return (-EINVAL);
3991			}
3992			STm->default_blksize = value;
3993			printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3994					  name, STm->default_blksize);
3995		}
3996	}
3997	else if (code == MT_ST_TIMEOUTS) {
3998		value = (options & ~MT_ST_OPTIONS);
3999		if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
4000			STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
4001			printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
4002					     (value & ~MT_ST_SET_LONG_TIMEOUT));
4003		}
4004		else {
4005			STp->timeout = value * HZ;
4006			printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
4007		}
4008	}
4009	else if (code == MT_ST_DEF_OPTIONS) {
4010		code = (options & ~MT_ST_CLEAR_DEFAULT);
4011		value = (options & MT_ST_CLEAR_DEFAULT);
4012		if (code == MT_ST_DEF_DENSITY) {
4013			if (value == MT_ST_CLEAR_DEFAULT) {
4014				STm->default_density = (-1);
4015				printk(KERN_INFO "%s:I: Density default disabled.\n", name);
4016			}
4017			else {
4018				STm->default_density = value & 0xff;
4019				printk(KERN_INFO "%s:I: Density default set to %x\n",
4020						  name, STm->default_density);
4021			}
4022		}
4023		else if (code == MT_ST_DEF_DRVBUFFER) {
4024			if (value == MT_ST_CLEAR_DEFAULT) {
4025				STp->default_drvbuffer = 0xff;
4026				printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
4027			}
4028			else {
4029				STp->default_drvbuffer = value & 7;
4030				printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
4031						  name, STp->default_drvbuffer);
4032			}
4033		}
4034		else if (code == MT_ST_DEF_COMPRESSION) {
4035			if (value == MT_ST_CLEAR_DEFAULT) {
4036				STm->default_compression = ST_DONT_TOUCH;
4037				printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
4038			}
4039			else {
4040				STm->default_compression = (value & 1 ? ST_YES : ST_NO);
4041				printk(KERN_INFO "%s:I: Compression default set to %x\n",
4042						  name, (value & 1));
4043			}
4044		}
4045	}
4046	else
4047		return (-EIO);
4048
4049	return 0;
4050}
4051
4052
4053/* Internal ioctl function */
4054static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
4055			     unsigned int cmd_in, unsigned long arg)
4056{
4057	int			timeout;
4058	long			ltmp;
4059	int			i, ioctl_result;
4060	int			chg_eof = 1;
4061	unsigned char		cmd[MAX_COMMAND_SIZE];
4062	struct osst_request   * SRpnt = * aSRpnt;
4063	struct st_partstat    * STps;
4064	int			fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
4065	int			datalen = 0, direction = DMA_NONE;
4066	char		      * name = tape_name(STp);
4067
4068	if (STp->ready != ST_READY && cmd_in != MTLOAD) {
4069		if (STp->ready == ST_NO_TAPE)
4070			return (-ENOMEDIUM);
4071		else
4072			return (-EIO);
4073	}
4074	timeout = STp->long_timeout;
4075	STps = &(STp->ps[STp->partition]);
4076	fileno = STps->drv_file;
4077	blkno = STps->drv_block;
4078	at_sm = STps->at_sm;
4079	frame_seq_numbr = STp->frame_seq_number;
4080	logical_blk_num = STp->logical_blk_num;
4081
4082	memset(cmd, 0, MAX_COMMAND_SIZE);
4083	switch (cmd_in) {
4084	 case MTFSFM:
4085		chg_eof = 0; /* Changed from the FSF after this */
4086	 case MTFSF:
4087		if (STp->raw)
4088		   return (-EIO);
4089		if (STp->linux_media)
4090		   ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4091		else
4092		   ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4093		if (fileno >= 0)
4094		   fileno += arg;
4095		blkno = 0;
4096		at_sm &= (arg == 0);
4097		goto os_bypass;
4098
4099	 case MTBSF:
4100		chg_eof = 0; /* Changed from the FSF after this */
4101	 case MTBSFM:
4102		if (STp->raw)
4103		   return (-EIO);
4104		ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4105		if (fileno >= 0)
4106		   fileno -= arg;
4107		blkno = (-1);  /* We can't know the block number */
4108		at_sm &= (arg == 0);
4109		goto os_bypass;
4110
4111	 case MTFSR:
4112	 case MTBSR:
4113#if DEBUG
4114		if (debugging)
4115		   printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4116				name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4117#endif
4118		if (cmd_in == MTFSR) {
4119		   logical_blk_num += arg;
4120		   if (blkno >= 0) blkno += arg;
4121		}
4122		else {
4123		   logical_blk_num -= arg;
4124		   if (blkno >= 0) blkno -= arg;
4125		}
4126		ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4127		fileno = STps->drv_file;
4128		blkno  = STps->drv_block;
4129		at_sm &= (arg == 0);
4130		goto os_bypass;
4131
4132	 case MTFSS:
4133		cmd[0] = SPACE;
4134		cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4135		cmd[2] = (arg >> 16);
4136		cmd[3] = (arg >> 8);
4137		cmd[4] = arg;
4138#if DEBUG
4139		if (debugging)
4140			printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4141		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4142#endif
4143		if (arg != 0) {
4144			blkno = fileno = (-1);
4145			at_sm = 1;
4146		}
4147		break;
4148	 case MTBSS:
4149		cmd[0] = SPACE;
4150		cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4151		ltmp = (-arg);
4152		cmd[2] = (ltmp >> 16);
4153		cmd[3] = (ltmp >> 8);
4154		cmd[4] = ltmp;
4155#if DEBUG
4156		if (debugging) {
4157			if (cmd[2] & 0x80)
4158			   ltmp = 0xff000000;
4159			ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4160			printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4161						name, (-ltmp));
4162		 }
4163#endif
4164		 if (arg != 0) {
4165			blkno = fileno = (-1);
4166			at_sm = 1;
4167		 }
4168		 break;
4169	 case MTWEOF:
4170		 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4171			STp->write_type = OS_WRITE_DATA;
4172			ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4173		 } else
4174			ioctl_result = 0;
4175#if DEBUG
4176		 if (debugging) 
4177			   printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4178#endif
4179		 for (i=0; i<arg; i++)
4180			ioctl_result |= osst_write_filemark(STp, &SRpnt);
4181		 if (fileno >= 0) fileno += arg;
4182		 if (blkno  >= 0) blkno   = 0;
4183		 goto os_bypass;
4184
4185	 case MTWSM:
4186		 if (STp->write_prot)
4187			return (-EACCES);
4188		 if (!STp->raw)
4189			return 0;
4190		 cmd[0] = WRITE_FILEMARKS;   /* FIXME -- need OS version */
4191		 if (cmd_in == MTWSM)
4192			 cmd[1] = 2;
4193		 cmd[2] = (arg >> 16);
4194		 cmd[3] = (arg >> 8);
4195		 cmd[4] = arg;
4196		 timeout = STp->timeout;
4197#if DEBUG
4198		 if (debugging) 
4199			   printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4200				  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4201#endif
4202		 if (fileno >= 0)
4203			fileno += arg;
4204		 blkno = 0;
4205		 at_sm = (cmd_in == MTWSM);
4206		 break;
4207	 case MTOFFL:
4208	 case MTLOAD:
4209	 case MTUNLOAD:
4210	 case MTRETEN:
4211		 cmd[0] = START_STOP;
4212		 cmd[1] = 1;			/* Don't wait for completion */
4213		 if (cmd_in == MTLOAD) {
4214		     if (STp->ready == ST_NO_TAPE)
4215			 cmd[4] = 4;		/* open tray */
4216		      else
4217			 cmd[4] = 1;		/* load */
4218		 }
4219		 if (cmd_in == MTRETEN)
4220			 cmd[4] = 3;		/* retension then mount */
4221		 if (cmd_in == MTOFFL)
4222			 cmd[4] = 4;		/* rewind then eject */
4223		 timeout = STp->timeout;
4224#if DEBUG
4225		 if (debugging) {
4226			 switch (cmd_in) {
4227				 case MTUNLOAD:
4228					 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4229					 break;
4230				 case MTLOAD:
4231					 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4232					 break;
4233				 case MTRETEN:
4234					 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4235					 break;
4236				 case MTOFFL:
4237					 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4238					 break;
4239			 }
4240		 }
4241#endif
4242       fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4243		 break;
4244	 case MTNOP:
4245#if DEBUG
4246		 if (debugging)
4247			 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4248#endif
4249		 return 0;  /* Should do something ? */
4250		 break;
4251	 case MTEOM:
4252#if DEBUG
4253		if (debugging)
4254		   printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4255#endif
4256		if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4257			    (osst_get_logical_frame(STp, &SRpnt, -1, 0)               < 0)) {
4258		   ioctl_result = -EIO;
4259		   goto os_bypass;
4260		}
4261		if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4262#if DEBUG
4263		   printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4264#endif
4265		   ioctl_result = -EIO;
4266		   goto os_bypass;
4267		}
4268		ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4269		fileno = STp->filemark_cnt;
4270		blkno  = at_sm = 0;
4271		goto os_bypass;
4272
4273	 case MTERASE:
4274		if (STp->write_prot)
4275		   return (-EACCES);
4276		ioctl_result = osst_reset_header(STp, &SRpnt);
4277		i = osst_write_eod(STp, &SRpnt);
4278		if (i < ioctl_result) ioctl_result = i;
4279		i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4280		if (i < ioctl_result) ioctl_result = i;
4281		fileno = blkno = at_sm = 0 ;
4282		goto os_bypass;
4283
4284	 case MTREW:
4285		cmd[0] = REZERO_UNIT; /* rewind */
4286		cmd[1] = 1;
4287#if DEBUG
4288		if (debugging)
4289		   printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4290#endif
4291		fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4292		break;
4293
4294	 case MTSETBLK:           /* Set block length */
4295		 if ((STps->drv_block == 0 )			  &&
4296		     !STp->dirty				  &&
4297		     ((STp->buffer)->buffer_bytes == 0)		  &&
4298		     ((arg & MT_ST_BLKSIZE_MASK) >= 512 )	  && 
4299		     ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4300		     !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))  ) {
4301			 /*
4302			  * Only allowed to change the block size if you opened the
4303			  * device at the beginning of a file before writing anything.
4304			  * Note, that when reading, changing block_size is futile,
4305			  * as the size used when writing overrides it.
4306			  */
4307			 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4308			 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4309					   name, STp->block_size);
4310			 return 0;
4311		 }
4312	 case MTSETDENSITY:       /* Set tape density */
4313	 case MTSETDRVBUFFER:     /* Set drive buffering */
4314	 case SET_DENS_AND_BLK:   /* Set density and block size */
4315		 chg_eof = 0;
4316		 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4317			 return (-EIO);       /* Not allowed if data in buffer */
4318		 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4319		     (arg & MT_ST_BLKSIZE_MASK) != 0                    &&
4320		     (arg & MT_ST_BLKSIZE_MASK) != STp->block_size       ) {
4321			 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4322						name, (int)(arg & MT_ST_BLKSIZE_MASK),
4323						(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4324			 return (-EINVAL);
4325		 }
4326		 return 0;  /* FIXME silently ignore if block size didn't change */
4327
4328	 default:
4329		return (-ENOSYS);
4330	}
4331
4332	SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4333
4334	ioctl_result = (STp->buffer)->syscall_result;
4335
4336	if (!SRpnt) {
4337#if DEBUG
4338		printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4339#endif
4340		return ioctl_result;
4341	}
4342
4343	if (!ioctl_result) {  /* SCSI command successful */
4344		STp->frame_seq_number = frame_seq_numbr;
4345		STp->logical_blk_num  = logical_blk_num;
4346	}
4347
4348os_bypass:
4349#if DEBUG
4350	if (debugging)
4351		printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4352#endif
4353
4354	if (!ioctl_result) {				/* success */
4355
4356		if (cmd_in == MTFSFM) {
4357			 fileno--;
4358			 blkno--;
4359		}
4360		if (cmd_in == MTBSFM) {
4361			 fileno++;
4362			 blkno++;
4363		}
4364		STps->drv_block = blkno;
4365		STps->drv_file = fileno;
4366		STps->at_sm = at_sm;
4367
4368		if (cmd_in == MTEOM)
4369			STps->eof = ST_EOD;
4370		else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4371			ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4372			STps->drv_block++;
4373			STp->logical_blk_num++;
4374			STp->frame_seq_number++;
4375			STp->frame_in_buffer = 0;
4376			STp->buffer->read_pointer = 0;
4377		}
4378		else if (cmd_in == MTFSF)
4379			STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4380		else if (chg_eof)
4381			STps->eof = ST_NOEOF;
4382
4383		if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4384			STp->rew_at_close = 0;
4385		else if (cmd_in == MTLOAD) {
4386			for (i=0; i < ST_NBR_PARTITIONS; i++) {
4387			    STp->ps[i].rw = ST_IDLE;
4388			    STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4389			}
4390			STp->partition = 0;
4391		}
4392
4393		if (cmd_in == MTREW) {
4394			ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos); 
4395			if (ioctl_result > 0)
4396				ioctl_result = 0;
4397		}
4398
4399	} else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4400		if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4401			STps->drv_file = STps->drv_block = -1;
4402		else
4403			STps->drv_file = STps->drv_block = 0;
4404		STps->eof = ST_NOEOF;
4405	} else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4406		if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4407			STps->drv_file = STps->drv_block = -1;
4408		else {
4409			STps->drv_file  = STp->filemark_cnt;
4410			STps->drv_block = 0;
4411		}
4412		STps->eof = ST_EOD;
4413	} else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4414		STps->drv_file = STps->drv_block = (-1);
4415		STps->eof = ST_NOEOF;
4416		STp->header_ok = 0;
4417	} else if (cmd_in == MTERASE) {
4418		STp->header_ok = 0;
4419	} else if (SRpnt) {  /* SCSI command was not completely successful. */
4420		if (SRpnt->sense[2] & 0x40) {
4421			STps->eof = ST_EOM_OK;
4422			STps->drv_block = 0;
4423		}
4424		if (chg_eof)
4425			STps->eof = ST_NOEOF;
4426
4427		if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4428			STps->eof = ST_EOD;
4429
4430		if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4431			ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4432	}
4433	*aSRpnt = SRpnt;
4434
4435	return ioctl_result;
4436}
4437
4438
4439/* Open the device */
4440static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4441{
4442	unsigned short	      flags;
4443	int		      i, b_size, new_session = 0, retval = 0;
4444	unsigned char	      cmd[MAX_COMMAND_SIZE];
4445	struct osst_request * SRpnt = NULL;
4446	struct osst_tape    * STp;
4447	struct st_modedef   * STm;
4448	struct st_partstat  * STps;
4449	char		    * name;
4450	int		      dev  = TAPE_NR(inode);
4451	int		      mode = TAPE_MODE(inode);
4452
4453	/*
4454	 * We really want to do nonseekable_open(inode, filp); here, but some
4455	 * versions of tar incorrectly call lseek on tapes and bail out if that
4456	 * fails.  So we disallow pread() and pwrite(), but permit lseeks.
4457	 */
4458	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4459
4460	write_lock(&os_scsi_tapes_lock);
4461	if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4462	    (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4463		write_unlock(&os_scsi_tapes_lock);
4464		return (-ENXIO);
4465	}
4466
4467	name = tape_name(STp);
4468
4469	if (STp->in_use) {
4470		write_unlock(&os_scsi_tapes_lock);
4471#if DEBUG
4472		printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4473#endif
4474		return (-EBUSY);
4475	}
4476	if (scsi_device_get(STp->device)) {
4477		write_unlock(&os_scsi_tapes_lock);
4478#if DEBUG
4479                printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4480#endif
4481		return (-ENXIO);
4482	}
4483	filp->private_data = STp;
4484	STp->in_use = 1;
4485	write_unlock(&os_scsi_tapes_lock);
4486	STp->rew_at_close = TAPE_REWIND(inode);
4487
4488	if( !scsi_block_when_processing_errors(STp->device) ) {
4489		return -ENXIO;
4490	}
4491
4492	if (mode != STp->current_mode) {
4493#if DEBUG
4494		if (debugging)
4495			printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4496					       name, STp->current_mode, mode);
4497#endif
4498		new_session = 1;
4499		STp->current_mode = mode;
4500	}
4501	STm = &(STp->modes[STp->current_mode]);
4502
4503	flags = filp->f_flags;
4504	STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4505
4506	STp->raw = TAPE_IS_RAW(inode);
4507	if (STp->raw)
4508		STp->header_ok = 0;
4509
4510	/* Allocate data segments for this device's tape buffer */
4511	if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4512		printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4513		retval = (-EOVERFLOW);
4514		goto err_out;
4515	}
4516	if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4517		for (i = 0, b_size = 0; 
4518		     (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE); 
4519		     b_size += STp->buffer->sg[i++].length);
4520		STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4521#if DEBUG
4522		printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4523			STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4524		printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4525			 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4526#endif
4527	} else {
4528		STp->buffer->aux = NULL; /* this had better never happen! */
4529		printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4530		retval = (-EIO);
4531		goto err_out;
4532	}
4533	STp->buffer->writing = 0;
4534	STp->buffer->syscall_result = 0;
4535	STp->dirty = 0;
4536	for (i=0; i < ST_NBR_PARTITIONS; i++) {
4537		STps = &(STp->ps[i]);
4538		STps->rw = ST_IDLE;
4539	}
4540	STp->ready = ST_READY;
4541#if DEBUG
4542	STp->nbr_waits = STp->nbr_finished = 0;
4543#endif
4544
4545	memset (cmd, 0, MAX_COMMAND_SIZE);
4546	cmd[0] = TEST_UNIT_READY;
4547
4548	SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4549	if (!SRpnt) {
4550		retval = (STp->buffer)->syscall_result;		/* FIXME - valid? */
4551		goto err_out;
4552	}
4553	if ((SRpnt->sense[0] & 0x70) == 0x70      &&
4554	    (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4555	     SRpnt->sense[12]        == 4         ) {
4556#if DEBUG
4557		printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4558#endif
4559		if (filp->f_flags & O_NONBLOCK) {
4560			retval = -EAGAIN;
4561			goto err_out;
4562		}
4563		if (SRpnt->sense[13] == 2) {	/* initialize command required (LOAD) */
4564			memset (cmd, 0, MAX_COMMAND_SIZE);
4565        		cmd[0] = START_STOP;
4566			cmd[1] = 1;
4567			cmd[4] = 1;
4568			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4569					     STp->timeout, MAX_RETRIES, 1);
4570		}
4571		osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4572	}
4573	if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4574	    (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4575#if DEBUG
4576		printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4577#endif
4578		STp->header_ok = 0;
4579
4580		for (i=0; i < 10; i++) {
4581
4582			memset (cmd, 0, MAX_COMMAND_SIZE);
4583			cmd[0] = TEST_UNIT_READY;
4584
4585			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4586					     STp->timeout, MAX_RETRIES, 1);
4587			if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4588			    (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4589				break;
4590		}
4591
4592		STp->pos_unknown = 0;
4593		STp->partition = STp->new_partition = 0;
4594		if (STp->can_partitions)
4595			STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4596		for (i=0; i < ST_NBR_PARTITIONS; i++) {
4597			STps = &(STp->ps[i]);
4598			STps->rw = ST_IDLE;		/* FIXME - seems to be redundant... */
4599			STps->eof = ST_NOEOF;
4600			STps->at_sm = 0;
4601			STps->last_block_valid = 0;
4602			STps->drv_block = 0;
4603			STps->drv_file = 0 ;
4604		}
4605		new_session = 1;
4606		STp->recover_count = 0;
4607		STp->abort_count = 0;
4608	}
4609	/*
4610	 * if we have valid headers from before, and the drive/tape seem untouched,
4611	 * open without reconfiguring and re-reading the headers
4612	 */
4613	if (!STp->buffer->syscall_result && STp->header_ok &&
4614	    !SRpnt->result && SRpnt->sense[0] == 0) {
4615
4616		memset(cmd, 0, MAX_COMMAND_SIZE);
4617		cmd[0] = MODE_SENSE;
4618		cmd[1] = 8;
4619		cmd[2] = VENDOR_IDENT_PAGE;
4620		cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4621
4622		SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4623
4624		if (STp->buffer->syscall_result                     ||
4625		    STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4626		    STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4627		    STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4628		    STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4'  ) {
4629#if DEBUG
4630			printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4631			  STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4632			  STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4633			  STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4634			  STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4635#endif
4636			STp->header_ok = 0;
4637		}
4638		i = STp->first_frame_position;
4639		if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4640			if (STp->door_locked == ST_UNLOCKED) {
4641				if (do_door_lock(STp, 1))
4642					printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4643				else
4644					STp->door_locked = ST_LOCKED_AUTO;
4645			}
4646			if (!STp->frame_in_buffer) {
4647				STp->block_size = (STm->default_blksize > 0) ?
4648							STm->default_blksize : OS_DATA_SIZE;
4649				STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4650			}
4651			STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4652			STp->fast_open = 1;
4653			osst_release_request(SRpnt);
4654			return 0;
4655		}
4656#if DEBUG
4657		if (i != STp->first_frame_position)
4658			printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4659						name, i, STp->first_frame_position);
4660#endif
4661		STp->header_ok = 0;
4662	}
4663	STp->fast_open = 0;
4664
4665	if ((STp->buffer)->syscall_result != 0 &&   /* in all error conditions except no medium */ 
4666	    (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4667
4668		memset(cmd, 0, MAX_COMMAND_SIZE);
4669		cmd[0] = MODE_SELECT;
4670		cmd[1] = 0x10;
4671		cmd[4] = 4 + MODE_HEADER_LENGTH;
4672
4673		(STp->buffer)->b_data[0] = cmd[4] - 1;
4674		(STp->buffer)->b_data[1] = 0;			/* Medium Type - ignoring */
4675		(STp->buffer)->b_data[2] = 0;			/* Reserved */
4676		(STp->buffer)->b_data[3] = 0;			/* Block Descriptor Length */
4677		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4678		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4679		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4680		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4681
4682#if DEBUG
4683		printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4684#endif
4685		SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4686
4687		STp->header_ok = 0;
4688
4689		for (i=0; i < 10; i++) {
4690
4691			memset (cmd, 0, MAX_COMMAND_SIZE);
4692			cmd[0] = TEST_UNIT_READY;
4693
4694			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4695						    STp->timeout, MAX_RETRIES, 1);
4696			if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4697			    (SRpnt->sense[2] & 0x0f) == NOT_READY)
4698			break;
4699
4700			if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4701				int j;
4702
4703				STp->pos_unknown = 0;
4704				STp->partition = STp->new_partition = 0;
4705				if (STp->can_partitions)
4706					STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4707				for (j = 0; j < ST_NBR_PARTITIONS; j++) {
4708					STps = &(STp->ps[j]);
4709					STps->rw = ST_IDLE;
4710					STps->eof = ST_NOEOF;
4711					STps->at_sm = 0;
4712					STps->last_block_valid = 0;
4713					STps->drv_block = 0;
4714					STps->drv_file = 0 ;
4715				}
4716				new_session = 1;
4717			}
4718		}
4719	}
4720
4721	if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))		/* FIXME - not allowed with NOBLOCK */
4722		 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4723
4724	if ((STp->buffer)->syscall_result != 0) {
4725		if ((STp->device)->scsi_level >= SCSI_2 &&
4726		    (SRpnt->sense[0] & 0x70) == 0x70 &&
4727		    (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4728		     SRpnt->sense[12] == 0x3a) { /* Check ASC */
4729			STp->ready = ST_NO_TAPE;
4730		} else
4731			STp->ready = ST_NOT_READY;
4732		osst_release_request(SRpnt);
4733		SRpnt = NULL;
4734		STp->density = 0;   	/* Clear the erroneous "residue" */
4735		STp->write_prot = 0;
4736		STp->block_size = 0;
4737		STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4738		STp->partition = STp->new_partition = 0;
4739		STp->door_locked = ST_UNLOCKED;
4740		return 0;
4741	}
4742
4743	osst_configure_onstream(STp, &SRpnt);
4744
4745	STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4746			     (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4747	STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4748	STp->buffer->buffer_bytes  =
4749	STp->buffer->read_pointer  =
4750	STp->frame_in_buffer       = 0;
4751
4752#if DEBUG
4753	if (debugging)
4754		printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4755		     name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4756		     (STp->buffer)->buffer_blocks);
4757#endif
4758
4759	if (STp->drv_write_prot) {
4760		STp->write_prot = 1;
4761#if DEBUG
4762		if (debugging)
4763			printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4764#endif
4765		if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4766			retval = (-EROFS);
4767			goto err_out;
4768		}
4769	}
4770
4771	if (new_session) {  /* Change the drive parameters for the new mode */
4772#if DEBUG
4773		if (debugging)
4774	printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4775#endif
4776		STp->density_changed = STp->blksize_changed = 0;
4777		STp->compression_changed = 0;
4778	}
4779
4780	/*
4781	 * properly position the tape and check the ADR headers
4782	 */
4783	if (STp->door_locked == ST_UNLOCKED) {
4784		 if (do_door_lock(STp, 1))
4785			printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4786		 else
4787			STp->door_locked = ST_LOCKED_AUTO;
4788	}
4789
4790	osst_analyze_headers(STp, &SRpnt);
4791
4792	osst_release_request(SRpnt);
4793	SRpnt = NULL;
4794
4795	return 0;
4796
4797err_out:
4798	if (SRpnt != NULL)
4799		osst_release_request(SRpnt);
4800	normalize_buffer(STp->buffer);
4801	STp->header_ok = 0;
4802	STp->in_use = 0;
4803	scsi_device_put(STp->device);
4804
4805	return retval;
4806}
4807
4808/* BKL pushdown: spaghetti avoidance wrapper */
4809static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4810{
4811	int ret;
4812
4813	mutex_lock(&osst_int_mutex);
4814	ret = __os_scsi_tape_open(inode, filp);
4815	mutex_unlock(&osst_int_mutex);
4816	return ret;
4817}
4818
4819
4820
4821/* Flush the tape buffer before close */
4822static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4823{
4824	int		      result = 0, result2;
4825	struct osst_tape    * STp    = filp->private_data;
4826	struct st_modedef   * STm    = &(STp->modes[STp->current_mode]);
4827	struct st_partstat  * STps   = &(STp->ps[STp->partition]);
4828	struct osst_request * SRpnt  = NULL;
4829	char		    * name   = tape_name(STp);
4830
4831	if (file_count(filp) > 1)
4832		return 0;
4833
4834	if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4835		STp->write_type = OS_WRITE_DATA;
4836		result = osst_flush_write_buffer(STp, &SRpnt);
4837		if (result != 0 && result != (-ENOSPC))
4838			goto out;
4839	}
4840	if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4841
4842#if DEBUG
4843		if (debugging) {
4844			printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4845					       name, (long)(filp->f_pos));
4846			printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4847					       name, STp->nbr_waits, STp->nbr_finished);
4848		}
4849#endif
4850		result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4851#if DEBUG
4852		if (debugging)
4853			printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4854					       name, 1+STp->two_fm);
4855#endif
4856	}
4857	else if (!STp->rew_at_close) {
4858		STps = &(STp->ps[STp->partition]);
4859		if (!STm->sysv || STps->rw != ST_READING) {
4860			if (STp->can_bsr)
4861				result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4862			else if (STps->eof == ST_FM_HIT) {
4863				result = cross_eof(STp, &SRpnt, 0);
4864					if (result) {
4865						if (STps->drv_file >= 0)
4866							STps->drv_file++;
4867						STps->drv_block = 0;
4868						STps->eof = ST_FM;
4869					}
4870					else
4871						STps->eof = ST_NOEOF;
4872			}
4873		}
4874		else if ((STps->eof == ST_NOEOF &&
4875			  !(result = cross_eof(STp, &SRpnt, 1))) ||
4876			 STps->eof == ST_FM_HIT) {
4877			if (STps->drv_file >= 0)
4878				STps->drv_file++;
4879			STps->drv_block = 0;
4880			STps->eof = ST_FM;
4881		}
4882	}
4883
4884out:
4885	if (STp->rew_at_close) {
4886		result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4887		STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4888		if (result == 0 && result2 < 0)
4889			result = result2;
4890	}
4891	if (SRpnt) osst_release_request(SRpnt);
4892
4893	if (STp->abort_count || STp->recover_count) {
4894		printk(KERN_INFO "%s:I:", name);
4895		if (STp->abort_count)
4896			printk(" %d unrecovered errors", STp->abort_count);
4897		if (STp->recover_count)
4898			printk(" %d recovered errors", STp->recover_count);
4899		if (STp->write_count)
4900			printk(" in %d frames written", STp->write_count);
4901		if (STp->read_count)
4902			printk(" in %d frames read", STp->read_count);
4903		printk("\n");
4904		STp->recover_count = 0;
4905		STp->abort_count   = 0;
4906	}
4907	STp->write_count = 0;
4908	STp->read_count  = 0;
4909
4910	return result;
4911}
4912
4913
4914/* Close the device and release it */
4915static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4916{
4917	int		      result = 0;
4918	struct osst_tape    * STp    = filp->private_data;
4919
4920	if (STp->door_locked == ST_LOCKED_AUTO)
4921		do_door_lock(STp, 0);
4922
4923	if (STp->raw)
4924		STp->header_ok = 0;
4925	
4926	normalize_buffer(STp->buffer);
4927	write_lock(&os_scsi_tapes_lock);
4928	STp->in_use = 0;
4929	write_unlock(&os_scsi_tapes_lock);
4930
4931	scsi_device_put(STp->device);
4932
4933	return result;
4934}
4935
4936
4937/* The ioctl command */
4938static long osst_ioctl(struct file * file,
4939	 unsigned int cmd_in, unsigned long arg)
4940{
4941	int		      i, cmd_nr, cmd_type, blk, retval = 0;
4942	struct st_modedef   * STm;
4943	struct st_partstat  * STps;
4944	struct osst_request * SRpnt = NULL;
4945	struct osst_tape    * STp   = file->private_data;
4946	char		    * name  = tape_name(STp);
4947	void	    __user  * p     = (void __user *)arg;
4948
4949	mutex_lock(&osst_int_mutex);
4950	if (mutex_lock_interruptible(&STp->lock)) {
4951		mutex_unlock(&osst_int_mutex);
4952		return -ERESTARTSYS;
4953	}
4954
4955#if DEBUG
4956	if (debugging && !STp->in_use) {
4957		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4958		retval = (-EIO);
4959		goto out;
4960	}
4961#endif
4962	STm = &(STp->modes[STp->current_mode]);
4963	STps = &(STp->ps[STp->partition]);
4964
4965	/*
4966	 * If we are in the middle of error recovery, don't let anyone
4967	 * else try and use this device.  Also, if error recovery fails, it
4968	 * may try and take the device offline, in which case all further
4969	 * access to the device is prohibited.
4970	 */
4971	if( !scsi_block_when_processing_errors(STp->device) ) {
4972		retval = (-ENXIO);
4973		goto out;
4974	}
4975
4976	cmd_type = _IOC_TYPE(cmd_in);
4977	cmd_nr   = _IOC_NR(cmd_in);
4978#if DEBUG
4979	printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4980			    cmd_type, cmd_nr, STp->raw?"raw":"normal");
4981#endif
4982	if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4983		struct mtop mtc;
4984		int    auto_weof = 0;
4985
4986		if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4987			retval = (-EINVAL);
4988			goto out;
4989		}
4990
4991		i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4992		if (i) {
4993			retval = (-EFAULT);
4994			goto out;
4995		}
4996
4997		if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4998			printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4999			retval = (-EPERM);
5000			goto out;
5001		}
5002
5003		if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
5004			retval = (-ENXIO);
5005			goto out;
5006		}
5007
5008		if (!STp->pos_unknown) {
5009
5010			if (STps->eof == ST_FM_HIT) {
5011				if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
5012					mtc.mt_count -= 1;
5013					if (STps->drv_file >= 0)
5014						STps->drv_file += 1;
5015				}
5016				else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
5017					mtc.mt_count += 1;
5018					if (STps->drv_file >= 0)
5019						STps->drv_file += 1;
5020				}
5021			}
5022
5023			if (mtc.mt_op == MTSEEK) {
5024				/* Old position must be restored if partition will be changed */
5025				i = !STp->can_partitions || (STp->new_partition != STp->partition);
5026			}
5027			else {
5028				i = mtc.mt_op == MTREW   || mtc.mt_op == MTOFFL ||
5029				    mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM  ||
5030				    mtc.mt_op == MTLOCK  || mtc.mt_op == MTLOAD ||
5031				    mtc.mt_op == MTFSF   || mtc.mt_op == MTFSFM ||
5032				    mtc.mt_op == MTBSF   || mtc.mt_op == MTBSFM ||
5033				    mtc.mt_op == MTCOMPRESSION;
5034			}
5035			i = osst_flush_buffer(STp, &SRpnt, i);
5036			if (i < 0) {
5037				retval = i;
5038				goto out;
5039			}
5040		}
5041		else {
5042			/*
5043			 * If there was a bus reset, block further access
5044			 * to this device.  If the user wants to rewind the tape,
5045			 * then reset the flag and allow access again.
5046			 */
5047			if(mtc.mt_op != MTREW   &&
5048			   mtc.mt_op != MTOFFL  &&
5049			   mtc.mt_op != MTRETEN &&
5050			   mtc.mt_op != MTERASE &&
5051			   mtc.mt_op != MTSEEK  &&
5052			   mtc.mt_op != MTEOM)   {
5053				retval = (-EIO);
5054				goto out;
5055			}
5056			reset_state(STp);
5057			/* remove this when the midlevel properly clears was_reset */
5058			STp->device->was_reset = 0;
5059		}
5060
5061		if (mtc.mt_op != MTCOMPRESSION  && mtc.mt_op != MTLOCK         &&
5062		    mtc.mt_op != MTNOP          && mtc.mt_op != MTSETBLK       &&
5063		    mtc.mt_op != MTSETDENSITY   && mtc.mt_op != MTSETDRVBUFFER && 
5064		    mtc.mt_op != MTMKPART       && mtc.mt_op != MTSETPART      &&
5065		    mtc.mt_op != MTWEOF         && mtc.mt_op != MTWSM           ) {
5066
5067			/*
5068			 * The user tells us to move to another position on the tape.
5069			 * If we were appending to the tape content, that would leave
5070			 * the tape without proper end, in that case write EOD and
5071			 * update the header to reflect its position.
5072			 */
5073#if DEBUG
5074			printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
5075					STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
5076					STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
5077					STp->logical_blk_num, STps->drv_file, STps->drv_block );
5078#endif
5079			if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
5080				auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
5081							!(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5082				i = osst_write_trailer(STp, &SRpnt,
5083							!(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5084#if DEBUG
5085				printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5086						name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5087						STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5088#endif
5089				if (i < 0) {
5090					retval = i;
5091					goto out;
5092				}
5093			}
5094			STps->rw = ST_IDLE;
5095		}
5096
5097		if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5098			do_door_lock(STp, 0);  /* Ignore result! */
5099
5100		if (mtc.mt_op == MTSETDRVBUFFER &&
5101		   (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5102			retval = osst_set_options(STp, mtc.mt_count);
5103			goto out;
5104		}
5105
5106		if (mtc.mt_op == MTSETPART) {
5107			if (mtc.mt_count >= STp->nbr_partitions)
5108				retval = -EINVAL;
5109			else {
5110				STp->new_partition = mtc.mt_count;
5111				retval = 0;
5112			}
5113			goto out;
5114		}
5115
5116		if (mtc.mt_op == MTMKPART) {
5117			if (!STp->can_partitions) {
5118				retval = (-EINVAL);
5119				goto out;
5120			}
5121			if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5122			    (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5123				retval = i;
5124				goto out;
5125			}
5126			for (i=0; i < ST_NBR_PARTITIONS; i++) {
5127				STp->ps[i].rw = ST_IDLE;
5128				STp->ps[i].at_sm = 0;
5129				STp->ps[i].last_block_valid = 0;
5130			}
5131			STp->partition = STp->new_partition = 0;
5132			STp->nbr_partitions = 1;  /* Bad guess ?-) */
5133			STps->drv_block = STps->drv_file = 0;
5134			retval = 0;
5135			goto out;
5136	 	}
5137
5138		if (mtc.mt_op == MTSEEK) {
5139			if (STp->raw)
5140				i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5141			else
5142				i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5143			if (!STp->can_partitions)
5144				STp->ps[0].rw = ST_IDLE;
5145			retval = i;
5146			goto out;
5147		}
5148 
5149		if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5150			retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5151			goto out;
5152		}
5153
5154		if (auto_weof)
5155			cross_eof(STp, &SRpnt, 0);
5156
5157		if (mtc.mt_op == MTCOMPRESSION)
5158			retval = -EINVAL;       /* OnStream drives don't have compression hardware */
5159		else
5160			/* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5161			 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5162			retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5163		goto out;
5164	}
5165
5166	if (!STm->defined) {
5167		retval = (-ENXIO);
5168		goto out;
5169	}
5170
5171	if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5172		retval = i;
5173		goto out;
5174	}
5175
5176	if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5177		struct mtget mt_status;
5178
5179		if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5180			 retval = (-EINVAL);
5181			 goto out;
5182		}
5183
5184		mt_status.mt_type = MT_ISONSTREAM_SC;
5185		mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5186		mt_status.mt_dsreg =
5187			((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5188			((STp->density    << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5189		mt_status.mt_blkno = STps->drv_block;
5190		mt_status.mt_fileno = STps->drv_file;
5191		if (STp->block_size != 0) {
5192			if (STps->rw == ST_WRITING)
5193				mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5194			else if (STps->rw == ST_READING)
5195				mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5196							STp->block_size - 1) / STp->block_size;
5197		}
5198
5199		mt_status.mt_gstat = 0;
5200		if (STp->drv_write_prot)
5201			mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5202		if (mt_status.mt_blkno == 0) {
5203			if (mt_status.mt_fileno == 0)
5204				mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5205			else
5206				mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5207		}
5208		mt_status.mt_resid = STp->partition;
5209		if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5210			mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5211		else if (STps->eof >= ST_EOM_OK)
5212			mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5213		if (STp->density == 1)
5214			mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5215		else if (STp->density == 2)
5216			mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5217		else if (STp->density == 3)
5218			mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5219		if (STp->ready == ST_READY)
5220			mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5221		if (STp->ready == ST_NO_TAPE)
5222			mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5223		if (STps->at_sm)
5224			mt_status.mt_gstat |= GMT_SM(0xffffffff);
5225		if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5226		    STp->drv_buffer != 0)
5227			mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5228
5229		i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5230		if (i) {
5231			retval = (-EFAULT);
5232			goto out;
5233		}
5234
5235		STp->recover_erreg = 0;  /* Clear after read */
5236		retval = 0;
5237		goto out;
5238	} /* End of MTIOCGET */
5239
5240	if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5241		struct mtpos mt_pos;
5242
5243		if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5244			retval = (-EINVAL);
5245			goto out;
5246		}
5247		if (STp->raw)
5248			blk = osst_get_frame_position(STp, &SRpnt);
5249		else
5250			blk = osst_get_sector(STp, &SRpnt);
5251		if (blk < 0) {
5252			retval = blk;
5253			goto out;
5254		}
5255		mt_pos.mt_blkno = blk;
5256		i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5257		if (i)
5258			retval = -EFAULT;
5259		goto out;
5260	}
5261	if (SRpnt) osst_release_request(SRpnt);
5262
5263	mutex_unlock(&STp->lock);
5264
5265	retval = scsi_ioctl(STp->device, cmd_in, p);
5266	mutex_unlock(&osst_int_mutex);
5267	return retval;
5268
5269out:
5270	if (SRpnt) osst_release_request(SRpnt);
5271
5272	mutex_unlock(&STp->lock);
5273	mutex_unlock(&osst_int_mutex);
5274
5275	return retval;
5276}
5277
5278#ifdef CONFIG_COMPAT
5279static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5280{
5281	struct osst_tape *STp = file->private_data;
5282	struct scsi_device *sdev = STp->device;
5283	int ret = -ENOIOCTLCMD;
5284	if (sdev->host->hostt->compat_ioctl) {
5285
5286		ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5287
5288	}
5289	return ret;
5290}
5291#endif
5292
5293
5294
5295/* Memory handling routines */
5296
5297/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5298static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5299{
5300	int i;
5301	gfp_t priority;
5302	struct osst_buffer *tb;
5303
5304	if (from_initialization)
5305		priority = GFP_ATOMIC;
5306	else
5307		priority = GFP_KERNEL;
5308
5309	i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5310	tb = kzalloc(i, priority);
5311	if (!tb) {
5312		printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5313		return NULL;
5314	}
5315
5316	tb->sg_segs = tb->orig_sg_segs = 0;
5317	tb->use_sg = max_sg;
5318	tb->in_use = 1;
5319	tb->dma = need_dma;
5320	tb->buffer_size = 0;
5321#if DEBUG
5322	if (debugging) 
5323		printk(OSST_DEB_MSG
5324			"osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5325			   i, max_sg, need_dma);
5326#endif
5327	return tb;
5328}
5329
5330/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5331static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5332{
5333	int segs, nbr, max_segs, b_size, order, got;
5334	gfp_t priority;
5335
5336	if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5337		return 1;
5338
5339	if (STbuffer->sg_segs) {
5340		printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5341		normalize_buffer(STbuffer);
5342	}
5343	/* See how many segments we can use -- need at least two */
5344	nbr = max_segs = STbuffer->use_sg;
5345	if (nbr <= 2)
5346		return 0;
5347
5348	priority = GFP_KERNEL /* | __GFP_NOWARN */;
5349	if (need_dma)
5350		priority |= GFP_DMA;
5351
5352	/* Try to allocate the first segment up to OS_DATA_SIZE and the others
5353	   big enough to reach the goal (code assumes no segments in place) */
5354	for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5355		struct page *page = alloc_pages(priority, order);
5356
5357		STbuffer->sg[0].offset = 0;
5358		if (page != NULL) {
5359		    sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5360		    STbuffer->b_data = page_address(page);
5361		    break;
5362		}
5363	}
5364	if (sg_page(&STbuffer->sg[0]) == NULL) {
5365		printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5366		return 0;
5367	}
5368	/* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5369	for (segs=STbuffer->sg_segs=1, got=b_size;
5370	     segs < max_segs && got < OS_FRAME_SIZE; ) {
5371		struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5372		STbuffer->sg[segs].offset = 0;
5373		if (page == NULL) {
5374			printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5375						OS_FRAME_SIZE);
5376#if DEBUG
5377			STbuffer->buffer_size = got;
5378#endif
5379			normalize_buffer(STbuffer);
5380			return 0;
5381		}
5382		sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5383		got += STbuffer->sg[segs].length;
5384		STbuffer->buffer_size = got;
5385		STbuffer->sg_segs = ++segs;
5386	}
5387#if DEBUG
5388	if (debugging) {
5389		printk(OSST_DEB_MSG
5390			   "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5391			   got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5392		printk(OSST_DEB_MSG
5393			   "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5394			   STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5395			   STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5396	}
5397#endif
5398
5399	return 1;
5400}
5401
5402
5403/* Release the segments */
5404static void normalize_buffer(struct osst_buffer *STbuffer)
5405{
5406  int i, order, b_size;
5407
5408	for (i=0; i < STbuffer->sg_segs; i++) {
5409
5410		for (b_size = PAGE_SIZE, order = 0;
5411		     b_size < STbuffer->sg[i].length;
5412		     b_size *= 2, order++);
5413
5414		__free_pages(sg_page(&STbuffer->sg[i]), order);
5415		STbuffer->buffer_size -= STbuffer->sg[i].length;
5416	}
5417#if DEBUG
5418	if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5419		printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5420			     STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5421#endif
5422	STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5423}
5424
5425
5426/* Move data from the user buffer to the tape buffer. Returns zero (success) or
5427   negative error code. */
5428static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5429{
5430	int i, cnt, res, offset;
5431
5432	for (i=0, offset=st_bp->buffer_bytes;
5433	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5434	offset -= st_bp->sg[i].length;
5435	if (i == st_bp->sg_segs) {  /* Should never happen */
5436		printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5437		return (-EIO);
5438	}
5439	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5440		cnt = st_bp->sg[i].length - offset < do_count ?
5441		      st_bp->sg[i].length - offset : do_count;
5442		res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5443		if (res)
5444			return (-EFAULT);
5445		do_count -= cnt;
5446		st_bp->buffer_bytes += cnt;
5447		ubp += cnt;
5448		offset = 0;
5449	}
5450	if (do_count) {  /* Should never happen */
5451		printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5452		       do_count);
5453		return (-EIO);
5454	}
5455	return 0;
5456}
5457
5458
5459/* Move data from the tape buffer to the user buffer. Returns zero (success) or
5460   negative error code. */
5461static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5462{
5463	int i, cnt, res, offset;
5464
5465	for (i=0, offset=st_bp->read_pointer;
5466	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5467		offset -= st_bp->sg[i].length;
5468	if (i == st_bp->sg_segs) {  /* Should never happen */
5469		printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5470		return (-EIO);
5471	}
5472	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5473		cnt = st_bp->sg[i].length - offset < do_count ?
5474		      st_bp->sg[i].length - offset : do_count;
5475		res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5476		if (res)
5477			return (-EFAULT);
5478		do_count -= cnt;
5479		st_bp->buffer_bytes -= cnt;
5480		st_bp->read_pointer += cnt;
5481		ubp += cnt;
5482		offset = 0;
5483	}
5484	if (do_count) {  /* Should never happen */
5485		printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5486		return (-EIO);
5487	}
5488	return 0;
5489}
5490
5491/* Sets the tail of the buffer after fill point to zero.
5492   Returns zero (success) or negative error code.        */
5493static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5494{
5495	int	i, offset, do_count, cnt;
5496
5497	for (i = 0, offset = st_bp->buffer_bytes;
5498	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5499		offset -= st_bp->sg[i].length;
5500	if (i == st_bp->sg_segs) {  /* Should never happen */
5501		printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5502		return (-EIO);
5503	}
5504	for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5505	     i < st_bp->sg_segs && do_count > 0; i++) {
5506		cnt = st_bp->sg[i].length - offset < do_count ?
5507		      st_bp->sg[i].length - offset : do_count ;
5508		memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5509		do_count -= cnt;
5510		offset = 0;
5511	}
5512	if (do_count) {  /* Should never happen */
5513		printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5514		return (-EIO);
5515	}
5516	return 0;
5517}
5518
5519/* Copy a osst 32K chunk of memory into the buffer.
5520   Returns zero (success) or negative error code.  */
5521static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5522{
5523	int	i, cnt, do_count = OS_DATA_SIZE;
5524
5525	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5526		cnt = st_bp->sg[i].length < do_count ?
5527		      st_bp->sg[i].length : do_count ;
5528		memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5529		do_count -= cnt;
5530		ptr      += cnt;
5531	}
5532	if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5533		printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5534					 do_count, i);
5535		return (-EIO);
5536	}
5537	return 0;
5538}
5539
5540/* Copy a osst 32K chunk of memory from the buffer.
5541   Returns zero (success) or negative error code.  */
5542static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5543{
5544	int	i, cnt, do_count = OS_DATA_SIZE;
5545
5546	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5547		cnt = st_bp->sg[i].length < do_count ?
5548		      st_bp->sg[i].length : do_count ;
5549		memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5550		do_count -= cnt;
5551		ptr      += cnt;
5552	}
5553	if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5554		printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5555					 do_count, i);
5556		return (-EIO);
5557	}
5558	return 0;
5559}
5560
5561
5562/* Module housekeeping */
5563
5564static void validate_options (void)
5565{
5566  if (max_dev > 0)
5567		osst_max_dev = max_dev;  
5568  if (write_threshold_kbs > 0)
5569		osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5570  if (osst_write_threshold > osst_buffer_size)
5571		osst_write_threshold = osst_buffer_size;
5572  if (max_sg_segs >= OSST_FIRST_SG)
5573		osst_max_sg_segs = max_sg_segs;
5574#if DEBUG
5575  printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5576			   osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5577#endif
5578}
5579	
5580#ifndef MODULE
5581/* Set the boot options. Syntax: osst=xxx,yyy,...
5582   where xxx is write threshold in 1024 byte blocks,
5583   and   yyy is number of s/g segments to use. */
5584static int __init osst_setup (char *str)
5585{
5586  int i, ints[5];
5587  char *stp;
5588
5589  stp = get_options(str, ARRAY_SIZE(ints), ints);
5590
5591  if (ints[0] > 0) {
5592	for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5593		  *parms[i].val = ints[i + 1];
5594  } else {
5595	while (stp != NULL) {
5596		for (i = 0; i < ARRAY_SIZE(parms); i++) {
5597			int len = strlen(parms[i].name);
5598			if (!strncmp(stp, parms[i].name, len) &&
5599			    (*(stp + len) == ':' || *(stp + len) == '=')) {
5600				*parms[i].val =
5601					simple_strtoul(stp + len + 1, NULL, 0);
5602				break;
5603			}
5604		}
5605		if (i >= ARRAY_SIZE(parms))
5606			printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5607			       stp);
5608		stp = strchr(stp, ',');
5609		if (stp)
5610			stp++;
5611	}
5612  }
5613
5614  return 1;
5615}
5616
5617__setup("osst=", osst_setup);
5618
5619#endif
5620
5621static const struct file_operations osst_fops = {
5622	.owner =        THIS_MODULE,
5623	.read =         osst_read,
5624	.write =        osst_write,
5625	.unlocked_ioctl = osst_ioctl,
5626#ifdef CONFIG_COMPAT
5627	.compat_ioctl = osst_compat_ioctl,
5628#endif
5629	.open =         os_scsi_tape_open,
5630	.flush =        os_scsi_tape_flush,
5631	.release =      os_scsi_tape_close,
5632	.llseek =	noop_llseek,
5633};
5634
5635static int osst_supports(struct scsi_device * SDp)
5636{
5637	struct	osst_support_data {
5638		char *vendor;
5639		char *model;
5640		char *rev;
5641		char *driver_hint; /* Name of the correct driver, NULL if unknown */
5642	};
5643
5644static	struct	osst_support_data support_list[] = {
5645		/* {"XXX", "Yy-", "", NULL},  example */
5646		SIGS_FROM_OSST,
5647		{NULL, }};
5648
5649	struct	osst_support_data *rp;
5650
5651	/* We are willing to drive OnStream SC-x0 as well as the
5652	 * 	 * IDE, ParPort, FireWire, USB variants, if accessible by
5653	 * 	 	 * emulation layer (ide-scsi, usb-storage, ...) */
5654
5655	for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5656		if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5657		    !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5658		    !strncmp(rp->rev, SDp->rev, strlen(rp->rev))) 
5659			return 1;
5660	return 0;
5661}
5662
5663/*
5664 * sysfs support for osst driver parameter information
5665 */
5666
5667static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5668{
5669	return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5670}
5671
5672static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5673
5674static int osst_create_sysfs_files(struct device_driver *sysfs)
5675{
5676	return driver_create_file(sysfs, &driver_attr_version);
5677}
5678
5679static void osst_remove_sysfs_files(struct device_driver *sysfs)
5680{
5681	driver_remove_file(sysfs, &driver_attr_version);
5682}
5683
5684/*
5685 * sysfs support for accessing ADR header information
5686 */
5687
5688static ssize_t osst_adr_rev_show(struct device *dev,
5689				 struct device_attribute *attr, char *buf)
5690{
5691	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5692	ssize_t l = 0;
5693
5694	if (STp && STp->header_ok && STp->linux_media)
5695		l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5696	return l;
5697}
5698
5699DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5700
5701static ssize_t osst_linux_media_version_show(struct device *dev,
5702					     struct device_attribute *attr,
5703					     char *buf)
5704{
5705	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5706	ssize_t l = 0;
5707
5708	if (STp && STp->header_ok && STp->linux_media)
5709		l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5710	return l;
5711}
5712
5713DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5714
5715static ssize_t osst_capacity_show(struct device *dev,
5716				  struct device_attribute *attr, char *buf)
5717{
5718	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5719	ssize_t l = 0;
5720
5721	if (STp && STp->header_ok && STp->linux_media)
5722		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5723	return l;
5724}
5725
5726DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5727
5728static ssize_t osst_first_data_ppos_show(struct device *dev,
5729					 struct device_attribute *attr,
5730					 char *buf)
5731{
5732	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5733	ssize_t l = 0;
5734
5735	if (STp && STp->header_ok && STp->linux_media)
5736		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5737	return l;
5738}
5739
5740DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5741
5742static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5743					struct device_attribute *attr,
5744					char *buf)
5745{
5746	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5747	ssize_t l = 0;
5748
5749	if (STp && STp->header_ok && STp->linux_media)
5750		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5751	return l;
5752}
5753
5754DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5755
5756static ssize_t osst_filemark_cnt_show(struct device *dev,
5757				      struct device_attribute *attr, char *buf)
5758{
5759	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5760	ssize_t l = 0;
5761
5762	if (STp && STp->header_ok && STp->linux_media)
5763		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5764	return l;
5765}
5766
5767DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5768
5769static struct class *osst_sysfs_class;
5770
5771static int osst_sysfs_init(void)
5772{
5773	osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5774	if (IS_ERR(osst_sysfs_class)) {
5775		printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5776		return PTR_ERR(osst_sysfs_class);
5777	}
5778
5779	return 0;
5780}
5781
5782static void osst_sysfs_destroy(dev_t dev)
5783{
5784	device_destroy(osst_sysfs_class, dev);
5785}
5786
5787static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5788{
5789	struct device *osst_member;
5790	int err;
5791
5792	osst_member = device_create(osst_sysfs_class, device, dev, STp,
5793				    "%s", name);
5794	if (IS_ERR(osst_member)) {
5795		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5796		return PTR_ERR(osst_member);
5797	}
5798
5799	err = device_create_file(osst_member, &dev_attr_ADR_rev);
5800	if (err)
5801		goto err_out;
5802	err = device_create_file(osst_member, &dev_attr_media_version);
5803	if (err)
5804		goto err_out;
5805	err = device_create_file(osst_member, &dev_attr_capacity);
5806	if (err)
5807		goto err_out;
5808	err = device_create_file(osst_member, &dev_attr_BOT_frame);
5809	if (err)
5810		goto err_out;
5811	err = device_create_file(osst_member, &dev_attr_EOD_frame);
5812	if (err)
5813		goto err_out;
5814	err = device_create_file(osst_member, &dev_attr_file_count);
5815	if (err)
5816		goto err_out;
5817
5818	return 0;
5819
5820err_out:
5821	osst_sysfs_destroy(dev);
5822	return err;
5823}
5824
5825static void osst_sysfs_cleanup(void)
5826{
5827	class_destroy(osst_sysfs_class);
5828}
5829
5830/*
5831 * osst startup / cleanup code
5832 */
5833
5834static int osst_probe(struct device *dev)
5835{
5836	struct scsi_device * SDp = to_scsi_device(dev);
5837	struct osst_tape   * tpnt;
5838	struct st_modedef  * STm;
5839	struct st_partstat * STps;
5840	struct osst_buffer * buffer;
5841	struct gendisk	   * drive;
5842	int		     i, dev_num, err = -ENODEV;
5843
5844	if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5845		return -ENODEV;
5846
5847	drive = alloc_disk(1);
5848	if (!drive) {
5849		printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5850		return -ENODEV;
5851	}
5852
5853	/* if this is the first attach, build the infrastructure */
5854	write_lock(&os_scsi_tapes_lock);
5855	if (os_scsi_tapes == NULL) {
5856		os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC);
5857		if (os_scsi_tapes == NULL) {
5858			write_unlock(&os_scsi_tapes_lock);
5859			printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5860			goto out_put_disk;
5861		}
5862		for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5863	}
5864	
5865	if (osst_nr_dev >= osst_max_dev) {
5866		write_unlock(&os_scsi_tapes_lock);
5867		printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5868		goto out_put_disk;
5869	}
5870
5871	/* find a free minor number */
5872	for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++)
5873		;
5874	if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5875	dev_num = i;
5876
5877	/* allocate a struct osst_tape for this device */
5878	tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5879	if (!tpnt) {
5880		write_unlock(&os_scsi_tapes_lock);
5881		printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5882		goto out_put_disk;
5883	}
5884
5885	/* allocate a buffer for this device */
5886	i = SDp->host->sg_tablesize;
5887	if (osst_max_sg_segs < i)
5888		i = osst_max_sg_segs;
5889	buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5890	if (buffer == NULL) {
5891		write_unlock(&os_scsi_tapes_lock);
5892		printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5893		kfree(tpnt);
5894		goto out_put_disk;
5895	}
5896	os_scsi_tapes[dev_num] = tpnt;
5897	tpnt->buffer = buffer;
5898	tpnt->device = SDp;
5899	drive->private_data = &tpnt->driver;
5900	sprintf(drive->disk_name, "osst%d", dev_num);
5901	tpnt->driver = &osst_template;
5902	tpnt->drive = drive;
5903	tpnt->in_use = 0;
5904	tpnt->capacity = 0xfffff;
5905	tpnt->dirty = 0;
5906	tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
5907	tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5908	tpnt->density = 0;
5909	tpnt->do_auto_lock = OSST_AUTO_LOCK;
5910	tpnt->can_bsr = OSST_IN_FILE_POS;
5911	tpnt->can_partitions = 0;
5912	tpnt->two_fm = OSST_TWO_FM;
5913	tpnt->fast_mteom = OSST_FAST_MTEOM;
5914	tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5915	tpnt->write_threshold = osst_write_threshold;
5916	tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5917	tpnt->partition = 0;
5918	tpnt->new_partition = 0;
5919	tpnt->nbr_partitions = 0;
5920	tpnt->min_block = 512;
5921	tpnt->max_block = OS_DATA_SIZE;
5922	tpnt->timeout = OSST_TIMEOUT;
5923	tpnt->long_timeout = OSST_LONG_TIMEOUT;
5924
5925	/* Recognize OnStream tapes */
5926	/* We don't need to test for OnStream, as this has been done in detect () */
5927	tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5928	tpnt->omit_blklims = 1;
5929
5930	tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || 
5931		     (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5932	tpnt->frame_in_buffer = 0;
5933	tpnt->header_ok = 0;
5934	tpnt->linux_media = 0;
5935	tpnt->header_cache = NULL;
5936
5937	for (i=0; i < ST_NBR_MODES; i++) {
5938		STm = &(tpnt->modes[i]);
5939		STm->defined = 0;
5940		STm->sysv = OSST_SYSV;
5941		STm->defaults_for_writes = 0;
5942		STm->do_async_writes = OSST_ASYNC_WRITES;
5943		STm->do_buffer_writes = OSST_BUFFER_WRITES;
5944		STm->do_read_ahead = OSST_READ_AHEAD;
5945		STm->default_compression = ST_DONT_TOUCH;
5946		STm->default_blksize = 512;
5947		STm->default_density = (-1);  /* No forced density */
5948	}
5949
5950	for (i=0; i < ST_NBR_PARTITIONS; i++) {
5951		STps = &(tpnt->ps[i]);
5952		STps->rw = ST_IDLE;
5953		STps->eof = ST_NOEOF;
5954		STps->at_sm = 0;
5955		STps->last_block_valid = 0;
5956		STps->drv_block = (-1);
5957		STps->drv_file = (-1);
5958	}
5959
5960	tpnt->current_mode = 0;
5961	tpnt->modes[0].defined = 1;
5962	tpnt->modes[2].defined = 1;
5963	tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5964
5965	mutex_init(&tpnt->lock);
5966	osst_nr_dev++;
5967	write_unlock(&os_scsi_tapes_lock);
5968
5969	{
5970		char name[8];
5971
5972		/*  Rewind entry  */
5973		err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5974		if (err)
5975			goto out_free_buffer;
5976
5977		/*  No-rewind entry  */
5978		snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5979		err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5980		if (err)
5981			goto out_free_sysfs1;
5982	}
5983
5984	sdev_printk(KERN_INFO, SDp,
5985		"osst :I: Attached OnStream %.5s tape as %s\n",
5986		SDp->model, tape_name(tpnt));
5987
5988	return 0;
5989
5990out_free_sysfs1:
5991	osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5992out_free_buffer:
5993	kfree(buffer);
5994out_put_disk:
5995        put_disk(drive);
5996        return err;
5997};
5998
5999static int osst_remove(struct device *dev)
6000{
6001	struct scsi_device * SDp = to_scsi_device(dev);
6002	struct osst_tape * tpnt;
6003	int i;
6004
6005	if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
6006		return 0;
6007
6008	write_lock(&os_scsi_tapes_lock);
6009	for(i=0; i < osst_max_dev; i++) {
6010		if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
6011			osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
6012			osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
6013			tpnt->device = NULL;
6014			put_disk(tpnt->drive);
6015			os_scsi_tapes[i] = NULL;
6016			osst_nr_dev--;
6017			write_unlock(&os_scsi_tapes_lock);
6018			vfree(tpnt->header_cache);
6019			if (tpnt->buffer) {
6020				normalize_buffer(tpnt->buffer);
6021				kfree(tpnt->buffer);
6022			}
6023			kfree(tpnt);
6024			return 0;
6025		}
6026	}
6027	write_unlock(&os_scsi_tapes_lock);
6028	return 0;
6029}
6030
6031static int __init init_osst(void) 
6032{
6033	int err;
6034
6035	printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
6036
6037	validate_options();
6038
6039	err = osst_sysfs_init();
6040	if (err)
6041		return err;
6042
6043	err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
6044	if (err < 0) {
6045		printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
6046		goto err_out;
6047	}
6048
6049	err = scsi_register_driver(&osst_template.gendrv);
6050	if (err)
6051		goto err_out_chrdev;
6052
6053	err = osst_create_sysfs_files(&osst_template.gendrv);
6054	if (err)
6055		goto err_out_scsidrv;
6056
6057	return 0;
6058
6059err_out_scsidrv:
6060	scsi_unregister_driver(&osst_template.gendrv);
6061err_out_chrdev:
6062	unregister_chrdev(OSST_MAJOR, "osst");
6063err_out:
6064	osst_sysfs_cleanup();
6065	return err;
6066}
6067
6068static void __exit exit_osst (void)
6069{
6070	int i;
6071	struct osst_tape * STp;
6072
6073	osst_remove_sysfs_files(&osst_template.gendrv);
6074	scsi_unregister_driver(&osst_template.gendrv);
6075	unregister_chrdev(OSST_MAJOR, "osst");
6076	osst_sysfs_cleanup();
6077
6078	if (os_scsi_tapes) {
6079		for (i=0; i < osst_max_dev; ++i) {
6080			if (!(STp = os_scsi_tapes[i])) continue;
6081			/* This is defensive, supposed to happen during detach */
6082			vfree(STp->header_cache);
6083			if (STp->buffer) {
6084				normalize_buffer(STp->buffer);
6085				kfree(STp->buffer);
6086			}
6087			put_disk(STp->drive);
6088			kfree(STp);
6089		}
6090		kfree(os_scsi_tapes);
6091	}
6092	printk(KERN_INFO "osst :I: Unloaded.\n");
6093}
6094
6095module_init(init_osst);
6096module_exit(exit_osst);
v3.5.6
   1/*
   2  SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
   3  file Documentation/scsi/st.txt for more information.
   4
   5  History:
   6
   7  OnStream SCSI Tape support (osst) cloned from st.c by
   8  Willem Riede (osst@riede.org) Feb 2000
   9  Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
  10
  11  Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
  12  Contribution and ideas from several people including (in alphabetical
  13  order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
  14  Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
  15
  16  Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
  17	 email osst@riede.org
  18
  19  $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
  20
  21  Microscopic alterations - Rik Ling, 2000/12/21
  22  Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
  23  Some small formal changes - aeb, 950809
  24*/
  25
  26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
  27static const char * osst_version = "0.99.4";
  28
  29/* The "failure to reconnect" firmware bug */
  30#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
  31#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
  32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
  33
  34#include <linux/module.h>
  35
  36#include <linux/fs.h>
  37#include <linux/kernel.h>
  38#include <linux/sched.h>
  39#include <linux/proc_fs.h>
  40#include <linux/mm.h>
  41#include <linux/slab.h>
  42#include <linux/init.h>
  43#include <linux/string.h>
  44#include <linux/errno.h>
  45#include <linux/mtio.h>
  46#include <linux/ioctl.h>
  47#include <linux/fcntl.h>
  48#include <linux/spinlock.h>
  49#include <linux/vmalloc.h>
  50#include <linux/blkdev.h>
  51#include <linux/moduleparam.h>
  52#include <linux/delay.h>
  53#include <linux/jiffies.h>
  54#include <linux/mutex.h>
  55#include <asm/uaccess.h>
  56#include <asm/dma.h>
 
  57
  58/* The driver prints some debugging information on the console if DEBUG
  59   is defined and non-zero. */
  60#define DEBUG 0
  61
  62/* The message level for the debug messages is currently set to KERN_NOTICE
  63   so that people can easily see the messages. Later when the debugging messages
  64   in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
  65#define OSST_DEB_MSG  KERN_NOTICE
  66
  67#include <scsi/scsi.h>
  68#include <scsi/scsi_dbg.h>
  69#include <scsi/scsi_device.h>
  70#include <scsi/scsi_driver.h>
  71#include <scsi/scsi_eh.h>
  72#include <scsi/scsi_host.h>
  73#include <scsi/scsi_ioctl.h>
  74
  75#define ST_KILOBYTE 1024
  76
  77#include "st.h"
  78#include "osst.h"
  79#include "osst_options.h"
  80#include "osst_detect.h"
  81
  82static DEFINE_MUTEX(osst_int_mutex);
  83static int max_dev = 0;
  84static int write_threshold_kbs = 0;
  85static int max_sg_segs = 0;
  86
  87#ifdef MODULE
  88MODULE_AUTHOR("Willem Riede");
  89MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
  90MODULE_LICENSE("GPL");
  91MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
  92MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
  93
  94module_param(max_dev, int, 0444);
  95MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
  96
  97module_param(write_threshold_kbs, int, 0644);
  98MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
  99
 100module_param(max_sg_segs, int, 0644);
 101MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
 102#else
 103static struct osst_dev_parm {
 104       char   *name;
 105       int    *val;
 106} parms[] __initdata = {
 107       { "max_dev",             &max_dev             },
 108       { "write_threshold_kbs", &write_threshold_kbs },
 109       { "max_sg_segs",         &max_sg_segs         }
 110};
 111#endif
 112
 113/* Some default definitions have been moved to osst_options.h */
 114#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
 115#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
 116
 117/* The buffer size should fit into the 24 bits for length in the
 118   6-byte SCSI read and write commands. */
 119#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
 120#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
 121#endif
 122
 123#if DEBUG
 124static int debugging = 1;
 125/* uncomment define below to test error recovery */
 126// #define OSST_INJECT_ERRORS 1 
 127#endif
 128
 129/* Do not retry! The drive firmware already retries when appropriate,
 130   and when it tries to tell us something, we had better listen... */
 131#define MAX_RETRIES 0
 132
 133#define NO_TAPE  NOT_READY
 134
 135#define OSST_WAIT_POSITION_COMPLETE   (HZ > 200 ? HZ / 200 : 1)
 136#define OSST_WAIT_WRITE_COMPLETE      (HZ / 12)
 137#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
 138	
 139#define OSST_TIMEOUT (200 * HZ)
 140#define OSST_LONG_TIMEOUT (1800 * HZ)
 141
 142#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
 143#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
 144#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
 145#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
 146
 147/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
 148   24 bits) */
 149#define SET_DENS_AND_BLK 0x10001
 150
 151static int osst_buffer_size       = OSST_BUFFER_SIZE;
 152static int osst_write_threshold   = OSST_WRITE_THRESHOLD;
 153static int osst_max_sg_segs       = OSST_MAX_SG;
 154static int osst_max_dev           = OSST_MAX_TAPES;
 155static int osst_nr_dev;
 156
 157static struct osst_tape **os_scsi_tapes = NULL;
 158static DEFINE_RWLOCK(os_scsi_tapes_lock);
 159
 160static int modes_defined = 0;
 161
 162static struct osst_buffer *new_tape_buffer(int, int, int);
 163static int enlarge_buffer(struct osst_buffer *, int);
 164static void normalize_buffer(struct osst_buffer *);
 165static int append_to_buffer(const char __user *, struct osst_buffer *, int);
 166static int from_buffer(struct osst_buffer *, char __user *, int);
 167static int osst_zero_buffer_tail(struct osst_buffer *);
 168static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
 169static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
 170
 171static int osst_probe(struct device *);
 172static int osst_remove(struct device *);
 173
 174static struct scsi_driver osst_template = {
 175	.owner			= THIS_MODULE,
 176	.gendrv = {
 177		.name		=  "osst",
 178		.probe		= osst_probe,
 179		.remove		= osst_remove,
 180	}
 181};
 182
 183static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
 184			    unsigned int cmd_in, unsigned long arg);
 185
 186static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
 187
 188static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
 189
 190static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
 191
 192static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
 193
 194static inline char *tape_name(struct osst_tape *tape)
 195{
 196	return tape->drive->disk_name;
 197}
 198
 199/* Routines that handle the interaction with mid-layer SCSI routines */
 200
 201
 202/* Normalize Sense */
 203static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
 204{
 205	const u8 *ucp;
 206	const u8 *sense = SRpnt->sense;
 207
 208	s->have_sense = scsi_normalize_sense(SRpnt->sense,
 209				SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
 210	s->flags = 0;
 211
 212	if (s->have_sense) {
 213		s->deferred = 0;
 214		s->remainder_valid =
 215			scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
 216		switch (sense[0] & 0x7f) {
 217		case 0x71:
 218			s->deferred = 1;
 219		case 0x70:
 220			s->fixed_format = 1;
 221			s->flags = sense[2] & 0xe0;
 222			break;
 223		case 0x73:
 224			s->deferred = 1;
 225		case 0x72:
 226			s->fixed_format = 0;
 227			ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
 228			s->flags = ucp ? (ucp[3] & 0xe0) : 0;
 229			break;
 230		}
 231	}
 232}
 233
 234/* Convert the result to success code */
 235static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
 236{
 237	char *name = tape_name(STp);
 238	int result = SRpnt->result;
 239	u8 * sense = SRpnt->sense, scode;
 240#if DEBUG
 241	const char *stp;
 242#endif
 243	struct st_cmdstatus *cmdstatp;
 244
 245	if (!result)
 246		return 0;
 247
 248	cmdstatp = &STp->buffer->cmdstat;
 249	osst_analyze_sense(SRpnt, cmdstatp);
 250
 251	if (cmdstatp->have_sense)
 252		scode = STp->buffer->cmdstat.sense_hdr.sense_key;
 253	else
 254		scode = 0;
 255#if DEBUG
 256	if (debugging) {
 257		printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
 258		   name, result,
 259		   SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
 260		   SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
 261		if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
 262			       	name, scode, sense[12], sense[13]);
 263		if (cmdstatp->have_sense)
 264			__scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 265	}
 266	else
 267#endif
 268	if (cmdstatp->have_sense && (
 269		 scode != NO_SENSE &&
 270		 scode != RECOVERED_ERROR &&
 271/*      	 scode != UNIT_ATTENTION && */
 272		 scode != BLANK_CHECK &&
 273		 scode != VOLUME_OVERFLOW &&
 274		 SRpnt->cmd[0] != MODE_SENSE &&
 275		 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
 276		if (cmdstatp->have_sense) {
 277			printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
 278			__scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 279		}
 280		else {
 281			static	int	notyetprinted = 1;
 282
 283			printk(KERN_WARNING
 284			     "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
 285			     name, result, driver_byte(result),
 286			     host_byte(result));
 287			if (notyetprinted) {
 288				notyetprinted = 0;
 289				printk(KERN_INFO
 290					"%s:I: This warning may be caused by your scsi controller,\n", name);
 291				printk(KERN_INFO
 292					"%s:I: it has been reported with some Buslogic cards.\n", name);
 293			}
 294		}
 295	}
 296	STp->pos_unknown |= STp->device->was_reset;
 297
 298	if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
 299		STp->recover_count++;
 300		STp->recover_erreg++;
 301#if DEBUG
 302		if (debugging) {
 303			if (SRpnt->cmd[0] == READ_6)
 304				stp = "read";
 305			else if (SRpnt->cmd[0] == WRITE_6)
 306				stp = "write";
 307			else
 308				stp = "ioctl";
 309			printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
 310					     STp->recover_count);
 311		}
 312#endif
 313		if ((sense[2] & 0xe0) == 0)
 314			return 0;
 315	}
 316	return (-EIO);
 317}
 318
 319
 320/* Wakeup from interrupt */
 321static void osst_end_async(struct request *req, int update)
 322{
 323	struct osst_request *SRpnt = req->end_io_data;
 324	struct osst_tape *STp = SRpnt->stp;
 325	struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
 326
 327	STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
 328#if DEBUG
 329	STp->write_pending = 0;
 330#endif
 331	if (SRpnt->waiting)
 332		complete(SRpnt->waiting);
 333
 334	if (SRpnt->bio) {
 335		kfree(mdata->pages);
 336		blk_rq_unmap_user(SRpnt->bio);
 337	}
 338
 339	__blk_put_request(req->q, req);
 340}
 341
 342/* osst_request memory management */
 343static struct osst_request *osst_allocate_request(void)
 344{
 345	return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
 346}
 347
 348static void osst_release_request(struct osst_request *streq)
 349{
 350	kfree(streq);
 351}
 352
 353static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
 354			int cmd_len, int data_direction, void *buffer, unsigned bufflen,
 355			int use_sg, int timeout, int retries)
 356{
 357	struct request *req;
 358	struct page **pages = NULL;
 359	struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
 360
 361	int err = 0;
 362	int write = (data_direction == DMA_TO_DEVICE);
 363
 364	req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
 365	if (!req)
 366		return DRIVER_ERROR << 24;
 367
 368	req->cmd_type = REQ_TYPE_BLOCK_PC;
 369	req->cmd_flags |= REQ_QUIET;
 370
 371	SRpnt->bio = NULL;
 372
 373	if (use_sg) {
 374		struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
 375		int i;
 376
 377		pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
 378		if (!pages)
 379			goto free_req;
 380
 381		for_each_sg(sgl, sg, use_sg, i)
 382			pages[i] = sg_page(sg);
 383
 384		mdata->null_mapped = 1;
 385
 386		mdata->page_order = get_order(sgl[0].length);
 387		mdata->nr_entries =
 388			DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
 389		mdata->offset = 0;
 390
 391		err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
 392		if (err) {
 393			kfree(pages);
 394			goto free_req;
 395		}
 396		SRpnt->bio = req->bio;
 397		mdata->pages = pages;
 398
 399	} else if (bufflen) {
 400		err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
 401		if (err)
 402			goto free_req;
 403	}
 404
 405	req->cmd_len = cmd_len;
 406	memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
 407	memcpy(req->cmd, cmd, req->cmd_len);
 408	req->sense = SRpnt->sense;
 409	req->sense_len = 0;
 410	req->timeout = timeout;
 411	req->retries = retries;
 412	req->end_io_data = SRpnt;
 413
 414	blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
 415	return 0;
 416free_req:
 417	blk_put_request(req);
 418	return DRIVER_ERROR << 24;
 419}
 420
 421/* Do the scsi command. Waits until command performed if do_wait is true.
 422   Otherwise osst_write_behind_check() is used to check that the command
 423   has finished. */
 424static	struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp, 
 425	unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
 426{
 427	unsigned char *bp;
 428	unsigned short use_sg;
 429#ifdef OSST_INJECT_ERRORS
 430	static   int   inject = 0;
 431	static   int   repeat = 0;
 432#endif
 433	struct completion *waiting;
 434
 435	/* if async, make sure there's no command outstanding */
 436	if (!do_wait && ((STp->buffer)->last_SRpnt)) {
 437		printk(KERN_ERR "%s: Async command already active.\n",
 438		       tape_name(STp));
 439		if (signal_pending(current))
 440			(STp->buffer)->syscall_result = (-EINTR);
 441		else
 442			(STp->buffer)->syscall_result = (-EBUSY);
 443		return NULL;
 444	}
 445
 446	if (SRpnt == NULL) {
 447		SRpnt = osst_allocate_request();
 448		if (SRpnt == NULL) {
 449			printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
 450				     tape_name(STp));
 451			if (signal_pending(current))
 452				(STp->buffer)->syscall_result = (-EINTR);
 453			else
 454				(STp->buffer)->syscall_result = (-EBUSY);
 455			return NULL;
 456		}
 457		SRpnt->stp = STp;
 458	}
 459
 460	/* If async IO, set last_SRpnt. This ptr tells write_behind_check
 461	   which IO is outstanding. It's nulled out when the IO completes. */
 462	if (!do_wait)
 463		(STp->buffer)->last_SRpnt = SRpnt;
 464
 465	waiting = &STp->wait;
 466	init_completion(waiting);
 467	SRpnt->waiting = waiting;
 468
 469	use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
 470	if (use_sg) {
 471		bp = (char *)&(STp->buffer->sg[0]);
 472		if (STp->buffer->sg_segs < use_sg)
 473			use_sg = STp->buffer->sg_segs;
 474	}
 475	else
 476		bp = (STp->buffer)->b_data;
 477
 478	memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
 479	STp->buffer->cmdstat.have_sense = 0;
 480	STp->buffer->syscall_result = 0;
 481
 482	if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
 483			 use_sg, timeout, retries))
 484		/* could not allocate the buffer or request was too large */
 485		(STp->buffer)->syscall_result = (-EBUSY);
 486	else if (do_wait) {
 487		wait_for_completion(waiting);
 488		SRpnt->waiting = NULL;
 489		STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
 490#ifdef OSST_INJECT_ERRORS
 491		if (STp->buffer->syscall_result == 0 &&
 492		    cmd[0] == READ_6 &&
 493		    cmd[4] && 
 494		    ( (++ inject % 83) == 29  ||
 495		      (STp->first_frame_position == 240 
 496			         /* or STp->read_error_frame to fail again on the block calculated above */ &&
 497				 ++repeat < 3))) {
 498			printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
 499			STp->buffer->last_result_fatal = 1;
 500		}
 501#endif
 502	}
 503	return SRpnt;
 504}
 505
 506
 507/* Handle the write-behind checking (downs the semaphore) */
 508static void osst_write_behind_check(struct osst_tape *STp)
 509{
 510	struct osst_buffer * STbuffer;
 511
 512	STbuffer = STp->buffer;
 513
 514#if DEBUG
 515	if (STp->write_pending)
 516		STp->nbr_waits++;
 517	else
 518		STp->nbr_finished++;
 519#endif
 520	wait_for_completion(&(STp->wait));
 521	STp->buffer->last_SRpnt->waiting = NULL;
 522
 523	STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
 524
 525	if (STp->buffer->syscall_result)
 526		STp->buffer->syscall_result =
 527			osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
 528	else
 529		STp->first_frame_position++;
 530
 531	osst_release_request(STp->buffer->last_SRpnt);
 532
 533	if (STbuffer->writing < STbuffer->buffer_bytes)
 534		printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
 535
 536	STbuffer->last_SRpnt = NULL;
 537	STbuffer->buffer_bytes -= STbuffer->writing;
 538	STbuffer->writing = 0;
 539
 540	return;
 541}
 542
 543
 544
 545/* Onstream specific Routines */
 546/*
 547 * Initialize the OnStream AUX
 548 */
 549static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
 550					 int logical_blk_num, int blk_sz, int blk_cnt)
 551{
 552	os_aux_t       *aux = STp->buffer->aux;
 553	os_partition_t *par = &aux->partition;
 554	os_dat_t       *dat = &aux->dat;
 555
 556	if (STp->raw) return;
 557
 558	memset(aux, 0, sizeof(*aux));
 559	aux->format_id = htonl(0);
 560	memcpy(aux->application_sig, "LIN4", 4);
 561	aux->hdwr = htonl(0);
 562	aux->frame_type = frame_type;
 563
 564	switch (frame_type) {
 565	  case	OS_FRAME_TYPE_HEADER:
 566		aux->update_frame_cntr    = htonl(STp->update_frame_cntr);
 567		par->partition_num        = OS_CONFIG_PARTITION;
 568		par->par_desc_ver         = OS_PARTITION_VERSION;
 569		par->wrt_pass_cntr        = htons(0xffff);
 570		/* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
 571		par->first_frame_ppos     = htonl(0);
 572		par->last_frame_ppos      = htonl(0xbb7);
 573		aux->frame_seq_num        = htonl(0);
 574		aux->logical_blk_num_high = htonl(0);
 575		aux->logical_blk_num      = htonl(0);
 576		aux->next_mark_ppos       = htonl(STp->first_mark_ppos);
 577		break;
 578	  case	OS_FRAME_TYPE_DATA:
 579	  case	OS_FRAME_TYPE_MARKER:
 580		dat->dat_sz = 8;
 581		dat->reserved1 = 0;
 582		dat->entry_cnt = 1;
 583		dat->reserved3 = 0;
 584		dat->dat_list[0].blk_sz   = htonl(blk_sz);
 585		dat->dat_list[0].blk_cnt  = htons(blk_cnt);
 586		dat->dat_list[0].flags    = frame_type==OS_FRAME_TYPE_MARKER?
 587							OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
 588		dat->dat_list[0].reserved = 0;
 589	  case	OS_FRAME_TYPE_EOD:
 590		aux->update_frame_cntr    = htonl(0);
 591		par->partition_num        = OS_DATA_PARTITION;
 592		par->par_desc_ver         = OS_PARTITION_VERSION;
 593		par->wrt_pass_cntr        = htons(STp->wrt_pass_cntr);
 594		par->first_frame_ppos     = htonl(STp->first_data_ppos);
 595		par->last_frame_ppos      = htonl(STp->capacity);
 596		aux->frame_seq_num        = htonl(frame_seq_number);
 597		aux->logical_blk_num_high = htonl(0);
 598		aux->logical_blk_num      = htonl(logical_blk_num);
 599		break;
 600	  default: ; /* probably FILL */
 601	}
 602	aux->filemark_cnt = htonl(STp->filemark_cnt);
 603	aux->phys_fm = htonl(0xffffffff);
 604	aux->last_mark_ppos = htonl(STp->last_mark_ppos);
 605	aux->last_mark_lbn  = htonl(STp->last_mark_lbn);
 606}
 607
 608/*
 609 * Verify that we have the correct tape frame
 610 */
 611static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
 612{
 613	char               * name = tape_name(STp);
 614	os_aux_t           * aux  = STp->buffer->aux;
 615	os_partition_t     * par  = &(aux->partition);
 616	struct st_partstat * STps = &(STp->ps[STp->partition]);
 617	int		     blk_cnt, blk_sz, i;
 618
 619	if (STp->raw) {
 620		if (STp->buffer->syscall_result) {
 621			for (i=0; i < STp->buffer->sg_segs; i++)
 622				memset(page_address(sg_page(&STp->buffer->sg[i])),
 623				       0, STp->buffer->sg[i].length);
 624			strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
 625                } else
 626			STp->buffer->buffer_bytes = OS_FRAME_SIZE;
 627		return 1;
 628	}
 629	if (STp->buffer->syscall_result) {
 630#if DEBUG
 631		printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
 632#endif
 633		return 0;
 634	}
 635	if (ntohl(aux->format_id) != 0) {
 636#if DEBUG
 637		printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
 638#endif
 639		goto err_out;
 640	}
 641	if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
 642	    (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
 643#if DEBUG
 644		printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
 645#endif
 646		goto err_out;
 647	}
 648	if (par->partition_num != OS_DATA_PARTITION) {
 649		if (!STp->linux_media || STp->linux_media_version != 2) {
 650#if DEBUG
 651			printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
 652					    name, par->partition_num);
 653#endif
 654			goto err_out;
 655		}
 656	}
 657	if (par->par_desc_ver != OS_PARTITION_VERSION) {
 658#if DEBUG
 659		printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
 660#endif
 661		goto err_out;
 662	}
 663	if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
 664#if DEBUG
 665		printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", 
 666				    name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
 667#endif
 668		goto err_out;
 669	}
 670	if (aux->frame_type != OS_FRAME_TYPE_DATA &&
 671	    aux->frame_type != OS_FRAME_TYPE_EOD &&
 672	    aux->frame_type != OS_FRAME_TYPE_MARKER) {
 673		if (!quiet) {
 674#if DEBUG
 675			printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
 676#endif
 677		}
 678		goto err_out;
 679	}
 680	if (aux->frame_type == OS_FRAME_TYPE_EOD &&
 681	    STp->first_frame_position < STp->eod_frame_ppos) {
 682		printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
 683				 STp->first_frame_position);
 684		goto err_out;
 685	}
 686        if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
 687		if (!quiet) {
 688#if DEBUG
 689			printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n", 
 690					    name, ntohl(aux->frame_seq_num), frame_seq_number);
 691#endif
 692		}
 693		goto err_out;
 694	}
 695	if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
 696		STps->eof = ST_FM_HIT;
 697
 698		i = ntohl(aux->filemark_cnt);
 699		if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
 700		    STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
 701#if DEBUG
 702			printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
 703				  STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
 704				  i, STp->first_frame_position - 1);
 705#endif
 706			STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
 707			if (i >= STp->filemark_cnt)
 708				 STp->filemark_cnt = i+1;
 709		}
 710	}
 711	if (aux->frame_type == OS_FRAME_TYPE_EOD) {
 712		STps->eof = ST_EOD_1;
 713		STp->frame_in_buffer = 1;
 714	}
 715	if (aux->frame_type == OS_FRAME_TYPE_DATA) {
 716                blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
 717		blk_sz  = ntohl(aux->dat.dat_list[0].blk_sz);
 718		STp->buffer->buffer_bytes = blk_cnt * blk_sz;
 719		STp->buffer->read_pointer = 0;
 720		STp->frame_in_buffer = 1;
 721
 722		/* See what block size was used to write file */
 723		if (STp->block_size != blk_sz && blk_sz > 0) {
 724			printk(KERN_INFO
 725	    	"%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
 726       				name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
 727				STp->block_size<1024?STp->block_size:STp->block_size/1024,
 728				STp->block_size<1024?'b':'k');
 729			STp->block_size            = blk_sz;
 730			STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
 731		}
 732		STps->eof = ST_NOEOF;
 733	}
 734        STp->frame_seq_number = ntohl(aux->frame_seq_num);
 735	STp->logical_blk_num  = ntohl(aux->logical_blk_num);
 736	return 1;
 737
 738err_out:
 739	if (STp->read_error_frame == 0)
 740		STp->read_error_frame = STp->first_frame_position - 1;
 741	return 0;
 742}
 743
 744/*
 745 * Wait for the unit to become Ready
 746 */
 747static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
 748				 unsigned timeout, int initial_delay)
 749{
 750	unsigned char		cmd[MAX_COMMAND_SIZE];
 751	struct osst_request   * SRpnt;
 752	unsigned long		startwait = jiffies;
 753#if DEBUG
 754	int			dbg  = debugging;
 755	char    	      * name = tape_name(STp);
 756
 757	printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
 758#endif
 759
 760	if (initial_delay > 0)
 761		msleep(jiffies_to_msecs(initial_delay));
 762
 763	memset(cmd, 0, MAX_COMMAND_SIZE);
 764	cmd[0] = TEST_UNIT_READY;
 765
 766	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 767	*aSRpnt = SRpnt;
 768	if (!SRpnt) return (-EBUSY);
 769
 770	while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 771	       (( SRpnt->sense[2]  == 2 && SRpnt->sense[12] == 4    &&
 772		 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)    ) ||
 773		( SRpnt->sense[2]  == 6 && SRpnt->sense[12] == 0x28 &&
 774		  SRpnt->sense[13] == 0                                        )  )) {
 775#if DEBUG
 776	    if (debugging) {
 777		printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
 778		printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 779		debugging = 0;
 780	    }
 781#endif
 782	    msleep(100);
 783
 784	    memset(cmd, 0, MAX_COMMAND_SIZE);
 785	    cmd[0] = TEST_UNIT_READY;
 786
 787	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 788	}
 789	*aSRpnt = SRpnt;
 790#if DEBUG
 791	debugging = dbg;
 792#endif
 793	if ( STp->buffer->syscall_result &&
 794	     osst_write_error_recovery(STp, aSRpnt, 0) ) {
 795#if DEBUG
 796	    printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
 797	    printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 798			STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 799			SRpnt->sense[12], SRpnt->sense[13]);
 800#endif
 801	    return (-EIO);
 802	}
 803#if DEBUG
 804	printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
 805#endif
 806	return 0;
 807}
 808
 809/*
 810 * Wait for a tape to be inserted in the unit
 811 */
 812static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
 813{
 814	unsigned char		cmd[MAX_COMMAND_SIZE];
 815	struct osst_request   * SRpnt;
 816	unsigned long		startwait = jiffies;
 817#if DEBUG
 818	int			dbg = debugging;
 819	char    	      * name = tape_name(STp);
 820
 821	printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
 822#endif
 823
 824	memset(cmd, 0, MAX_COMMAND_SIZE);
 825	cmd[0] = TEST_UNIT_READY;
 826
 827	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 828	*aSRpnt = SRpnt;
 829	if (!SRpnt) return (-EBUSY);
 830
 831	while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 832		SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0  ) {
 833#if DEBUG
 834	    if (debugging) {
 835		printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
 836		printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 837		debugging = 0;
 838	    }
 839#endif
 840	    msleep(100);
 841
 842	    memset(cmd, 0, MAX_COMMAND_SIZE);
 843	    cmd[0] = TEST_UNIT_READY;
 844
 845	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 846	}
 847	*aSRpnt = SRpnt;
 848#if DEBUG
 849	debugging = dbg;
 850#endif
 851	if ( STp->buffer->syscall_result     && SRpnt->sense[2]  != 2 &&
 852	     SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
 853#if DEBUG
 854	    printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
 855	    printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 856			STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 857			SRpnt->sense[12], SRpnt->sense[13]);
 858#endif
 859	    return 0;
 860	}
 861#if DEBUG
 862	printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
 863#endif
 864	return 1;
 865}
 866
 867static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
 868{
 869	int	retval;
 870
 871	osst_wait_ready(STp, aSRpnt, 15 * 60, 0);			/* TODO - can this catch a write error? */
 872	retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
 873	if (retval) return (retval);
 874	osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
 875	return (osst_get_frame_position(STp, aSRpnt));
 876}
 877
 878/*
 879 * Wait for write(s) to complete
 880 */
 881static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
 882{
 883	unsigned char		cmd[MAX_COMMAND_SIZE];
 884	struct osst_request   * SRpnt;
 885	int			result = 0;
 886	int			delay  = OSST_WAIT_WRITE_COMPLETE;
 887#if DEBUG
 888	char		      * name = tape_name(STp);
 889
 890	printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
 891#endif
 892
 893	memset(cmd, 0, MAX_COMMAND_SIZE);
 894	cmd[0] = WRITE_FILEMARKS;
 895	cmd[1] = 1;
 896
 897	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 898	*aSRpnt = SRpnt;
 899	if (!SRpnt) return (-EBUSY);
 900	if (STp->buffer->syscall_result) {
 901		if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
 902			if (SRpnt->sense[13] == 8) {
 903				delay = OSST_WAIT_LONG_WRITE_COMPLETE;
 904			}
 905		} else
 906			result = osst_write_error_recovery(STp, aSRpnt, 0);
 907	}
 908	result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
 909	STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
 910
 911	return (result);
 912}
 913
 914#define OSST_POLL_PER_SEC 10
 915static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
 916{
 917	unsigned long	startwait = jiffies;
 918	char	      * name      = tape_name(STp);
 919#if DEBUG
 920	char	   notyetprinted  = 1;
 921#endif
 922	if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
 923		printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
 924
 925	while (time_before (jiffies, startwait + to*HZ))
 926	{ 
 927		int result;
 928		result = osst_get_frame_position(STp, aSRpnt);
 929		if (result == -EIO)
 930			if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
 931				return 0;	/* successful recovery leaves drive ready for frame */
 932		if (result < 0) break;
 933		if (STp->first_frame_position == curr &&
 934		    ((minlast < 0 &&
 935		      (signed)STp->last_frame_position > (signed)curr + minlast) ||
 936		     (minlast >= 0 && STp->cur_frames > minlast)
 937		    ) && result >= 0)
 938		{
 939#if DEBUG			
 940			if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
 941				printk (OSST_DEB_MSG
 942					"%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
 943					name, curr, curr+minlast, STp->first_frame_position,
 944					STp->last_frame_position, STp->cur_frames,
 945					result, (jiffies-startwait)/HZ, 
 946					(((jiffies-startwait)%HZ)*10)/HZ);
 947#endif
 948			return 0;
 949		}
 950#if DEBUG
 951		if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
 952		{
 953			printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
 954				name, curr, curr+minlast, STp->first_frame_position,
 955				STp->last_frame_position, STp->cur_frames, result);
 956			notyetprinted--;
 957		}
 958#endif
 959		msleep(1000 / OSST_POLL_PER_SEC);
 960	}
 961#if DEBUG
 962	printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
 963		name, curr, curr+minlast, STp->first_frame_position,
 964		STp->last_frame_position, STp->cur_frames,
 965		(jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
 966#endif	
 967	return -EBUSY;
 968}
 969
 970static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
 971{
 972	struct osst_request   * SRpnt;
 973	unsigned char		cmd[MAX_COMMAND_SIZE];
 974	unsigned long   	startwait = jiffies;
 975	int			retval    = 1;
 976        char		      * name      = tape_name(STp);
 977                                                                                                                                
 978	if (writing) {
 979		char	mybuf[24];
 980		char  * olddata = STp->buffer->b_data;
 981		int	oldsize = STp->buffer->buffer_size;
 982
 983		/* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
 984
 985		memset(cmd, 0, MAX_COMMAND_SIZE);
 986		cmd[0] = WRITE_FILEMARKS;
 987		cmd[1] = 1;
 988		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
 989								MAX_RETRIES, 1);
 990
 991		while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
 992
 993			if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
 994
 995				/* some failure - not just not-ready */
 996				retval = osst_write_error_recovery(STp, aSRpnt, 0);
 997				break;
 998			}
 999			schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
1000
1001			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1002			memset(cmd, 0, MAX_COMMAND_SIZE);
1003			cmd[0] = READ_POSITION;
1004
1005			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1006										MAX_RETRIES, 1);
1007
1008			retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1009			STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1010		}
1011		if (retval)
1012			printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1013	} else
1014		/* TODO - figure out which error conditions can be handled */
1015		if (STp->buffer->syscall_result)
1016			printk(KERN_WARNING
1017				"%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1018					(*aSRpnt)->sense[ 2] & 0x0f,
1019					(*aSRpnt)->sense[12],
1020					(*aSRpnt)->sense[13]);
1021
1022	return retval;
1023}
1024
1025/*
1026 * Read the next OnStream tape frame at the current location
1027 */
1028static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1029{
1030	unsigned char		cmd[MAX_COMMAND_SIZE];
1031	struct osst_request   * SRpnt;
1032	int			retval = 0;
1033#if DEBUG
1034	os_aux_t	      * aux    = STp->buffer->aux;
1035	char		      * name   = tape_name(STp);
1036#endif
1037
1038	if (STp->poll)
1039		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1040			retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1041
1042	memset(cmd, 0, MAX_COMMAND_SIZE);
1043	cmd[0] = READ_6;
1044	cmd[1] = 1;
1045	cmd[4] = 1;
1046
1047#if DEBUG
1048	if (debugging)
1049		printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1050#endif
1051	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1052				      STp->timeout, MAX_RETRIES, 1);
1053	*aSRpnt = SRpnt;
1054	if (!SRpnt)
1055		return (-EBUSY);
1056
1057	if ((STp->buffer)->syscall_result) {
1058	    retval = 1;
1059	    if (STp->read_error_frame == 0) {
1060		STp->read_error_frame = STp->first_frame_position;
1061#if DEBUG
1062		printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1063#endif
1064	    }
1065#if DEBUG
1066	    if (debugging)
1067		printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1068		   name,
1069		   SRpnt->sense[0], SRpnt->sense[1],
1070		   SRpnt->sense[2], SRpnt->sense[3],
1071		   SRpnt->sense[4], SRpnt->sense[5],
1072		   SRpnt->sense[6], SRpnt->sense[7]);
1073#endif
1074	}
1075	else
1076	    STp->first_frame_position++;
1077#if DEBUG
1078	if (debugging) {
1079	   char sig[8]; int i;
1080	   for (i=0;i<4;i++)
1081		   sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1082	   sig[4] = '\0';
1083	   printk(OSST_DEB_MSG 
1084		"%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1085			ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1086			aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1087			aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", 
1088			ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1089			ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1090	   if (aux->frame_type==2)
1091		printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1092			ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1093	   printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1094	}
1095#endif
1096	return (retval);
1097}
1098
1099static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1100{
1101	struct st_partstat    * STps   = &(STp->ps[STp->partition]);
1102	struct osst_request   * SRpnt  ;
1103	unsigned char		cmd[MAX_COMMAND_SIZE];
1104	int			retval = 0;
1105	char		      * name   = tape_name(STp);
1106
1107	if (STps->rw != ST_READING) {         /* Initialize read operation */
1108		if (STps->rw == ST_WRITING || STp->dirty) {
1109			STp->write_type = OS_WRITE_DATA;
1110                        osst_flush_write_buffer(STp, aSRpnt);
1111			osst_flush_drive_buffer(STp, aSRpnt);
1112		}
1113		STps->rw = ST_READING;
1114		STp->frame_in_buffer = 0;
1115
1116		/*
1117		 *      Issue a read 0 command to get the OnStream drive
1118                 *      read frames into its buffer.
1119		 */
1120		memset(cmd, 0, MAX_COMMAND_SIZE);
1121		cmd[0] = READ_6;
1122		cmd[1] = 1;
1123
1124#if DEBUG
1125		printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1126#endif
1127		SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1128		*aSRpnt = SRpnt;
1129		if ((retval = STp->buffer->syscall_result))
1130			printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1131	}
1132
1133	return retval;
1134}
1135
1136static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1137						int frame_seq_number, int quiet)
1138{
1139	struct st_partstat * STps  = &(STp->ps[STp->partition]);
1140	char		   * name  = tape_name(STp);
1141	int		     cnt   = 0,
1142			     bad   = 0,
1143			     past  = 0,
1144			     x,
1145			     position;
1146
1147	/*
1148	 * If we want just any frame (-1) and there is a frame in the buffer, return it
1149	 */
1150	if (frame_seq_number == -1 && STp->frame_in_buffer) {
1151#if DEBUG
1152		printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1153#endif
1154		return (STps->eof);
1155	}
1156	/*
1157         * Search and wait for the next logical tape frame
1158	 */
1159	while (1) {
1160		if (cnt++ > 400) {
1161                        printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1162					    name, frame_seq_number);
1163			if (STp->read_error_frame) {
1164				osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1165#if DEBUG
1166                        	printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1167						    name, STp->read_error_frame);
1168#endif
1169				STp->read_error_frame = 0;
1170				STp->abort_count++;
1171			}
1172			return (-EIO);
1173		}
1174#if DEBUG
1175		if (debugging)
1176			printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1177					  name, frame_seq_number, cnt);
1178#endif
1179		if ( osst_initiate_read(STp, aSRpnt)
1180                || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1181			if (STp->raw)
1182				return (-EIO);
1183			position = osst_get_frame_position(STp, aSRpnt);
1184			if (position >= 0xbae && position < 0xbb8)
1185				position = 0xbb8;
1186			else if (position > STp->eod_frame_ppos || ++bad == 10) {
1187				position = STp->read_error_frame - 1;
1188				bad = 0;
1189			}
1190			else {
1191				position += 29;
1192				cnt      += 19;
1193			}
1194#if DEBUG
1195			printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1196					 name, position);
1197#endif
1198			osst_set_frame_position(STp, aSRpnt, position, 0);
1199			continue;
1200		}
1201		if (osst_verify_frame(STp, frame_seq_number, quiet))
1202			break;
1203		if (osst_verify_frame(STp, -1, quiet)) {
1204			x = ntohl(STp->buffer->aux->frame_seq_num);
1205			if (STp->fast_open) {
1206				printk(KERN_WARNING
1207				       "%s:W: Found logical frame %d instead of %d after fast open\n",
1208				       name, x, frame_seq_number);
1209				STp->header_ok = 0;
1210				STp->read_error_frame = 0;
1211				return (-EIO);
1212			}
1213			if (x > frame_seq_number) {
1214				if (++past > 3) {
1215					/* positioning backwards did not bring us to the desired frame */
1216					position = STp->read_error_frame - 1;
1217				}
1218				else {
1219			        	position = osst_get_frame_position(STp, aSRpnt)
1220					         + frame_seq_number - x - 1;
1221
1222					if (STp->first_frame_position >= 3000 && position < 3000)
1223						position -= 10;
1224				}
1225#if DEBUG
1226                                printk(OSST_DEB_MSG
1227				       "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1228						name, x, frame_seq_number,
1229					       	STp->first_frame_position - position);
1230#endif
1231                        	osst_set_frame_position(STp, aSRpnt, position, 0);
1232				cnt += 10;
1233			}
1234			else
1235				past = 0;
1236		}
1237		if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1238#if DEBUG
1239			printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1240#endif
1241			osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1242			cnt--;
1243		}
1244		STp->frame_in_buffer = 0;
1245	}
1246	if (cnt > 1) {
1247		STp->recover_count++;
1248		STp->recover_erreg++;
1249		printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n", 
1250					name, STp->read_error_frame);
1251 	}
1252	STp->read_count++;
1253
1254#if DEBUG
1255	if (debugging || STps->eof)
1256		printk(OSST_DEB_MSG
1257			"%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1258			name, frame_seq_number, STp->frame_seq_number, STps->eof);
1259#endif
1260	STp->fast_open = 0;
1261	STp->read_error_frame = 0;
1262	return (STps->eof);
1263}
1264
1265static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1266{
1267        struct st_partstat * STps = &(STp->ps[STp->partition]);
1268	char		   * name = tape_name(STp);
1269	int	retries    = 0;
1270	int	frame_seq_estimate, ppos_estimate, move;
1271	
1272	if (logical_blk_num < 0) logical_blk_num = 0;
1273#if DEBUG
1274	printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1275				name, logical_blk_num, STp->logical_blk_num, 
1276				STp->block_size<1024?STp->block_size:STp->block_size/1024,
1277				STp->block_size<1024?'b':'k');
1278#endif
1279	/* Do we know where we are? */
1280	if (STps->drv_block >= 0) {
1281		move                = logical_blk_num - STp->logical_blk_num;
1282		if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1283		move               /= (OS_DATA_SIZE / STp->block_size);
1284		frame_seq_estimate  = STp->frame_seq_number + move;
1285	} else
1286		frame_seq_estimate  = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1287
1288	if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1289	else			       ppos_estimate = frame_seq_estimate + 20;
1290	while (++retries < 10) {
1291	   if (ppos_estimate > STp->eod_frame_ppos-2) {
1292	       frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1293	       ppos_estimate       = STp->eod_frame_ppos - 2;
1294	   }
1295	   if (frame_seq_estimate < 0) {
1296	       frame_seq_estimate = 0;
1297	       ppos_estimate      = 10;
1298	   }
1299	   osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1300	   if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1301	      /* we've located the estimated frame, now does it have our block? */
1302	      if (logical_blk_num <  STp->logical_blk_num ||
1303	          logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1304		 if (STps->eof == ST_FM_HIT)
1305		    move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1306		 else {
1307		    move                = logical_blk_num - STp->logical_blk_num;
1308		    if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1309		    move               /= (OS_DATA_SIZE / STp->block_size);
1310		 }
1311		 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1312#if DEBUG
1313		 printk(OSST_DEB_MSG
1314			"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1315				name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1316				STp->logical_blk_num, logical_blk_num, move);
1317#endif
1318		 frame_seq_estimate += move;
1319		 ppos_estimate      += move;
1320		 continue;
1321	      } else {
1322		 STp->buffer->read_pointer  = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1323		 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1324		 STp->logical_blk_num       =  logical_blk_num;
1325#if DEBUG
1326		 printk(OSST_DEB_MSG 
1327			"%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1328				name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer, 
1329				STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size, 
1330				STp->block_size);
1331#endif
1332		 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1333		 if (STps->eof == ST_FM_HIT) {
1334		     STps->drv_file++;
1335		     STps->drv_block = 0;
1336		 } else {
1337		     STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1338					  STp->logical_blk_num -
1339					     (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1340					-1;
1341		 }
1342		 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1343		 return 0;
1344	      }
1345	   }
1346	   if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1347	      goto error;
1348	   /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1349#if DEBUG
1350	   printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n", 
1351			   name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1352			   STp->logical_blk_num, logical_blk_num);
1353#endif
1354	   if (frame_seq_estimate != STp->frame_seq_number)
1355	      ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1356	   else
1357	      break;
1358	}
1359error:
1360	printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n", 
1361			    name, logical_blk_num, STp->logical_blk_num, retries);
1362	return (-EIO);
1363}
1364
1365/* The values below are based on the OnStream frame payload size of 32K == 2**15,
1366 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1367 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1368 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1369 */
1370#define OSST_FRAME_SHIFT  6
1371#define OSST_SECTOR_SHIFT 9
1372#define OSST_SECTOR_MASK  0x03F
1373
1374static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1375{
1376	int	sector;
1377#if DEBUG
1378	char  * name = tape_name(STp);
1379	
1380	printk(OSST_DEB_MSG 
1381		"%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1382		name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1383		STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block, 
1384		STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1385		STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1386		STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1387#endif
1388	/* do we know where we are inside a file? */
1389	if (STp->ps[STp->partition].drv_block >= 0) {
1390		sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1391				STp->first_frame_position) << OSST_FRAME_SHIFT;
1392		if (STp->ps[STp->partition].rw == ST_WRITING)
1393		       	sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1394		else
1395	       		sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1396	} else {
1397		sector = osst_get_frame_position(STp, aSRpnt);
1398		if (sector > 0)
1399			sector <<= OSST_FRAME_SHIFT;
1400	}
1401	return sector;
1402}
1403
1404static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1405{
1406        struct st_partstat * STps   = &(STp->ps[STp->partition]);
1407	int		     frame  = sector >> OSST_FRAME_SHIFT,
1408			     offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
1409			     r;
1410#if DEBUG
1411	char          * name = tape_name(STp);
1412
1413	printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1414				name, sector, frame, offset);
1415#endif
1416	if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1417
1418	if (frame <= STp->first_data_ppos) {
1419		STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1420		return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1421	}
1422	r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1423	if (r < 0) return r;
1424
1425	r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1426	if (r < 0) return r;
1427
1428	if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1429
1430	if (offset) {
1431		STp->logical_blk_num      += offset / STp->block_size;
1432		STp->buffer->read_pointer  = offset;
1433		STp->buffer->buffer_bytes -= offset;
1434	} else {
1435		STp->frame_seq_number++;
1436		STp->frame_in_buffer       = 0;
1437		STp->logical_blk_num      += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1438		STp->buffer->buffer_bytes  = STp->buffer->read_pointer = 0;
1439	}
1440	STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1441	if (STps->eof == ST_FM_HIT) {
1442		STps->drv_file++;
1443		STps->drv_block = 0;
1444	} else {
1445		STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1446				    STp->logical_blk_num -
1447					(STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1448				  -1;
1449	}
1450	STps->eof       = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1451#if DEBUG
1452	printk(OSST_DEB_MSG 
1453		"%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1454		name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1455		STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1456#endif
1457	return 0;
1458}
1459
1460/*
1461 * Read back the drive's internal buffer contents, as a part
1462 * of the write error recovery mechanism for old OnStream
1463 * firmware revisions.
1464 * Precondition for this function to work: all frames in the
1465 * drive's buffer must be of one type (DATA, MARK or EOD)!
1466 */
1467static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1468						unsigned int frame, unsigned int skip, int pending)
1469{
1470	struct osst_request   * SRpnt = * aSRpnt;
1471	unsigned char	      * buffer, * p;
1472	unsigned char		cmd[MAX_COMMAND_SIZE];
1473	int			flag, new_frame, i;
1474	int			nframes          = STp->cur_frames;
1475	int			blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1476	int			frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1477						- (nframes + pending - 1);
1478	int			logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
1479						- (nframes + pending - 1) * blks_per_frame;
1480	char		      * name             = tape_name(STp);
1481	unsigned long		startwait        = jiffies;
1482#if DEBUG
1483	int			dbg              = debugging;
1484#endif
1485
1486	if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1487		return (-EIO);
1488
1489	printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1490			 name, nframes, pending?" and one that was pending":"");
1491
1492	osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1493#if DEBUG
1494	if (pending && debugging)
1495		printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1496				name, frame_seq_number + nframes,
1497			       	logical_blk_num + nframes * blks_per_frame,
1498			       	p[0], p[1], p[2], p[3]);
1499#endif
1500	for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1501
1502		memset(cmd, 0, MAX_COMMAND_SIZE);
1503		cmd[0] = 0x3C;		/* Buffer Read           */
1504		cmd[1] = 6;		/* Retrieve Faulty Block */
1505		cmd[7] = 32768 >> 8;
1506		cmd[8] = 32768 & 0xff;
1507
1508		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1509					    STp->timeout, MAX_RETRIES, 1);
1510	
1511		if ((STp->buffer)->syscall_result || !SRpnt) {
1512			printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1513			vfree(buffer);
1514			*aSRpnt = SRpnt;
1515			return (-EIO);
1516		}
1517		osst_copy_from_buffer(STp->buffer, p);
1518#if DEBUG
1519		if (debugging)
1520			printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1521					  name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1522#endif
1523	}
1524	*aSRpnt = SRpnt;
1525	osst_get_frame_position(STp, aSRpnt);
1526
1527#if DEBUG
1528	printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1529#endif
1530	/* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1531	/* In the header we don't actually re-write the frames that fail, just the ones after them */
1532
1533	for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1534
1535		if (flag) {
1536			if (STp->write_type == OS_WRITE_HEADER) {
1537				i += skip;
1538				p += skip * OS_DATA_SIZE;
1539			}
1540			else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1541				new_frame = 3000-i;
1542			else
1543				new_frame += skip;
1544#if DEBUG
1545			printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1546						name, new_frame+i, frame_seq_number+i);
1547#endif
1548			osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1549			osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1550			osst_get_frame_position(STp, aSRpnt);
1551			SRpnt = * aSRpnt;
1552
1553			if (new_frame > frame + 1000) {
1554				printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1555				vfree(buffer);
1556				return (-EIO);
1557			}
1558			if ( i >= nframes + pending ) break;
1559			flag = 0;
1560		}
1561		osst_copy_to_buffer(STp->buffer, p);
1562		/*
1563		 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1564		 */
1565		osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1566			       	logical_blk_num + i*blks_per_frame,
1567			       	ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1568		memset(cmd, 0, MAX_COMMAND_SIZE);
1569		cmd[0] = WRITE_6;
1570		cmd[1] = 1;
1571		cmd[4] = 1;
1572
1573#if DEBUG
1574		if (debugging)
1575			printk(OSST_DEB_MSG
1576				"%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1577				name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1578				p[0], p[1], p[2], p[3]);
1579#endif
1580		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1581					    STp->timeout, MAX_RETRIES, 1);
1582
1583		if (STp->buffer->syscall_result)
1584			flag = 1;
1585		else {
1586			p += OS_DATA_SIZE; i++;
1587
1588			/* if we just sent the last frame, wait till all successfully written */
1589			if ( i == nframes + pending ) {
1590#if DEBUG
1591				printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1592#endif
1593				memset(cmd, 0, MAX_COMMAND_SIZE);
1594				cmd[0] = WRITE_FILEMARKS;
1595				cmd[1] = 1;
1596				SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1597							    STp->timeout, MAX_RETRIES, 1);
1598#if DEBUG
1599				if (debugging) {
1600					printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1601					printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1602					debugging = 0;
1603				}
1604#endif
1605				flag = STp->buffer->syscall_result;
1606				while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1607
1608					memset(cmd, 0, MAX_COMMAND_SIZE);
1609					cmd[0] = TEST_UNIT_READY;
1610
1611					SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1612												MAX_RETRIES, 1);
1613
1614					if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1615					    (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1616						/* in the process of becoming ready */
1617						msleep(100);
1618						continue;
1619					}
1620					if (STp->buffer->syscall_result)
1621						flag = 1;
1622					break;
1623				}
1624#if DEBUG
1625				debugging = dbg;
1626				printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1627#endif
1628			}
1629		}
1630		*aSRpnt = SRpnt;
1631		if (flag) {
1632			if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1633			     SRpnt->sense[12]         ==  0 &&
1634			     SRpnt->sense[13]         ==  2) {
1635				printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1636				vfree(buffer);
1637				return (-EIO);			/* hit end of tape = fail */
1638			}
1639			i = ((SRpnt->sense[3] << 24) |
1640			     (SRpnt->sense[4] << 16) |
1641			     (SRpnt->sense[5] <<  8) |
1642			      SRpnt->sense[6]        ) - new_frame;
1643			p = &buffer[i * OS_DATA_SIZE];
1644#if DEBUG
1645			printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1646#endif
1647			osst_get_frame_position(STp, aSRpnt);
1648#if DEBUG
1649			printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1650					  name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1651#endif
1652		}
1653	}
1654	if (flag) {
1655		/* error recovery did not successfully complete */
1656		printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1657				STp->write_type == OS_WRITE_HEADER?"header":"body");
1658	}
1659	if (!pending)
1660		osst_copy_to_buffer(STp->buffer, p);	/* so buffer content == at entry in all cases */
1661	vfree(buffer);
1662	return 0;
1663}
1664
1665static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1666					unsigned int frame, unsigned int skip, int pending)
1667{
1668	unsigned char		cmd[MAX_COMMAND_SIZE];
1669	struct osst_request   * SRpnt;
1670	char		      * name      = tape_name(STp);
1671	int			expected  = 0;
1672	int			attempts  = 1000 / skip;
1673	int			flag      = 1;
1674	unsigned long		startwait = jiffies;
1675#if DEBUG
1676	int			dbg       = debugging;
1677#endif
1678
1679	while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1680		if (flag) {
1681#if DEBUG
1682			debugging = dbg;
1683#endif
1684			if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1685				frame = 3000-skip;
1686			expected = frame+skip+STp->cur_frames+pending;
1687#if DEBUG
1688			printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1689					  name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1690#endif
1691			osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1692			flag = 0;
1693			attempts--;
1694			schedule_timeout_interruptible(msecs_to_jiffies(100));
1695		}
1696		if (osst_get_frame_position(STp, aSRpnt) < 0) {		/* additional write error */
1697#if DEBUG
1698			printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1699					  name, STp->first_frame_position,
1700					  STp->last_frame_position, STp->cur_frames);
1701#endif
1702			frame = STp->last_frame_position;
1703			flag = 1;
1704			continue;
1705		}
1706		if (pending && STp->cur_frames < 50) {
1707
1708			memset(cmd, 0, MAX_COMMAND_SIZE);
1709			cmd[0] = WRITE_6;
1710			cmd[1] = 1;
1711			cmd[4] = 1;
1712#if DEBUG
1713			printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1714					  name, STp->frame_seq_number-1, STp->first_frame_position);
1715#endif
1716			SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1717						      STp->timeout, MAX_RETRIES, 1);
1718			*aSRpnt = SRpnt;
1719
1720			if (STp->buffer->syscall_result) {		/* additional write error */
1721				if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1722				     SRpnt->sense[12]         ==  0 &&
1723				     SRpnt->sense[13]         ==  2) {
1724					printk(KERN_ERR
1725					       "%s:E: Volume overflow in write error recovery\n",
1726					       name);
1727					break;				/* hit end of tape = fail */
1728				}
1729				flag = 1;
1730			}
1731			else
1732				pending = 0;
1733
1734			continue;
1735		}
1736		if (STp->cur_frames == 0) {
1737#if DEBUG
1738			debugging = dbg;
1739			printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1740#endif
1741			if (STp->first_frame_position != expected) {
1742				printk(KERN_ERR "%s:A: Actual position %d - expected %d\n", 
1743						name, STp->first_frame_position, expected);
1744				return (-EIO);
1745			}
1746			return 0;
1747		}
1748#if DEBUG
1749		if (debugging) {
1750			printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1751			printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1752			debugging = 0;
1753		}
1754#endif
1755		schedule_timeout_interruptible(msecs_to_jiffies(100));
1756	}
1757	printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1758#if DEBUG
1759	debugging = dbg;
1760#endif
1761	return (-EIO);
1762}
1763
1764/*
1765 * Error recovery algorithm for the OnStream tape.
1766 */
1767
1768static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1769{
1770	struct osst_request * SRpnt  = * aSRpnt;
1771	struct st_partstat  * STps   = & STp->ps[STp->partition];
1772	char		    * name   = tape_name(STp);
1773	int		      retval = 0;
1774	int		      rw_state;
1775	unsigned int	      frame, skip;
1776
1777	rw_state = STps->rw;
1778
1779	if ((SRpnt->sense[ 2] & 0x0f) != 3
1780	  || SRpnt->sense[12]         != 12
1781	  || SRpnt->sense[13]         != 0) {
1782#if DEBUG
1783		printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1784			SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1785#endif
1786		return (-EIO);
1787	}
1788	frame =	(SRpnt->sense[3] << 24) |
1789		(SRpnt->sense[4] << 16) |
1790		(SRpnt->sense[5] <<  8) |
1791		 SRpnt->sense[6];
1792	skip  =  SRpnt->sense[9];
1793 
1794#if DEBUG
1795	printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1796#endif
1797	osst_get_frame_position(STp, aSRpnt);
1798#if DEBUG
1799	printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1800			name, STp->first_frame_position, STp->last_frame_position);
1801#endif
1802	switch (STp->write_type) {
1803	   case OS_WRITE_DATA:
1804	   case OS_WRITE_EOD:
1805	   case OS_WRITE_NEW_MARK:
1806		printk(KERN_WARNING 
1807			"%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1808			name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1809		if (STp->os_fw_rev >= 10600)
1810			retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1811		else
1812			retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1813		printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1814			       	retval?"E"    :"I",
1815			       	retval?""     :"Don't worry, ",
1816			       	retval?" not ":" ");
1817		break;
1818	   case OS_WRITE_LAST_MARK:
1819		printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1820		osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1821		retval = -EIO;
1822		break;
1823	   case OS_WRITE_HEADER:
1824		printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1825		retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1826		break;
1827	   default:
1828		printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1829		osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1830	}
1831	osst_get_frame_position(STp, aSRpnt);
1832#if DEBUG
1833	printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", 
1834			name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1835	printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1836#endif
1837	if (retval == 0) {
1838		STp->recover_count++;
1839		STp->recover_erreg++;
1840	} else
1841		STp->abort_count++;
1842
1843	STps->rw = rw_state;
1844	return retval;
1845}
1846
1847static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1848								 int mt_op, int mt_count)
1849{
1850	char  * name = tape_name(STp);
1851	int     cnt;
1852	int     last_mark_ppos = -1;
1853
1854#if DEBUG
1855	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1856#endif
1857	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1858#if DEBUG
1859		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1860#endif
1861		return -EIO;
1862	}
1863	if (STp->linux_media_version >= 4) {
1864		/*
1865		 * direct lookup in header filemark list
1866		 */
1867		cnt = ntohl(STp->buffer->aux->filemark_cnt);
1868		if (STp->header_ok                         && 
1869		    STp->header_cache != NULL              &&
1870		    (cnt - mt_count)  >= 0                 &&
1871		    (cnt - mt_count)   < OS_FM_TAB_MAX     &&
1872		    (cnt - mt_count)   < STp->filemark_cnt &&
1873		    STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1874
1875			last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1876#if DEBUG
1877		if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1878			printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1879			       STp->header_cache == NULL?"lack of header cache":"count out of range");
1880		else
1881			printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1882				name, cnt,
1883				((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1884				 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1885					 STp->buffer->aux->last_mark_ppos))?"match":"error",
1886			       mt_count, last_mark_ppos);
1887#endif
1888		if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1889			osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1890			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1891#if DEBUG
1892				printk(OSST_DEB_MSG 
1893					"%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1894#endif
1895				return (-EIO);
1896			}
1897			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1898				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1899						 name, last_mark_ppos);
1900				return (-EIO);
1901			}
1902			goto found;
1903		}
1904#if DEBUG
1905		printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1906#endif
1907	}
1908	cnt = 0;
1909	while (cnt != mt_count) {
1910		last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1911		if (last_mark_ppos == -1)
1912			return (-EIO);
1913#if DEBUG
1914		printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1915#endif
1916		osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1917		cnt++;
1918		if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1919#if DEBUG
1920			printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1921#endif
1922			return (-EIO);
1923		}
1924		if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1925			printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1926					 name, last_mark_ppos);
1927			return (-EIO);
1928		}
1929	}
1930found:
1931	if (mt_op == MTBSFM) {
1932		STp->frame_seq_number++;
1933		STp->frame_in_buffer      = 0;
1934		STp->buffer->buffer_bytes = 0;
1935		STp->buffer->read_pointer = 0;
1936		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1937	}
1938	return 0;
1939}
1940
1941/*
1942 * ADRL 1.1 compatible "slow" space filemarks fwd version
1943 *
1944 * Just scans for the filemark sequentially.
1945 */
1946static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1947								     int mt_op, int mt_count)
1948{
1949	int	cnt = 0;
1950#if DEBUG
1951	char  * name = tape_name(STp);
1952
1953	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1954#endif
1955	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1956#if DEBUG
1957		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1958#endif
1959		return (-EIO);
1960	}
1961	while (1) {
1962		if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1963#if DEBUG
1964			printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1965#endif
1966			return (-EIO);
1967		}
1968		if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1969			cnt++;
1970		if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1971#if DEBUG
1972			printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1973#endif
1974			if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1975#if DEBUG
1976				printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1977					       	name, STp->eod_frame_ppos, STp->first_frame_position-1);
1978#endif
1979				STp->eod_frame_ppos = STp->first_frame_position-1;
1980			}
1981			return (-EIO);
1982		}
1983		if (cnt == mt_count)
1984			break;
1985		STp->frame_in_buffer = 0;
1986	}
1987	if (mt_op == MTFSF) {
1988		STp->frame_seq_number++;
1989		STp->frame_in_buffer      = 0;
1990		STp->buffer->buffer_bytes = 0;
1991		STp->buffer->read_pointer = 0;
1992		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1993	}
1994	return 0;
1995}
1996
1997/*
1998 * Fast linux specific version of OnStream FSF
1999 */
2000static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
2001								     int mt_op, int mt_count)
2002{
2003	char  * name = tape_name(STp);
2004	int	cnt  = 0,
2005		next_mark_ppos = -1;
2006
2007#if DEBUG
2008	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
2009#endif
2010	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2011#if DEBUG
2012		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
2013#endif
2014		return (-EIO);
2015	}
2016
2017	if (STp->linux_media_version >= 4) {
2018		/*
2019		 * direct lookup in header filemark list
2020		 */
2021		cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
2022		if (STp->header_ok                         && 
2023		    STp->header_cache != NULL              &&
2024		    (cnt + mt_count)   < OS_FM_TAB_MAX     &&
2025		    (cnt + mt_count)   < STp->filemark_cnt &&
2026		    ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2027		     (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
2028
2029			next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
2030#if DEBUG
2031		if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
2032			printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
2033			       STp->header_cache == NULL?"lack of header cache":"count out of range");
2034		else
2035			printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2036			       name, cnt,
2037			       ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2038				(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
2039					 STp->buffer->aux->last_mark_ppos))?"match":"error",
2040			       mt_count, next_mark_ppos);
2041#endif
2042		if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
2043#if DEBUG
2044			printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2045#endif
2046			return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2047		} else {
2048			osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2049			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2050#if DEBUG
2051				printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2052						 name);
2053#endif
2054				return (-EIO);
2055			}
2056			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2057				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2058						 name, next_mark_ppos);
2059				return (-EIO);
2060			}
2061			if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
2062				printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
2063						 name, cnt+mt_count, next_mark_ppos,
2064						 ntohl(STp->buffer->aux->filemark_cnt));
2065       				return (-EIO);
2066			}
2067		}
2068	} else {
2069		/*
2070		 * Find nearest (usually previous) marker, then jump from marker to marker
2071		 */
2072		while (1) {
2073			if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
2074				break;
2075			if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2076#if DEBUG
2077				printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2078#endif
2079				return (-EIO);
2080			}
2081			if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2082				if (STp->first_mark_ppos == -1) {
2083#if DEBUG
2084					printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2085#endif
2086					return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2087				}
2088				osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2089				if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2090#if DEBUG
2091					printk(OSST_DEB_MSG
2092					       "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2093					       name);
2094#endif
2095					return (-EIO);
2096				}
2097				if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2098					printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2099							 name, STp->first_mark_ppos);
2100					return (-EIO);
2101				}
2102			} else {
2103				if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2104					return (-EIO);
2105				mt_count++;
2106			}
2107		}
2108		cnt++;
2109		while (cnt != mt_count) {
2110			next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2111			if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2112#if DEBUG
2113				printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2114#endif
2115				return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2116			}
2117#if DEBUG
2118			else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2119#endif
2120			osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2121			cnt++;
2122			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2123#if DEBUG
2124				printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2125						 name);
2126#endif
2127				return (-EIO);
2128			}
2129			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2130				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2131						 name, next_mark_ppos);
2132				return (-EIO);
2133			}
2134		}
2135	}
2136	if (mt_op == MTFSF) {
2137		STp->frame_seq_number++;
2138		STp->frame_in_buffer      = 0;
2139		STp->buffer->buffer_bytes = 0;
2140		STp->buffer->read_pointer = 0;
2141		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2142	}
2143	return 0;
2144}
2145
2146/*
2147 * In debug mode, we want to see as many errors as possible
2148 * to test the error recovery mechanism.
2149 */
2150#if DEBUG
2151static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2152{
2153	unsigned char		cmd[MAX_COMMAND_SIZE];
2154	struct osst_request   * SRpnt  = * aSRpnt;
2155	char		      * name   = tape_name(STp);
2156
2157	memset(cmd, 0, MAX_COMMAND_SIZE);
2158	cmd[0] = MODE_SELECT;
2159	cmd[1] = 0x10;
2160	cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2161
2162	(STp->buffer)->b_data[0] = cmd[4] - 1;
2163	(STp->buffer)->b_data[1] = 0;			/* Medium Type - ignoring */
2164	(STp->buffer)->b_data[2] = 0;			/* Reserved */
2165	(STp->buffer)->b_data[3] = 0;			/* Block Descriptor Length */
2166	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2167	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2168	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2169	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2170
2171	if (debugging)
2172	    printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2173
2174	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2175	*aSRpnt = SRpnt;
2176
2177	if ((STp->buffer)->syscall_result)
2178	    printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2179}
2180#endif
2181
2182
2183static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2184{
2185	int	result;
2186	int	this_mark_ppos = STp->first_frame_position;
2187	int	this_mark_lbn  = STp->logical_blk_num;
2188#if DEBUG
2189	char  * name = tape_name(STp);
2190#endif
2191
2192	if (STp->raw) return 0;
2193
2194	STp->write_type = OS_WRITE_NEW_MARK;
2195#if DEBUG
2196	printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n", 
2197	       name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2198#endif
2199	STp->dirty = 1;
2200	result  = osst_flush_write_buffer(STp, aSRpnt);
2201	result |= osst_flush_drive_buffer(STp, aSRpnt);
2202	STp->last_mark_ppos = this_mark_ppos;
2203	STp->last_mark_lbn  = this_mark_lbn;
2204	if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2205		STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2206	if (STp->filemark_cnt++ == 0)
2207		STp->first_mark_ppos = this_mark_ppos;
2208	return result;
2209}
2210
2211static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2212{
2213	int	result;
2214#if DEBUG
2215	char  * name = tape_name(STp);
2216#endif
2217
2218	if (STp->raw) return 0;
2219
2220	STp->write_type = OS_WRITE_EOD;
2221	STp->eod_frame_ppos = STp->first_frame_position;
2222#if DEBUG
2223	printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2224			STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2225#endif
2226	STp->dirty = 1;
2227
2228	result  = osst_flush_write_buffer(STp, aSRpnt);	
2229	result |= osst_flush_drive_buffer(STp, aSRpnt);
2230	STp->eod_frame_lfa = --(STp->frame_seq_number);
2231	return result;
2232}
2233
2234static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2235{
2236	char * name = tape_name(STp);
2237
2238#if DEBUG
2239	printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2240#endif
2241	osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2242	osst_set_frame_position(STp, aSRpnt, where, 0);
2243	STp->write_type = OS_WRITE_FILLER;
2244	while (count--) {
2245		memcpy(STp->buffer->b_data, "Filler", 6);
2246		STp->buffer->buffer_bytes = 6;
2247		STp->dirty = 1;
2248		if (osst_flush_write_buffer(STp, aSRpnt)) {
2249			printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2250			return (-EIO);
2251		}
2252	}
2253#if DEBUG
2254	printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2255#endif
2256	return osst_flush_drive_buffer(STp, aSRpnt);
2257}
2258
2259static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2260{
2261	char * name = tape_name(STp);
2262	int     result;
2263
2264#if DEBUG
2265	printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2266#endif
2267	osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2268	osst_set_frame_position(STp, aSRpnt, where, 0);
2269	STp->write_type = OS_WRITE_HEADER;
2270	while (count--) {
2271		osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2272		STp->buffer->buffer_bytes = sizeof(os_header_t);
2273		STp->dirty = 1;
2274		if (osst_flush_write_buffer(STp, aSRpnt)) {
2275			printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2276			return (-EIO);
2277		}
2278	}
2279	result = osst_flush_drive_buffer(STp, aSRpnt);
2280#if DEBUG
2281	printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2282#endif
2283	return result;
2284}
2285
2286static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2287{
2288	os_header_t * header;
2289	int	      result;
2290	char        * name = tape_name(STp);
2291
2292#if DEBUG
2293	printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2294#endif
2295	if (STp->raw) return 0;
2296
2297	if (STp->header_cache == NULL) {
2298		if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2299			printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2300			return (-ENOMEM);
2301		}
2302		memset(STp->header_cache, 0, sizeof(os_header_t));
2303#if DEBUG
2304		printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2305#endif
2306	}
2307	if (STp->header_ok) STp->update_frame_cntr++;
2308	else                STp->update_frame_cntr = 0;
2309
2310	header = STp->header_cache;
2311	strcpy(header->ident_str, "ADR_SEQ");
2312	header->major_rev      = 1;
2313	header->minor_rev      = 4;
2314	header->ext_trk_tb_off = htons(17192);
2315	header->pt_par_num     = 1;
2316	header->partition[0].partition_num              = OS_DATA_PARTITION;
2317	header->partition[0].par_desc_ver               = OS_PARTITION_VERSION;
2318	header->partition[0].wrt_pass_cntr              = htons(STp->wrt_pass_cntr);
2319	header->partition[0].first_frame_ppos           = htonl(STp->first_data_ppos);
2320	header->partition[0].last_frame_ppos            = htonl(STp->capacity);
2321	header->partition[0].eod_frame_ppos             = htonl(STp->eod_frame_ppos);
2322	header->cfg_col_width                           = htonl(20);
2323	header->dat_col_width                           = htonl(1500);
2324	header->qfa_col_width                           = htonl(0);
2325	header->ext_track_tb.nr_stream_part             = 1;
2326	header->ext_track_tb.et_ent_sz                  = 32;
2327	header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2328	header->ext_track_tb.dat_ext_trk_ey.fmt         = 1;
2329	header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  = htons(17736);
2330	header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2331	header->ext_track_tb.dat_ext_trk_ey.last_hlb    = htonl(STp->eod_frame_lfa);
2332	header->ext_track_tb.dat_ext_trk_ey.last_pp	= htonl(STp->eod_frame_ppos);
2333	header->dat_fm_tab.fm_part_num                  = 0;
2334	header->dat_fm_tab.fm_tab_ent_sz                = 4;
2335	header->dat_fm_tab.fm_tab_ent_cnt               = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2336								STp->filemark_cnt:OS_FM_TAB_MAX);
2337
2338	result  = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2339	if (STp->update_frame_cntr == 0)
2340		    osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2341	result &= __osst_write_header(STp, aSRpnt,     5, 5);
2342
2343	if (locate_eod) {
2344#if DEBUG
2345		printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2346#endif
2347		osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2348	}
2349	if (result)
2350		printk(KERN_ERR "%s:E: Write header failed\n", name);
2351	else {
2352		memcpy(STp->application_sig, "LIN4", 4);
2353		STp->linux_media         = 1;
2354		STp->linux_media_version = 4;
2355		STp->header_ok           = 1;
2356	}
2357	return result;
2358}
2359
2360static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2361{
2362	if (STp->header_cache != NULL)
2363		memset(STp->header_cache, 0, sizeof(os_header_t));
2364
2365	STp->logical_blk_num = STp->frame_seq_number = 0;
2366	STp->frame_in_buffer = 0;
2367	STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2368	STp->filemark_cnt = 0;
2369	STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2370	return osst_write_header(STp, aSRpnt, 1);
2371}
2372
2373static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2374{
2375	char        * name = tape_name(STp);
2376	os_header_t * header;
2377	os_aux_t    * aux;
2378	char          id_string[8];
2379	int	      linux_media_version,
2380		      update_frame_cntr;
2381
2382	if (STp->raw)
2383		return 1;
2384
2385	if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2386		if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2387			printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2388		osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2389		if (osst_initiate_read (STp, aSRpnt)) {
2390			printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2391			return 0;
2392		}
2393	}
2394	if (osst_read_frame(STp, aSRpnt, 180)) {
2395#if DEBUG
2396		printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2397#endif
2398		return 0;
2399	}
2400	header = (os_header_t *) STp->buffer->b_data;	/* warning: only first segment addressable */
2401	aux = STp->buffer->aux;
2402	if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2403#if DEBUG
2404		printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2405#endif
2406		return 0;
2407	}
2408	if (ntohl(aux->frame_seq_num)              != 0                   ||
2409	    ntohl(aux->logical_blk_num)            != 0                   ||
2410	          aux->partition.partition_num     != OS_CONFIG_PARTITION ||
2411	    ntohl(aux->partition.first_frame_ppos) != 0                   ||
2412	    ntohl(aux->partition.last_frame_ppos)  != 0xbb7               ) {
2413#if DEBUG
2414		printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2415				ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2416			       	aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2417			       	ntohl(aux->partition.last_frame_ppos));
2418#endif
2419		return 0;
2420	}
2421	if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2422	    strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2423		strlcpy(id_string, header->ident_str, 8);
2424#if DEBUG
2425		printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2426#endif
2427		return 0;
2428	}
2429	update_frame_cntr = ntohl(aux->update_frame_cntr);
2430	if (update_frame_cntr < STp->update_frame_cntr) {
2431#if DEBUG
2432		printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2433				   name, ppos, update_frame_cntr, STp->update_frame_cntr);
2434#endif
2435		return 0;
2436	}
2437	if (header->major_rev != 1 || header->minor_rev != 4 ) {
2438#if DEBUG
2439		printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n", 
2440				 name, (header->major_rev != 1 || header->minor_rev < 2 || 
2441				       header->minor_rev  > 4 )? "Invalid" : "Warning:",
2442				 header->major_rev, header->minor_rev);
2443#endif
2444		if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2445			return 0;
2446	}
2447#if DEBUG
2448	if (header->pt_par_num != 1)
2449		printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n", 
2450				 name, header->pt_par_num);
2451#endif
2452	memcpy(id_string, aux->application_sig, 4);
2453	id_string[4] = 0;
2454	if (memcmp(id_string, "LIN", 3) == 0) {
2455		STp->linux_media = 1;
2456		linux_media_version = id_string[3] - '0';
2457		if (linux_media_version != 4)
2458			printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2459					 name, linux_media_version);
2460	} else {
2461		printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2462		return 0;
2463	}
2464	if (linux_media_version < STp->linux_media_version) {
2465#if DEBUG
2466		printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2467				  name, ppos, linux_media_version);
2468#endif
2469		return 0;
2470	}
2471	if (linux_media_version > STp->linux_media_version) {
2472#if DEBUG
2473		printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2474				   name, ppos, linux_media_version);
2475#endif
2476		memcpy(STp->application_sig, id_string, 5);
2477		STp->linux_media_version = linux_media_version;
2478		STp->update_frame_cntr = -1;
2479	}
2480	if (update_frame_cntr > STp->update_frame_cntr) {
2481#if DEBUG
2482		printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2483				   name, ppos, update_frame_cntr);
2484#endif
2485		if (STp->header_cache == NULL) {
2486			if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2487				printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2488				return 0;
2489			}
2490#if DEBUG
2491			printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2492#endif
2493		}
2494		osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2495		header = STp->header_cache;	/* further accesses from cached (full) copy */
2496
2497		STp->wrt_pass_cntr     = ntohs(header->partition[0].wrt_pass_cntr);
2498		STp->first_data_ppos   = ntohl(header->partition[0].first_frame_ppos);
2499		STp->eod_frame_ppos    = ntohl(header->partition[0].eod_frame_ppos);
2500		STp->eod_frame_lfa     = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2501		STp->filemark_cnt      = ntohl(aux->filemark_cnt);
2502		STp->first_mark_ppos   = ntohl(aux->next_mark_ppos);
2503		STp->last_mark_ppos    = ntohl(aux->last_mark_ppos);
2504		STp->last_mark_lbn     = ntohl(aux->last_mark_lbn);
2505		STp->update_frame_cntr = update_frame_cntr;
2506#if DEBUG
2507	printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2508			  name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2509	printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2510			  STp->first_data_ppos,
2511			  ntohl(header->partition[0].last_frame_ppos),
2512			  ntohl(header->partition[0].eod_frame_ppos));
2513	printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n", 
2514			  name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2515#endif
2516		if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2517#if DEBUG
2518			printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2519#endif
2520			memcpy((void *)header->dat_fm_tab.fm_tab_ent, 
2521			       (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2522			memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2523		}
2524		if (header->minor_rev == 4   &&
2525		    (header->ext_trk_tb_off                          != htons(17192)               ||
2526		     header->partition[0].partition_num              != OS_DATA_PARTITION          ||
2527		     header->partition[0].par_desc_ver               != OS_PARTITION_VERSION       ||
2528		     header->partition[0].last_frame_ppos            != htonl(STp->capacity)       ||
2529		     header->cfg_col_width                           != htonl(20)                  ||
2530		     header->dat_col_width                           != htonl(1500)                ||
2531		     header->qfa_col_width                           != htonl(0)                   ||
2532		     header->ext_track_tb.nr_stream_part             != 1                          ||
2533		     header->ext_track_tb.et_ent_sz                  != 32                         ||
2534		     header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION          ||
2535		     header->ext_track_tb.dat_ext_trk_ey.fmt         != 1                          ||
2536		     header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  != htons(17736)               ||
2537		     header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0                          ||
2538		     header->ext_track_tb.dat_ext_trk_ey.last_pp     != htonl(STp->eod_frame_ppos) ||
2539		     header->dat_fm_tab.fm_part_num                  != OS_DATA_PARTITION          ||
2540		     header->dat_fm_tab.fm_tab_ent_sz                != 4                          ||
2541		     header->dat_fm_tab.fm_tab_ent_cnt               !=
2542			     htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2543			printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2544
2545	}
2546
2547	return 1;
2548}
2549
2550static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2551{
2552	int	position, ppos;
2553	int	first, last;
2554	int	valid = 0;
2555	char  * name  = tape_name(STp);
2556
2557	position = osst_get_frame_position(STp, aSRpnt);
2558
2559	if (STp->raw) {
2560		STp->header_ok = STp->linux_media = 1;
2561		STp->linux_media_version = 0;
2562		return 1;
2563	}
2564	STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2565	STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2566	STp->eod_frame_ppos = STp->first_data_ppos = -1;
2567	STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2568#if DEBUG
2569	printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2570#endif
2571
2572	/* optimization for speed - if we are positioned at ppos 10, read second group first  */	
2573	/* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2574
2575	first = position==10?0xbae: 5;
2576	last  = position==10?0xbb3:10;
2577
2578	for (ppos = first; ppos < last; ppos++)
2579		if (__osst_analyze_headers(STp, aSRpnt, ppos))
2580			valid = 1;
2581
2582	first = position==10? 5:0xbae;
2583	last  = position==10?10:0xbb3;
2584
2585	for (ppos = first; ppos < last; ppos++)
2586		if (__osst_analyze_headers(STp, aSRpnt, ppos))
2587			valid = 1;
2588
2589	if (!valid) {
2590		printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2591		STp->eod_frame_ppos = STp->first_data_ppos = 0;
2592		osst_set_frame_position(STp, aSRpnt, 10, 0);
2593		return 0;
2594	}
2595	if (position <= STp->first_data_ppos) {
2596		position = STp->first_data_ppos;
2597		STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2598	}
2599	osst_set_frame_position(STp, aSRpnt, position, 0);
2600	STp->header_ok = 1;
2601
2602	return 1;
2603}
2604
2605static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2606{
2607	int	frame_position  = STp->first_frame_position;
2608	int	frame_seq_numbr = STp->frame_seq_number;
2609	int	logical_blk_num = STp->logical_blk_num;
2610       	int	halfway_frame   = STp->frame_in_buffer;
2611	int	read_pointer    = STp->buffer->read_pointer;
2612	int	prev_mark_ppos  = -1;
2613	int	actual_mark_ppos, i, n;
2614#if DEBUG
2615	char  * name = tape_name(STp);
2616
2617	printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2618#endif
2619	osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2620	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2621#if DEBUG
2622		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2623#endif
2624		return (-EIO);
2625	}
2626	if (STp->linux_media_version >= 4) {
2627		for (i=0; i<STp->filemark_cnt; i++)
2628			if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2629				prev_mark_ppos = n;
2630	} else
2631		prev_mark_ppos = frame_position - 1;  /* usually - we don't really know */
2632	actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2633				frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2634	if (frame_position  != STp->first_frame_position                   ||
2635	    frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2636	    prev_mark_ppos  != actual_mark_ppos                            ) {
2637#if DEBUG
2638		printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2639				  STp->first_frame_position, frame_position, 
2640				  STp->frame_seq_number + (halfway_frame?0:1),
2641				  frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2642#endif
2643		return (-EIO);
2644	}
2645	if (halfway_frame) {
2646		/* prepare buffer for append and rewrite on top of original */
2647		osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2648		STp->buffer->buffer_bytes  = read_pointer;
2649		STp->ps[STp->partition].rw = ST_WRITING;
2650		STp->dirty                 = 1;
2651	}
2652	STp->frame_in_buffer  = halfway_frame;
2653	STp->frame_seq_number = frame_seq_numbr;
2654	STp->logical_blk_num  = logical_blk_num;
2655	return 0;
2656}
2657
2658/* Acc. to OnStream, the vers. numbering is the following:
2659 * X.XX for released versions (X=digit), 
2660 * XXXY for unreleased versions (Y=letter)
2661 * Ordering 1.05 < 106A < 106B < ...  < 106a < ... < 1.06
2662 * This fn makes monoton numbers out of this scheme ...
2663 */
2664static unsigned int osst_parse_firmware_rev (const char * str)
2665{
2666	if (str[1] == '.') {
2667		return (str[0]-'0')*10000
2668			+(str[2]-'0')*1000
2669			+(str[3]-'0')*100;
2670	} else {
2671		return (str[0]-'0')*10000
2672			+(str[1]-'0')*1000
2673			+(str[2]-'0')*100 - 100
2674			+(str[3]-'@');
2675	}
2676}
2677
2678/*
2679 * Configure the OnStream SCII tape drive for default operation
2680 */
2681static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2682{
2683	unsigned char                  cmd[MAX_COMMAND_SIZE];
2684	char                         * name = tape_name(STp);
2685	struct osst_request          * SRpnt = * aSRpnt;
2686	osst_mode_parameter_header_t * header;
2687	osst_block_size_page_t       * bs;
2688	osst_capabilities_page_t     * cp;
2689	osst_tape_paramtr_page_t     * prm;
2690	int                            drive_buffer_size;
2691
2692	if (STp->ready != ST_READY) {
2693#if DEBUG
2694	    printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2695#endif
2696	    return (-EIO);
2697	}
2698	
2699	if (STp->os_fw_rev < 10600) {
2700	    printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2701	    printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2702	}
2703
2704	/*
2705	 * Configure 32.5KB (data+aux) frame size.
2706         * Get the current frame size from the block size mode page
2707	 */
2708	memset(cmd, 0, MAX_COMMAND_SIZE);
2709	cmd[0] = MODE_SENSE;
2710	cmd[1] = 8;
2711	cmd[2] = BLOCK_SIZE_PAGE;
2712	cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2713
2714	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2715	if (SRpnt == NULL) {
2716#if DEBUG
2717 	    printk(OSST_DEB_MSG "osst :D: Busy\n");
2718#endif
2719	    return (-EBUSY);
2720	}
2721	*aSRpnt = SRpnt;
2722	if ((STp->buffer)->syscall_result != 0) {
2723	    printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2724	    return (-EIO);
2725	}
2726
2727	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2728	bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2729
2730#if DEBUG
2731	printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n",   name, bs->play32     ? "Yes" : "No");
2732	printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5   ? "Yes" : "No");
2733	printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n",      name, bs->record32   ? "Yes" : "No");
2734	printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n",    name, bs->record32_5 ? "Yes" : "No");
2735#endif
2736
2737	/*
2738	 * Configure default auto columns mode, 32.5KB transfer mode
2739	 */ 
2740	bs->one = 1;
2741	bs->play32 = 0;
2742	bs->play32_5 = 1;
2743	bs->record32 = 0;
2744	bs->record32_5 = 1;
2745
2746	memset(cmd, 0, MAX_COMMAND_SIZE);
2747	cmd[0] = MODE_SELECT;
2748	cmd[1] = 0x10;
2749	cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2750
2751	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2752	*aSRpnt = SRpnt;
2753	if ((STp->buffer)->syscall_result != 0) {
2754	    printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2755	    return (-EIO);
2756	}
2757
2758#if DEBUG
2759	printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2760	 /*
2761	 * In debug mode, we want to see as many errors as possible
2762	 * to test the error recovery mechanism.
2763	 */
2764	osst_set_retries(STp, aSRpnt, 0);
2765	SRpnt = * aSRpnt;
2766#endif
2767
2768	/*
2769	 * Set vendor name to 'LIN4' for "Linux support version 4".
2770	 */
2771
2772	memset(cmd, 0, MAX_COMMAND_SIZE);
2773	cmd[0] = MODE_SELECT;
2774	cmd[1] = 0x10;
2775	cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2776
2777	header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2778	header->medium_type      = 0;	/* Medium Type - ignoring */
2779	header->dsp              = 0;	/* Reserved */
2780	header->bdl              = 0;	/* Block Descriptor Length */
2781	
2782	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2783	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2784	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2785	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2786	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2787	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2788	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2789	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2790
2791	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2792	*aSRpnt = SRpnt;
2793
2794	if ((STp->buffer)->syscall_result != 0) {
2795	    printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name, 
2796			(char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2797	    return (-EIO);
2798	}
2799
2800	memset(cmd, 0, MAX_COMMAND_SIZE);
2801	cmd[0] = MODE_SENSE;
2802	cmd[1] = 8;
2803	cmd[2] = CAPABILITIES_PAGE;
2804	cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2805
2806	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2807	*aSRpnt = SRpnt;
2808
2809	if ((STp->buffer)->syscall_result != 0) {
2810	    printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2811	    return (-EIO);
2812	}
2813
2814	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2815	cp     = (osst_capabilities_page_t    *) ((STp->buffer)->b_data +
2816		 sizeof(osst_mode_parameter_header_t) + header->bdl);
2817
2818	drive_buffer_size = ntohs(cp->buffer_size) / 2;
2819
2820	memset(cmd, 0, MAX_COMMAND_SIZE);
2821	cmd[0] = MODE_SENSE;
2822	cmd[1] = 8;
2823	cmd[2] = TAPE_PARAMTR_PAGE;
2824	cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2825
2826	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2827	*aSRpnt = SRpnt;
2828
2829	if ((STp->buffer)->syscall_result != 0) {
2830	    printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2831	    return (-EIO);
2832	}
2833
2834	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2835	prm    = (osst_tape_paramtr_page_t    *) ((STp->buffer)->b_data +
2836		 sizeof(osst_mode_parameter_header_t) + header->bdl);
2837
2838	STp->density  = prm->density;
2839	STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2840#if DEBUG
2841	printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2842			  name, STp->density, STp->capacity / 32, drive_buffer_size);
2843#endif
2844
2845	return 0;
2846	
2847}
2848
2849
2850/* Step over EOF if it has been inadvertently crossed (ioctl not used because
2851   it messes up the block number). */
2852static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2853{
2854	int	result;
2855	char  * name = tape_name(STp);
2856
2857#if DEBUG
2858	if (debugging)
2859		printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2860	   			  name, forward ? "forward" : "backward");
2861#endif
2862
2863	if (forward) {
2864	   /* assumes that the filemark is already read by the drive, so this is low cost */
2865	   result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2866	}
2867	else
2868	   /* assumes this is only called if we just read the filemark! */
2869	   result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2870
2871	if (result < 0)
2872	   printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2873				name, forward ? "forward" : "backward");
2874
2875	return result;
2876}
2877
2878
2879/* Get the tape position. */
2880
2881static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2882{
2883	unsigned char		scmd[MAX_COMMAND_SIZE];
2884	struct osst_request   * SRpnt;
2885	int			result = 0;
2886	char    	      * name   = tape_name(STp);
2887
2888	/* KG: We want to be able to use it for checking Write Buffer availability
2889	 *  and thus don't want to risk to overwrite anything. Exchange buffers ... */
2890	char		mybuf[24];
2891	char	      * olddata = STp->buffer->b_data;
2892	int		oldsize = STp->buffer->buffer_size;
2893
2894	if (STp->ready != ST_READY) return (-EIO);
2895
2896	memset (scmd, 0, MAX_COMMAND_SIZE);
2897	scmd[0] = READ_POSITION;
2898
2899	STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2900	SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2901				      STp->timeout, MAX_RETRIES, 1);
2902	if (!SRpnt) {
2903		STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2904		return (-EBUSY);
2905	}
2906	*aSRpnt = SRpnt;
2907
2908	if (STp->buffer->syscall_result)
2909		result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL;	/* 3: Write Error */
2910
2911	if (result == -EINVAL)
2912		printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2913	else {
2914		if (result == -EIO) {	/* re-read position - this needs to preserve media errors */
2915			unsigned char mysense[16];
2916			memcpy (mysense, SRpnt->sense, 16);
2917			memset (scmd, 0, MAX_COMMAND_SIZE);
2918			scmd[0] = READ_POSITION;
2919			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2920			SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2921						    STp->timeout, MAX_RETRIES, 1);
2922#if DEBUG
2923			printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2924					name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2925					SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2926#endif
2927			if (!STp->buffer->syscall_result)
2928				memcpy (SRpnt->sense, mysense, 16);
2929			else
2930				printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2931		}
2932		STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2933					  + ((STp->buffer)->b_data[5] << 16)
2934					  + ((STp->buffer)->b_data[6] << 8)
2935					  +  (STp->buffer)->b_data[7];
2936		STp->last_frame_position  = ((STp->buffer)->b_data[ 8] << 24)
2937					  + ((STp->buffer)->b_data[ 9] << 16)
2938					  + ((STp->buffer)->b_data[10] <<  8)
2939					  +  (STp->buffer)->b_data[11];
2940		STp->cur_frames           =  (STp->buffer)->b_data[15];
2941#if DEBUG
2942		if (debugging) {
2943			printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2944					    STp->first_frame_position, STp->last_frame_position,
2945					    ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2946					    ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2947					    STp->cur_frames);
2948		}
2949#endif
2950		if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2951#if DEBUG
2952			printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2953					STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2954#endif
2955			STp->first_frame_position = STp->last_frame_position;
2956		}
2957	}
2958	STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2959
2960	return (result == 0 ? STp->first_frame_position : result);
2961}
2962
2963
2964/* Set the tape block */
2965static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2966{
2967	unsigned char		scmd[MAX_COMMAND_SIZE];
2968	struct osst_request   * SRpnt;
2969	struct st_partstat    * STps;
2970	int			result = 0;
2971	int			pp     = (ppos == 3000 && !skip)? 0 : ppos;
2972	char		      * name   = tape_name(STp);
2973
2974	if (STp->ready != ST_READY) return (-EIO);
2975
2976	STps = &(STp->ps[STp->partition]);
2977
2978	if (ppos < 0 || ppos > STp->capacity) {
2979		printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2980		pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2981		result = (-EINVAL);
2982	}
2983
2984	do {
2985#if DEBUG
2986		if (debugging)
2987			printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2988#endif
2989		memset (scmd, 0, MAX_COMMAND_SIZE);
2990		scmd[0] = SEEK_10;
2991		scmd[1] = 1;
2992		scmd[3] = (pp >> 24);
2993		scmd[4] = (pp >> 16);
2994		scmd[5] = (pp >> 8);
2995		scmd[6] =  pp;
2996		if (skip)
2997			scmd[9] = 0x80;
2998
2999		SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
3000								MAX_RETRIES, 1);
3001		if (!SRpnt)
3002			return (-EBUSY);
3003		*aSRpnt  = SRpnt;
3004
3005		if ((STp->buffer)->syscall_result != 0) {
3006#if DEBUG
3007			printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
3008					name, STp->first_frame_position, pp);
3009#endif
3010			result = (-EIO);
3011		}
3012		if (pp != ppos)
3013			osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
3014	} while ((pp != ppos) && (pp = ppos));
3015	STp->first_frame_position = STp->last_frame_position = ppos;
3016	STps->eof = ST_NOEOF;
3017	STps->at_sm = 0;
3018	STps->rw = ST_IDLE;
3019	STp->frame_in_buffer = 0;
3020	return result;
3021}
3022
3023static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
3024{
3025	struct st_partstat * STps = &(STp->ps[STp->partition]);
3026	int result = 0;
3027
3028	if (STp->write_type != OS_WRITE_NEW_MARK) {
3029		/* true unless the user wrote the filemark for us */
3030		result = osst_flush_drive_buffer(STp, aSRpnt);
3031		if (result < 0) goto out;
3032		result = osst_write_filemark(STp, aSRpnt);
3033		if (result < 0) goto out;
3034
3035		if (STps->drv_file >= 0)
3036			STps->drv_file++ ;
3037		STps->drv_block = 0;
3038	}
3039	result = osst_write_eod(STp, aSRpnt);
3040	osst_write_header(STp, aSRpnt, leave_at_EOT);
3041
3042	STps->eof = ST_FM;
3043out:
3044	return result;
3045}
3046
3047/* osst versions of st functions - augmented and stripped to suit OnStream only */
3048
3049/* Flush the write buffer (never need to write if variable blocksize). */
3050static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
3051{
3052	int			offset, transfer, blks = 0;
3053	int			result = 0;
3054	unsigned char		cmd[MAX_COMMAND_SIZE];
3055	struct osst_request   * SRpnt = *aSRpnt;
3056	struct st_partstat    * STps;
3057	char		      * name = tape_name(STp);
3058
3059	if ((STp->buffer)->writing) {
3060		if (SRpnt == (STp->buffer)->last_SRpnt)
3061#if DEBUG
3062			{ printk(OSST_DEB_MSG
3063	 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
3064#endif
3065			*aSRpnt = SRpnt = NULL;
3066#if DEBUG
3067			} else if (SRpnt)
3068				printk(OSST_DEB_MSG
3069	 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
3070#endif	
3071		osst_write_behind_check(STp);
3072		if ((STp->buffer)->syscall_result) {
3073#if DEBUG
3074			if (debugging)
3075				printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3076				       name, (STp->buffer)->midlevel_result);
3077#endif
3078			if ((STp->buffer)->midlevel_result == INT_MAX)
3079				return (-ENOSPC);
3080			return (-EIO);
3081		}
3082	}
3083
3084	result = 0;
3085	if (STp->dirty == 1) {
3086
3087		STp->write_count++;
3088		STps     = &(STp->ps[STp->partition]);
3089		STps->rw = ST_WRITING;
3090		offset   = STp->buffer->buffer_bytes;
3091		blks     = (offset + STp->block_size - 1) / STp->block_size;
3092		transfer = OS_FRAME_SIZE;
3093		
3094		if (offset < OS_DATA_SIZE)
3095			osst_zero_buffer_tail(STp->buffer);
3096
3097		if (STp->poll)
3098			if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3099				result = osst_recover_wait_frame(STp, aSRpnt, 1);
3100
3101		memset(cmd, 0, MAX_COMMAND_SIZE);
3102		cmd[0] = WRITE_6;
3103		cmd[1] = 1;
3104		cmd[4] = 1;
3105
3106		switch	(STp->write_type) {
3107		   case OS_WRITE_DATA:
3108#if DEBUG
3109   			if (debugging)
3110				printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3111					name, blks, STp->frame_seq_number, 
3112					STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3113#endif
3114			osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3115				      STp->logical_blk_num - blks, STp->block_size, blks);
3116			break;
3117		   case OS_WRITE_EOD:
3118			osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3119				      STp->logical_blk_num, 0, 0);
3120			break;
3121		   case OS_WRITE_NEW_MARK:
3122			osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3123				      STp->logical_blk_num++, 0, blks=1);
3124			break;
3125		   case OS_WRITE_HEADER:
3126			osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3127			break;
3128		default: /* probably FILLER */
3129			osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3130		}
3131#if DEBUG
3132		if (debugging)
3133			printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3134			  			 name, offset, transfer, blks);
3135#endif
3136
3137		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3138					      STp->timeout, MAX_RETRIES, 1);
3139		*aSRpnt = SRpnt;
3140		if (!SRpnt)
3141			return (-EBUSY);
3142
3143		if ((STp->buffer)->syscall_result != 0) {
3144#if DEBUG
3145			printk(OSST_DEB_MSG
3146				"%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3147				name, SRpnt->sense[0], SRpnt->sense[2],
3148				SRpnt->sense[12], SRpnt->sense[13]);
3149#endif
3150			if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3151			    (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3152			    (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3153				STp->dirty = 0;
3154				(STp->buffer)->buffer_bytes = 0;
3155				result = (-ENOSPC);
3156			}
3157			else {
3158				if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3159					printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3160					result = (-EIO);
3161				}
3162			}
3163			STps->drv_block = (-1);		/* FIXME - even if write recovery succeeds? */
3164		}
3165		else {
3166			STp->first_frame_position++;
3167			STp->dirty = 0;
3168			(STp->buffer)->buffer_bytes = 0;
3169		}
3170	}
3171#if DEBUG
3172	printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3173#endif
3174	return result;
3175}
3176
3177
3178/* Flush the tape buffer. The tape will be positioned correctly unless
3179   seek_next is true. */
3180static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3181{
3182	struct st_partstat * STps;
3183	int    backspace = 0, result = 0;
3184#if DEBUG
3185	char * name = tape_name(STp);
3186#endif
3187
3188	/*
3189	 * If there was a bus reset, block further access
3190	 * to this device.
3191	 */
3192	if( STp->pos_unknown)
3193		return (-EIO);
3194
3195	if (STp->ready != ST_READY)
3196		return 0;
3197
3198	STps = &(STp->ps[STp->partition]);
3199	if (STps->rw == ST_WRITING || STp->dirty) {	/* Writing */
3200		STp->write_type = OS_WRITE_DATA;
3201		return osst_flush_write_buffer(STp, aSRpnt);
3202	}
3203	if (STp->block_size == 0)
3204		return 0;
3205
3206#if DEBUG
3207	printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3208#endif
3209
3210	if (!STp->can_bsr) {
3211		backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3212			    ((STp->buffer)->read_pointer + STp->block_size - 1        ) / STp->block_size ;
3213		(STp->buffer)->buffer_bytes = 0;
3214		(STp->buffer)->read_pointer = 0;
3215		STp->frame_in_buffer = 0;		/* FIXME is this relevant w. OSST? */
3216	}
3217
3218	if (!seek_next) {
3219		if (STps->eof == ST_FM_HIT) {
3220			result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3221			if (!result)
3222				STps->eof = ST_NOEOF;
3223			else {
3224				if (STps->drv_file >= 0)
3225					STps->drv_file++;
3226				STps->drv_block = 0;
3227			}
3228		}
3229		if (!result && backspace > 0)	/* TODO -- design and run a test case for this */
3230			result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3231	}
3232	else if (STps->eof == ST_FM_HIT) {
3233		if (STps->drv_file >= 0)
3234			STps->drv_file++;
3235		STps->drv_block = 0;
3236		STps->eof = ST_NOEOF;
3237	}
3238
3239	return result;
3240}
3241
3242static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3243{
3244	unsigned char		cmd[MAX_COMMAND_SIZE];
3245	struct osst_request   * SRpnt;
3246	int			blks;
3247#if DEBUG
3248	char		      * name = tape_name(STp);
3249#endif
3250
3251	if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3252#if DEBUG
3253		printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3254#endif
3255		if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3256			return (-EIO);
3257		}
3258		/* error recovery may have bumped us past the header partition */
3259		if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3260#if DEBUG
3261			printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3262#endif
3263		osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3264		}
3265	}
3266
3267	if (STp->poll)
3268		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3269			if (osst_recover_wait_frame(STp, aSRpnt, 1))
3270				return (-EIO);
3271
3272//	osst_build_stats(STp, &SRpnt);
3273
3274	STp->ps[STp->partition].rw = ST_WRITING;
3275	STp->write_type            = OS_WRITE_DATA;
3276			
3277	memset(cmd, 0, MAX_COMMAND_SIZE);
3278	cmd[0]   = WRITE_6;
3279	cmd[1]   = 1;
3280	cmd[4]   = 1;						/* one frame at a time... */
3281	blks     = STp->buffer->buffer_bytes / STp->block_size;
3282#if DEBUG
3283	if (debugging)
3284		printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks, 
3285			STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3286#endif
3287	osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3288		      STp->logical_blk_num - blks, STp->block_size, blks);
3289
3290#if DEBUG
3291	if (!synchronous)
3292		STp->write_pending = 1;
3293#endif
3294	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3295									MAX_RETRIES, synchronous);
3296	if (!SRpnt)
3297		return (-EBUSY);
3298	*aSRpnt = SRpnt;
3299
3300	if (synchronous) {
3301		if (STp->buffer->syscall_result != 0) {
3302#if DEBUG
3303			if (debugging)
3304				printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3305#endif
3306			if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3307			    (SRpnt->sense[2] & 0x40)) {
3308				if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3309					return (-ENOSPC);
3310			}
3311			else {
3312				if (osst_write_error_recovery(STp, aSRpnt, 1))
3313					return (-EIO);
3314			}
3315		}
3316		else
3317			STp->first_frame_position++;
3318	}
3319
3320	STp->write_count++;
3321
3322	return 0;
3323}
3324
3325/* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3326static int do_door_lock(struct osst_tape * STp, int do_lock)
3327{
3328	int retval, cmd;
3329
3330	cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3331#if DEBUG
3332	printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3333#endif
3334	retval = scsi_ioctl(STp->device, cmd, NULL);
3335	if (!retval) {
3336		STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3337	}
3338	else {
3339		STp->door_locked = ST_LOCK_FAILS;
3340	}
3341	return retval;
3342}
3343
3344/* Set the internal state after reset */
3345static void reset_state(struct osst_tape *STp)
3346{
3347	int i;
3348	struct st_partstat *STps;
3349
3350	STp->pos_unknown = 0;
3351	for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3352		STps = &(STp->ps[i]);
3353		STps->rw = ST_IDLE;
3354		STps->eof = ST_NOEOF;
3355		STps->at_sm = 0;
3356		STps->last_block_valid = 0;
3357		STps->drv_block = -1;
3358		STps->drv_file = -1;
3359	}
3360}
3361				
3362
3363/* Entry points to osst */
3364
3365/* Write command */
3366static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3367{
3368	ssize_t		      total, retval = 0;
3369	ssize_t		      i, do_count, blks, transfer;
3370	int		      write_threshold;
3371	int		      doing_write = 0;
3372	const char   __user * b_point;
3373	struct osst_request * SRpnt = NULL;
3374	struct st_modedef   * STm;
3375	struct st_partstat  * STps;
3376	struct osst_tape    * STp  = filp->private_data;
3377	char		    * name = tape_name(STp);
3378
3379
3380	if (mutex_lock_interruptible(&STp->lock))
3381		return (-ERESTARTSYS);
3382
3383	/*
3384	 * If we are in the middle of error recovery, don't let anyone
3385	 * else try and use this device.  Also, if error recovery fails, it
3386	 * may try and take the device offline, in which case all further
3387	 * access to the device is prohibited.
3388	 */
3389	if( !scsi_block_when_processing_errors(STp->device) ) {
3390		retval = (-ENXIO);
3391		goto out;
3392	}
3393	
3394	if (STp->ready != ST_READY) {
3395		if (STp->ready == ST_NO_TAPE)
3396			retval = (-ENOMEDIUM);
3397		else
3398			retval = (-EIO);
3399		goto out;
3400	}
3401	STm = &(STp->modes[STp->current_mode]);
3402	if (!STm->defined) {
3403		retval = (-ENXIO);
3404		goto out;
3405	}
3406	if (count == 0)
3407		goto out;
3408
3409	/*
3410	 * If there was a bus reset, block further access
3411	 * to this device.
3412	 */
3413	if (STp->pos_unknown) {
3414		retval = (-EIO);
3415		goto out;
3416	}
3417
3418#if DEBUG
3419	if (!STp->in_use) {
3420		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3421		retval = (-EIO);
3422		goto out;
3423	}
3424#endif
3425
3426	if (STp->write_prot) {
3427		retval = (-EACCES);
3428		goto out;
3429	}
3430
3431	/* Write must be integral number of blocks */
3432	if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3433		printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3434				       name, count, STp->block_size<1024?
3435				       STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3436		retval = (-EINVAL);
3437		goto out;
3438	}
3439
3440	if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3441		printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3442				       name, STp->first_frame_position);
3443		retval = (-ENOSPC);
3444		goto out;
3445	}
3446
3447	if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3448		STp->door_locked = ST_LOCKED_AUTO;
3449
3450	STps = &(STp->ps[STp->partition]);
3451
3452	if (STps->rw == ST_READING) {
3453#if DEBUG
3454		printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name, 
3455					STps->drv_file, STps->drv_block);
3456#endif
3457		retval = osst_flush_buffer(STp, &SRpnt, 0);
3458		if (retval)
3459			goto out;
3460		STps->rw = ST_IDLE;
3461	}
3462	if (STps->rw != ST_WRITING) {
3463		/* Are we totally rewriting this tape? */
3464		if (!STp->header_ok ||
3465		    (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3466		    (STps->drv_file == 0 && STps->drv_block == 0)) {
3467			STp->wrt_pass_cntr++;
3468#if DEBUG
3469			printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3470						  name, STp->wrt_pass_cntr);
3471#endif
3472			osst_reset_header(STp, &SRpnt);
3473			STps->drv_file = STps->drv_block = 0;
3474		}
3475		/* Do we know where we'll be writing on the tape? */
3476		else {
3477			if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3478			  		STps->drv_file < 0 || STps->drv_block < 0) {
3479				if (STp->first_frame_position == STp->eod_frame_ppos) {	/* at EOD */
3480			  		STps->drv_file = STp->filemark_cnt;
3481			  		STps->drv_block = 0;
3482				}
3483				else {
3484					/* We have no idea where the tape is positioned - give up */
3485#if DEBUG
3486					printk(OSST_DEB_MSG
3487						"%s:D: Cannot write at indeterminate position.\n", name);
3488#endif
3489					retval = (-EIO);
3490					goto out;
3491				}
3492      			}	  
3493			if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3494				STp->filemark_cnt = STps->drv_file;
3495				STp->last_mark_ppos =
3496				       	ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3497				printk(KERN_WARNING
3498					"%s:W: Overwriting file %d with old write pass counter %d\n",
3499						name, STps->drv_file, STp->wrt_pass_cntr);
3500				printk(KERN_WARNING
3501					"%s:W: may lead to stale data being accepted on reading back!\n",
3502						name);
3503#if DEBUG
3504				printk(OSST_DEB_MSG
3505				  "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3506					name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3507#endif
3508			}
3509		}
3510		STp->fast_open = 0;
3511	}
3512	if (!STp->header_ok) {
3513#if DEBUG
3514		printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3515#endif
3516		retval = (-EIO);
3517		goto out;
3518	}
3519
3520	if ((STp->buffer)->writing) {
3521if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3522		osst_write_behind_check(STp);
3523		if ((STp->buffer)->syscall_result) {
3524#if DEBUG
3525		if (debugging)
3526			printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3527						 (STp->buffer)->midlevel_result);
3528#endif
3529		if ((STp->buffer)->midlevel_result == INT_MAX)
3530			STps->eof = ST_EOM_OK;
3531		else
3532			STps->eof = ST_EOM_ERROR;
3533		}
3534	}
3535	if (STps->eof == ST_EOM_OK) {
3536		retval = (-ENOSPC);
3537		goto out;
3538	}
3539	else if (STps->eof == ST_EOM_ERROR) {
3540		retval = (-EIO);
3541		goto out;
3542	}
3543
3544	/* Check the buffer readability in cases where copy_user might catch
3545		 the problems after some tape movement. */
3546	if ((copy_from_user(&i, buf, 1) != 0 ||
3547	     copy_from_user(&i, buf + count - 1, 1) != 0)) {
3548		retval = (-EFAULT);
3549		goto out;
3550	}
3551
3552	if (!STm->do_buffer_writes) {
3553		write_threshold = 1;
3554	}
3555	else
3556		write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3557	if (!STm->do_async_writes)
3558		write_threshold--;
3559
3560	total = count;
3561#if DEBUG
3562	if (debugging)
3563		printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3564				name, (int) count, STps->drv_file, STps->drv_block,
3565				STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3566#endif
3567	b_point = buf;
3568	while ((STp->buffer)->buffer_bytes + count > write_threshold)
3569	{
3570		doing_write = 1;
3571		do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3572			   (STp->buffer)->buffer_bytes;
3573		if (do_count > count)
3574			do_count = count;
3575
3576		i = append_to_buffer(b_point, STp->buffer, do_count);
3577		if (i) {
3578			retval = i;
3579			goto out;
3580		}
3581
3582		blks = do_count / STp->block_size;
3583		STp->logical_blk_num += blks;  /* logical_blk_num is incremented as data is moved from user */
3584  
3585		i = osst_write_frame(STp, &SRpnt, 1);
3586
3587		if (i == (-ENOSPC)) {
3588			transfer = STp->buffer->writing;	/* FIXME -- check this logic */
3589			if (transfer <= do_count) {
3590				*ppos += do_count - transfer;
3591				count -= do_count - transfer;
3592				if (STps->drv_block >= 0) {
3593					STps->drv_block += (do_count - transfer) / STp->block_size;
3594				}
3595				STps->eof = ST_EOM_OK;
3596				retval = (-ENOSPC);		/* EOM within current request */
3597#if DEBUG
3598				if (debugging)
3599				      printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3600							     name, (int) transfer);
3601#endif
3602			}
3603			else {
3604				STps->eof = ST_EOM_ERROR;
3605				STps->drv_block = (-1);		/* Too cautious? */
3606				retval = (-EIO);		/* EOM for old data */
3607#if DEBUG
3608				if (debugging)
3609				      printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3610#endif
3611			}
3612		}
3613		else
3614			retval = i;
3615			
3616		if (retval < 0) {
3617			if (SRpnt != NULL) {
3618				osst_release_request(SRpnt);
3619				SRpnt = NULL;
3620			}
3621			STp->buffer->buffer_bytes = 0;
3622			STp->dirty = 0;
3623			if (count < total)
3624				retval = total - count;
3625			goto out;
3626		}
3627
3628		*ppos += do_count;
3629		b_point += do_count;
3630		count -= do_count;
3631		if (STps->drv_block >= 0) {
3632			STps->drv_block += blks;
3633		}
3634		STp->buffer->buffer_bytes = 0;
3635		STp->dirty = 0;
3636	}  /* end while write threshold exceeded */
3637
3638	if (count != 0) {
3639		STp->dirty = 1;
3640		i = append_to_buffer(b_point, STp->buffer, count);
3641		if (i) {
3642			retval = i;
3643			goto out;
3644		}
3645		blks = count / STp->block_size;
3646		STp->logical_blk_num += blks;
3647		if (STps->drv_block >= 0) {
3648			STps->drv_block += blks;
3649		}
3650		*ppos += count;
3651		count = 0;
3652	}
3653
3654	if (doing_write && (STp->buffer)->syscall_result != 0) {
3655		retval = (STp->buffer)->syscall_result;
3656		goto out;
3657	}
3658
3659	if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) { 
3660		/* Schedule an asynchronous write */
3661		(STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3662					   STp->block_size) * STp->block_size;
3663		STp->dirty = !((STp->buffer)->writing ==
3664				          (STp->buffer)->buffer_bytes);
3665
3666		i = osst_write_frame(STp, &SRpnt, 0);
3667		if (i < 0) {
3668			retval = (-EIO);
3669			goto out;
3670		}
3671		SRpnt = NULL;			/* Prevent releasing this request! */
3672	}
3673	STps->at_sm &= (total == 0);
3674	if (total > 0)
3675		STps->eof = ST_NOEOF;
3676
3677	retval = total;
3678
3679out:
3680	if (SRpnt != NULL) osst_release_request(SRpnt);
3681
3682	mutex_unlock(&STp->lock);
3683
3684	return retval;
3685}
3686
3687
3688/* Read command */
3689static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3690{
3691	ssize_t		      total, retval = 0;
3692	ssize_t		      i, transfer;
3693	int		      special;
3694	struct st_modedef   * STm;
3695	struct st_partstat  * STps;
3696	struct osst_request * SRpnt = NULL;
3697	struct osst_tape    * STp   = filp->private_data;
3698	char		    * name  = tape_name(STp);
3699
3700
3701	if (mutex_lock_interruptible(&STp->lock))
3702		return (-ERESTARTSYS);
3703
3704	/*
3705	 * If we are in the middle of error recovery, don't let anyone
3706	 * else try and use this device.  Also, if error recovery fails, it
3707	 * may try and take the device offline, in which case all further
3708	 * access to the device is prohibited.
3709	 */
3710	if( !scsi_block_when_processing_errors(STp->device) ) {
3711		retval = (-ENXIO);
3712		goto out;
3713	}
3714	
3715	if (STp->ready != ST_READY) {
3716		if (STp->ready == ST_NO_TAPE)
3717			retval = (-ENOMEDIUM);
3718		else
3719			retval = (-EIO);
3720		goto out;
3721	}
3722	STm = &(STp->modes[STp->current_mode]);
3723	if (!STm->defined) {
3724		retval = (-ENXIO);
3725		goto out;
3726	}
3727#if DEBUG
3728	if (!STp->in_use) {
3729		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3730		retval = (-EIO);
3731		goto out;
3732	}
3733#endif
3734	/* Must have initialized medium */
3735	if (!STp->header_ok) {
3736		retval = (-EIO);
3737		goto out;
3738	}
3739
3740	if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3741		STp->door_locked = ST_LOCKED_AUTO;
3742
3743	STps = &(STp->ps[STp->partition]);
3744	if (STps->rw == ST_WRITING) {
3745		retval = osst_flush_buffer(STp, &SRpnt, 0);
3746		if (retval)
3747			goto out;
3748		STps->rw = ST_IDLE;
3749		/* FIXME -- this may leave the tape without EOD and up2date headers */
3750	}
3751
3752	if ((count % STp->block_size) != 0) {
3753		printk(KERN_WARNING
3754		    "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3755		    STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3756	}
3757
3758#if DEBUG
3759	if (debugging && STps->eof != ST_NOEOF)
3760		printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3761				     STps->eof, (STp->buffer)->buffer_bytes);
3762#endif
3763	if ((STp->buffer)->buffer_bytes == 0 &&
3764	     STps->eof >= ST_EOD_1) {
3765		if (STps->eof < ST_EOD) {
3766			STps->eof += 1;
3767			retval = 0;
3768			goto out;
3769		}
3770		retval = (-EIO);  /* EOM or Blank Check */
3771		goto out;
3772	}
3773
3774	/* Check the buffer writability before any tape movement. Don't alter
3775		 buffer data. */
3776	if (copy_from_user(&i, buf, 1)             != 0 ||
3777	    copy_to_user  (buf, &i, 1)             != 0 ||
3778	    copy_from_user(&i, buf + count - 1, 1) != 0 ||
3779	    copy_to_user  (buf + count - 1, &i, 1) != 0) {
3780		retval = (-EFAULT);
3781		goto out;
3782	}
3783
3784	/* Loop until enough data in buffer or a special condition found */
3785	for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3786
3787		/* Get new data if the buffer is empty */
3788		if ((STp->buffer)->buffer_bytes == 0) {
3789			if (STps->eof == ST_FM_HIT)
3790				break;
3791			special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3792			if (special < 0) { 			/* No need to continue read */
3793				STp->frame_in_buffer = 0;
3794				retval = special;
3795				goto out;
3796			}
3797		}
3798
3799		/* Move the data from driver buffer to user buffer */
3800		if ((STp->buffer)->buffer_bytes > 0) {
3801#if DEBUG
3802			if (debugging && STps->eof != ST_NOEOF)
3803			    printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3804						 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3805#endif
3806		       	/* force multiple of block size, note block_size may have been adjusted */
3807			transfer = (((STp->buffer)->buffer_bytes < count - total ?
3808				     (STp->buffer)->buffer_bytes : count - total)/
3809					STp->block_size) * STp->block_size;
3810
3811			if (transfer == 0) {
3812				printk(KERN_WARNING
3813				  "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n",
3814			   		name, count, STp->block_size < 1024?
3815					STp->block_size:STp->block_size/1024,
3816				       	STp->block_size<1024?'b':'k');
3817				break;
3818			}
3819			i = from_buffer(STp->buffer, buf, transfer);
3820			if (i)  {
3821				retval = i;
3822				goto out;
3823			}
3824			STp->logical_blk_num += transfer / STp->block_size;
3825			STps->drv_block      += transfer / STp->block_size;
3826			*ppos          += transfer;
3827			buf                  += transfer;
3828			total                += transfer;
3829		}
3830 
3831		if ((STp->buffer)->buffer_bytes == 0) {
3832#if DEBUG
3833			if (debugging)
3834				printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3835					       	name, STp->frame_seq_number);
3836#endif
3837			STp->frame_in_buffer = 0;
3838			STp->frame_seq_number++;              /* frame to look for next time */
3839		}
3840	} /* for (total = 0, special = 0; total < count && !special; ) */
3841
3842	/* Change the eof state if no data from tape or buffer */
3843	if (total == 0) {
3844		if (STps->eof == ST_FM_HIT) {
3845			STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3846			STps->drv_block = 0;
3847			if (STps->drv_file >= 0)
3848				STps->drv_file++;
3849		}
3850		else if (STps->eof == ST_EOD_1) {
3851			STps->eof = ST_EOD_2;
3852			if (STps->drv_block > 0 && STps->drv_file >= 0)
3853				STps->drv_file++;
3854			STps->drv_block = 0;
3855		}
3856		else if (STps->eof == ST_EOD_2)
3857			STps->eof = ST_EOD;
3858	}
3859	else if (STps->eof == ST_FM)
3860		STps->eof = ST_NOEOF;
3861
3862	retval = total;
3863
3864out:
3865	if (SRpnt != NULL) osst_release_request(SRpnt);
3866
3867	mutex_unlock(&STp->lock);
3868
3869	return retval;
3870}
3871
3872
3873/* Set the driver options */
3874static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3875{
3876  printk(KERN_INFO
3877"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3878	 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3879	 STm->do_read_ahead);
3880  printk(KERN_INFO
3881"%s:I:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3882	 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3883  printk(KERN_INFO
3884"%s:I:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3885	 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3886	 STp->scsi2_logical);
3887  printk(KERN_INFO
3888"%s:I:    sysv: %d\n", name, STm->sysv);
3889#if DEBUG
3890  printk(KERN_INFO
3891	 "%s:D:    debugging: %d\n",
3892	 name, debugging);
3893#endif
3894}
3895
3896
3897static int osst_set_options(struct osst_tape *STp, long options)
3898{
3899	int		    value;
3900	long		    code;
3901	struct st_modedef * STm;
3902	char		  * name = tape_name(STp);
3903
3904	STm = &(STp->modes[STp->current_mode]);
3905	if (!STm->defined) {
3906		memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3907		modes_defined = 1;
3908#if DEBUG
3909		if (debugging)
3910			printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3911					     name, STp->current_mode);
3912#endif
3913	}
3914
3915	code = options & MT_ST_OPTIONS;
3916	if (code == MT_ST_BOOLEANS) {
3917		STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3918		STm->do_async_writes  = (options & MT_ST_ASYNC_WRITES) != 0;
3919		STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3920		STm->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
3921		STp->two_fm	      = (options & MT_ST_TWO_FM) != 0;
3922		STp->fast_mteom	      = (options & MT_ST_FAST_MTEOM) != 0;
3923		STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
3924		STp->can_bsr          = (options & MT_ST_CAN_BSR) != 0;
3925		STp->omit_blklims     = (options & MT_ST_NO_BLKLIMS) != 0;
3926		if ((STp->device)->scsi_level >= SCSI_2)
3927			STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3928		STp->scsi2_logical    = (options & MT_ST_SCSI2LOGICAL) != 0;
3929		STm->sysv	      = (options & MT_ST_SYSV) != 0;
3930#if DEBUG
3931		debugging = (options & MT_ST_DEBUGGING) != 0;
3932#endif
3933		osst_log_options(STp, STm, name);
3934	}
3935	else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3936		value = (code == MT_ST_SETBOOLEANS);
3937		if ((options & MT_ST_BUFFER_WRITES) != 0)
3938			STm->do_buffer_writes = value;
3939		if ((options & MT_ST_ASYNC_WRITES) != 0)
3940			STm->do_async_writes = value;
3941		if ((options & MT_ST_DEF_WRITES) != 0)
3942			STm->defaults_for_writes = value;
3943		if ((options & MT_ST_READ_AHEAD) != 0)
3944			STm->do_read_ahead = value;
3945		if ((options & MT_ST_TWO_FM) != 0)
3946			STp->two_fm = value;
3947		if ((options & MT_ST_FAST_MTEOM) != 0)
3948			STp->fast_mteom = value;
3949		if ((options & MT_ST_AUTO_LOCK) != 0)
3950			STp->do_auto_lock = value;
3951		if ((options & MT_ST_CAN_BSR) != 0)
3952			STp->can_bsr = value;
3953		if ((options & MT_ST_NO_BLKLIMS) != 0)
3954			STp->omit_blklims = value;
3955		if ((STp->device)->scsi_level >= SCSI_2 &&
3956		    (options & MT_ST_CAN_PARTITIONS) != 0)
3957			STp->can_partitions = value;
3958		if ((options & MT_ST_SCSI2LOGICAL) != 0)
3959			STp->scsi2_logical = value;
3960		if ((options & MT_ST_SYSV) != 0)
3961			STm->sysv = value;
3962#if DEBUG
3963		if ((options & MT_ST_DEBUGGING) != 0)
3964			debugging = value;
3965#endif
3966		osst_log_options(STp, STm, name);
3967	}
3968	else if (code == MT_ST_WRITE_THRESHOLD) {
3969		value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3970		if (value < 1 || value > osst_buffer_size) {
3971			printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3972					     name, value);
3973			return (-EIO);
3974		}
3975		STp->write_threshold = value;
3976		printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3977				  name, value);
3978	}
3979	else if (code == MT_ST_DEF_BLKSIZE) {
3980		value = (options & ~MT_ST_OPTIONS);
3981		if (value == ~MT_ST_OPTIONS) {
3982			STm->default_blksize = (-1);
3983			printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3984		}
3985		else {
3986			if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3987				printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3988							 name, value);
3989				return (-EINVAL);
3990			}
3991			STm->default_blksize = value;
3992			printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3993					  name, STm->default_blksize);
3994		}
3995	}
3996	else if (code == MT_ST_TIMEOUTS) {
3997		value = (options & ~MT_ST_OPTIONS);
3998		if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3999			STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
4000			printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
4001					     (value & ~MT_ST_SET_LONG_TIMEOUT));
4002		}
4003		else {
4004			STp->timeout = value * HZ;
4005			printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
4006		}
4007	}
4008	else if (code == MT_ST_DEF_OPTIONS) {
4009		code = (options & ~MT_ST_CLEAR_DEFAULT);
4010		value = (options & MT_ST_CLEAR_DEFAULT);
4011		if (code == MT_ST_DEF_DENSITY) {
4012			if (value == MT_ST_CLEAR_DEFAULT) {
4013				STm->default_density = (-1);
4014				printk(KERN_INFO "%s:I: Density default disabled.\n", name);
4015			}
4016			else {
4017				STm->default_density = value & 0xff;
4018				printk(KERN_INFO "%s:I: Density default set to %x\n",
4019						  name, STm->default_density);
4020			}
4021		}
4022		else if (code == MT_ST_DEF_DRVBUFFER) {
4023			if (value == MT_ST_CLEAR_DEFAULT) {
4024				STp->default_drvbuffer = 0xff;
4025				printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
4026			}
4027			else {
4028				STp->default_drvbuffer = value & 7;
4029				printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
4030						  name, STp->default_drvbuffer);
4031			}
4032		}
4033		else if (code == MT_ST_DEF_COMPRESSION) {
4034			if (value == MT_ST_CLEAR_DEFAULT) {
4035				STm->default_compression = ST_DONT_TOUCH;
4036				printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
4037			}
4038			else {
4039				STm->default_compression = (value & 1 ? ST_YES : ST_NO);
4040				printk(KERN_INFO "%s:I: Compression default set to %x\n",
4041						  name, (value & 1));
4042			}
4043		}
4044	}
4045	else
4046		return (-EIO);
4047
4048	return 0;
4049}
4050
4051
4052/* Internal ioctl function */
4053static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
4054			     unsigned int cmd_in, unsigned long arg)
4055{
4056	int			timeout;
4057	long			ltmp;
4058	int			i, ioctl_result;
4059	int			chg_eof = 1;
4060	unsigned char		cmd[MAX_COMMAND_SIZE];
4061	struct osst_request   * SRpnt = * aSRpnt;
4062	struct st_partstat    * STps;
4063	int			fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
4064	int			datalen = 0, direction = DMA_NONE;
4065	char		      * name = tape_name(STp);
4066
4067	if (STp->ready != ST_READY && cmd_in != MTLOAD) {
4068		if (STp->ready == ST_NO_TAPE)
4069			return (-ENOMEDIUM);
4070		else
4071			return (-EIO);
4072	}
4073	timeout = STp->long_timeout;
4074	STps = &(STp->ps[STp->partition]);
4075	fileno = STps->drv_file;
4076	blkno = STps->drv_block;
4077	at_sm = STps->at_sm;
4078	frame_seq_numbr = STp->frame_seq_number;
4079	logical_blk_num = STp->logical_blk_num;
4080
4081	memset(cmd, 0, MAX_COMMAND_SIZE);
4082	switch (cmd_in) {
4083	 case MTFSFM:
4084		chg_eof = 0; /* Changed from the FSF after this */
4085	 case MTFSF:
4086		if (STp->raw)
4087		   return (-EIO);
4088		if (STp->linux_media)
4089		   ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4090		else
4091		   ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4092		if (fileno >= 0)
4093		   fileno += arg;
4094		blkno = 0;
4095		at_sm &= (arg == 0);
4096		goto os_bypass;
4097
4098	 case MTBSF:
4099		chg_eof = 0; /* Changed from the FSF after this */
4100	 case MTBSFM:
4101		if (STp->raw)
4102		   return (-EIO);
4103		ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4104		if (fileno >= 0)
4105		   fileno -= arg;
4106		blkno = (-1);  /* We can't know the block number */
4107		at_sm &= (arg == 0);
4108		goto os_bypass;
4109
4110	 case MTFSR:
4111	 case MTBSR:
4112#if DEBUG
4113		if (debugging)
4114		   printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4115				name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4116#endif
4117		if (cmd_in == MTFSR) {
4118		   logical_blk_num += arg;
4119		   if (blkno >= 0) blkno += arg;
4120		}
4121		else {
4122		   logical_blk_num -= arg;
4123		   if (blkno >= 0) blkno -= arg;
4124		}
4125		ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4126		fileno = STps->drv_file;
4127		blkno  = STps->drv_block;
4128		at_sm &= (arg == 0);
4129		goto os_bypass;
4130
4131	 case MTFSS:
4132		cmd[0] = SPACE;
4133		cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4134		cmd[2] = (arg >> 16);
4135		cmd[3] = (arg >> 8);
4136		cmd[4] = arg;
4137#if DEBUG
4138		if (debugging)
4139			printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4140		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4141#endif
4142		if (arg != 0) {
4143			blkno = fileno = (-1);
4144			at_sm = 1;
4145		}
4146		break;
4147	 case MTBSS:
4148		cmd[0] = SPACE;
4149		cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4150		ltmp = (-arg);
4151		cmd[2] = (ltmp >> 16);
4152		cmd[3] = (ltmp >> 8);
4153		cmd[4] = ltmp;
4154#if DEBUG
4155		if (debugging) {
4156			if (cmd[2] & 0x80)
4157			   ltmp = 0xff000000;
4158			ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4159			printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4160						name, (-ltmp));
4161		 }
4162#endif
4163		 if (arg != 0) {
4164			blkno = fileno = (-1);
4165			at_sm = 1;
4166		 }
4167		 break;
4168	 case MTWEOF:
4169		 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4170			STp->write_type = OS_WRITE_DATA;
4171			ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4172		 } else
4173			ioctl_result = 0;
4174#if DEBUG
4175		 if (debugging) 
4176			   printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4177#endif
4178		 for (i=0; i<arg; i++)
4179			ioctl_result |= osst_write_filemark(STp, &SRpnt);
4180		 if (fileno >= 0) fileno += arg;
4181		 if (blkno  >= 0) blkno   = 0;
4182		 goto os_bypass;
4183
4184	 case MTWSM:
4185		 if (STp->write_prot)
4186			return (-EACCES);
4187		 if (!STp->raw)
4188			return 0;
4189		 cmd[0] = WRITE_FILEMARKS;   /* FIXME -- need OS version */
4190		 if (cmd_in == MTWSM)
4191			 cmd[1] = 2;
4192		 cmd[2] = (arg >> 16);
4193		 cmd[3] = (arg >> 8);
4194		 cmd[4] = arg;
4195		 timeout = STp->timeout;
4196#if DEBUG
4197		 if (debugging) 
4198			   printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4199				  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4200#endif
4201		 if (fileno >= 0)
4202			fileno += arg;
4203		 blkno = 0;
4204		 at_sm = (cmd_in == MTWSM);
4205		 break;
4206	 case MTOFFL:
4207	 case MTLOAD:
4208	 case MTUNLOAD:
4209	 case MTRETEN:
4210		 cmd[0] = START_STOP;
4211		 cmd[1] = 1;			/* Don't wait for completion */
4212		 if (cmd_in == MTLOAD) {
4213		     if (STp->ready == ST_NO_TAPE)
4214			 cmd[4] = 4;		/* open tray */
4215		      else
4216			 cmd[4] = 1;		/* load */
4217		 }
4218		 if (cmd_in == MTRETEN)
4219			 cmd[4] = 3;		/* retension then mount */
4220		 if (cmd_in == MTOFFL)
4221			 cmd[4] = 4;		/* rewind then eject */
4222		 timeout = STp->timeout;
4223#if DEBUG
4224		 if (debugging) {
4225			 switch (cmd_in) {
4226				 case MTUNLOAD:
4227					 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4228					 break;
4229				 case MTLOAD:
4230					 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4231					 break;
4232				 case MTRETEN:
4233					 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4234					 break;
4235				 case MTOFFL:
4236					 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4237					 break;
4238			 }
4239		 }
4240#endif
4241       fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4242		 break;
4243	 case MTNOP:
4244#if DEBUG
4245		 if (debugging)
4246			 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4247#endif
4248		 return 0;  /* Should do something ? */
4249		 break;
4250	 case MTEOM:
4251#if DEBUG
4252		if (debugging)
4253		   printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4254#endif
4255		if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4256			    (osst_get_logical_frame(STp, &SRpnt, -1, 0)               < 0)) {
4257		   ioctl_result = -EIO;
4258		   goto os_bypass;
4259		}
4260		if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4261#if DEBUG
4262		   printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4263#endif
4264		   ioctl_result = -EIO;
4265		   goto os_bypass;
4266		}
4267		ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4268		fileno = STp->filemark_cnt;
4269		blkno  = at_sm = 0;
4270		goto os_bypass;
4271
4272	 case MTERASE:
4273		if (STp->write_prot)
4274		   return (-EACCES);
4275		ioctl_result = osst_reset_header(STp, &SRpnt);
4276		i = osst_write_eod(STp, &SRpnt);
4277		if (i < ioctl_result) ioctl_result = i;
4278		i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4279		if (i < ioctl_result) ioctl_result = i;
4280		fileno = blkno = at_sm = 0 ;
4281		goto os_bypass;
4282
4283	 case MTREW:
4284		cmd[0] = REZERO_UNIT; /* rewind */
4285		cmd[1] = 1;
4286#if DEBUG
4287		if (debugging)
4288		   printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4289#endif
4290		fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4291		break;
4292
4293	 case MTSETBLK:           /* Set block length */
4294		 if ((STps->drv_block == 0 )			  &&
4295		     !STp->dirty				  &&
4296		     ((STp->buffer)->buffer_bytes == 0)		  &&
4297		     ((arg & MT_ST_BLKSIZE_MASK) >= 512 )	  && 
4298		     ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4299		     !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))  ) {
4300			 /*
4301			  * Only allowed to change the block size if you opened the
4302			  * device at the beginning of a file before writing anything.
4303			  * Note, that when reading, changing block_size is futile,
4304			  * as the size used when writing overrides it.
4305			  */
4306			 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4307			 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4308					   name, STp->block_size);
4309			 return 0;
4310		 }
4311	 case MTSETDENSITY:       /* Set tape density */
4312	 case MTSETDRVBUFFER:     /* Set drive buffering */
4313	 case SET_DENS_AND_BLK:   /* Set density and block size */
4314		 chg_eof = 0;
4315		 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4316			 return (-EIO);       /* Not allowed if data in buffer */
4317		 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4318		     (arg & MT_ST_BLKSIZE_MASK) != 0                    &&
4319		     (arg & MT_ST_BLKSIZE_MASK) != STp->block_size       ) {
4320			 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4321						name, (int)(arg & MT_ST_BLKSIZE_MASK),
4322						(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4323			 return (-EINVAL);
4324		 }
4325		 return 0;  /* FIXME silently ignore if block size didn't change */
4326
4327	 default:
4328		return (-ENOSYS);
4329	}
4330
4331	SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4332
4333	ioctl_result = (STp->buffer)->syscall_result;
4334
4335	if (!SRpnt) {
4336#if DEBUG
4337		printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4338#endif
4339		return ioctl_result;
4340	}
4341
4342	if (!ioctl_result) {  /* SCSI command successful */
4343		STp->frame_seq_number = frame_seq_numbr;
4344		STp->logical_blk_num  = logical_blk_num;
4345	}
4346
4347os_bypass:
4348#if DEBUG
4349	if (debugging)
4350		printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4351#endif
4352
4353	if (!ioctl_result) {				/* success */
4354
4355		if (cmd_in == MTFSFM) {
4356			 fileno--;
4357			 blkno--;
4358		}
4359		if (cmd_in == MTBSFM) {
4360			 fileno++;
4361			 blkno++;
4362		}
4363		STps->drv_block = blkno;
4364		STps->drv_file = fileno;
4365		STps->at_sm = at_sm;
4366
4367		if (cmd_in == MTEOM)
4368			STps->eof = ST_EOD;
4369		else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4370			ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4371			STps->drv_block++;
4372			STp->logical_blk_num++;
4373			STp->frame_seq_number++;
4374			STp->frame_in_buffer = 0;
4375			STp->buffer->read_pointer = 0;
4376		}
4377		else if (cmd_in == MTFSF)
4378			STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4379		else if (chg_eof)
4380			STps->eof = ST_NOEOF;
4381
4382		if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4383			STp->rew_at_close = 0;
4384		else if (cmd_in == MTLOAD) {
4385			for (i=0; i < ST_NBR_PARTITIONS; i++) {
4386			    STp->ps[i].rw = ST_IDLE;
4387			    STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4388			}
4389			STp->partition = 0;
4390		}
4391
4392		if (cmd_in == MTREW) {
4393			ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos); 
4394			if (ioctl_result > 0)
4395				ioctl_result = 0;
4396		}
4397
4398	} else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4399		if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4400			STps->drv_file = STps->drv_block = -1;
4401		else
4402			STps->drv_file = STps->drv_block = 0;
4403		STps->eof = ST_NOEOF;
4404	} else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4405		if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4406			STps->drv_file = STps->drv_block = -1;
4407		else {
4408			STps->drv_file  = STp->filemark_cnt;
4409			STps->drv_block = 0;
4410		}
4411		STps->eof = ST_EOD;
4412	} else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4413		STps->drv_file = STps->drv_block = (-1);
4414		STps->eof = ST_NOEOF;
4415		STp->header_ok = 0;
4416	} else if (cmd_in == MTERASE) {
4417		STp->header_ok = 0;
4418	} else if (SRpnt) {  /* SCSI command was not completely successful. */
4419		if (SRpnt->sense[2] & 0x40) {
4420			STps->eof = ST_EOM_OK;
4421			STps->drv_block = 0;
4422		}
4423		if (chg_eof)
4424			STps->eof = ST_NOEOF;
4425
4426		if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4427			STps->eof = ST_EOD;
4428
4429		if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4430			ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4431	}
4432	*aSRpnt = SRpnt;
4433
4434	return ioctl_result;
4435}
4436
4437
4438/* Open the device */
4439static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4440{
4441	unsigned short	      flags;
4442	int		      i, b_size, new_session = 0, retval = 0;
4443	unsigned char	      cmd[MAX_COMMAND_SIZE];
4444	struct osst_request * SRpnt = NULL;
4445	struct osst_tape    * STp;
4446	struct st_modedef   * STm;
4447	struct st_partstat  * STps;
4448	char		    * name;
4449	int		      dev  = TAPE_NR(inode);
4450	int		      mode = TAPE_MODE(inode);
4451
4452	/*
4453	 * We really want to do nonseekable_open(inode, filp); here, but some
4454	 * versions of tar incorrectly call lseek on tapes and bail out if that
4455	 * fails.  So we disallow pread() and pwrite(), but permit lseeks.
4456	 */
4457	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4458
4459	write_lock(&os_scsi_tapes_lock);
4460	if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4461	    (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4462		write_unlock(&os_scsi_tapes_lock);
4463		return (-ENXIO);
4464	}
4465
4466	name = tape_name(STp);
4467
4468	if (STp->in_use) {
4469		write_unlock(&os_scsi_tapes_lock);
4470#if DEBUG
4471		printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4472#endif
4473		return (-EBUSY);
4474	}
4475	if (scsi_device_get(STp->device)) {
4476		write_unlock(&os_scsi_tapes_lock);
4477#if DEBUG
4478                printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4479#endif
4480		return (-ENXIO);
4481	}
4482	filp->private_data = STp;
4483	STp->in_use = 1;
4484	write_unlock(&os_scsi_tapes_lock);
4485	STp->rew_at_close = TAPE_REWIND(inode);
4486
4487	if( !scsi_block_when_processing_errors(STp->device) ) {
4488		return -ENXIO;
4489	}
4490
4491	if (mode != STp->current_mode) {
4492#if DEBUG
4493		if (debugging)
4494			printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4495					       name, STp->current_mode, mode);
4496#endif
4497		new_session = 1;
4498		STp->current_mode = mode;
4499	}
4500	STm = &(STp->modes[STp->current_mode]);
4501
4502	flags = filp->f_flags;
4503	STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4504
4505	STp->raw = TAPE_IS_RAW(inode);
4506	if (STp->raw)
4507		STp->header_ok = 0;
4508
4509	/* Allocate data segments for this device's tape buffer */
4510	if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4511		printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4512		retval = (-EOVERFLOW);
4513		goto err_out;
4514	}
4515	if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4516		for (i = 0, b_size = 0; 
4517		     (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE); 
4518		     b_size += STp->buffer->sg[i++].length);
4519		STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4520#if DEBUG
4521		printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4522			STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4523		printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4524			 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4525#endif
4526	} else {
4527		STp->buffer->aux = NULL; /* this had better never happen! */
4528		printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4529		retval = (-EIO);
4530		goto err_out;
4531	}
4532	STp->buffer->writing = 0;
4533	STp->buffer->syscall_result = 0;
4534	STp->dirty = 0;
4535	for (i=0; i < ST_NBR_PARTITIONS; i++) {
4536		STps = &(STp->ps[i]);
4537		STps->rw = ST_IDLE;
4538	}
4539	STp->ready = ST_READY;
4540#if DEBUG
4541	STp->nbr_waits = STp->nbr_finished = 0;
4542#endif
4543
4544	memset (cmd, 0, MAX_COMMAND_SIZE);
4545	cmd[0] = TEST_UNIT_READY;
4546
4547	SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4548	if (!SRpnt) {
4549		retval = (STp->buffer)->syscall_result;		/* FIXME - valid? */
4550		goto err_out;
4551	}
4552	if ((SRpnt->sense[0] & 0x70) == 0x70      &&
4553	    (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4554	     SRpnt->sense[12]        == 4         ) {
4555#if DEBUG
4556		printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4557#endif
4558		if (filp->f_flags & O_NONBLOCK) {
4559			retval = -EAGAIN;
4560			goto err_out;
4561		}
4562		if (SRpnt->sense[13] == 2) {	/* initialize command required (LOAD) */
4563			memset (cmd, 0, MAX_COMMAND_SIZE);
4564        		cmd[0] = START_STOP;
4565			cmd[1] = 1;
4566			cmd[4] = 1;
4567			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4568					     STp->timeout, MAX_RETRIES, 1);
4569		}
4570		osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4571	}
4572	if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4573	    (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4574#if DEBUG
4575		printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4576#endif
4577		STp->header_ok = 0;
4578
4579		for (i=0; i < 10; i++) {
4580
4581			memset (cmd, 0, MAX_COMMAND_SIZE);
4582			cmd[0] = TEST_UNIT_READY;
4583
4584			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4585					     STp->timeout, MAX_RETRIES, 1);
4586			if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4587			    (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4588				break;
4589		}
4590
4591		STp->pos_unknown = 0;
4592		STp->partition = STp->new_partition = 0;
4593		if (STp->can_partitions)
4594			STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4595		for (i=0; i < ST_NBR_PARTITIONS; i++) {
4596			STps = &(STp->ps[i]);
4597			STps->rw = ST_IDLE;		/* FIXME - seems to be redundant... */
4598			STps->eof = ST_NOEOF;
4599			STps->at_sm = 0;
4600			STps->last_block_valid = 0;
4601			STps->drv_block = 0;
4602			STps->drv_file = 0 ;
4603		}
4604		new_session = 1;
4605		STp->recover_count = 0;
4606		STp->abort_count = 0;
4607	}
4608	/*
4609	 * if we have valid headers from before, and the drive/tape seem untouched,
4610	 * open without reconfiguring and re-reading the headers
4611	 */
4612	if (!STp->buffer->syscall_result && STp->header_ok &&
4613	    !SRpnt->result && SRpnt->sense[0] == 0) {
4614
4615		memset(cmd, 0, MAX_COMMAND_SIZE);
4616		cmd[0] = MODE_SENSE;
4617		cmd[1] = 8;
4618		cmd[2] = VENDOR_IDENT_PAGE;
4619		cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4620
4621		SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4622
4623		if (STp->buffer->syscall_result                     ||
4624		    STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4625		    STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4626		    STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4627		    STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4'  ) {
4628#if DEBUG
4629			printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4630			  STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4631			  STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4632			  STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4633			  STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4634#endif
4635			STp->header_ok = 0;
4636		}
4637		i = STp->first_frame_position;
4638		if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4639			if (STp->door_locked == ST_UNLOCKED) {
4640				if (do_door_lock(STp, 1))
4641					printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4642				else
4643					STp->door_locked = ST_LOCKED_AUTO;
4644			}
4645			if (!STp->frame_in_buffer) {
4646				STp->block_size = (STm->default_blksize > 0) ?
4647							STm->default_blksize : OS_DATA_SIZE;
4648				STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4649			}
4650			STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4651			STp->fast_open = 1;
4652			osst_release_request(SRpnt);
4653			return 0;
4654		}
4655#if DEBUG
4656		if (i != STp->first_frame_position)
4657			printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4658						name, i, STp->first_frame_position);
4659#endif
4660		STp->header_ok = 0;
4661	}
4662	STp->fast_open = 0;
4663
4664	if ((STp->buffer)->syscall_result != 0 &&   /* in all error conditions except no medium */ 
4665	    (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4666
4667		memset(cmd, 0, MAX_COMMAND_SIZE);
4668		cmd[0] = MODE_SELECT;
4669		cmd[1] = 0x10;
4670		cmd[4] = 4 + MODE_HEADER_LENGTH;
4671
4672		(STp->buffer)->b_data[0] = cmd[4] - 1;
4673		(STp->buffer)->b_data[1] = 0;			/* Medium Type - ignoring */
4674		(STp->buffer)->b_data[2] = 0;			/* Reserved */
4675		(STp->buffer)->b_data[3] = 0;			/* Block Descriptor Length */
4676		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4677		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4678		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4679		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4680
4681#if DEBUG
4682		printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4683#endif
4684		SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4685
4686		STp->header_ok = 0;
4687
4688		for (i=0; i < 10; i++) {
4689
4690			memset (cmd, 0, MAX_COMMAND_SIZE);
4691			cmd[0] = TEST_UNIT_READY;
4692
4693			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4694						    STp->timeout, MAX_RETRIES, 1);
4695			if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4696			    (SRpnt->sense[2] & 0x0f) == NOT_READY)
4697			break;
4698
4699			if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4700				int j;
4701
4702				STp->pos_unknown = 0;
4703				STp->partition = STp->new_partition = 0;
4704				if (STp->can_partitions)
4705					STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4706				for (j = 0; j < ST_NBR_PARTITIONS; j++) {
4707					STps = &(STp->ps[j]);
4708					STps->rw = ST_IDLE;
4709					STps->eof = ST_NOEOF;
4710					STps->at_sm = 0;
4711					STps->last_block_valid = 0;
4712					STps->drv_block = 0;
4713					STps->drv_file = 0 ;
4714				}
4715				new_session = 1;
4716			}
4717		}
4718	}
4719
4720	if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))		/* FIXME - not allowed with NOBLOCK */
4721		 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4722
4723	if ((STp->buffer)->syscall_result != 0) {
4724		if ((STp->device)->scsi_level >= SCSI_2 &&
4725		    (SRpnt->sense[0] & 0x70) == 0x70 &&
4726		    (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4727		     SRpnt->sense[12] == 0x3a) { /* Check ASC */
4728			STp->ready = ST_NO_TAPE;
4729		} else
4730			STp->ready = ST_NOT_READY;
4731		osst_release_request(SRpnt);
4732		SRpnt = NULL;
4733		STp->density = 0;   	/* Clear the erroneous "residue" */
4734		STp->write_prot = 0;
4735		STp->block_size = 0;
4736		STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4737		STp->partition = STp->new_partition = 0;
4738		STp->door_locked = ST_UNLOCKED;
4739		return 0;
4740	}
4741
4742	osst_configure_onstream(STp, &SRpnt);
4743
4744	STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4745			     (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4746	STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4747	STp->buffer->buffer_bytes  =
4748	STp->buffer->read_pointer  =
4749	STp->frame_in_buffer       = 0;
4750
4751#if DEBUG
4752	if (debugging)
4753		printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4754		     name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4755		     (STp->buffer)->buffer_blocks);
4756#endif
4757
4758	if (STp->drv_write_prot) {
4759		STp->write_prot = 1;
4760#if DEBUG
4761		if (debugging)
4762			printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4763#endif
4764		if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4765			retval = (-EROFS);
4766			goto err_out;
4767		}
4768	}
4769
4770	if (new_session) {  /* Change the drive parameters for the new mode */
4771#if DEBUG
4772		if (debugging)
4773	printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4774#endif
4775		STp->density_changed = STp->blksize_changed = 0;
4776		STp->compression_changed = 0;
4777	}
4778
4779	/*
4780	 * properly position the tape and check the ADR headers
4781	 */
4782	if (STp->door_locked == ST_UNLOCKED) {
4783		 if (do_door_lock(STp, 1))
4784			printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4785		 else
4786			STp->door_locked = ST_LOCKED_AUTO;
4787	}
4788
4789	osst_analyze_headers(STp, &SRpnt);
4790
4791	osst_release_request(SRpnt);
4792	SRpnt = NULL;
4793
4794	return 0;
4795
4796err_out:
4797	if (SRpnt != NULL)
4798		osst_release_request(SRpnt);
4799	normalize_buffer(STp->buffer);
4800	STp->header_ok = 0;
4801	STp->in_use = 0;
4802	scsi_device_put(STp->device);
4803
4804	return retval;
4805}
4806
4807/* BKL pushdown: spaghetti avoidance wrapper */
4808static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4809{
4810	int ret;
4811
4812	mutex_lock(&osst_int_mutex);
4813	ret = __os_scsi_tape_open(inode, filp);
4814	mutex_unlock(&osst_int_mutex);
4815	return ret;
4816}
4817
4818
4819
4820/* Flush the tape buffer before close */
4821static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4822{
4823	int		      result = 0, result2;
4824	struct osst_tape    * STp    = filp->private_data;
4825	struct st_modedef   * STm    = &(STp->modes[STp->current_mode]);
4826	struct st_partstat  * STps   = &(STp->ps[STp->partition]);
4827	struct osst_request * SRpnt  = NULL;
4828	char		    * name   = tape_name(STp);
4829
4830	if (file_count(filp) > 1)
4831		return 0;
4832
4833	if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4834		STp->write_type = OS_WRITE_DATA;
4835		result = osst_flush_write_buffer(STp, &SRpnt);
4836		if (result != 0 && result != (-ENOSPC))
4837			goto out;
4838	}
4839	if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4840
4841#if DEBUG
4842		if (debugging) {
4843			printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4844					       name, (long)(filp->f_pos));
4845			printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4846					       name, STp->nbr_waits, STp->nbr_finished);
4847		}
4848#endif
4849		result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4850#if DEBUG
4851		if (debugging)
4852			printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4853					       name, 1+STp->two_fm);
4854#endif
4855	}
4856	else if (!STp->rew_at_close) {
4857		STps = &(STp->ps[STp->partition]);
4858		if (!STm->sysv || STps->rw != ST_READING) {
4859			if (STp->can_bsr)
4860				result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4861			else if (STps->eof == ST_FM_HIT) {
4862				result = cross_eof(STp, &SRpnt, 0);
4863					if (result) {
4864						if (STps->drv_file >= 0)
4865							STps->drv_file++;
4866						STps->drv_block = 0;
4867						STps->eof = ST_FM;
4868					}
4869					else
4870						STps->eof = ST_NOEOF;
4871			}
4872		}
4873		else if ((STps->eof == ST_NOEOF &&
4874			  !(result = cross_eof(STp, &SRpnt, 1))) ||
4875			 STps->eof == ST_FM_HIT) {
4876			if (STps->drv_file >= 0)
4877				STps->drv_file++;
4878			STps->drv_block = 0;
4879			STps->eof = ST_FM;
4880		}
4881	}
4882
4883out:
4884	if (STp->rew_at_close) {
4885		result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4886		STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4887		if (result == 0 && result2 < 0)
4888			result = result2;
4889	}
4890	if (SRpnt) osst_release_request(SRpnt);
4891
4892	if (STp->abort_count || STp->recover_count) {
4893		printk(KERN_INFO "%s:I:", name);
4894		if (STp->abort_count)
4895			printk(" %d unrecovered errors", STp->abort_count);
4896		if (STp->recover_count)
4897			printk(" %d recovered errors", STp->recover_count);
4898		if (STp->write_count)
4899			printk(" in %d frames written", STp->write_count);
4900		if (STp->read_count)
4901			printk(" in %d frames read", STp->read_count);
4902		printk("\n");
4903		STp->recover_count = 0;
4904		STp->abort_count   = 0;
4905	}
4906	STp->write_count = 0;
4907	STp->read_count  = 0;
4908
4909	return result;
4910}
4911
4912
4913/* Close the device and release it */
4914static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4915{
4916	int		      result = 0;
4917	struct osst_tape    * STp    = filp->private_data;
4918
4919	if (STp->door_locked == ST_LOCKED_AUTO)
4920		do_door_lock(STp, 0);
4921
4922	if (STp->raw)
4923		STp->header_ok = 0;
4924	
4925	normalize_buffer(STp->buffer);
4926	write_lock(&os_scsi_tapes_lock);
4927	STp->in_use = 0;
4928	write_unlock(&os_scsi_tapes_lock);
4929
4930	scsi_device_put(STp->device);
4931
4932	return result;
4933}
4934
4935
4936/* The ioctl command */
4937static long osst_ioctl(struct file * file,
4938	 unsigned int cmd_in, unsigned long arg)
4939{
4940	int		      i, cmd_nr, cmd_type, blk, retval = 0;
4941	struct st_modedef   * STm;
4942	struct st_partstat  * STps;
4943	struct osst_request * SRpnt = NULL;
4944	struct osst_tape    * STp   = file->private_data;
4945	char		    * name  = tape_name(STp);
4946	void	    __user  * p     = (void __user *)arg;
4947
4948	mutex_lock(&osst_int_mutex);
4949	if (mutex_lock_interruptible(&STp->lock)) {
4950		mutex_unlock(&osst_int_mutex);
4951		return -ERESTARTSYS;
4952	}
4953
4954#if DEBUG
4955	if (debugging && !STp->in_use) {
4956		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4957		retval = (-EIO);
4958		goto out;
4959	}
4960#endif
4961	STm = &(STp->modes[STp->current_mode]);
4962	STps = &(STp->ps[STp->partition]);
4963
4964	/*
4965	 * If we are in the middle of error recovery, don't let anyone
4966	 * else try and use this device.  Also, if error recovery fails, it
4967	 * may try and take the device offline, in which case all further
4968	 * access to the device is prohibited.
4969	 */
4970	if( !scsi_block_when_processing_errors(STp->device) ) {
4971		retval = (-ENXIO);
4972		goto out;
4973	}
4974
4975	cmd_type = _IOC_TYPE(cmd_in);
4976	cmd_nr   = _IOC_NR(cmd_in);
4977#if DEBUG
4978	printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4979			    cmd_type, cmd_nr, STp->raw?"raw":"normal");
4980#endif
4981	if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4982		struct mtop mtc;
4983		int    auto_weof = 0;
4984
4985		if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4986			retval = (-EINVAL);
4987			goto out;
4988		}
4989
4990		i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4991		if (i) {
4992			retval = (-EFAULT);
4993			goto out;
4994		}
4995
4996		if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4997			printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4998			retval = (-EPERM);
4999			goto out;
5000		}
5001
5002		if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
5003			retval = (-ENXIO);
5004			goto out;
5005		}
5006
5007		if (!STp->pos_unknown) {
5008
5009			if (STps->eof == ST_FM_HIT) {
5010				if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
5011					mtc.mt_count -= 1;
5012					if (STps->drv_file >= 0)
5013						STps->drv_file += 1;
5014				}
5015				else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
5016					mtc.mt_count += 1;
5017					if (STps->drv_file >= 0)
5018						STps->drv_file += 1;
5019				}
5020			}
5021
5022			if (mtc.mt_op == MTSEEK) {
5023				/* Old position must be restored if partition will be changed */
5024				i = !STp->can_partitions || (STp->new_partition != STp->partition);
5025			}
5026			else {
5027				i = mtc.mt_op == MTREW   || mtc.mt_op == MTOFFL ||
5028				    mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM  ||
5029				    mtc.mt_op == MTLOCK  || mtc.mt_op == MTLOAD ||
5030				    mtc.mt_op == MTFSF   || mtc.mt_op == MTFSFM ||
5031				    mtc.mt_op == MTBSF   || mtc.mt_op == MTBSFM ||
5032				    mtc.mt_op == MTCOMPRESSION;
5033			}
5034			i = osst_flush_buffer(STp, &SRpnt, i);
5035			if (i < 0) {
5036				retval = i;
5037				goto out;
5038			}
5039		}
5040		else {
5041			/*
5042			 * If there was a bus reset, block further access
5043			 * to this device.  If the user wants to rewind the tape,
5044			 * then reset the flag and allow access again.
5045			 */
5046			if(mtc.mt_op != MTREW   &&
5047			   mtc.mt_op != MTOFFL  &&
5048			   mtc.mt_op != MTRETEN &&
5049			   mtc.mt_op != MTERASE &&
5050			   mtc.mt_op != MTSEEK  &&
5051			   mtc.mt_op != MTEOM)   {
5052				retval = (-EIO);
5053				goto out;
5054			}
5055			reset_state(STp);
5056			/* remove this when the midlevel properly clears was_reset */
5057			STp->device->was_reset = 0;
5058		}
5059
5060		if (mtc.mt_op != MTCOMPRESSION  && mtc.mt_op != MTLOCK         &&
5061		    mtc.mt_op != MTNOP          && mtc.mt_op != MTSETBLK       &&
5062		    mtc.mt_op != MTSETDENSITY   && mtc.mt_op != MTSETDRVBUFFER && 
5063		    mtc.mt_op != MTMKPART       && mtc.mt_op != MTSETPART      &&
5064		    mtc.mt_op != MTWEOF         && mtc.mt_op != MTWSM           ) {
5065
5066			/*
5067			 * The user tells us to move to another position on the tape.
5068			 * If we were appending to the tape content, that would leave
5069			 * the tape without proper end, in that case write EOD and
5070			 * update the header to reflect its position.
5071			 */
5072#if DEBUG
5073			printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
5074					STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
5075					STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
5076					STp->logical_blk_num, STps->drv_file, STps->drv_block );
5077#endif
5078			if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
5079				auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
5080							!(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5081				i = osst_write_trailer(STp, &SRpnt,
5082							!(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5083#if DEBUG
5084				printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5085						name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5086						STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5087#endif
5088				if (i < 0) {
5089					retval = i;
5090					goto out;
5091				}
5092			}
5093			STps->rw = ST_IDLE;
5094		}
5095
5096		if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5097			do_door_lock(STp, 0);  /* Ignore result! */
5098
5099		if (mtc.mt_op == MTSETDRVBUFFER &&
5100		   (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5101			retval = osst_set_options(STp, mtc.mt_count);
5102			goto out;
5103		}
5104
5105		if (mtc.mt_op == MTSETPART) {
5106			if (mtc.mt_count >= STp->nbr_partitions)
5107				retval = -EINVAL;
5108			else {
5109				STp->new_partition = mtc.mt_count;
5110				retval = 0;
5111			}
5112			goto out;
5113		}
5114
5115		if (mtc.mt_op == MTMKPART) {
5116			if (!STp->can_partitions) {
5117				retval = (-EINVAL);
5118				goto out;
5119			}
5120			if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5121			    (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5122				retval = i;
5123				goto out;
5124			}
5125			for (i=0; i < ST_NBR_PARTITIONS; i++) {
5126				STp->ps[i].rw = ST_IDLE;
5127				STp->ps[i].at_sm = 0;
5128				STp->ps[i].last_block_valid = 0;
5129			}
5130			STp->partition = STp->new_partition = 0;
5131			STp->nbr_partitions = 1;  /* Bad guess ?-) */
5132			STps->drv_block = STps->drv_file = 0;
5133			retval = 0;
5134			goto out;
5135	 	}
5136
5137		if (mtc.mt_op == MTSEEK) {
5138			if (STp->raw)
5139				i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5140			else
5141				i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5142			if (!STp->can_partitions)
5143				STp->ps[0].rw = ST_IDLE;
5144			retval = i;
5145			goto out;
5146		}
5147 
5148		if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5149			retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5150			goto out;
5151		}
5152
5153		if (auto_weof)
5154			cross_eof(STp, &SRpnt, 0);
5155
5156		if (mtc.mt_op == MTCOMPRESSION)
5157			retval = -EINVAL;       /* OnStream drives don't have compression hardware */
5158		else
5159			/* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5160			 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5161			retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5162		goto out;
5163	}
5164
5165	if (!STm->defined) {
5166		retval = (-ENXIO);
5167		goto out;
5168	}
5169
5170	if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5171		retval = i;
5172		goto out;
5173	}
5174
5175	if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5176		struct mtget mt_status;
5177
5178		if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5179			 retval = (-EINVAL);
5180			 goto out;
5181		}
5182
5183		mt_status.mt_type = MT_ISONSTREAM_SC;
5184		mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5185		mt_status.mt_dsreg =
5186			((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5187			((STp->density    << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5188		mt_status.mt_blkno = STps->drv_block;
5189		mt_status.mt_fileno = STps->drv_file;
5190		if (STp->block_size != 0) {
5191			if (STps->rw == ST_WRITING)
5192				mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5193			else if (STps->rw == ST_READING)
5194				mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5195							STp->block_size - 1) / STp->block_size;
5196		}
5197
5198		mt_status.mt_gstat = 0;
5199		if (STp->drv_write_prot)
5200			mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5201		if (mt_status.mt_blkno == 0) {
5202			if (mt_status.mt_fileno == 0)
5203				mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5204			else
5205				mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5206		}
5207		mt_status.mt_resid = STp->partition;
5208		if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5209			mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5210		else if (STps->eof >= ST_EOM_OK)
5211			mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5212		if (STp->density == 1)
5213			mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5214		else if (STp->density == 2)
5215			mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5216		else if (STp->density == 3)
5217			mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5218		if (STp->ready == ST_READY)
5219			mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5220		if (STp->ready == ST_NO_TAPE)
5221			mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5222		if (STps->at_sm)
5223			mt_status.mt_gstat |= GMT_SM(0xffffffff);
5224		if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5225		    STp->drv_buffer != 0)
5226			mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5227
5228		i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5229		if (i) {
5230			retval = (-EFAULT);
5231			goto out;
5232		}
5233
5234		STp->recover_erreg = 0;  /* Clear after read */
5235		retval = 0;
5236		goto out;
5237	} /* End of MTIOCGET */
5238
5239	if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5240		struct mtpos mt_pos;
5241
5242		if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5243			retval = (-EINVAL);
5244			goto out;
5245		}
5246		if (STp->raw)
5247			blk = osst_get_frame_position(STp, &SRpnt);
5248		else
5249			blk = osst_get_sector(STp, &SRpnt);
5250		if (blk < 0) {
5251			retval = blk;
5252			goto out;
5253		}
5254		mt_pos.mt_blkno = blk;
5255		i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5256		if (i)
5257			retval = -EFAULT;
5258		goto out;
5259	}
5260	if (SRpnt) osst_release_request(SRpnt);
5261
5262	mutex_unlock(&STp->lock);
5263
5264	retval = scsi_ioctl(STp->device, cmd_in, p);
5265	mutex_unlock(&osst_int_mutex);
5266	return retval;
5267
5268out:
5269	if (SRpnt) osst_release_request(SRpnt);
5270
5271	mutex_unlock(&STp->lock);
5272	mutex_unlock(&osst_int_mutex);
5273
5274	return retval;
5275}
5276
5277#ifdef CONFIG_COMPAT
5278static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5279{
5280	struct osst_tape *STp = file->private_data;
5281	struct scsi_device *sdev = STp->device;
5282	int ret = -ENOIOCTLCMD;
5283	if (sdev->host->hostt->compat_ioctl) {
5284
5285		ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5286
5287	}
5288	return ret;
5289}
5290#endif
5291
5292
5293
5294/* Memory handling routines */
5295
5296/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5297static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5298{
5299	int i;
5300	gfp_t priority;
5301	struct osst_buffer *tb;
5302
5303	if (from_initialization)
5304		priority = GFP_ATOMIC;
5305	else
5306		priority = GFP_KERNEL;
5307
5308	i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5309	tb = kzalloc(i, priority);
5310	if (!tb) {
5311		printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5312		return NULL;
5313	}
5314
5315	tb->sg_segs = tb->orig_sg_segs = 0;
5316	tb->use_sg = max_sg;
5317	tb->in_use = 1;
5318	tb->dma = need_dma;
5319	tb->buffer_size = 0;
5320#if DEBUG
5321	if (debugging) 
5322		printk(OSST_DEB_MSG
5323			"osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5324			   i, max_sg, need_dma);
5325#endif
5326	return tb;
5327}
5328
5329/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5330static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5331{
5332	int segs, nbr, max_segs, b_size, order, got;
5333	gfp_t priority;
5334
5335	if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5336		return 1;
5337
5338	if (STbuffer->sg_segs) {
5339		printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5340		normalize_buffer(STbuffer);
5341	}
5342	/* See how many segments we can use -- need at least two */
5343	nbr = max_segs = STbuffer->use_sg;
5344	if (nbr <= 2)
5345		return 0;
5346
5347	priority = GFP_KERNEL /* | __GFP_NOWARN */;
5348	if (need_dma)
5349		priority |= GFP_DMA;
5350
5351	/* Try to allocate the first segment up to OS_DATA_SIZE and the others
5352	   big enough to reach the goal (code assumes no segments in place) */
5353	for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5354		struct page *page = alloc_pages(priority, order);
5355
5356		STbuffer->sg[0].offset = 0;
5357		if (page != NULL) {
5358		    sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5359		    STbuffer->b_data = page_address(page);
5360		    break;
5361		}
5362	}
5363	if (sg_page(&STbuffer->sg[0]) == NULL) {
5364		printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5365		return 0;
5366	}
5367	/* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5368	for (segs=STbuffer->sg_segs=1, got=b_size;
5369	     segs < max_segs && got < OS_FRAME_SIZE; ) {
5370		struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5371		STbuffer->sg[segs].offset = 0;
5372		if (page == NULL) {
5373			printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5374						OS_FRAME_SIZE);
5375#if DEBUG
5376			STbuffer->buffer_size = got;
5377#endif
5378			normalize_buffer(STbuffer);
5379			return 0;
5380		}
5381		sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5382		got += STbuffer->sg[segs].length;
5383		STbuffer->buffer_size = got;
5384		STbuffer->sg_segs = ++segs;
5385	}
5386#if DEBUG
5387	if (debugging) {
5388		printk(OSST_DEB_MSG
5389			   "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5390			   got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5391		printk(OSST_DEB_MSG
5392			   "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5393			   STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5394			   STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5395	}
5396#endif
5397
5398	return 1;
5399}
5400
5401
5402/* Release the segments */
5403static void normalize_buffer(struct osst_buffer *STbuffer)
5404{
5405  int i, order, b_size;
5406
5407	for (i=0; i < STbuffer->sg_segs; i++) {
5408
5409		for (b_size = PAGE_SIZE, order = 0;
5410		     b_size < STbuffer->sg[i].length;
5411		     b_size *= 2, order++);
5412
5413		__free_pages(sg_page(&STbuffer->sg[i]), order);
5414		STbuffer->buffer_size -= STbuffer->sg[i].length;
5415	}
5416#if DEBUG
5417	if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5418		printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5419			     STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5420#endif
5421	STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5422}
5423
5424
5425/* Move data from the user buffer to the tape buffer. Returns zero (success) or
5426   negative error code. */
5427static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5428{
5429	int i, cnt, res, offset;
5430
5431	for (i=0, offset=st_bp->buffer_bytes;
5432	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5433	offset -= st_bp->sg[i].length;
5434	if (i == st_bp->sg_segs) {  /* Should never happen */
5435		printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5436		return (-EIO);
5437	}
5438	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5439		cnt = st_bp->sg[i].length - offset < do_count ?
5440		      st_bp->sg[i].length - offset : do_count;
5441		res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5442		if (res)
5443			return (-EFAULT);
5444		do_count -= cnt;
5445		st_bp->buffer_bytes += cnt;
5446		ubp += cnt;
5447		offset = 0;
5448	}
5449	if (do_count) {  /* Should never happen */
5450		printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5451		       do_count);
5452		return (-EIO);
5453	}
5454	return 0;
5455}
5456
5457
5458/* Move data from the tape buffer to the user buffer. Returns zero (success) or
5459   negative error code. */
5460static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5461{
5462	int i, cnt, res, offset;
5463
5464	for (i=0, offset=st_bp->read_pointer;
5465	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5466		offset -= st_bp->sg[i].length;
5467	if (i == st_bp->sg_segs) {  /* Should never happen */
5468		printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5469		return (-EIO);
5470	}
5471	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5472		cnt = st_bp->sg[i].length - offset < do_count ?
5473		      st_bp->sg[i].length - offset : do_count;
5474		res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5475		if (res)
5476			return (-EFAULT);
5477		do_count -= cnt;
5478		st_bp->buffer_bytes -= cnt;
5479		st_bp->read_pointer += cnt;
5480		ubp += cnt;
5481		offset = 0;
5482	}
5483	if (do_count) {  /* Should never happen */
5484		printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5485		return (-EIO);
5486	}
5487	return 0;
5488}
5489
5490/* Sets the tail of the buffer after fill point to zero.
5491   Returns zero (success) or negative error code.        */
5492static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5493{
5494	int	i, offset, do_count, cnt;
5495
5496	for (i = 0, offset = st_bp->buffer_bytes;
5497	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5498		offset -= st_bp->sg[i].length;
5499	if (i == st_bp->sg_segs) {  /* Should never happen */
5500		printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5501		return (-EIO);
5502	}
5503	for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5504	     i < st_bp->sg_segs && do_count > 0; i++) {
5505		cnt = st_bp->sg[i].length - offset < do_count ?
5506		      st_bp->sg[i].length - offset : do_count ;
5507		memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5508		do_count -= cnt;
5509		offset = 0;
5510	}
5511	if (do_count) {  /* Should never happen */
5512		printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5513		return (-EIO);
5514	}
5515	return 0;
5516}
5517
5518/* Copy a osst 32K chunk of memory into the buffer.
5519   Returns zero (success) or negative error code.  */
5520static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5521{
5522	int	i, cnt, do_count = OS_DATA_SIZE;
5523
5524	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5525		cnt = st_bp->sg[i].length < do_count ?
5526		      st_bp->sg[i].length : do_count ;
5527		memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5528		do_count -= cnt;
5529		ptr      += cnt;
5530	}
5531	if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5532		printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5533					 do_count, i);
5534		return (-EIO);
5535	}
5536	return 0;
5537}
5538
5539/* Copy a osst 32K chunk of memory from the buffer.
5540   Returns zero (success) or negative error code.  */
5541static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5542{
5543	int	i, cnt, do_count = OS_DATA_SIZE;
5544
5545	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5546		cnt = st_bp->sg[i].length < do_count ?
5547		      st_bp->sg[i].length : do_count ;
5548		memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5549		do_count -= cnt;
5550		ptr      += cnt;
5551	}
5552	if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5553		printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5554					 do_count, i);
5555		return (-EIO);
5556	}
5557	return 0;
5558}
5559
5560
5561/* Module housekeeping */
5562
5563static void validate_options (void)
5564{
5565  if (max_dev > 0)
5566		osst_max_dev = max_dev;  
5567  if (write_threshold_kbs > 0)
5568		osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5569  if (osst_write_threshold > osst_buffer_size)
5570		osst_write_threshold = osst_buffer_size;
5571  if (max_sg_segs >= OSST_FIRST_SG)
5572		osst_max_sg_segs = max_sg_segs;
5573#if DEBUG
5574  printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5575			   osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5576#endif
5577}
5578	
5579#ifndef MODULE
5580/* Set the boot options. Syntax: osst=xxx,yyy,...
5581   where xxx is write threshold in 1024 byte blocks,
5582   and   yyy is number of s/g segments to use. */
5583static int __init osst_setup (char *str)
5584{
5585  int i, ints[5];
5586  char *stp;
5587
5588  stp = get_options(str, ARRAY_SIZE(ints), ints);
5589
5590  if (ints[0] > 0) {
5591	for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5592		  *parms[i].val = ints[i + 1];
5593  } else {
5594	while (stp != NULL) {
5595		for (i = 0; i < ARRAY_SIZE(parms); i++) {
5596			int len = strlen(parms[i].name);
5597			if (!strncmp(stp, parms[i].name, len) &&
5598			    (*(stp + len) == ':' || *(stp + len) == '=')) {
5599				*parms[i].val =
5600					simple_strtoul(stp + len + 1, NULL, 0);
5601				break;
5602			}
5603		}
5604		if (i >= ARRAY_SIZE(parms))
5605			printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5606			       stp);
5607		stp = strchr(stp, ',');
5608		if (stp)
5609			stp++;
5610	}
5611  }
5612
5613  return 1;
5614}
5615
5616__setup("osst=", osst_setup);
5617
5618#endif
5619
5620static const struct file_operations osst_fops = {
5621	.owner =        THIS_MODULE,
5622	.read =         osst_read,
5623	.write =        osst_write,
5624	.unlocked_ioctl = osst_ioctl,
5625#ifdef CONFIG_COMPAT
5626	.compat_ioctl = osst_compat_ioctl,
5627#endif
5628	.open =         os_scsi_tape_open,
5629	.flush =        os_scsi_tape_flush,
5630	.release =      os_scsi_tape_close,
5631	.llseek =	noop_llseek,
5632};
5633
5634static int osst_supports(struct scsi_device * SDp)
5635{
5636	struct	osst_support_data {
5637		char *vendor;
5638		char *model;
5639		char *rev;
5640		char *driver_hint; /* Name of the correct driver, NULL if unknown */
5641	};
5642
5643static	struct	osst_support_data support_list[] = {
5644		/* {"XXX", "Yy-", "", NULL},  example */
5645		SIGS_FROM_OSST,
5646		{NULL, }};
5647
5648	struct	osst_support_data *rp;
5649
5650	/* We are willing to drive OnStream SC-x0 as well as the
5651	 * 	 * IDE, ParPort, FireWire, USB variants, if accessible by
5652	 * 	 	 * emulation layer (ide-scsi, usb-storage, ...) */
5653
5654	for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5655		if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5656		    !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5657		    !strncmp(rp->rev, SDp->rev, strlen(rp->rev))) 
5658			return 1;
5659	return 0;
5660}
5661
5662/*
5663 * sysfs support for osst driver parameter information
5664 */
5665
5666static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5667{
5668	return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5669}
5670
5671static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5672
5673static int osst_create_sysfs_files(struct device_driver *sysfs)
5674{
5675	return driver_create_file(sysfs, &driver_attr_version);
5676}
5677
5678static void osst_remove_sysfs_files(struct device_driver *sysfs)
5679{
5680	driver_remove_file(sysfs, &driver_attr_version);
5681}
5682
5683/*
5684 * sysfs support for accessing ADR header information
5685 */
5686
5687static ssize_t osst_adr_rev_show(struct device *dev,
5688				 struct device_attribute *attr, char *buf)
5689{
5690	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5691	ssize_t l = 0;
5692
5693	if (STp && STp->header_ok && STp->linux_media)
5694		l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5695	return l;
5696}
5697
5698DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5699
5700static ssize_t osst_linux_media_version_show(struct device *dev,
5701					     struct device_attribute *attr,
5702					     char *buf)
5703{
5704	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5705	ssize_t l = 0;
5706
5707	if (STp && STp->header_ok && STp->linux_media)
5708		l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5709	return l;
5710}
5711
5712DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5713
5714static ssize_t osst_capacity_show(struct device *dev,
5715				  struct device_attribute *attr, char *buf)
5716{
5717	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5718	ssize_t l = 0;
5719
5720	if (STp && STp->header_ok && STp->linux_media)
5721		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5722	return l;
5723}
5724
5725DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5726
5727static ssize_t osst_first_data_ppos_show(struct device *dev,
5728					 struct device_attribute *attr,
5729					 char *buf)
5730{
5731	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5732	ssize_t l = 0;
5733
5734	if (STp && STp->header_ok && STp->linux_media)
5735		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5736	return l;
5737}
5738
5739DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5740
5741static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5742					struct device_attribute *attr,
5743					char *buf)
5744{
5745	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5746	ssize_t l = 0;
5747
5748	if (STp && STp->header_ok && STp->linux_media)
5749		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5750	return l;
5751}
5752
5753DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5754
5755static ssize_t osst_filemark_cnt_show(struct device *dev,
5756				      struct device_attribute *attr, char *buf)
5757{
5758	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5759	ssize_t l = 0;
5760
5761	if (STp && STp->header_ok && STp->linux_media)
5762		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5763	return l;
5764}
5765
5766DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5767
5768static struct class *osst_sysfs_class;
5769
5770static int osst_sysfs_init(void)
5771{
5772	osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5773	if (IS_ERR(osst_sysfs_class)) {
5774		printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5775		return PTR_ERR(osst_sysfs_class);
5776	}
5777
5778	return 0;
5779}
5780
5781static void osst_sysfs_destroy(dev_t dev)
5782{
5783	device_destroy(osst_sysfs_class, dev);
5784}
5785
5786static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5787{
5788	struct device *osst_member;
5789	int err;
5790
5791	osst_member = device_create(osst_sysfs_class, device, dev, STp,
5792				    "%s", name);
5793	if (IS_ERR(osst_member)) {
5794		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5795		return PTR_ERR(osst_member);
5796	}
5797
5798	err = device_create_file(osst_member, &dev_attr_ADR_rev);
5799	if (err)
5800		goto err_out;
5801	err = device_create_file(osst_member, &dev_attr_media_version);
5802	if (err)
5803		goto err_out;
5804	err = device_create_file(osst_member, &dev_attr_capacity);
5805	if (err)
5806		goto err_out;
5807	err = device_create_file(osst_member, &dev_attr_BOT_frame);
5808	if (err)
5809		goto err_out;
5810	err = device_create_file(osst_member, &dev_attr_EOD_frame);
5811	if (err)
5812		goto err_out;
5813	err = device_create_file(osst_member, &dev_attr_file_count);
5814	if (err)
5815		goto err_out;
5816
5817	return 0;
5818
5819err_out:
5820	osst_sysfs_destroy(dev);
5821	return err;
5822}
5823
5824static void osst_sysfs_cleanup(void)
5825{
5826	class_destroy(osst_sysfs_class);
5827}
5828
5829/*
5830 * osst startup / cleanup code
5831 */
5832
5833static int osst_probe(struct device *dev)
5834{
5835	struct scsi_device * SDp = to_scsi_device(dev);
5836	struct osst_tape   * tpnt;
5837	struct st_modedef  * STm;
5838	struct st_partstat * STps;
5839	struct osst_buffer * buffer;
5840	struct gendisk	   * drive;
5841	int		     i, dev_num, err = -ENODEV;
5842
5843	if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5844		return -ENODEV;
5845
5846	drive = alloc_disk(1);
5847	if (!drive) {
5848		printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5849		return -ENODEV;
5850	}
5851
5852	/* if this is the first attach, build the infrastructure */
5853	write_lock(&os_scsi_tapes_lock);
5854	if (os_scsi_tapes == NULL) {
5855		os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC);
5856		if (os_scsi_tapes == NULL) {
5857			write_unlock(&os_scsi_tapes_lock);
5858			printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5859			goto out_put_disk;
5860		}
5861		for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5862	}
5863	
5864	if (osst_nr_dev >= osst_max_dev) {
5865		write_unlock(&os_scsi_tapes_lock);
5866		printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5867		goto out_put_disk;
5868	}
5869
5870	/* find a free minor number */
5871	for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++)
5872		;
5873	if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5874	dev_num = i;
5875
5876	/* allocate a struct osst_tape for this device */
5877	tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5878	if (!tpnt) {
5879		write_unlock(&os_scsi_tapes_lock);
5880		printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5881		goto out_put_disk;
5882	}
5883
5884	/* allocate a buffer for this device */
5885	i = SDp->host->sg_tablesize;
5886	if (osst_max_sg_segs < i)
5887		i = osst_max_sg_segs;
5888	buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5889	if (buffer == NULL) {
5890		write_unlock(&os_scsi_tapes_lock);
5891		printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5892		kfree(tpnt);
5893		goto out_put_disk;
5894	}
5895	os_scsi_tapes[dev_num] = tpnt;
5896	tpnt->buffer = buffer;
5897	tpnt->device = SDp;
5898	drive->private_data = &tpnt->driver;
5899	sprintf(drive->disk_name, "osst%d", dev_num);
5900	tpnt->driver = &osst_template;
5901	tpnt->drive = drive;
5902	tpnt->in_use = 0;
5903	tpnt->capacity = 0xfffff;
5904	tpnt->dirty = 0;
5905	tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
5906	tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5907	tpnt->density = 0;
5908	tpnt->do_auto_lock = OSST_AUTO_LOCK;
5909	tpnt->can_bsr = OSST_IN_FILE_POS;
5910	tpnt->can_partitions = 0;
5911	tpnt->two_fm = OSST_TWO_FM;
5912	tpnt->fast_mteom = OSST_FAST_MTEOM;
5913	tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5914	tpnt->write_threshold = osst_write_threshold;
5915	tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5916	tpnt->partition = 0;
5917	tpnt->new_partition = 0;
5918	tpnt->nbr_partitions = 0;
5919	tpnt->min_block = 512;
5920	tpnt->max_block = OS_DATA_SIZE;
5921	tpnt->timeout = OSST_TIMEOUT;
5922	tpnt->long_timeout = OSST_LONG_TIMEOUT;
5923
5924	/* Recognize OnStream tapes */
5925	/* We don't need to test for OnStream, as this has been done in detect () */
5926	tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5927	tpnt->omit_blklims = 1;
5928
5929	tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || 
5930		     (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5931	tpnt->frame_in_buffer = 0;
5932	tpnt->header_ok = 0;
5933	tpnt->linux_media = 0;
5934	tpnt->header_cache = NULL;
5935
5936	for (i=0; i < ST_NBR_MODES; i++) {
5937		STm = &(tpnt->modes[i]);
5938		STm->defined = 0;
5939		STm->sysv = OSST_SYSV;
5940		STm->defaults_for_writes = 0;
5941		STm->do_async_writes = OSST_ASYNC_WRITES;
5942		STm->do_buffer_writes = OSST_BUFFER_WRITES;
5943		STm->do_read_ahead = OSST_READ_AHEAD;
5944		STm->default_compression = ST_DONT_TOUCH;
5945		STm->default_blksize = 512;
5946		STm->default_density = (-1);  /* No forced density */
5947	}
5948
5949	for (i=0; i < ST_NBR_PARTITIONS; i++) {
5950		STps = &(tpnt->ps[i]);
5951		STps->rw = ST_IDLE;
5952		STps->eof = ST_NOEOF;
5953		STps->at_sm = 0;
5954		STps->last_block_valid = 0;
5955		STps->drv_block = (-1);
5956		STps->drv_file = (-1);
5957	}
5958
5959	tpnt->current_mode = 0;
5960	tpnt->modes[0].defined = 1;
5961	tpnt->modes[2].defined = 1;
5962	tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5963
5964	mutex_init(&tpnt->lock);
5965	osst_nr_dev++;
5966	write_unlock(&os_scsi_tapes_lock);
5967
5968	{
5969		char name[8];
5970
5971		/*  Rewind entry  */
5972		err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5973		if (err)
5974			goto out_free_buffer;
5975
5976		/*  No-rewind entry  */
5977		snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5978		err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5979		if (err)
5980			goto out_free_sysfs1;
5981	}
5982
5983	sdev_printk(KERN_INFO, SDp,
5984		"osst :I: Attached OnStream %.5s tape as %s\n",
5985		SDp->model, tape_name(tpnt));
5986
5987	return 0;
5988
5989out_free_sysfs1:
5990	osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5991out_free_buffer:
5992	kfree(buffer);
5993out_put_disk:
5994        put_disk(drive);
5995        return err;
5996};
5997
5998static int osst_remove(struct device *dev)
5999{
6000	struct scsi_device * SDp = to_scsi_device(dev);
6001	struct osst_tape * tpnt;
6002	int i;
6003
6004	if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
6005		return 0;
6006
6007	write_lock(&os_scsi_tapes_lock);
6008	for(i=0; i < osst_max_dev; i++) {
6009		if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
6010			osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
6011			osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
6012			tpnt->device = NULL;
6013			put_disk(tpnt->drive);
6014			os_scsi_tapes[i] = NULL;
6015			osst_nr_dev--;
6016			write_unlock(&os_scsi_tapes_lock);
6017			vfree(tpnt->header_cache);
6018			if (tpnt->buffer) {
6019				normalize_buffer(tpnt->buffer);
6020				kfree(tpnt->buffer);
6021			}
6022			kfree(tpnt);
6023			return 0;
6024		}
6025	}
6026	write_unlock(&os_scsi_tapes_lock);
6027	return 0;
6028}
6029
6030static int __init init_osst(void) 
6031{
6032	int err;
6033
6034	printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
6035
6036	validate_options();
6037
6038	err = osst_sysfs_init();
6039	if (err)
6040		return err;
6041
6042	err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
6043	if (err < 0) {
6044		printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
6045		goto err_out;
6046	}
6047
6048	err = scsi_register_driver(&osst_template.gendrv);
6049	if (err)
6050		goto err_out_chrdev;
6051
6052	err = osst_create_sysfs_files(&osst_template.gendrv);
6053	if (err)
6054		goto err_out_scsidrv;
6055
6056	return 0;
6057
6058err_out_scsidrv:
6059	scsi_unregister_driver(&osst_template.gendrv);
6060err_out_chrdev:
6061	unregister_chrdev(OSST_MAJOR, "osst");
6062err_out:
6063	osst_sysfs_cleanup();
6064	return err;
6065}
6066
6067static void __exit exit_osst (void)
6068{
6069	int i;
6070	struct osst_tape * STp;
6071
6072	osst_remove_sysfs_files(&osst_template.gendrv);
6073	scsi_unregister_driver(&osst_template.gendrv);
6074	unregister_chrdev(OSST_MAJOR, "osst");
6075	osst_sysfs_cleanup();
6076
6077	if (os_scsi_tapes) {
6078		for (i=0; i < osst_max_dev; ++i) {
6079			if (!(STp = os_scsi_tapes[i])) continue;
6080			/* This is defensive, supposed to happen during detach */
6081			vfree(STp->header_cache);
6082			if (STp->buffer) {
6083				normalize_buffer(STp->buffer);
6084				kfree(STp->buffer);
6085			}
6086			put_disk(STp->drive);
6087			kfree(STp);
6088		}
6089		kfree(os_scsi_tapes);
6090	}
6091	printk(KERN_INFO "osst :I: Unloaded.\n");
6092}
6093
6094module_init(init_osst);
6095module_exit(exit_osst);