Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
   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/signal.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 <linux/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	.gendrv = {
 176		.name		=  "osst",
 177		.owner		= THIS_MODULE,
 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(STp->device, name,
 265					   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(STp->device, name,
 280					   SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 281		}
 282		else {
 283			static	int	notyetprinted = 1;
 284
 285			printk(KERN_WARNING
 286			     "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
 287			     name, result, driver_byte(result),
 288			     host_byte(result));
 289			if (notyetprinted) {
 290				notyetprinted = 0;
 291				printk(KERN_INFO
 292					"%s:I: This warning may be caused by your scsi controller,\n", name);
 293				printk(KERN_INFO
 294					"%s:I: it has been reported with some Buslogic cards.\n", name);
 295			}
 296		}
 297	}
 298	STp->pos_unknown |= STp->device->was_reset;
 299
 300	if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
 301		STp->recover_count++;
 302		STp->recover_erreg++;
 303#if DEBUG
 304		if (debugging) {
 305			if (SRpnt->cmd[0] == READ_6)
 306				stp = "read";
 307			else if (SRpnt->cmd[0] == WRITE_6)
 308				stp = "write";
 309			else
 310				stp = "ioctl";
 311			printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
 312					     STp->recover_count);
 313		}
 314#endif
 315		if ((sense[2] & 0xe0) == 0)
 316			return 0;
 317	}
 318	return (-EIO);
 319}
 320
 321
 322/* Wakeup from interrupt */
 323static void osst_end_async(struct request *req, blk_status_t status)
 324{
 325	struct scsi_request *rq = scsi_req(req);
 326	struct osst_request *SRpnt = req->end_io_data;
 327	struct osst_tape *STp = SRpnt->stp;
 328	struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
 329
 330	STp->buffer->cmdstat.midlevel_result = SRpnt->result = rq->result;
 331#if DEBUG
 332	STp->write_pending = 0;
 333#endif
 334	if (rq->sense_len)
 335		memcpy(SRpnt->sense, rq->sense, SCSI_SENSE_BUFFERSIZE);
 336	if (SRpnt->waiting)
 337		complete(SRpnt->waiting);
 338
 339	if (SRpnt->bio) {
 340		kfree(mdata->pages);
 341		blk_rq_unmap_user(SRpnt->bio);
 342	}
 343
 344	__blk_put_request(req->q, req);
 345}
 346
 347/* osst_request memory management */
 348static struct osst_request *osst_allocate_request(void)
 349{
 350	return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
 351}
 352
 353static void osst_release_request(struct osst_request *streq)
 354{
 355	kfree(streq);
 356}
 357
 358static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
 359			int cmd_len, int data_direction, void *buffer, unsigned bufflen,
 360			int use_sg, int timeout, int retries)
 361{
 362	struct request *req;
 363	struct scsi_request *rq;
 364	struct page **pages = NULL;
 365	struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
 366
 367	int err = 0;
 368	int write = (data_direction == DMA_TO_DEVICE);
 369
 370	req = blk_get_request(SRpnt->stp->device->request_queue,
 371			write ? REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, GFP_KERNEL);
 372	if (IS_ERR(req))
 373		return DRIVER_ERROR << 24;
 374
 375	rq = scsi_req(req);
 376	req->rq_flags |= RQF_QUIET;
 377
 378	SRpnt->bio = NULL;
 379
 380	if (use_sg) {
 381		struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
 382		int i;
 383
 384		pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
 385		if (!pages)
 386			goto free_req;
 387
 388		for_each_sg(sgl, sg, use_sg, i)
 389			pages[i] = sg_page(sg);
 390
 391		mdata->null_mapped = 1;
 392
 393		mdata->page_order = get_order(sgl[0].length);
 394		mdata->nr_entries =
 395			DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
 396		mdata->offset = 0;
 397
 398		err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
 399		if (err) {
 400			kfree(pages);
 401			goto free_req;
 402		}
 403		SRpnt->bio = req->bio;
 404		mdata->pages = pages;
 405
 406	} else if (bufflen) {
 407		err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
 408		if (err)
 409			goto free_req;
 410	}
 411
 412	rq->cmd_len = cmd_len;
 413	memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
 414	memcpy(rq->cmd, cmd, rq->cmd_len);
 415	req->timeout = timeout;
 416	rq->retries = retries;
 417	req->end_io_data = SRpnt;
 418
 419	blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
 420	return 0;
 421free_req:
 422	blk_put_request(req);
 423	return DRIVER_ERROR << 24;
 424}
 425
 426/* Do the scsi command. Waits until command performed if do_wait is true.
 427   Otherwise osst_write_behind_check() is used to check that the command
 428   has finished. */
 429static	struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp, 
 430	unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
 431{
 432	unsigned char *bp;
 433	unsigned short use_sg;
 434#ifdef OSST_INJECT_ERRORS
 435	static   int   inject = 0;
 436	static   int   repeat = 0;
 437#endif
 438	struct completion *waiting;
 439
 440	/* if async, make sure there's no command outstanding */
 441	if (!do_wait && ((STp->buffer)->last_SRpnt)) {
 442		printk(KERN_ERR "%s: Async command already active.\n",
 443		       tape_name(STp));
 444		if (signal_pending(current))
 445			(STp->buffer)->syscall_result = (-EINTR);
 446		else
 447			(STp->buffer)->syscall_result = (-EBUSY);
 448		return NULL;
 449	}
 450
 451	if (SRpnt == NULL) {
 452		SRpnt = osst_allocate_request();
 453		if (SRpnt == NULL) {
 454			printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
 455				     tape_name(STp));
 456			if (signal_pending(current))
 457				(STp->buffer)->syscall_result = (-EINTR);
 458			else
 459				(STp->buffer)->syscall_result = (-EBUSY);
 460			return NULL;
 461		}
 462		SRpnt->stp = STp;
 463	}
 464
 465	/* If async IO, set last_SRpnt. This ptr tells write_behind_check
 466	   which IO is outstanding. It's nulled out when the IO completes. */
 467	if (!do_wait)
 468		(STp->buffer)->last_SRpnt = SRpnt;
 469
 470	waiting = &STp->wait;
 471	init_completion(waiting);
 472	SRpnt->waiting = waiting;
 473
 474	use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
 475	if (use_sg) {
 476		bp = (char *)&(STp->buffer->sg[0]);
 477		if (STp->buffer->sg_segs < use_sg)
 478			use_sg = STp->buffer->sg_segs;
 479	}
 480	else
 481		bp = (STp->buffer)->b_data;
 482
 483	memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
 484	STp->buffer->cmdstat.have_sense = 0;
 485	STp->buffer->syscall_result = 0;
 486
 487	if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
 488			 use_sg, timeout, retries))
 489		/* could not allocate the buffer or request was too large */
 490		(STp->buffer)->syscall_result = (-EBUSY);
 491	else if (do_wait) {
 492		wait_for_completion(waiting);
 493		SRpnt->waiting = NULL;
 494		STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
 495#ifdef OSST_INJECT_ERRORS
 496		if (STp->buffer->syscall_result == 0 &&
 497		    cmd[0] == READ_6 &&
 498		    cmd[4] && 
 499		    ( (++ inject % 83) == 29  ||
 500		      (STp->first_frame_position == 240 
 501			         /* or STp->read_error_frame to fail again on the block calculated above */ &&
 502				 ++repeat < 3))) {
 503			printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
 504			STp->buffer->last_result_fatal = 1;
 505		}
 506#endif
 507	}
 508	return SRpnt;
 509}
 510
 511
 512/* Handle the write-behind checking (downs the semaphore) */
 513static void osst_write_behind_check(struct osst_tape *STp)
 514{
 515	struct osst_buffer * STbuffer;
 516
 517	STbuffer = STp->buffer;
 518
 519#if DEBUG
 520	if (STp->write_pending)
 521		STp->nbr_waits++;
 522	else
 523		STp->nbr_finished++;
 524#endif
 525	wait_for_completion(&(STp->wait));
 526	STp->buffer->last_SRpnt->waiting = NULL;
 527
 528	STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
 529
 530	if (STp->buffer->syscall_result)
 531		STp->buffer->syscall_result =
 532			osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
 533	else
 534		STp->first_frame_position++;
 535
 536	osst_release_request(STp->buffer->last_SRpnt);
 537
 538	if (STbuffer->writing < STbuffer->buffer_bytes)
 539		printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
 540
 541	STbuffer->last_SRpnt = NULL;
 542	STbuffer->buffer_bytes -= STbuffer->writing;
 543	STbuffer->writing = 0;
 544
 545	return;
 546}
 547
 548
 549
 550/* Onstream specific Routines */
 551/*
 552 * Initialize the OnStream AUX
 553 */
 554static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
 555					 int logical_blk_num, int blk_sz, int blk_cnt)
 556{
 557	os_aux_t       *aux = STp->buffer->aux;
 558	os_partition_t *par = &aux->partition;
 559	os_dat_t       *dat = &aux->dat;
 560
 561	if (STp->raw) return;
 562
 563	memset(aux, 0, sizeof(*aux));
 564	aux->format_id = htonl(0);
 565	memcpy(aux->application_sig, "LIN4", 4);
 566	aux->hdwr = htonl(0);
 567	aux->frame_type = frame_type;
 568
 569	switch (frame_type) {
 570	  case	OS_FRAME_TYPE_HEADER:
 571		aux->update_frame_cntr    = htonl(STp->update_frame_cntr);
 572		par->partition_num        = OS_CONFIG_PARTITION;
 573		par->par_desc_ver         = OS_PARTITION_VERSION;
 574		par->wrt_pass_cntr        = htons(0xffff);
 575		/* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
 576		par->first_frame_ppos     = htonl(0);
 577		par->last_frame_ppos      = htonl(0xbb7);
 578		aux->frame_seq_num        = htonl(0);
 579		aux->logical_blk_num_high = htonl(0);
 580		aux->logical_blk_num      = htonl(0);
 581		aux->next_mark_ppos       = htonl(STp->first_mark_ppos);
 582		break;
 583	  case	OS_FRAME_TYPE_DATA:
 584	  case	OS_FRAME_TYPE_MARKER:
 585		dat->dat_sz = 8;
 586		dat->reserved1 = 0;
 587		dat->entry_cnt = 1;
 588		dat->reserved3 = 0;
 589		dat->dat_list[0].blk_sz   = htonl(blk_sz);
 590		dat->dat_list[0].blk_cnt  = htons(blk_cnt);
 591		dat->dat_list[0].flags    = frame_type==OS_FRAME_TYPE_MARKER?
 592							OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
 593		dat->dat_list[0].reserved = 0;
 594	  case	OS_FRAME_TYPE_EOD:
 595		aux->update_frame_cntr    = htonl(0);
 596		par->partition_num        = OS_DATA_PARTITION;
 597		par->par_desc_ver         = OS_PARTITION_VERSION;
 598		par->wrt_pass_cntr        = htons(STp->wrt_pass_cntr);
 599		par->first_frame_ppos     = htonl(STp->first_data_ppos);
 600		par->last_frame_ppos      = htonl(STp->capacity);
 601		aux->frame_seq_num        = htonl(frame_seq_number);
 602		aux->logical_blk_num_high = htonl(0);
 603		aux->logical_blk_num      = htonl(logical_blk_num);
 604		break;
 605	  default: ; /* probably FILL */
 606	}
 607	aux->filemark_cnt = htonl(STp->filemark_cnt);
 608	aux->phys_fm = htonl(0xffffffff);
 609	aux->last_mark_ppos = htonl(STp->last_mark_ppos);
 610	aux->last_mark_lbn  = htonl(STp->last_mark_lbn);
 611}
 612
 613/*
 614 * Verify that we have the correct tape frame
 615 */
 616static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
 617{
 618	char               * name = tape_name(STp);
 619	os_aux_t           * aux  = STp->buffer->aux;
 620	os_partition_t     * par  = &(aux->partition);
 621	struct st_partstat * STps = &(STp->ps[STp->partition]);
 622	unsigned int	     blk_cnt, blk_sz, i;
 623
 624	if (STp->raw) {
 625		if (STp->buffer->syscall_result) {
 626			for (i=0; i < STp->buffer->sg_segs; i++)
 627				memset(page_address(sg_page(&STp->buffer->sg[i])),
 628				       0, STp->buffer->sg[i].length);
 629			strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
 630                } else
 631			STp->buffer->buffer_bytes = OS_FRAME_SIZE;
 632		return 1;
 633	}
 634	if (STp->buffer->syscall_result) {
 635#if DEBUG
 636		printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
 637#endif
 638		return 0;
 639	}
 640	if (ntohl(aux->format_id) != 0) {
 641#if DEBUG
 642		printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
 643#endif
 644		goto err_out;
 645	}
 646	if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
 647	    (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
 648#if DEBUG
 649		printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
 650#endif
 651		goto err_out;
 652	}
 653	if (par->partition_num != OS_DATA_PARTITION) {
 654		if (!STp->linux_media || STp->linux_media_version != 2) {
 655#if DEBUG
 656			printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
 657					    name, par->partition_num);
 658#endif
 659			goto err_out;
 660		}
 661	}
 662	if (par->par_desc_ver != OS_PARTITION_VERSION) {
 663#if DEBUG
 664		printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
 665#endif
 666		goto err_out;
 667	}
 668	if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
 669#if DEBUG
 670		printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", 
 671				    name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
 672#endif
 673		goto err_out;
 674	}
 675	if (aux->frame_type != OS_FRAME_TYPE_DATA &&
 676	    aux->frame_type != OS_FRAME_TYPE_EOD &&
 677	    aux->frame_type != OS_FRAME_TYPE_MARKER) {
 678		if (!quiet) {
 679#if DEBUG
 680			printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
 681#endif
 682		}
 683		goto err_out;
 684	}
 685	if (aux->frame_type == OS_FRAME_TYPE_EOD &&
 686	    STp->first_frame_position < STp->eod_frame_ppos) {
 687		printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
 688				 STp->first_frame_position);
 689		goto err_out;
 690	}
 691        if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
 692		if (!quiet) {
 693#if DEBUG
 694			printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n", 
 695					    name, ntohl(aux->frame_seq_num), frame_seq_number);
 696#endif
 697		}
 698		goto err_out;
 699	}
 700	if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
 701		STps->eof = ST_FM_HIT;
 702
 703		i = ntohl(aux->filemark_cnt);
 704		if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
 705		    STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
 706#if DEBUG
 707			printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
 708				  STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
 709				  i, STp->first_frame_position - 1);
 710#endif
 711			STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
 712			if (i >= STp->filemark_cnt)
 713				 STp->filemark_cnt = i+1;
 714		}
 715	}
 716	if (aux->frame_type == OS_FRAME_TYPE_EOD) {
 717		STps->eof = ST_EOD_1;
 718		STp->frame_in_buffer = 1;
 719	}
 720	if (aux->frame_type == OS_FRAME_TYPE_DATA) {
 721                blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
 722		blk_sz  = ntohl(aux->dat.dat_list[0].blk_sz);
 723		STp->buffer->buffer_bytes = blk_cnt * blk_sz;
 724		STp->buffer->read_pointer = 0;
 725		STp->frame_in_buffer = 1;
 726
 727		/* See what block size was used to write file */
 728		if (STp->block_size != blk_sz && blk_sz > 0) {
 729			printk(KERN_INFO
 730	    	"%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
 731       				name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
 732				STp->block_size<1024?STp->block_size:STp->block_size/1024,
 733				STp->block_size<1024?'b':'k');
 734			STp->block_size            = blk_sz;
 735			STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
 736		}
 737		STps->eof = ST_NOEOF;
 738	}
 739        STp->frame_seq_number = ntohl(aux->frame_seq_num);
 740	STp->logical_blk_num  = ntohl(aux->logical_blk_num);
 741	return 1;
 742
 743err_out:
 744	if (STp->read_error_frame == 0)
 745		STp->read_error_frame = STp->first_frame_position - 1;
 746	return 0;
 747}
 748
 749/*
 750 * Wait for the unit to become Ready
 751 */
 752static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
 753				 unsigned timeout, int initial_delay)
 754{
 755	unsigned char		cmd[MAX_COMMAND_SIZE];
 756	struct osst_request   * SRpnt;
 757	unsigned long		startwait = jiffies;
 758#if DEBUG
 759	int			dbg  = debugging;
 760	char    	      * name = tape_name(STp);
 761
 762	printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
 763#endif
 764
 765	if (initial_delay > 0)
 766		msleep(jiffies_to_msecs(initial_delay));
 767
 768	memset(cmd, 0, MAX_COMMAND_SIZE);
 769	cmd[0] = TEST_UNIT_READY;
 770
 771	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 772	*aSRpnt = SRpnt;
 773	if (!SRpnt) return (-EBUSY);
 774
 775	while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 776	       (( SRpnt->sense[2]  == 2 && SRpnt->sense[12] == 4    &&
 777		 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)    ) ||
 778		( SRpnt->sense[2]  == 6 && SRpnt->sense[12] == 0x28 &&
 779		  SRpnt->sense[13] == 0                                        )  )) {
 780#if DEBUG
 781	    if (debugging) {
 782		printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
 783		printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 784		debugging = 0;
 785	    }
 786#endif
 787	    msleep(100);
 788
 789	    memset(cmd, 0, MAX_COMMAND_SIZE);
 790	    cmd[0] = TEST_UNIT_READY;
 791
 792	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 793	}
 794	*aSRpnt = SRpnt;
 795#if DEBUG
 796	debugging = dbg;
 797#endif
 798	if ( STp->buffer->syscall_result &&
 799	     osst_write_error_recovery(STp, aSRpnt, 0) ) {
 800#if DEBUG
 801	    printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
 802	    printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 803			STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 804			SRpnt->sense[12], SRpnt->sense[13]);
 805#endif
 806	    return (-EIO);
 807	}
 808#if DEBUG
 809	printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
 810#endif
 811	return 0;
 812}
 813
 814/*
 815 * Wait for a tape to be inserted in the unit
 816 */
 817static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
 818{
 819	unsigned char		cmd[MAX_COMMAND_SIZE];
 820	struct osst_request   * SRpnt;
 821	unsigned long		startwait = jiffies;
 822#if DEBUG
 823	int			dbg = debugging;
 824	char    	      * name = tape_name(STp);
 825
 826	printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
 827#endif
 828
 829	memset(cmd, 0, MAX_COMMAND_SIZE);
 830	cmd[0] = TEST_UNIT_READY;
 831
 832	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 833	*aSRpnt = SRpnt;
 834	if (!SRpnt) return (-EBUSY);
 835
 836	while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 837		SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0  ) {
 838#if DEBUG
 839	    if (debugging) {
 840		printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
 841		printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 842		debugging = 0;
 843	    }
 844#endif
 845	    msleep(100);
 846
 847	    memset(cmd, 0, MAX_COMMAND_SIZE);
 848	    cmd[0] = TEST_UNIT_READY;
 849
 850	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 851	}
 852	*aSRpnt = SRpnt;
 853#if DEBUG
 854	debugging = dbg;
 855#endif
 856	if ( STp->buffer->syscall_result     && SRpnt->sense[2]  != 2 &&
 857	     SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
 858#if DEBUG
 859	    printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
 860	    printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 861			STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 862			SRpnt->sense[12], SRpnt->sense[13]);
 863#endif
 864	    return 0;
 865	}
 866#if DEBUG
 867	printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
 868#endif
 869	return 1;
 870}
 871
 872static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
 873{
 874	int	retval;
 875
 876	osst_wait_ready(STp, aSRpnt, 15 * 60, 0);			/* TODO - can this catch a write error? */
 877	retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
 878	if (retval) return (retval);
 879	osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
 880	return (osst_get_frame_position(STp, aSRpnt));
 881}
 882
 883/*
 884 * Wait for write(s) to complete
 885 */
 886static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
 887{
 888	unsigned char		cmd[MAX_COMMAND_SIZE];
 889	struct osst_request   * SRpnt;
 890	int			result = 0;
 891	int			delay  = OSST_WAIT_WRITE_COMPLETE;
 892#if DEBUG
 893	char		      * name = tape_name(STp);
 894
 895	printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
 896#endif
 897
 898	memset(cmd, 0, MAX_COMMAND_SIZE);
 899	cmd[0] = WRITE_FILEMARKS;
 900	cmd[1] = 1;
 901
 902	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 903	*aSRpnt = SRpnt;
 904	if (!SRpnt) return (-EBUSY);
 905	if (STp->buffer->syscall_result) {
 906		if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
 907			if (SRpnt->sense[13] == 8) {
 908				delay = OSST_WAIT_LONG_WRITE_COMPLETE;
 909			}
 910		} else
 911			result = osst_write_error_recovery(STp, aSRpnt, 0);
 912	}
 913	result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
 914	STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
 915
 916	return (result);
 917}
 918
 919#define OSST_POLL_PER_SEC 10
 920static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
 921{
 922	unsigned long	startwait = jiffies;
 923	char	      * name      = tape_name(STp);
 924#if DEBUG
 925	char	   notyetprinted  = 1;
 926#endif
 927	if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
 928		printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
 929
 930	while (time_before (jiffies, startwait + to*HZ))
 931	{ 
 932		int result;
 933		result = osst_get_frame_position(STp, aSRpnt);
 934		if (result == -EIO)
 935			if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
 936				return 0;	/* successful recovery leaves drive ready for frame */
 937		if (result < 0) break;
 938		if (STp->first_frame_position == curr &&
 939		    ((minlast < 0 &&
 940		      (signed)STp->last_frame_position > (signed)curr + minlast) ||
 941		     (minlast >= 0 && STp->cur_frames > minlast)
 942		    ) && result >= 0)
 943		{
 944#if DEBUG			
 945			if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
 946				printk (OSST_DEB_MSG
 947					"%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
 948					name, curr, curr+minlast, STp->first_frame_position,
 949					STp->last_frame_position, STp->cur_frames,
 950					result, (jiffies-startwait)/HZ, 
 951					(((jiffies-startwait)%HZ)*10)/HZ);
 952#endif
 953			return 0;
 954		}
 955#if DEBUG
 956		if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
 957		{
 958			printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
 959				name, curr, curr+minlast, STp->first_frame_position,
 960				STp->last_frame_position, STp->cur_frames, result);
 961			notyetprinted--;
 962		}
 963#endif
 964		msleep(1000 / OSST_POLL_PER_SEC);
 965	}
 966#if DEBUG
 967	printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
 968		name, curr, curr+minlast, STp->first_frame_position,
 969		STp->last_frame_position, STp->cur_frames,
 970		(jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
 971#endif	
 972	return -EBUSY;
 973}
 974
 975static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
 976{
 977	struct osst_request   * SRpnt;
 978	unsigned char		cmd[MAX_COMMAND_SIZE];
 979	unsigned long   	startwait = jiffies;
 980	int			retval    = 1;
 981        char		      * name      = tape_name(STp);
 982                                                                                                                                
 983	if (writing) {
 984		char	mybuf[24];
 985		char  * olddata = STp->buffer->b_data;
 986		int	oldsize = STp->buffer->buffer_size;
 987
 988		/* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
 989
 990		memset(cmd, 0, MAX_COMMAND_SIZE);
 991		cmd[0] = WRITE_FILEMARKS;
 992		cmd[1] = 1;
 993		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
 994								MAX_RETRIES, 1);
 995
 996		while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
 997
 998			if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
 999
1000				/* some failure - not just not-ready */
1001				retval = osst_write_error_recovery(STp, aSRpnt, 0);
1002				break;
1003			}
1004			schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
1005
1006			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1007			memset(cmd, 0, MAX_COMMAND_SIZE);
1008			cmd[0] = READ_POSITION;
1009
1010			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1011										MAX_RETRIES, 1);
1012
1013			retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1014			STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1015		}
1016		if (retval)
1017			printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1018	} else
1019		/* TODO - figure out which error conditions can be handled */
1020		if (STp->buffer->syscall_result)
1021			printk(KERN_WARNING
1022				"%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1023					(*aSRpnt)->sense[ 2] & 0x0f,
1024					(*aSRpnt)->sense[12],
1025					(*aSRpnt)->sense[13]);
1026
1027	return retval;
1028}
1029
1030/*
1031 * Read the next OnStream tape frame at the current location
1032 */
1033static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1034{
1035	unsigned char		cmd[MAX_COMMAND_SIZE];
1036	struct osst_request   * SRpnt;
1037	int			retval = 0;
1038#if DEBUG
1039	os_aux_t	      * aux    = STp->buffer->aux;
1040	char		      * name   = tape_name(STp);
1041#endif
1042
1043	if (STp->poll)
1044		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1045			retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1046
1047	memset(cmd, 0, MAX_COMMAND_SIZE);
1048	cmd[0] = READ_6;
1049	cmd[1] = 1;
1050	cmd[4] = 1;
1051
1052#if DEBUG
1053	if (debugging)
1054		printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1055#endif
1056	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1057				      STp->timeout, MAX_RETRIES, 1);
1058	*aSRpnt = SRpnt;
1059	if (!SRpnt)
1060		return (-EBUSY);
1061
1062	if ((STp->buffer)->syscall_result) {
1063	    retval = 1;
1064	    if (STp->read_error_frame == 0) {
1065		STp->read_error_frame = STp->first_frame_position;
1066#if DEBUG
1067		printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1068#endif
1069	    }
1070#if DEBUG
1071	    if (debugging)
1072		printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1073		   name,
1074		   SRpnt->sense[0], SRpnt->sense[1],
1075		   SRpnt->sense[2], SRpnt->sense[3],
1076		   SRpnt->sense[4], SRpnt->sense[5],
1077		   SRpnt->sense[6], SRpnt->sense[7]);
1078#endif
1079	}
1080	else
1081	    STp->first_frame_position++;
1082#if DEBUG
1083	if (debugging) {
1084	   char sig[8]; int i;
1085	   for (i=0;i<4;i++)
1086		   sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1087	   sig[4] = '\0';
1088	   printk(OSST_DEB_MSG 
1089		"%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1090			ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1091			aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1092			aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", 
1093			ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1094			ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1095	   if (aux->frame_type==2)
1096		printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1097			ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1098	   printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1099	}
1100#endif
1101	return (retval);
1102}
1103
1104static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1105{
1106	struct st_partstat    * STps   = &(STp->ps[STp->partition]);
1107	struct osst_request   * SRpnt  ;
1108	unsigned char		cmd[MAX_COMMAND_SIZE];
1109	int			retval = 0;
1110	char		      * name   = tape_name(STp);
1111
1112	if (STps->rw != ST_READING) {         /* Initialize read operation */
1113		if (STps->rw == ST_WRITING || STp->dirty) {
1114			STp->write_type = OS_WRITE_DATA;
1115                        osst_flush_write_buffer(STp, aSRpnt);
1116			osst_flush_drive_buffer(STp, aSRpnt);
1117		}
1118		STps->rw = ST_READING;
1119		STp->frame_in_buffer = 0;
1120
1121		/*
1122		 *      Issue a read 0 command to get the OnStream drive
1123                 *      read frames into its buffer.
1124		 */
1125		memset(cmd, 0, MAX_COMMAND_SIZE);
1126		cmd[0] = READ_6;
1127		cmd[1] = 1;
1128
1129#if DEBUG
1130		printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1131#endif
1132		SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1133		*aSRpnt = SRpnt;
1134		if ((retval = STp->buffer->syscall_result))
1135			printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1136	}
1137
1138	return retval;
1139}
1140
1141static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1142						int frame_seq_number, int quiet)
1143{
1144	struct st_partstat * STps  = &(STp->ps[STp->partition]);
1145	char		   * name  = tape_name(STp);
1146	int		     cnt   = 0,
1147			     bad   = 0,
1148			     past  = 0,
1149			     x,
1150			     position;
1151
1152	/*
1153	 * If we want just any frame (-1) and there is a frame in the buffer, return it
1154	 */
1155	if (frame_seq_number == -1 && STp->frame_in_buffer) {
1156#if DEBUG
1157		printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1158#endif
1159		return (STps->eof);
1160	}
1161	/*
1162         * Search and wait for the next logical tape frame
1163	 */
1164	while (1) {
1165		if (cnt++ > 400) {
1166                        printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1167					    name, frame_seq_number);
1168			if (STp->read_error_frame) {
1169				osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1170#if DEBUG
1171                        	printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1172						    name, STp->read_error_frame);
1173#endif
1174				STp->read_error_frame = 0;
1175				STp->abort_count++;
1176			}
1177			return (-EIO);
1178		}
1179#if DEBUG
1180		if (debugging)
1181			printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1182					  name, frame_seq_number, cnt);
1183#endif
1184		if ( osst_initiate_read(STp, aSRpnt)
1185                || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1186			if (STp->raw)
1187				return (-EIO);
1188			position = osst_get_frame_position(STp, aSRpnt);
1189			if (position >= 0xbae && position < 0xbb8)
1190				position = 0xbb8;
1191			else if (position > STp->eod_frame_ppos || ++bad == 10) {
1192				position = STp->read_error_frame - 1;
1193				bad = 0;
1194			}
1195			else {
1196				position += 29;
1197				cnt      += 19;
1198			}
1199#if DEBUG
1200			printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1201					 name, position);
1202#endif
1203			osst_set_frame_position(STp, aSRpnt, position, 0);
1204			continue;
1205		}
1206		if (osst_verify_frame(STp, frame_seq_number, quiet))
1207			break;
1208		if (osst_verify_frame(STp, -1, quiet)) {
1209			x = ntohl(STp->buffer->aux->frame_seq_num);
1210			if (STp->fast_open) {
1211				printk(KERN_WARNING
1212				       "%s:W: Found logical frame %d instead of %d after fast open\n",
1213				       name, x, frame_seq_number);
1214				STp->header_ok = 0;
1215				STp->read_error_frame = 0;
1216				return (-EIO);
1217			}
1218			if (x > frame_seq_number) {
1219				if (++past > 3) {
1220					/* positioning backwards did not bring us to the desired frame */
1221					position = STp->read_error_frame - 1;
1222				}
1223				else {
1224			        	position = osst_get_frame_position(STp, aSRpnt)
1225					         + frame_seq_number - x - 1;
1226
1227					if (STp->first_frame_position >= 3000 && position < 3000)
1228						position -= 10;
1229				}
1230#if DEBUG
1231                                printk(OSST_DEB_MSG
1232				       "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1233						name, x, frame_seq_number,
1234					       	STp->first_frame_position - position);
1235#endif
1236                        	osst_set_frame_position(STp, aSRpnt, position, 0);
1237				cnt += 10;
1238			}
1239			else
1240				past = 0;
1241		}
1242		if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1243#if DEBUG
1244			printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1245#endif
1246			osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1247			cnt--;
1248		}
1249		STp->frame_in_buffer = 0;
1250	}
1251	if (cnt > 1) {
1252		STp->recover_count++;
1253		STp->recover_erreg++;
1254		printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n", 
1255					name, STp->read_error_frame);
1256 	}
1257	STp->read_count++;
1258
1259#if DEBUG
1260	if (debugging || STps->eof)
1261		printk(OSST_DEB_MSG
1262			"%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1263			name, frame_seq_number, STp->frame_seq_number, STps->eof);
1264#endif
1265	STp->fast_open = 0;
1266	STp->read_error_frame = 0;
1267	return (STps->eof);
1268}
1269
1270static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1271{
1272        struct st_partstat * STps = &(STp->ps[STp->partition]);
1273	char		   * name = tape_name(STp);
1274	int	retries    = 0;
1275	int	frame_seq_estimate, ppos_estimate, move;
1276	
1277	if (logical_blk_num < 0) logical_blk_num = 0;
1278#if DEBUG
1279	printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1280				name, logical_blk_num, STp->logical_blk_num, 
1281				STp->block_size<1024?STp->block_size:STp->block_size/1024,
1282				STp->block_size<1024?'b':'k');
1283#endif
1284	/* Do we know where we are? */
1285	if (STps->drv_block >= 0) {
1286		move                = logical_blk_num - STp->logical_blk_num;
1287		if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1288		move               /= (OS_DATA_SIZE / STp->block_size);
1289		frame_seq_estimate  = STp->frame_seq_number + move;
1290	} else
1291		frame_seq_estimate  = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1292
1293	if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1294	else			       ppos_estimate = frame_seq_estimate + 20;
1295	while (++retries < 10) {
1296	   if (ppos_estimate > STp->eod_frame_ppos-2) {
1297	       frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1298	       ppos_estimate       = STp->eod_frame_ppos - 2;
1299	   }
1300	   if (frame_seq_estimate < 0) {
1301	       frame_seq_estimate = 0;
1302	       ppos_estimate      = 10;
1303	   }
1304	   osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1305	   if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1306	      /* we've located the estimated frame, now does it have our block? */
1307	      if (logical_blk_num <  STp->logical_blk_num ||
1308	          logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1309		 if (STps->eof == ST_FM_HIT)
1310		    move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1311		 else {
1312		    move                = logical_blk_num - STp->logical_blk_num;
1313		    if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1314		    move               /= (OS_DATA_SIZE / STp->block_size);
1315		 }
1316		 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1317#if DEBUG
1318		 printk(OSST_DEB_MSG
1319			"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1320				name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1321				STp->logical_blk_num, logical_blk_num, move);
1322#endif
1323		 frame_seq_estimate += move;
1324		 ppos_estimate      += move;
1325		 continue;
1326	      } else {
1327		 STp->buffer->read_pointer  = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1328		 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1329		 STp->logical_blk_num       =  logical_blk_num;
1330#if DEBUG
1331		 printk(OSST_DEB_MSG 
1332			"%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1333				name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer, 
1334				STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size, 
1335				STp->block_size);
1336#endif
1337		 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1338		 if (STps->eof == ST_FM_HIT) {
1339		     STps->drv_file++;
1340		     STps->drv_block = 0;
1341		 } else {
1342		     STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1343					  STp->logical_blk_num -
1344					     (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1345					-1;
1346		 }
1347		 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1348		 return 0;
1349	      }
1350	   }
1351	   if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1352	      goto error;
1353	   /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1354#if DEBUG
1355	   printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n", 
1356			   name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1357			   STp->logical_blk_num, logical_blk_num);
1358#endif
1359	   if (frame_seq_estimate != STp->frame_seq_number)
1360	      ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1361	   else
1362	      break;
1363	}
1364error:
1365	printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n", 
1366			    name, logical_blk_num, STp->logical_blk_num, retries);
1367	return (-EIO);
1368}
1369
1370/* The values below are based on the OnStream frame payload size of 32K == 2**15,
1371 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1372 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1373 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1374 */
1375#define OSST_FRAME_SHIFT  6
1376#define OSST_SECTOR_SHIFT 9
1377#define OSST_SECTOR_MASK  0x03F
1378
1379static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1380{
1381	int	sector;
1382#if DEBUG
1383	char  * name = tape_name(STp);
1384	
1385	printk(OSST_DEB_MSG 
1386		"%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1387		name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1388		STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block, 
1389		STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1390		STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1391		STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1392#endif
1393	/* do we know where we are inside a file? */
1394	if (STp->ps[STp->partition].drv_block >= 0) {
1395		sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1396				STp->first_frame_position) << OSST_FRAME_SHIFT;
1397		if (STp->ps[STp->partition].rw == ST_WRITING)
1398		       	sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1399		else
1400	       		sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1401	} else {
1402		sector = osst_get_frame_position(STp, aSRpnt);
1403		if (sector > 0)
1404			sector <<= OSST_FRAME_SHIFT;
1405	}
1406	return sector;
1407}
1408
1409static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1410{
1411        struct st_partstat * STps   = &(STp->ps[STp->partition]);
1412	int		     frame  = sector >> OSST_FRAME_SHIFT,
1413			     offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
1414			     r;
1415#if DEBUG
1416	char          * name = tape_name(STp);
1417
1418	printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1419				name, sector, frame, offset);
1420#endif
1421	if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1422
1423	if (frame <= STp->first_data_ppos) {
1424		STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1425		return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1426	}
1427	r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1428	if (r < 0) return r;
1429
1430	r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1431	if (r < 0) return r;
1432
1433	if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1434
1435	if (offset) {
1436		STp->logical_blk_num      += offset / STp->block_size;
1437		STp->buffer->read_pointer  = offset;
1438		STp->buffer->buffer_bytes -= offset;
1439	} else {
1440		STp->frame_seq_number++;
1441		STp->frame_in_buffer       = 0;
1442		STp->logical_blk_num      += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1443		STp->buffer->buffer_bytes  = STp->buffer->read_pointer = 0;
1444	}
1445	STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1446	if (STps->eof == ST_FM_HIT) {
1447		STps->drv_file++;
1448		STps->drv_block = 0;
1449	} else {
1450		STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1451				    STp->logical_blk_num -
1452					(STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1453				  -1;
1454	}
1455	STps->eof       = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1456#if DEBUG
1457	printk(OSST_DEB_MSG 
1458		"%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1459		name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1460		STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1461#endif
1462	return 0;
1463}
1464
1465/*
1466 * Read back the drive's internal buffer contents, as a part
1467 * of the write error recovery mechanism for old OnStream
1468 * firmware revisions.
1469 * Precondition for this function to work: all frames in the
1470 * drive's buffer must be of one type (DATA, MARK or EOD)!
1471 */
1472static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1473						unsigned int frame, unsigned int skip, int pending)
1474{
1475	struct osst_request   * SRpnt = * aSRpnt;
1476	unsigned char	      * buffer, * p;
1477	unsigned char		cmd[MAX_COMMAND_SIZE];
1478	int			flag, new_frame, i;
1479	int			nframes          = STp->cur_frames;
1480	int			blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1481	int			frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1482						- (nframes + pending - 1);
1483	int			logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
1484						- (nframes + pending - 1) * blks_per_frame;
1485	char		      * name             = tape_name(STp);
1486	unsigned long		startwait        = jiffies;
1487#if DEBUG
1488	int			dbg              = debugging;
1489#endif
1490
1491	if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1492		return (-EIO);
1493
1494	printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1495			 name, nframes, pending?" and one that was pending":"");
1496
1497	osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1498#if DEBUG
1499	if (pending && debugging)
1500		printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1501				name, frame_seq_number + nframes,
1502			       	logical_blk_num + nframes * blks_per_frame,
1503			       	p[0], p[1], p[2], p[3]);
1504#endif
1505	for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1506
1507		memset(cmd, 0, MAX_COMMAND_SIZE);
1508		cmd[0] = 0x3C;		/* Buffer Read           */
1509		cmd[1] = 6;		/* Retrieve Faulty Block */
1510		cmd[7] = 32768 >> 8;
1511		cmd[8] = 32768 & 0xff;
1512
1513		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1514					    STp->timeout, MAX_RETRIES, 1);
1515	
1516		if ((STp->buffer)->syscall_result || !SRpnt) {
1517			printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1518			vfree(buffer);
1519			*aSRpnt = SRpnt;
1520			return (-EIO);
1521		}
1522		osst_copy_from_buffer(STp->buffer, p);
1523#if DEBUG
1524		if (debugging)
1525			printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1526					  name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1527#endif
1528	}
1529	*aSRpnt = SRpnt;
1530	osst_get_frame_position(STp, aSRpnt);
1531
1532#if DEBUG
1533	printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1534#endif
1535	/* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1536	/* In the header we don't actually re-write the frames that fail, just the ones after them */
1537
1538	for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1539
1540		if (flag) {
1541			if (STp->write_type == OS_WRITE_HEADER) {
1542				i += skip;
1543				p += skip * OS_DATA_SIZE;
1544			}
1545			else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1546				new_frame = 3000-i;
1547			else
1548				new_frame += skip;
1549#if DEBUG
1550			printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1551						name, new_frame+i, frame_seq_number+i);
1552#endif
1553			osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1554			osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1555			osst_get_frame_position(STp, aSRpnt);
1556			SRpnt = * aSRpnt;
1557
1558			if (new_frame > frame + 1000) {
1559				printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1560				vfree(buffer);
1561				return (-EIO);
1562			}
1563			if ( i >= nframes + pending ) break;
1564			flag = 0;
1565		}
1566		osst_copy_to_buffer(STp->buffer, p);
1567		/*
1568		 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1569		 */
1570		osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1571			       	logical_blk_num + i*blks_per_frame,
1572			       	ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1573		memset(cmd, 0, MAX_COMMAND_SIZE);
1574		cmd[0] = WRITE_6;
1575		cmd[1] = 1;
1576		cmd[4] = 1;
1577
1578#if DEBUG
1579		if (debugging)
1580			printk(OSST_DEB_MSG
1581				"%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1582				name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1583				p[0], p[1], p[2], p[3]);
1584#endif
1585		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1586					    STp->timeout, MAX_RETRIES, 1);
1587
1588		if (STp->buffer->syscall_result)
1589			flag = 1;
1590		else {
1591			p += OS_DATA_SIZE; i++;
1592
1593			/* if we just sent the last frame, wait till all successfully written */
1594			if ( i == nframes + pending ) {
1595#if DEBUG
1596				printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1597#endif
1598				memset(cmd, 0, MAX_COMMAND_SIZE);
1599				cmd[0] = WRITE_FILEMARKS;
1600				cmd[1] = 1;
1601				SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1602							    STp->timeout, MAX_RETRIES, 1);
1603#if DEBUG
1604				if (debugging) {
1605					printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1606					printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1607					debugging = 0;
1608				}
1609#endif
1610				flag = STp->buffer->syscall_result;
1611				while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1612
1613					memset(cmd, 0, MAX_COMMAND_SIZE);
1614					cmd[0] = TEST_UNIT_READY;
1615
1616					SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1617												MAX_RETRIES, 1);
1618
1619					if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1620					    (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1621						/* in the process of becoming ready */
1622						msleep(100);
1623						continue;
1624					}
1625					if (STp->buffer->syscall_result)
1626						flag = 1;
1627					break;
1628				}
1629#if DEBUG
1630				debugging = dbg;
1631				printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1632#endif
1633			}
1634		}
1635		*aSRpnt = SRpnt;
1636		if (flag) {
1637			if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1638			     SRpnt->sense[12]         ==  0 &&
1639			     SRpnt->sense[13]         ==  2) {
1640				printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1641				vfree(buffer);
1642				return (-EIO);			/* hit end of tape = fail */
1643			}
1644			i = ((SRpnt->sense[3] << 24) |
1645			     (SRpnt->sense[4] << 16) |
1646			     (SRpnt->sense[5] <<  8) |
1647			      SRpnt->sense[6]        ) - new_frame;
1648			p = &buffer[i * OS_DATA_SIZE];
1649#if DEBUG
1650			printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1651#endif
1652			osst_get_frame_position(STp, aSRpnt);
1653#if DEBUG
1654			printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1655					  name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1656#endif
1657		}
1658	}
1659	if (flag) {
1660		/* error recovery did not successfully complete */
1661		printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1662				STp->write_type == OS_WRITE_HEADER?"header":"body");
1663	}
1664	if (!pending)
1665		osst_copy_to_buffer(STp->buffer, p);	/* so buffer content == at entry in all cases */
1666	vfree(buffer);
1667	return 0;
1668}
1669
1670static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1671					unsigned int frame, unsigned int skip, int pending)
1672{
1673	unsigned char		cmd[MAX_COMMAND_SIZE];
1674	struct osst_request   * SRpnt;
1675	char		      * name      = tape_name(STp);
1676	int			expected  = 0;
1677	int			attempts  = 1000 / skip;
1678	int			flag      = 1;
1679	unsigned long		startwait = jiffies;
1680#if DEBUG
1681	int			dbg       = debugging;
1682#endif
1683
1684	while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1685		if (flag) {
1686#if DEBUG
1687			debugging = dbg;
1688#endif
1689			if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1690				frame = 3000-skip;
1691			expected = frame+skip+STp->cur_frames+pending;
1692#if DEBUG
1693			printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1694					  name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1695#endif
1696			osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1697			flag = 0;
1698			attempts--;
1699			schedule_timeout_interruptible(msecs_to_jiffies(100));
1700		}
1701		if (osst_get_frame_position(STp, aSRpnt) < 0) {		/* additional write error */
1702#if DEBUG
1703			printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1704					  name, STp->first_frame_position,
1705					  STp->last_frame_position, STp->cur_frames);
1706#endif
1707			frame = STp->last_frame_position;
1708			flag = 1;
1709			continue;
1710		}
1711		if (pending && STp->cur_frames < 50) {
1712
1713			memset(cmd, 0, MAX_COMMAND_SIZE);
1714			cmd[0] = WRITE_6;
1715			cmd[1] = 1;
1716			cmd[4] = 1;
1717#if DEBUG
1718			printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1719					  name, STp->frame_seq_number-1, STp->first_frame_position);
1720#endif
1721			SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1722						      STp->timeout, MAX_RETRIES, 1);
1723			*aSRpnt = SRpnt;
1724
1725			if (STp->buffer->syscall_result) {		/* additional write error */
1726				if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1727				     SRpnt->sense[12]         ==  0 &&
1728				     SRpnt->sense[13]         ==  2) {
1729					printk(KERN_ERR
1730					       "%s:E: Volume overflow in write error recovery\n",
1731					       name);
1732					break;				/* hit end of tape = fail */
1733				}
1734				flag = 1;
1735			}
1736			else
1737				pending = 0;
1738
1739			continue;
1740		}
1741		if (STp->cur_frames == 0) {
1742#if DEBUG
1743			debugging = dbg;
1744			printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1745#endif
1746			if (STp->first_frame_position != expected) {
1747				printk(KERN_ERR "%s:A: Actual position %d - expected %d\n", 
1748						name, STp->first_frame_position, expected);
1749				return (-EIO);
1750			}
1751			return 0;
1752		}
1753#if DEBUG
1754		if (debugging) {
1755			printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1756			printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1757			debugging = 0;
1758		}
1759#endif
1760		schedule_timeout_interruptible(msecs_to_jiffies(100));
1761	}
1762	printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1763#if DEBUG
1764	debugging = dbg;
1765#endif
1766	return (-EIO);
1767}
1768
1769/*
1770 * Error recovery algorithm for the OnStream tape.
1771 */
1772
1773static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1774{
1775	struct osst_request * SRpnt  = * aSRpnt;
1776	struct st_partstat  * STps   = & STp->ps[STp->partition];
1777	char		    * name   = tape_name(STp);
1778	int		      retval = 0;
1779	int		      rw_state;
1780	unsigned int	      frame, skip;
1781
1782	rw_state = STps->rw;
1783
1784	if ((SRpnt->sense[ 2] & 0x0f) != 3
1785	  || SRpnt->sense[12]         != 12
1786	  || SRpnt->sense[13]         != 0) {
1787#if DEBUG
1788		printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1789			SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1790#endif
1791		return (-EIO);
1792	}
1793	frame =	(SRpnt->sense[3] << 24) |
1794		(SRpnt->sense[4] << 16) |
1795		(SRpnt->sense[5] <<  8) |
1796		 SRpnt->sense[6];
1797	skip  =  SRpnt->sense[9];
1798 
1799#if DEBUG
1800	printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1801#endif
1802	osst_get_frame_position(STp, aSRpnt);
1803#if DEBUG
1804	printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1805			name, STp->first_frame_position, STp->last_frame_position);
1806#endif
1807	switch (STp->write_type) {
1808	   case OS_WRITE_DATA:
1809	   case OS_WRITE_EOD:
1810	   case OS_WRITE_NEW_MARK:
1811		printk(KERN_WARNING 
1812			"%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1813			name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1814		if (STp->os_fw_rev >= 10600)
1815			retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1816		else
1817			retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1818		printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1819			       	retval?"E"    :"I",
1820			       	retval?""     :"Don't worry, ",
1821			       	retval?" not ":" ");
1822		break;
1823	   case OS_WRITE_LAST_MARK:
1824		printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1825		osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1826		retval = -EIO;
1827		break;
1828	   case OS_WRITE_HEADER:
1829		printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1830		retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1831		break;
1832	   default:
1833		printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1834		osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1835	}
1836	osst_get_frame_position(STp, aSRpnt);
1837#if DEBUG
1838	printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", 
1839			name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1840	printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1841#endif
1842	if (retval == 0) {
1843		STp->recover_count++;
1844		STp->recover_erreg++;
1845	} else
1846		STp->abort_count++;
1847
1848	STps->rw = rw_state;
1849	return retval;
1850}
1851
1852static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1853								 int mt_op, int mt_count)
1854{
1855	char  * name = tape_name(STp);
1856	int     cnt;
1857	int     last_mark_ppos = -1;
1858
1859#if DEBUG
1860	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1861#endif
1862	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1863#if DEBUG
1864		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1865#endif
1866		return -EIO;
1867	}
1868	if (STp->linux_media_version >= 4) {
1869		/*
1870		 * direct lookup in header filemark list
1871		 */
1872		cnt = ntohl(STp->buffer->aux->filemark_cnt);
1873		if (STp->header_ok                         && 
1874		    STp->header_cache != NULL              &&
1875		    (cnt - mt_count)  >= 0                 &&
1876		    (cnt - mt_count)   < OS_FM_TAB_MAX     &&
1877		    (cnt - mt_count)   < STp->filemark_cnt &&
1878		    STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1879
1880			last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1881#if DEBUG
1882		if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1883			printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1884			       STp->header_cache == NULL?"lack of header cache":"count out of range");
1885		else
1886			printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1887				name, cnt,
1888				((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1889				 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1890					 STp->buffer->aux->last_mark_ppos))?"match":"error",
1891			       mt_count, last_mark_ppos);
1892#endif
1893		if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1894			osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1895			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1896#if DEBUG
1897				printk(OSST_DEB_MSG 
1898					"%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1899#endif
1900				return (-EIO);
1901			}
1902			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1903				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1904						 name, last_mark_ppos);
1905				return (-EIO);
1906			}
1907			goto found;
1908		}
1909#if DEBUG
1910		printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1911#endif
1912	}
1913	cnt = 0;
1914	while (cnt != mt_count) {
1915		last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1916		if (last_mark_ppos == -1)
1917			return (-EIO);
1918#if DEBUG
1919		printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1920#endif
1921		osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1922		cnt++;
1923		if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1924#if DEBUG
1925			printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1926#endif
1927			return (-EIO);
1928		}
1929		if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1930			printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1931					 name, last_mark_ppos);
1932			return (-EIO);
1933		}
1934	}
1935found:
1936	if (mt_op == MTBSFM) {
1937		STp->frame_seq_number++;
1938		STp->frame_in_buffer      = 0;
1939		STp->buffer->buffer_bytes = 0;
1940		STp->buffer->read_pointer = 0;
1941		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1942	}
1943	return 0;
1944}
1945
1946/*
1947 * ADRL 1.1 compatible "slow" space filemarks fwd version
1948 *
1949 * Just scans for the filemark sequentially.
1950 */
1951static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1952								     int mt_op, int mt_count)
1953{
1954	int	cnt = 0;
1955#if DEBUG
1956	char  * name = tape_name(STp);
1957
1958	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1959#endif
1960	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1961#if DEBUG
1962		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1963#endif
1964		return (-EIO);
1965	}
1966	while (1) {
1967		if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1968#if DEBUG
1969			printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1970#endif
1971			return (-EIO);
1972		}
1973		if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1974			cnt++;
1975		if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1976#if DEBUG
1977			printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1978#endif
1979			if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1980#if DEBUG
1981				printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1982					       	name, STp->eod_frame_ppos, STp->first_frame_position-1);
1983#endif
1984				STp->eod_frame_ppos = STp->first_frame_position-1;
1985			}
1986			return (-EIO);
1987		}
1988		if (cnt == mt_count)
1989			break;
1990		STp->frame_in_buffer = 0;
1991	}
1992	if (mt_op == MTFSF) {
1993		STp->frame_seq_number++;
1994		STp->frame_in_buffer      = 0;
1995		STp->buffer->buffer_bytes = 0;
1996		STp->buffer->read_pointer = 0;
1997		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1998	}
1999	return 0;
2000}
2001
2002/*
2003 * Fast linux specific version of OnStream FSF
2004 */
2005static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
2006								     int mt_op, int mt_count)
2007{
2008	char  * name = tape_name(STp);
2009	int	cnt  = 0,
2010		next_mark_ppos = -1;
2011
2012#if DEBUG
2013	printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
2014#endif
2015	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2016#if DEBUG
2017		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
2018#endif
2019		return (-EIO);
2020	}
2021
2022	if (STp->linux_media_version >= 4) {
2023		/*
2024		 * direct lookup in header filemark list
2025		 */
2026		cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
2027		if (STp->header_ok                         && 
2028		    STp->header_cache != NULL              &&
2029		    (cnt + mt_count)   < OS_FM_TAB_MAX     &&
2030		    (cnt + mt_count)   < STp->filemark_cnt &&
2031		    ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2032		     (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
2033
2034			next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
2035#if DEBUG
2036		if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
2037			printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
2038			       STp->header_cache == NULL?"lack of header cache":"count out of range");
2039		else
2040			printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2041			       name, cnt,
2042			       ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2043				(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
2044					 STp->buffer->aux->last_mark_ppos))?"match":"error",
2045			       mt_count, next_mark_ppos);
2046#endif
2047		if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
2048#if DEBUG
2049			printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2050#endif
2051			return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2052		} else {
2053			osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2054			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2055#if DEBUG
2056				printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2057						 name);
2058#endif
2059				return (-EIO);
2060			}
2061			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2062				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2063						 name, next_mark_ppos);
2064				return (-EIO);
2065			}
2066			if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
2067				printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
2068						 name, cnt+mt_count, next_mark_ppos,
2069						 ntohl(STp->buffer->aux->filemark_cnt));
2070       				return (-EIO);
2071			}
2072		}
2073	} else {
2074		/*
2075		 * Find nearest (usually previous) marker, then jump from marker to marker
2076		 */
2077		while (1) {
2078			if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
2079				break;
2080			if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2081#if DEBUG
2082				printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2083#endif
2084				return (-EIO);
2085			}
2086			if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2087				if (STp->first_mark_ppos == -1) {
2088#if DEBUG
2089					printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2090#endif
2091					return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2092				}
2093				osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2094				if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2095#if DEBUG
2096					printk(OSST_DEB_MSG
2097					       "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2098					       name);
2099#endif
2100					return (-EIO);
2101				}
2102				if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2103					printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2104							 name, STp->first_mark_ppos);
2105					return (-EIO);
2106				}
2107			} else {
2108				if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2109					return (-EIO);
2110				mt_count++;
2111			}
2112		}
2113		cnt++;
2114		while (cnt != mt_count) {
2115			next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2116			if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2117#if DEBUG
2118				printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2119#endif
2120				return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2121			}
2122#if DEBUG
2123			else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2124#endif
2125			osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2126			cnt++;
2127			if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2128#if DEBUG
2129				printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2130						 name);
2131#endif
2132				return (-EIO);
2133			}
2134			if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2135				printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2136						 name, next_mark_ppos);
2137				return (-EIO);
2138			}
2139		}
2140	}
2141	if (mt_op == MTFSF) {
2142		STp->frame_seq_number++;
2143		STp->frame_in_buffer      = 0;
2144		STp->buffer->buffer_bytes = 0;
2145		STp->buffer->read_pointer = 0;
2146		STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2147	}
2148	return 0;
2149}
2150
2151/*
2152 * In debug mode, we want to see as many errors as possible
2153 * to test the error recovery mechanism.
2154 */
2155#if DEBUG
2156static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2157{
2158	unsigned char		cmd[MAX_COMMAND_SIZE];
2159	struct osst_request   * SRpnt  = * aSRpnt;
2160	char		      * name   = tape_name(STp);
2161
2162	memset(cmd, 0, MAX_COMMAND_SIZE);
2163	cmd[0] = MODE_SELECT;
2164	cmd[1] = 0x10;
2165	cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2166
2167	(STp->buffer)->b_data[0] = cmd[4] - 1;
2168	(STp->buffer)->b_data[1] = 0;			/* Medium Type - ignoring */
2169	(STp->buffer)->b_data[2] = 0;			/* Reserved */
2170	(STp->buffer)->b_data[3] = 0;			/* Block Descriptor Length */
2171	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2172	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2173	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2174	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2175
2176	if (debugging)
2177	    printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2178
2179	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2180	*aSRpnt = SRpnt;
2181
2182	if ((STp->buffer)->syscall_result)
2183	    printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2184}
2185#endif
2186
2187
2188static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2189{
2190	int	result;
2191	int	this_mark_ppos = STp->first_frame_position;
2192	int	this_mark_lbn  = STp->logical_blk_num;
2193#if DEBUG
2194	char  * name = tape_name(STp);
2195#endif
2196
2197	if (STp->raw) return 0;
2198
2199	STp->write_type = OS_WRITE_NEW_MARK;
2200#if DEBUG
2201	printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n", 
2202	       name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2203#endif
2204	STp->dirty = 1;
2205	result  = osst_flush_write_buffer(STp, aSRpnt);
2206	result |= osst_flush_drive_buffer(STp, aSRpnt);
2207	STp->last_mark_ppos = this_mark_ppos;
2208	STp->last_mark_lbn  = this_mark_lbn;
2209	if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2210		STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2211	if (STp->filemark_cnt++ == 0)
2212		STp->first_mark_ppos = this_mark_ppos;
2213	return result;
2214}
2215
2216static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2217{
2218	int	result;
2219#if DEBUG
2220	char  * name = tape_name(STp);
2221#endif
2222
2223	if (STp->raw) return 0;
2224
2225	STp->write_type = OS_WRITE_EOD;
2226	STp->eod_frame_ppos = STp->first_frame_position;
2227#if DEBUG
2228	printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2229			STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2230#endif
2231	STp->dirty = 1;
2232
2233	result  = osst_flush_write_buffer(STp, aSRpnt);	
2234	result |= osst_flush_drive_buffer(STp, aSRpnt);
2235	STp->eod_frame_lfa = --(STp->frame_seq_number);
2236	return result;
2237}
2238
2239static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2240{
2241	char * name = tape_name(STp);
2242
2243#if DEBUG
2244	printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2245#endif
2246	osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2247	osst_set_frame_position(STp, aSRpnt, where, 0);
2248	STp->write_type = OS_WRITE_FILLER;
2249	while (count--) {
2250		memcpy(STp->buffer->b_data, "Filler", 6);
2251		STp->buffer->buffer_bytes = 6;
2252		STp->dirty = 1;
2253		if (osst_flush_write_buffer(STp, aSRpnt)) {
2254			printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2255			return (-EIO);
2256		}
2257	}
2258#if DEBUG
2259	printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2260#endif
2261	return osst_flush_drive_buffer(STp, aSRpnt);
2262}
2263
2264static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2265{
2266	char * name = tape_name(STp);
2267	int     result;
2268
2269#if DEBUG
2270	printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2271#endif
2272	osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2273	osst_set_frame_position(STp, aSRpnt, where, 0);
2274	STp->write_type = OS_WRITE_HEADER;
2275	while (count--) {
2276		osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2277		STp->buffer->buffer_bytes = sizeof(os_header_t);
2278		STp->dirty = 1;
2279		if (osst_flush_write_buffer(STp, aSRpnt)) {
2280			printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2281			return (-EIO);
2282		}
2283	}
2284	result = osst_flush_drive_buffer(STp, aSRpnt);
2285#if DEBUG
2286	printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2287#endif
2288	return result;
2289}
2290
2291static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2292{
2293	os_header_t * header;
2294	int	      result;
2295	char        * name = tape_name(STp);
2296
2297#if DEBUG
2298	printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2299#endif
2300	if (STp->raw) return 0;
2301
2302	if (STp->header_cache == NULL) {
2303		if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2304			printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2305			return (-ENOMEM);
2306		}
2307		memset(STp->header_cache, 0, sizeof(os_header_t));
2308#if DEBUG
2309		printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2310#endif
2311	}
2312	if (STp->header_ok) STp->update_frame_cntr++;
2313	else                STp->update_frame_cntr = 0;
2314
2315	header = STp->header_cache;
2316	strcpy(header->ident_str, "ADR_SEQ");
2317	header->major_rev      = 1;
2318	header->minor_rev      = 4;
2319	header->ext_trk_tb_off = htons(17192);
2320	header->pt_par_num     = 1;
2321	header->partition[0].partition_num              = OS_DATA_PARTITION;
2322	header->partition[0].par_desc_ver               = OS_PARTITION_VERSION;
2323	header->partition[0].wrt_pass_cntr              = htons(STp->wrt_pass_cntr);
2324	header->partition[0].first_frame_ppos           = htonl(STp->first_data_ppos);
2325	header->partition[0].last_frame_ppos            = htonl(STp->capacity);
2326	header->partition[0].eod_frame_ppos             = htonl(STp->eod_frame_ppos);
2327	header->cfg_col_width                           = htonl(20);
2328	header->dat_col_width                           = htonl(1500);
2329	header->qfa_col_width                           = htonl(0);
2330	header->ext_track_tb.nr_stream_part             = 1;
2331	header->ext_track_tb.et_ent_sz                  = 32;
2332	header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2333	header->ext_track_tb.dat_ext_trk_ey.fmt         = 1;
2334	header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  = htons(17736);
2335	header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2336	header->ext_track_tb.dat_ext_trk_ey.last_hlb    = htonl(STp->eod_frame_lfa);
2337	header->ext_track_tb.dat_ext_trk_ey.last_pp	= htonl(STp->eod_frame_ppos);
2338	header->dat_fm_tab.fm_part_num                  = 0;
2339	header->dat_fm_tab.fm_tab_ent_sz                = 4;
2340	header->dat_fm_tab.fm_tab_ent_cnt               = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2341								STp->filemark_cnt:OS_FM_TAB_MAX);
2342
2343	result  = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2344	if (STp->update_frame_cntr == 0)
2345		    osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2346	result &= __osst_write_header(STp, aSRpnt,     5, 5);
2347
2348	if (locate_eod) {
2349#if DEBUG
2350		printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2351#endif
2352		osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2353	}
2354	if (result)
2355		printk(KERN_ERR "%s:E: Write header failed\n", name);
2356	else {
2357		memcpy(STp->application_sig, "LIN4", 4);
2358		STp->linux_media         = 1;
2359		STp->linux_media_version = 4;
2360		STp->header_ok           = 1;
2361	}
2362	return result;
2363}
2364
2365static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2366{
2367	if (STp->header_cache != NULL)
2368		memset(STp->header_cache, 0, sizeof(os_header_t));
2369
2370	STp->logical_blk_num = STp->frame_seq_number = 0;
2371	STp->frame_in_buffer = 0;
2372	STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2373	STp->filemark_cnt = 0;
2374	STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2375	return osst_write_header(STp, aSRpnt, 1);
2376}
2377
2378static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2379{
2380	char        * name = tape_name(STp);
2381	os_header_t * header;
2382	os_aux_t    * aux;
2383	char          id_string[8];
2384	int	      linux_media_version,
2385		      update_frame_cntr;
2386
2387	if (STp->raw)
2388		return 1;
2389
2390	if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2391		if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2392			printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2393		osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2394		if (osst_initiate_read (STp, aSRpnt)) {
2395			printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2396			return 0;
2397		}
2398	}
2399	if (osst_read_frame(STp, aSRpnt, 180)) {
2400#if DEBUG
2401		printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2402#endif
2403		return 0;
2404	}
2405	header = (os_header_t *) STp->buffer->b_data;	/* warning: only first segment addressable */
2406	aux = STp->buffer->aux;
2407	if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2408#if DEBUG
2409		printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2410#endif
2411		return 0;
2412	}
2413	if (ntohl(aux->frame_seq_num)              != 0                   ||
2414	    ntohl(aux->logical_blk_num)            != 0                   ||
2415	          aux->partition.partition_num     != OS_CONFIG_PARTITION ||
2416	    ntohl(aux->partition.first_frame_ppos) != 0                   ||
2417	    ntohl(aux->partition.last_frame_ppos)  != 0xbb7               ) {
2418#if DEBUG
2419		printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2420				ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2421			       	aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2422			       	ntohl(aux->partition.last_frame_ppos));
2423#endif
2424		return 0;
2425	}
2426	if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2427	    strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2428		strlcpy(id_string, header->ident_str, 8);
2429#if DEBUG
2430		printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2431#endif
2432		return 0;
2433	}
2434	update_frame_cntr = ntohl(aux->update_frame_cntr);
2435	if (update_frame_cntr < STp->update_frame_cntr) {
2436#if DEBUG
2437		printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2438				   name, ppos, update_frame_cntr, STp->update_frame_cntr);
2439#endif
2440		return 0;
2441	}
2442	if (header->major_rev != 1 || header->minor_rev != 4 ) {
2443#if DEBUG
2444		printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n", 
2445				 name, (header->major_rev != 1 || header->minor_rev < 2 || 
2446				       header->minor_rev  > 4 )? "Invalid" : "Warning:",
2447				 header->major_rev, header->minor_rev);
2448#endif
2449		if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2450			return 0;
2451	}
2452#if DEBUG
2453	if (header->pt_par_num != 1)
2454		printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n", 
2455				 name, header->pt_par_num);
2456#endif
2457	memcpy(id_string, aux->application_sig, 4);
2458	id_string[4] = 0;
2459	if (memcmp(id_string, "LIN", 3) == 0) {
2460		STp->linux_media = 1;
2461		linux_media_version = id_string[3] - '0';
2462		if (linux_media_version != 4)
2463			printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2464					 name, linux_media_version);
2465	} else {
2466		printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2467		return 0;
2468	}
2469	if (linux_media_version < STp->linux_media_version) {
2470#if DEBUG
2471		printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2472				  name, ppos, linux_media_version);
2473#endif
2474		return 0;
2475	}
2476	if (linux_media_version > STp->linux_media_version) {
2477#if DEBUG
2478		printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2479				   name, ppos, linux_media_version);
2480#endif
2481		memcpy(STp->application_sig, id_string, 5);
2482		STp->linux_media_version = linux_media_version;
2483		STp->update_frame_cntr = -1;
2484	}
2485	if (update_frame_cntr > STp->update_frame_cntr) {
2486#if DEBUG
2487		printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2488				   name, ppos, update_frame_cntr);
2489#endif
2490		if (STp->header_cache == NULL) {
2491			if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2492				printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2493				return 0;
2494			}
2495#if DEBUG
2496			printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2497#endif
2498		}
2499		osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2500		header = STp->header_cache;	/* further accesses from cached (full) copy */
2501
2502		STp->wrt_pass_cntr     = ntohs(header->partition[0].wrt_pass_cntr);
2503		STp->first_data_ppos   = ntohl(header->partition[0].first_frame_ppos);
2504		STp->eod_frame_ppos    = ntohl(header->partition[0].eod_frame_ppos);
2505		STp->eod_frame_lfa     = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2506		STp->filemark_cnt      = ntohl(aux->filemark_cnt);
2507		STp->first_mark_ppos   = ntohl(aux->next_mark_ppos);
2508		STp->last_mark_ppos    = ntohl(aux->last_mark_ppos);
2509		STp->last_mark_lbn     = ntohl(aux->last_mark_lbn);
2510		STp->update_frame_cntr = update_frame_cntr;
2511#if DEBUG
2512	printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2513			  name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2514	printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2515			  STp->first_data_ppos,
2516			  ntohl(header->partition[0].last_frame_ppos),
2517			  ntohl(header->partition[0].eod_frame_ppos));
2518	printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n", 
2519			  name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2520#endif
2521		if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2522#if DEBUG
2523			printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2524#endif
2525			memcpy((void *)header->dat_fm_tab.fm_tab_ent, 
2526			       (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2527			memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2528		}
2529		if (header->minor_rev == 4   &&
2530		    (header->ext_trk_tb_off                          != htons(17192)               ||
2531		     header->partition[0].partition_num              != OS_DATA_PARTITION          ||
2532		     header->partition[0].par_desc_ver               != OS_PARTITION_VERSION       ||
2533		     header->partition[0].last_frame_ppos            != htonl(STp->capacity)       ||
2534		     header->cfg_col_width                           != htonl(20)                  ||
2535		     header->dat_col_width                           != htonl(1500)                ||
2536		     header->qfa_col_width                           != htonl(0)                   ||
2537		     header->ext_track_tb.nr_stream_part             != 1                          ||
2538		     header->ext_track_tb.et_ent_sz                  != 32                         ||
2539		     header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION          ||
2540		     header->ext_track_tb.dat_ext_trk_ey.fmt         != 1                          ||
2541		     header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  != htons(17736)               ||
2542		     header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0                          ||
2543		     header->ext_track_tb.dat_ext_trk_ey.last_pp     != htonl(STp->eod_frame_ppos) ||
2544		     header->dat_fm_tab.fm_part_num                  != OS_DATA_PARTITION          ||
2545		     header->dat_fm_tab.fm_tab_ent_sz                != 4                          ||
2546		     header->dat_fm_tab.fm_tab_ent_cnt               !=
2547			     htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2548			printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2549
2550	}
2551
2552	return 1;
2553}
2554
2555static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2556{
2557	int	position, ppos;
2558	int	first, last;
2559	int	valid = 0;
2560	char  * name  = tape_name(STp);
2561
2562	position = osst_get_frame_position(STp, aSRpnt);
2563
2564	if (STp->raw) {
2565		STp->header_ok = STp->linux_media = 1;
2566		STp->linux_media_version = 0;
2567		return 1;
2568	}
2569	STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2570	STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2571	STp->eod_frame_ppos = STp->first_data_ppos = -1;
2572	STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2573#if DEBUG
2574	printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2575#endif
2576
2577	/* optimization for speed - if we are positioned at ppos 10, read second group first  */	
2578	/* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2579
2580	first = position==10?0xbae: 5;
2581	last  = position==10?0xbb3:10;
2582
2583	for (ppos = first; ppos < last; ppos++)
2584		if (__osst_analyze_headers(STp, aSRpnt, ppos))
2585			valid = 1;
2586
2587	first = position==10? 5:0xbae;
2588	last  = position==10?10:0xbb3;
2589
2590	for (ppos = first; ppos < last; ppos++)
2591		if (__osst_analyze_headers(STp, aSRpnt, ppos))
2592			valid = 1;
2593
2594	if (!valid) {
2595		printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2596		STp->eod_frame_ppos = STp->first_data_ppos = 0;
2597		osst_set_frame_position(STp, aSRpnt, 10, 0);
2598		return 0;
2599	}
2600	if (position <= STp->first_data_ppos) {
2601		position = STp->first_data_ppos;
2602		STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2603	}
2604	osst_set_frame_position(STp, aSRpnt, position, 0);
2605	STp->header_ok = 1;
2606
2607	return 1;
2608}
2609
2610static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2611{
2612	int	frame_position  = STp->first_frame_position;
2613	int	frame_seq_numbr = STp->frame_seq_number;
2614	int	logical_blk_num = STp->logical_blk_num;
2615       	int	halfway_frame   = STp->frame_in_buffer;
2616	int	read_pointer    = STp->buffer->read_pointer;
2617	int	prev_mark_ppos  = -1;
2618	int	actual_mark_ppos, i, n;
2619#if DEBUG
2620	char  * name = tape_name(STp);
2621
2622	printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2623#endif
2624	osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2625	if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2626#if DEBUG
2627		printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2628#endif
2629		return (-EIO);
2630	}
2631	if (STp->linux_media_version >= 4) {
2632		for (i=0; i<STp->filemark_cnt; i++)
2633			if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2634				prev_mark_ppos = n;
2635	} else
2636		prev_mark_ppos = frame_position - 1;  /* usually - we don't really know */
2637	actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2638				frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2639	if (frame_position  != STp->first_frame_position                   ||
2640	    frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2641	    prev_mark_ppos  != actual_mark_ppos                            ) {
2642#if DEBUG
2643		printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2644				  STp->first_frame_position, frame_position, 
2645				  STp->frame_seq_number + (halfway_frame?0:1),
2646				  frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2647#endif
2648		return (-EIO);
2649	}
2650	if (halfway_frame) {
2651		/* prepare buffer for append and rewrite on top of original */
2652		osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2653		STp->buffer->buffer_bytes  = read_pointer;
2654		STp->ps[STp->partition].rw = ST_WRITING;
2655		STp->dirty                 = 1;
2656	}
2657	STp->frame_in_buffer  = halfway_frame;
2658	STp->frame_seq_number = frame_seq_numbr;
2659	STp->logical_blk_num  = logical_blk_num;
2660	return 0;
2661}
2662
2663/* Acc. to OnStream, the vers. numbering is the following:
2664 * X.XX for released versions (X=digit), 
2665 * XXXY for unreleased versions (Y=letter)
2666 * Ordering 1.05 < 106A < 106B < ...  < 106a < ... < 1.06
2667 * This fn makes monoton numbers out of this scheme ...
2668 */
2669static unsigned int osst_parse_firmware_rev (const char * str)
2670{
2671	if (str[1] == '.') {
2672		return (str[0]-'0')*10000
2673			+(str[2]-'0')*1000
2674			+(str[3]-'0')*100;
2675	} else {
2676		return (str[0]-'0')*10000
2677			+(str[1]-'0')*1000
2678			+(str[2]-'0')*100 - 100
2679			+(str[3]-'@');
2680	}
2681}
2682
2683/*
2684 * Configure the OnStream SCII tape drive for default operation
2685 */
2686static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2687{
2688	unsigned char                  cmd[MAX_COMMAND_SIZE];
2689	char                         * name = tape_name(STp);
2690	struct osst_request          * SRpnt = * aSRpnt;
2691	osst_mode_parameter_header_t * header;
2692	osst_block_size_page_t       * bs;
2693	osst_capabilities_page_t     * cp;
2694	osst_tape_paramtr_page_t     * prm;
2695	int                            drive_buffer_size;
2696
2697	if (STp->ready != ST_READY) {
2698#if DEBUG
2699	    printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2700#endif
2701	    return (-EIO);
2702	}
2703	
2704	if (STp->os_fw_rev < 10600) {
2705	    printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2706	    printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2707	}
2708
2709	/*
2710	 * Configure 32.5KB (data+aux) frame size.
2711         * Get the current frame size from the block size mode page
2712	 */
2713	memset(cmd, 0, MAX_COMMAND_SIZE);
2714	cmd[0] = MODE_SENSE;
2715	cmd[1] = 8;
2716	cmd[2] = BLOCK_SIZE_PAGE;
2717	cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2718
2719	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2720	if (SRpnt == NULL) {
2721#if DEBUG
2722 	    printk(OSST_DEB_MSG "osst :D: Busy\n");
2723#endif
2724	    return (-EBUSY);
2725	}
2726	*aSRpnt = SRpnt;
2727	if ((STp->buffer)->syscall_result != 0) {
2728	    printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2729	    return (-EIO);
2730	}
2731
2732	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2733	bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2734
2735#if DEBUG
2736	printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n",   name, bs->play32     ? "Yes" : "No");
2737	printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5   ? "Yes" : "No");
2738	printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n",      name, bs->record32   ? "Yes" : "No");
2739	printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n",    name, bs->record32_5 ? "Yes" : "No");
2740#endif
2741
2742	/*
2743	 * Configure default auto columns mode, 32.5KB transfer mode
2744	 */ 
2745	bs->one = 1;
2746	bs->play32 = 0;
2747	bs->play32_5 = 1;
2748	bs->record32 = 0;
2749	bs->record32_5 = 1;
2750
2751	memset(cmd, 0, MAX_COMMAND_SIZE);
2752	cmd[0] = MODE_SELECT;
2753	cmd[1] = 0x10;
2754	cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2755
2756	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2757	*aSRpnt = SRpnt;
2758	if ((STp->buffer)->syscall_result != 0) {
2759	    printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2760	    return (-EIO);
2761	}
2762
2763#if DEBUG
2764	printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2765	 /*
2766	 * In debug mode, we want to see as many errors as possible
2767	 * to test the error recovery mechanism.
2768	 */
2769	osst_set_retries(STp, aSRpnt, 0);
2770	SRpnt = * aSRpnt;
2771#endif
2772
2773	/*
2774	 * Set vendor name to 'LIN4' for "Linux support version 4".
2775	 */
2776
2777	memset(cmd, 0, MAX_COMMAND_SIZE);
2778	cmd[0] = MODE_SELECT;
2779	cmd[1] = 0x10;
2780	cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2781
2782	header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2783	header->medium_type      = 0;	/* Medium Type - ignoring */
2784	header->dsp              = 0;	/* Reserved */
2785	header->bdl              = 0;	/* Block Descriptor Length */
2786	
2787	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2788	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2789	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2790	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2791	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2792	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2793	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2794	(STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2795
2796	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2797	*aSRpnt = SRpnt;
2798
2799	if ((STp->buffer)->syscall_result != 0) {
2800	    printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name, 
2801			(char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2802	    return (-EIO);
2803	}
2804
2805	memset(cmd, 0, MAX_COMMAND_SIZE);
2806	cmd[0] = MODE_SENSE;
2807	cmd[1] = 8;
2808	cmd[2] = CAPABILITIES_PAGE;
2809	cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2810
2811	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2812	*aSRpnt = SRpnt;
2813
2814	if ((STp->buffer)->syscall_result != 0) {
2815	    printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2816	    return (-EIO);
2817	}
2818
2819	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2820	cp     = (osst_capabilities_page_t    *) ((STp->buffer)->b_data +
2821		 sizeof(osst_mode_parameter_header_t) + header->bdl);
2822
2823	drive_buffer_size = ntohs(cp->buffer_size) / 2;
2824
2825	memset(cmd, 0, MAX_COMMAND_SIZE);
2826	cmd[0] = MODE_SENSE;
2827	cmd[1] = 8;
2828	cmd[2] = TAPE_PARAMTR_PAGE;
2829	cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2830
2831	SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2832	*aSRpnt = SRpnt;
2833
2834	if ((STp->buffer)->syscall_result != 0) {
2835	    printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2836	    return (-EIO);
2837	}
2838
2839	header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2840	prm    = (osst_tape_paramtr_page_t    *) ((STp->buffer)->b_data +
2841		 sizeof(osst_mode_parameter_header_t) + header->bdl);
2842
2843	STp->density  = prm->density;
2844	STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2845#if DEBUG
2846	printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2847			  name, STp->density, STp->capacity / 32, drive_buffer_size);
2848#endif
2849
2850	return 0;
2851	
2852}
2853
2854
2855/* Step over EOF if it has been inadvertently crossed (ioctl not used because
2856   it messes up the block number). */
2857static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2858{
2859	int	result;
2860	char  * name = tape_name(STp);
2861
2862#if DEBUG
2863	if (debugging)
2864		printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2865	   			  name, forward ? "forward" : "backward");
2866#endif
2867
2868	if (forward) {
2869	   /* assumes that the filemark is already read by the drive, so this is low cost */
2870	   result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2871	}
2872	else
2873	   /* assumes this is only called if we just read the filemark! */
2874	   result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2875
2876	if (result < 0)
2877	   printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2878				name, forward ? "forward" : "backward");
2879
2880	return result;
2881}
2882
2883
2884/* Get the tape position. */
2885
2886static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2887{
2888	unsigned char		scmd[MAX_COMMAND_SIZE];
2889	struct osst_request   * SRpnt;
2890	int			result = 0;
2891	char    	      * name   = tape_name(STp);
2892
2893	/* KG: We want to be able to use it for checking Write Buffer availability
2894	 *  and thus don't want to risk to overwrite anything. Exchange buffers ... */
2895	char		mybuf[24];
2896	char	      * olddata = STp->buffer->b_data;
2897	int		oldsize = STp->buffer->buffer_size;
2898
2899	if (STp->ready != ST_READY) return (-EIO);
2900
2901	memset (scmd, 0, MAX_COMMAND_SIZE);
2902	scmd[0] = READ_POSITION;
2903
2904	STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2905	SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2906				      STp->timeout, MAX_RETRIES, 1);
2907	if (!SRpnt) {
2908		STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2909		return (-EBUSY);
2910	}
2911	*aSRpnt = SRpnt;
2912
2913	if (STp->buffer->syscall_result)
2914		result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL;	/* 3: Write Error */
2915
2916	if (result == -EINVAL)
2917		printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2918	else {
2919		if (result == -EIO) {	/* re-read position - this needs to preserve media errors */
2920			unsigned char mysense[16];
2921			memcpy (mysense, SRpnt->sense, 16);
2922			memset (scmd, 0, MAX_COMMAND_SIZE);
2923			scmd[0] = READ_POSITION;
2924			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2925			SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2926						    STp->timeout, MAX_RETRIES, 1);
2927#if DEBUG
2928			printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2929					name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2930					SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2931#endif
2932			if (!STp->buffer->syscall_result)
2933				memcpy (SRpnt->sense, mysense, 16);
2934			else
2935				printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2936		}
2937		STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2938					  + ((STp->buffer)->b_data[5] << 16)
2939					  + ((STp->buffer)->b_data[6] << 8)
2940					  +  (STp->buffer)->b_data[7];
2941		STp->last_frame_position  = ((STp->buffer)->b_data[ 8] << 24)
2942					  + ((STp->buffer)->b_data[ 9] << 16)
2943					  + ((STp->buffer)->b_data[10] <<  8)
2944					  +  (STp->buffer)->b_data[11];
2945		STp->cur_frames           =  (STp->buffer)->b_data[15];
2946#if DEBUG
2947		if (debugging) {
2948			printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2949					    STp->first_frame_position, STp->last_frame_position,
2950					    ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2951					    ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2952					    STp->cur_frames);
2953		}
2954#endif
2955		if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2956#if DEBUG
2957			printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2958					STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2959#endif
2960			STp->first_frame_position = STp->last_frame_position;
2961		}
2962	}
2963	STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2964
2965	return (result == 0 ? STp->first_frame_position : result);
2966}
2967
2968
2969/* Set the tape block */
2970static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2971{
2972	unsigned char		scmd[MAX_COMMAND_SIZE];
2973	struct osst_request   * SRpnt;
2974	struct st_partstat    * STps;
2975	int			result = 0;
2976	int			pp     = (ppos == 3000 && !skip)? 0 : ppos;
2977	char		      * name   = tape_name(STp);
2978
2979	if (STp->ready != ST_READY) return (-EIO);
2980
2981	STps = &(STp->ps[STp->partition]);
2982
2983	if (ppos < 0 || ppos > STp->capacity) {
2984		printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2985		pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2986		result = (-EINVAL);
2987	}
2988
2989	do {
2990#if DEBUG
2991		if (debugging)
2992			printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2993#endif
2994		memset (scmd, 0, MAX_COMMAND_SIZE);
2995		scmd[0] = SEEK_10;
2996		scmd[1] = 1;
2997		scmd[3] = (pp >> 24);
2998		scmd[4] = (pp >> 16);
2999		scmd[5] = (pp >> 8);
3000		scmd[6] =  pp;
3001		if (skip)
3002			scmd[9] = 0x80;
3003
3004		SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
3005								MAX_RETRIES, 1);
3006		if (!SRpnt)
3007			return (-EBUSY);
3008		*aSRpnt  = SRpnt;
3009
3010		if ((STp->buffer)->syscall_result != 0) {
3011#if DEBUG
3012			printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
3013					name, STp->first_frame_position, pp);
3014#endif
3015			result = (-EIO);
3016		}
3017		if (pp != ppos)
3018			osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
3019	} while ((pp != ppos) && (pp = ppos));
3020	STp->first_frame_position = STp->last_frame_position = ppos;
3021	STps->eof = ST_NOEOF;
3022	STps->at_sm = 0;
3023	STps->rw = ST_IDLE;
3024	STp->frame_in_buffer = 0;
3025	return result;
3026}
3027
3028static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
3029{
3030	struct st_partstat * STps = &(STp->ps[STp->partition]);
3031	int result = 0;
3032
3033	if (STp->write_type != OS_WRITE_NEW_MARK) {
3034		/* true unless the user wrote the filemark for us */
3035		result = osst_flush_drive_buffer(STp, aSRpnt);
3036		if (result < 0) goto out;
3037		result = osst_write_filemark(STp, aSRpnt);
3038		if (result < 0) goto out;
3039
3040		if (STps->drv_file >= 0)
3041			STps->drv_file++ ;
3042		STps->drv_block = 0;
3043	}
3044	result = osst_write_eod(STp, aSRpnt);
3045	osst_write_header(STp, aSRpnt, leave_at_EOT);
3046
3047	STps->eof = ST_FM;
3048out:
3049	return result;
3050}
3051
3052/* osst versions of st functions - augmented and stripped to suit OnStream only */
3053
3054/* Flush the write buffer (never need to write if variable blocksize). */
3055static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
3056{
3057	int			offset, transfer, blks = 0;
3058	int			result = 0;
3059	unsigned char		cmd[MAX_COMMAND_SIZE];
3060	struct osst_request   * SRpnt = *aSRpnt;
3061	struct st_partstat    * STps;
3062	char		      * name = tape_name(STp);
3063
3064	if ((STp->buffer)->writing) {
3065		if (SRpnt == (STp->buffer)->last_SRpnt)
3066#if DEBUG
3067			{ printk(OSST_DEB_MSG
3068	 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
3069#endif
3070			*aSRpnt = SRpnt = NULL;
3071#if DEBUG
3072			} else if (SRpnt)
3073				printk(OSST_DEB_MSG
3074	 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
3075#endif	
3076		osst_write_behind_check(STp);
3077		if ((STp->buffer)->syscall_result) {
3078#if DEBUG
3079			if (debugging)
3080				printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3081				       name, (STp->buffer)->midlevel_result);
3082#endif
3083			if ((STp->buffer)->midlevel_result == INT_MAX)
3084				return (-ENOSPC);
3085			return (-EIO);
3086		}
3087	}
3088
3089	result = 0;
3090	if (STp->dirty == 1) {
3091
3092		STp->write_count++;
3093		STps     = &(STp->ps[STp->partition]);
3094		STps->rw = ST_WRITING;
3095		offset   = STp->buffer->buffer_bytes;
3096		blks     = (offset + STp->block_size - 1) / STp->block_size;
3097		transfer = OS_FRAME_SIZE;
3098		
3099		if (offset < OS_DATA_SIZE)
3100			osst_zero_buffer_tail(STp->buffer);
3101
3102		if (STp->poll)
3103			if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3104				result = osst_recover_wait_frame(STp, aSRpnt, 1);
3105
3106		memset(cmd, 0, MAX_COMMAND_SIZE);
3107		cmd[0] = WRITE_6;
3108		cmd[1] = 1;
3109		cmd[4] = 1;
3110
3111		switch	(STp->write_type) {
3112		   case OS_WRITE_DATA:
3113#if DEBUG
3114   			if (debugging)
3115				printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3116					name, blks, STp->frame_seq_number, 
3117					STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3118#endif
3119			osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3120				      STp->logical_blk_num - blks, STp->block_size, blks);
3121			break;
3122		   case OS_WRITE_EOD:
3123			osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3124				      STp->logical_blk_num, 0, 0);
3125			break;
3126		   case OS_WRITE_NEW_MARK:
3127			osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3128				      STp->logical_blk_num++, 0, blks=1);
3129			break;
3130		   case OS_WRITE_HEADER:
3131			osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3132			break;
3133		default: /* probably FILLER */
3134			osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3135		}
3136#if DEBUG
3137		if (debugging)
3138			printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3139			  			 name, offset, transfer, blks);
3140#endif
3141
3142		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3143					      STp->timeout, MAX_RETRIES, 1);
3144		*aSRpnt = SRpnt;
3145		if (!SRpnt)
3146			return (-EBUSY);
3147
3148		if ((STp->buffer)->syscall_result != 0) {
3149#if DEBUG
3150			printk(OSST_DEB_MSG
3151				"%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3152				name, SRpnt->sense[0], SRpnt->sense[2],
3153				SRpnt->sense[12], SRpnt->sense[13]);
3154#endif
3155			if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3156			    (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3157			    (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3158				STp->dirty = 0;
3159				(STp->buffer)->buffer_bytes = 0;
3160				result = (-ENOSPC);
3161			}
3162			else {
3163				if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3164					printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3165					result = (-EIO);
3166				}
3167			}
3168			STps->drv_block = (-1);		/* FIXME - even if write recovery succeeds? */
3169		}
3170		else {
3171			STp->first_frame_position++;
3172			STp->dirty = 0;
3173			(STp->buffer)->buffer_bytes = 0;
3174		}
3175	}
3176#if DEBUG
3177	printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3178#endif
3179	return result;
3180}
3181
3182
3183/* Flush the tape buffer. The tape will be positioned correctly unless
3184   seek_next is true. */
3185static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3186{
3187	struct st_partstat * STps;
3188	int    backspace = 0, result = 0;
3189#if DEBUG
3190	char * name = tape_name(STp);
3191#endif
3192
3193	/*
3194	 * If there was a bus reset, block further access
3195	 * to this device.
3196	 */
3197	if( STp->pos_unknown)
3198		return (-EIO);
3199
3200	if (STp->ready != ST_READY)
3201		return 0;
3202
3203	STps = &(STp->ps[STp->partition]);
3204	if (STps->rw == ST_WRITING || STp->dirty) {	/* Writing */
3205		STp->write_type = OS_WRITE_DATA;
3206		return osst_flush_write_buffer(STp, aSRpnt);
3207	}
3208	if (STp->block_size == 0)
3209		return 0;
3210
3211#if DEBUG
3212	printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3213#endif
3214
3215	if (!STp->can_bsr) {
3216		backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3217			    ((STp->buffer)->read_pointer + STp->block_size - 1        ) / STp->block_size ;
3218		(STp->buffer)->buffer_bytes = 0;
3219		(STp->buffer)->read_pointer = 0;
3220		STp->frame_in_buffer = 0;		/* FIXME is this relevant w. OSST? */
3221	}
3222
3223	if (!seek_next) {
3224		if (STps->eof == ST_FM_HIT) {
3225			result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3226			if (!result)
3227				STps->eof = ST_NOEOF;
3228			else {
3229				if (STps->drv_file >= 0)
3230					STps->drv_file++;
3231				STps->drv_block = 0;
3232			}
3233		}
3234		if (!result && backspace > 0)	/* TODO -- design and run a test case for this */
3235			result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3236	}
3237	else if (STps->eof == ST_FM_HIT) {
3238		if (STps->drv_file >= 0)
3239			STps->drv_file++;
3240		STps->drv_block = 0;
3241		STps->eof = ST_NOEOF;
3242	}
3243
3244	return result;
3245}
3246
3247static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3248{
3249	unsigned char		cmd[MAX_COMMAND_SIZE];
3250	struct osst_request   * SRpnt;
3251	int			blks;
3252#if DEBUG
3253	char		      * name = tape_name(STp);
3254#endif
3255
3256	if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3257#if DEBUG
3258		printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3259#endif
3260		if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3261			return (-EIO);
3262		}
3263		/* error recovery may have bumped us past the header partition */
3264		if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3265#if DEBUG
3266			printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3267#endif
3268		osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3269		}
3270	}
3271
3272	if (STp->poll)
3273		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3274			if (osst_recover_wait_frame(STp, aSRpnt, 1))
3275				return (-EIO);
3276
3277//	osst_build_stats(STp, &SRpnt);
3278
3279	STp->ps[STp->partition].rw = ST_WRITING;
3280	STp->write_type            = OS_WRITE_DATA;
3281			
3282	memset(cmd, 0, MAX_COMMAND_SIZE);
3283	cmd[0]   = WRITE_6;
3284	cmd[1]   = 1;
3285	cmd[4]   = 1;						/* one frame at a time... */
3286	blks     = STp->buffer->buffer_bytes / STp->block_size;
3287#if DEBUG
3288	if (debugging)
3289		printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks, 
3290			STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3291#endif
3292	osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3293		      STp->logical_blk_num - blks, STp->block_size, blks);
3294
3295#if DEBUG
3296	if (!synchronous)
3297		STp->write_pending = 1;
3298#endif
3299	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3300									MAX_RETRIES, synchronous);
3301	if (!SRpnt)
3302		return (-EBUSY);
3303	*aSRpnt = SRpnt;
3304
3305	if (synchronous) {
3306		if (STp->buffer->syscall_result != 0) {
3307#if DEBUG
3308			if (debugging)
3309				printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3310#endif
3311			if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3312			    (SRpnt->sense[2] & 0x40)) {
3313				if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3314					return (-ENOSPC);
3315			}
3316			else {
3317				if (osst_write_error_recovery(STp, aSRpnt, 1))
3318					return (-EIO);
3319			}
3320		}
3321		else
3322			STp->first_frame_position++;
3323	}
3324
3325	STp->write_count++;
3326
3327	return 0;
3328}
3329
3330/* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3331static int do_door_lock(struct osst_tape * STp, int do_lock)
3332{
3333	int retval;
3334
3335#if DEBUG
3336	printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3337#endif
3338
3339	retval = scsi_set_medium_removal(STp->device,
3340			do_lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
3341	if (!retval)
3342		STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3343	else
3344		STp->door_locked = ST_LOCK_FAILS;
3345	return retval;
3346}
3347
3348/* Set the internal state after reset */
3349static void reset_state(struct osst_tape *STp)
3350{
3351	int i;
3352	struct st_partstat *STps;
3353
3354	STp->pos_unknown = 0;
3355	for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3356		STps = &(STp->ps[i]);
3357		STps->rw = ST_IDLE;
3358		STps->eof = ST_NOEOF;
3359		STps->at_sm = 0;
3360		STps->last_block_valid = 0;
3361		STps->drv_block = -1;
3362		STps->drv_file = -1;
3363	}
3364}
3365				
3366
3367/* Entry points to osst */
3368
3369/* Write command */
3370static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3371{
3372	ssize_t		      total, retval = 0;
3373	ssize_t		      i, do_count, blks, transfer;
3374	int		      write_threshold;
3375	int		      doing_write = 0;
3376	const char   __user * b_point;
3377	struct osst_request * SRpnt = NULL;
3378	struct st_modedef   * STm;
3379	struct st_partstat  * STps;
3380	struct osst_tape    * STp  = filp->private_data;
3381	char		    * name = tape_name(STp);
3382
3383
3384	if (mutex_lock_interruptible(&STp->lock))
3385		return (-ERESTARTSYS);
3386
3387	/*
3388	 * If we are in the middle of error recovery, don't let anyone
3389	 * else try and use this device.  Also, if error recovery fails, it
3390	 * may try and take the device offline, in which case all further
3391	 * access to the device is prohibited.
3392	 */
3393	if( !scsi_block_when_processing_errors(STp->device) ) {
3394		retval = (-ENXIO);
3395		goto out;
3396	}
3397	
3398	if (STp->ready != ST_READY) {
3399		if (STp->ready == ST_NO_TAPE)
3400			retval = (-ENOMEDIUM);
3401		else
3402			retval = (-EIO);
3403		goto out;
3404	}
3405	STm = &(STp->modes[STp->current_mode]);
3406	if (!STm->defined) {
3407		retval = (-ENXIO);
3408		goto out;
3409	}
3410	if (count == 0)
3411		goto out;
3412
3413	/*
3414	 * If there was a bus reset, block further access
3415	 * to this device.
3416	 */
3417	if (STp->pos_unknown) {
3418		retval = (-EIO);
3419		goto out;
3420	}
3421
3422#if DEBUG
3423	if (!STp->in_use) {
3424		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3425		retval = (-EIO);
3426		goto out;
3427	}
3428#endif
3429
3430	if (STp->write_prot) {
3431		retval = (-EACCES);
3432		goto out;
3433	}
3434
3435	/* Write must be integral number of blocks */
3436	if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3437		printk(KERN_ERR "%s:E: Write (%zd bytes) not multiple of tape block size (%d%c).\n",
3438				       name, count, STp->block_size<1024?
3439				       STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3440		retval = (-EINVAL);
3441		goto out;
3442	}
3443
3444	if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3445		printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3446				       name, STp->first_frame_position);
3447		retval = (-ENOSPC);
3448		goto out;
3449	}
3450
3451	if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3452		STp->door_locked = ST_LOCKED_AUTO;
3453
3454	STps = &(STp->ps[STp->partition]);
3455
3456	if (STps->rw == ST_READING) {
3457#if DEBUG
3458		printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name, 
3459					STps->drv_file, STps->drv_block);
3460#endif
3461		retval = osst_flush_buffer(STp, &SRpnt, 0);
3462		if (retval)
3463			goto out;
3464		STps->rw = ST_IDLE;
3465	}
3466	if (STps->rw != ST_WRITING) {
3467		/* Are we totally rewriting this tape? */
3468		if (!STp->header_ok ||
3469		    (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3470		    (STps->drv_file == 0 && STps->drv_block == 0)) {
3471			STp->wrt_pass_cntr++;
3472#if DEBUG
3473			printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3474						  name, STp->wrt_pass_cntr);
3475#endif
3476			osst_reset_header(STp, &SRpnt);
3477			STps->drv_file = STps->drv_block = 0;
3478		}
3479		/* Do we know where we'll be writing on the tape? */
3480		else {
3481			if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3482			  		STps->drv_file < 0 || STps->drv_block < 0) {
3483				if (STp->first_frame_position == STp->eod_frame_ppos) {	/* at EOD */
3484			  		STps->drv_file = STp->filemark_cnt;
3485			  		STps->drv_block = 0;
3486				}
3487				else {
3488					/* We have no idea where the tape is positioned - give up */
3489#if DEBUG
3490					printk(OSST_DEB_MSG
3491						"%s:D: Cannot write at indeterminate position.\n", name);
3492#endif
3493					retval = (-EIO);
3494					goto out;
3495				}
3496      			}	  
3497			if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3498				STp->filemark_cnt = STps->drv_file;
3499				STp->last_mark_ppos =
3500				       	ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3501				printk(KERN_WARNING
3502					"%s:W: Overwriting file %d with old write pass counter %d\n",
3503						name, STps->drv_file, STp->wrt_pass_cntr);
3504				printk(KERN_WARNING
3505					"%s:W: may lead to stale data being accepted on reading back!\n",
3506						name);
3507#if DEBUG
3508				printk(OSST_DEB_MSG
3509				  "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3510					name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3511#endif
3512			}
3513		}
3514		STp->fast_open = 0;
3515	}
3516	if (!STp->header_ok) {
3517#if DEBUG
3518		printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3519#endif
3520		retval = (-EIO);
3521		goto out;
3522	}
3523
3524	if ((STp->buffer)->writing) {
3525if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3526		osst_write_behind_check(STp);
3527		if ((STp->buffer)->syscall_result) {
3528#if DEBUG
3529		if (debugging)
3530			printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3531						 (STp->buffer)->midlevel_result);
3532#endif
3533		if ((STp->buffer)->midlevel_result == INT_MAX)
3534			STps->eof = ST_EOM_OK;
3535		else
3536			STps->eof = ST_EOM_ERROR;
3537		}
3538	}
3539	if (STps->eof == ST_EOM_OK) {
3540		retval = (-ENOSPC);
3541		goto out;
3542	}
3543	else if (STps->eof == ST_EOM_ERROR) {
3544		retval = (-EIO);
3545		goto out;
3546	}
3547
3548	/* Check the buffer readability in cases where copy_user might catch
3549		 the problems after some tape movement. */
3550	if ((copy_from_user(&i, buf, 1) != 0 ||
3551	     copy_from_user(&i, buf + count - 1, 1) != 0)) {
3552		retval = (-EFAULT);
3553		goto out;
3554	}
3555
3556	if (!STm->do_buffer_writes) {
3557		write_threshold = 1;
3558	}
3559	else
3560		write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3561	if (!STm->do_async_writes)
3562		write_threshold--;
3563
3564	total = count;
3565#if DEBUG
3566	if (debugging)
3567		printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3568				name, (int) count, STps->drv_file, STps->drv_block,
3569				STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3570#endif
3571	b_point = buf;
3572	while ((STp->buffer)->buffer_bytes + count > write_threshold)
3573	{
3574		doing_write = 1;
3575		do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3576			   (STp->buffer)->buffer_bytes;
3577		if (do_count > count)
3578			do_count = count;
3579
3580		i = append_to_buffer(b_point, STp->buffer, do_count);
3581		if (i) {
3582			retval = i;
3583			goto out;
3584		}
3585
3586		blks = do_count / STp->block_size;
3587		STp->logical_blk_num += blks;  /* logical_blk_num is incremented as data is moved from user */
3588  
3589		i = osst_write_frame(STp, &SRpnt, 1);
3590
3591		if (i == (-ENOSPC)) {
3592			transfer = STp->buffer->writing;	/* FIXME -- check this logic */
3593			if (transfer <= do_count) {
3594				*ppos += do_count - transfer;
3595				count -= do_count - transfer;
3596				if (STps->drv_block >= 0) {
3597					STps->drv_block += (do_count - transfer) / STp->block_size;
3598				}
3599				STps->eof = ST_EOM_OK;
3600				retval = (-ENOSPC);		/* EOM within current request */
3601#if DEBUG
3602				if (debugging)
3603				      printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3604							     name, (int) transfer);
3605#endif
3606			}
3607			else {
3608				STps->eof = ST_EOM_ERROR;
3609				STps->drv_block = (-1);		/* Too cautious? */
3610				retval = (-EIO);		/* EOM for old data */
3611#if DEBUG
3612				if (debugging)
3613				      printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3614#endif
3615			}
3616		}
3617		else
3618			retval = i;
3619			
3620		if (retval < 0) {
3621			if (SRpnt != NULL) {
3622				osst_release_request(SRpnt);
3623				SRpnt = NULL;
3624			}
3625			STp->buffer->buffer_bytes = 0;
3626			STp->dirty = 0;
3627			if (count < total)
3628				retval = total - count;
3629			goto out;
3630		}
3631
3632		*ppos += do_count;
3633		b_point += do_count;
3634		count -= do_count;
3635		if (STps->drv_block >= 0) {
3636			STps->drv_block += blks;
3637		}
3638		STp->buffer->buffer_bytes = 0;
3639		STp->dirty = 0;
3640	}  /* end while write threshold exceeded */
3641
3642	if (count != 0) {
3643		STp->dirty = 1;
3644		i = append_to_buffer(b_point, STp->buffer, count);
3645		if (i) {
3646			retval = i;
3647			goto out;
3648		}
3649		blks = count / STp->block_size;
3650		STp->logical_blk_num += blks;
3651		if (STps->drv_block >= 0) {
3652			STps->drv_block += blks;
3653		}
3654		*ppos += count;
3655		count = 0;
3656	}
3657
3658	if (doing_write && (STp->buffer)->syscall_result != 0) {
3659		retval = (STp->buffer)->syscall_result;
3660		goto out;
3661	}
3662
3663	if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) { 
3664		/* Schedule an asynchronous write */
3665		(STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3666					   STp->block_size) * STp->block_size;
3667		STp->dirty = !((STp->buffer)->writing ==
3668				          (STp->buffer)->buffer_bytes);
3669
3670		i = osst_write_frame(STp, &SRpnt, 0);
3671		if (i < 0) {
3672			retval = (-EIO);
3673			goto out;
3674		}
3675		SRpnt = NULL;			/* Prevent releasing this request! */
3676	}
3677	STps->at_sm &= (total == 0);
3678	if (total > 0)
3679		STps->eof = ST_NOEOF;
3680
3681	retval = total;
3682
3683out:
3684	if (SRpnt != NULL) osst_release_request(SRpnt);
3685
3686	mutex_unlock(&STp->lock);
3687
3688	return retval;
3689}
3690
3691
3692/* Read command */
3693static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3694{
3695	ssize_t		      total, retval = 0;
3696	ssize_t		      i, transfer;
3697	int		      special;
3698	struct st_modedef   * STm;
3699	struct st_partstat  * STps;
3700	struct osst_request * SRpnt = NULL;
3701	struct osst_tape    * STp   = filp->private_data;
3702	char		    * name  = tape_name(STp);
3703
3704
3705	if (mutex_lock_interruptible(&STp->lock))
3706		return (-ERESTARTSYS);
3707
3708	/*
3709	 * If we are in the middle of error recovery, don't let anyone
3710	 * else try and use this device.  Also, if error recovery fails, it
3711	 * may try and take the device offline, in which case all further
3712	 * access to the device is prohibited.
3713	 */
3714	if( !scsi_block_when_processing_errors(STp->device) ) {
3715		retval = (-ENXIO);
3716		goto out;
3717	}
3718	
3719	if (STp->ready != ST_READY) {
3720		if (STp->ready == ST_NO_TAPE)
3721			retval = (-ENOMEDIUM);
3722		else
3723			retval = (-EIO);
3724		goto out;
3725	}
3726	STm = &(STp->modes[STp->current_mode]);
3727	if (!STm->defined) {
3728		retval = (-ENXIO);
3729		goto out;
3730	}
3731#if DEBUG
3732	if (!STp->in_use) {
3733		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3734		retval = (-EIO);
3735		goto out;
3736	}
3737#endif
3738	/* Must have initialized medium */
3739	if (!STp->header_ok) {
3740		retval = (-EIO);
3741		goto out;
3742	}
3743
3744	if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3745		STp->door_locked = ST_LOCKED_AUTO;
3746
3747	STps = &(STp->ps[STp->partition]);
3748	if (STps->rw == ST_WRITING) {
3749		retval = osst_flush_buffer(STp, &SRpnt, 0);
3750		if (retval)
3751			goto out;
3752		STps->rw = ST_IDLE;
3753		/* FIXME -- this may leave the tape without EOD and up2date headers */
3754	}
3755
3756	if ((count % STp->block_size) != 0) {
3757		printk(KERN_WARNING
3758		    "%s:W: Read (%zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3759		    STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3760	}
3761
3762#if DEBUG
3763	if (debugging && STps->eof != ST_NOEOF)
3764		printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3765				     STps->eof, (STp->buffer)->buffer_bytes);
3766#endif
3767	if ((STp->buffer)->buffer_bytes == 0 &&
3768	     STps->eof >= ST_EOD_1) {
3769		if (STps->eof < ST_EOD) {
3770			STps->eof += 1;
3771			retval = 0;
3772			goto out;
3773		}
3774		retval = (-EIO);  /* EOM or Blank Check */
3775		goto out;
3776	}
3777
3778	/* Check the buffer writability before any tape movement. Don't alter
3779		 buffer data. */
3780	if (copy_from_user(&i, buf, 1)             != 0 ||
3781	    copy_to_user  (buf, &i, 1)             != 0 ||
3782	    copy_from_user(&i, buf + count - 1, 1) != 0 ||
3783	    copy_to_user  (buf + count - 1, &i, 1) != 0) {
3784		retval = (-EFAULT);
3785		goto out;
3786	}
3787
3788	/* Loop until enough data in buffer or a special condition found */
3789	for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3790
3791		/* Get new data if the buffer is empty */
3792		if ((STp->buffer)->buffer_bytes == 0) {
3793			if (STps->eof == ST_FM_HIT)
3794				break;
3795			special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3796			if (special < 0) { 			/* No need to continue read */
3797				STp->frame_in_buffer = 0;
3798				retval = special;
3799				goto out;
3800			}
3801		}
3802
3803		/* Move the data from driver buffer to user buffer */
3804		if ((STp->buffer)->buffer_bytes > 0) {
3805#if DEBUG
3806			if (debugging && STps->eof != ST_NOEOF)
3807			    printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3808						 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3809#endif
3810		       	/* force multiple of block size, note block_size may have been adjusted */
3811			transfer = (((STp->buffer)->buffer_bytes < count - total ?
3812				     (STp->buffer)->buffer_bytes : count - total)/
3813					STp->block_size) * STp->block_size;
3814
3815			if (transfer == 0) {
3816				printk(KERN_WARNING
3817				  "%s:W: Nothing can be transferred, requested %zd, tape block size (%d%c).\n",
3818			   		name, count, STp->block_size < 1024?
3819					STp->block_size:STp->block_size/1024,
3820				       	STp->block_size<1024?'b':'k');
3821				break;
3822			}
3823			i = from_buffer(STp->buffer, buf, transfer);
3824			if (i)  {
3825				retval = i;
3826				goto out;
3827			}
3828			STp->logical_blk_num += transfer / STp->block_size;
3829			STps->drv_block      += transfer / STp->block_size;
3830			*ppos          += transfer;
3831			buf                  += transfer;
3832			total                += transfer;
3833		}
3834 
3835		if ((STp->buffer)->buffer_bytes == 0) {
3836#if DEBUG
3837			if (debugging)
3838				printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3839					       	name, STp->frame_seq_number);
3840#endif
3841			STp->frame_in_buffer = 0;
3842			STp->frame_seq_number++;              /* frame to look for next time */
3843		}
3844	} /* for (total = 0, special = 0; total < count && !special; ) */
3845
3846	/* Change the eof state if no data from tape or buffer */
3847	if (total == 0) {
3848		if (STps->eof == ST_FM_HIT) {
3849			STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3850			STps->drv_block = 0;
3851			if (STps->drv_file >= 0)
3852				STps->drv_file++;
3853		}
3854		else if (STps->eof == ST_EOD_1) {
3855			STps->eof = ST_EOD_2;
3856			if (STps->drv_block > 0 && STps->drv_file >= 0)
3857				STps->drv_file++;
3858			STps->drv_block = 0;
3859		}
3860		else if (STps->eof == ST_EOD_2)
3861			STps->eof = ST_EOD;
3862	}
3863	else if (STps->eof == ST_FM)
3864		STps->eof = ST_NOEOF;
3865
3866	retval = total;
3867
3868out:
3869	if (SRpnt != NULL) osst_release_request(SRpnt);
3870
3871	mutex_unlock(&STp->lock);
3872
3873	return retval;
3874}
3875
3876
3877/* Set the driver options */
3878static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3879{
3880  printk(KERN_INFO
3881"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3882	 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3883	 STm->do_read_ahead);
3884  printk(KERN_INFO
3885"%s:I:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3886	 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3887  printk(KERN_INFO
3888"%s:I:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3889	 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3890	 STp->scsi2_logical);
3891  printk(KERN_INFO
3892"%s:I:    sysv: %d\n", name, STm->sysv);
3893#if DEBUG
3894  printk(KERN_INFO
3895	 "%s:D:    debugging: %d\n",
3896	 name, debugging);
3897#endif
3898}
3899
3900
3901static int osst_set_options(struct osst_tape *STp, long options)
3902{
3903	int		    value;
3904	long		    code;
3905	struct st_modedef * STm;
3906	char		  * name = tape_name(STp);
3907
3908	STm = &(STp->modes[STp->current_mode]);
3909	if (!STm->defined) {
3910		memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3911		modes_defined = 1;
3912#if DEBUG
3913		if (debugging)
3914			printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3915					     name, STp->current_mode);
3916#endif
3917	}
3918
3919	code = options & MT_ST_OPTIONS;
3920	if (code == MT_ST_BOOLEANS) {
3921		STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3922		STm->do_async_writes  = (options & MT_ST_ASYNC_WRITES) != 0;
3923		STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3924		STm->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
3925		STp->two_fm	      = (options & MT_ST_TWO_FM) != 0;
3926		STp->fast_mteom	      = (options & MT_ST_FAST_MTEOM) != 0;
3927		STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
3928		STp->can_bsr          = (options & MT_ST_CAN_BSR) != 0;
3929		STp->omit_blklims     = (options & MT_ST_NO_BLKLIMS) != 0;
3930		if ((STp->device)->scsi_level >= SCSI_2)
3931			STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3932		STp->scsi2_logical    = (options & MT_ST_SCSI2LOGICAL) != 0;
3933		STm->sysv	      = (options & MT_ST_SYSV) != 0;
3934#if DEBUG
3935		debugging = (options & MT_ST_DEBUGGING) != 0;
3936#endif
3937		osst_log_options(STp, STm, name);
3938	}
3939	else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3940		value = (code == MT_ST_SETBOOLEANS);
3941		if ((options & MT_ST_BUFFER_WRITES) != 0)
3942			STm->do_buffer_writes = value;
3943		if ((options & MT_ST_ASYNC_WRITES) != 0)
3944			STm->do_async_writes = value;
3945		if ((options & MT_ST_DEF_WRITES) != 0)
3946			STm->defaults_for_writes = value;
3947		if ((options & MT_ST_READ_AHEAD) != 0)
3948			STm->do_read_ahead = value;
3949		if ((options & MT_ST_TWO_FM) != 0)
3950			STp->two_fm = value;
3951		if ((options & MT_ST_FAST_MTEOM) != 0)
3952			STp->fast_mteom = value;
3953		if ((options & MT_ST_AUTO_LOCK) != 0)
3954			STp->do_auto_lock = value;
3955		if ((options & MT_ST_CAN_BSR) != 0)
3956			STp->can_bsr = value;
3957		if ((options & MT_ST_NO_BLKLIMS) != 0)
3958			STp->omit_blklims = value;
3959		if ((STp->device)->scsi_level >= SCSI_2 &&
3960		    (options & MT_ST_CAN_PARTITIONS) != 0)
3961			STp->can_partitions = value;
3962		if ((options & MT_ST_SCSI2LOGICAL) != 0)
3963			STp->scsi2_logical = value;
3964		if ((options & MT_ST_SYSV) != 0)
3965			STm->sysv = value;
3966#if DEBUG
3967		if ((options & MT_ST_DEBUGGING) != 0)
3968			debugging = value;
3969#endif
3970		osst_log_options(STp, STm, name);
3971	}
3972	else if (code == MT_ST_WRITE_THRESHOLD) {
3973		value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3974		if (value < 1 || value > osst_buffer_size) {
3975			printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3976					     name, value);
3977			return (-EIO);
3978		}
3979		STp->write_threshold = value;
3980		printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3981				  name, value);
3982	}
3983	else if (code == MT_ST_DEF_BLKSIZE) {
3984		value = (options & ~MT_ST_OPTIONS);
3985		if (value == ~MT_ST_OPTIONS) {
3986			STm->default_blksize = (-1);
3987			printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3988		}
3989		else {
3990			if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3991				printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3992							 name, value);
3993				return (-EINVAL);
3994			}
3995			STm->default_blksize = value;
3996			printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3997					  name, STm->default_blksize);
3998		}
3999	}
4000	else if (code == MT_ST_TIMEOUTS) {
4001		value = (options & ~MT_ST_OPTIONS);
4002		if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
4003			STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
4004			printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
4005					     (value & ~MT_ST_SET_LONG_TIMEOUT));
4006		}
4007		else {
4008			STp->timeout = value * HZ;
4009			printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
4010		}
4011	}
4012	else if (code == MT_ST_DEF_OPTIONS) {
4013		code = (options & ~MT_ST_CLEAR_DEFAULT);
4014		value = (options & MT_ST_CLEAR_DEFAULT);
4015		if (code == MT_ST_DEF_DENSITY) {
4016			if (value == MT_ST_CLEAR_DEFAULT) {
4017				STm->default_density = (-1);
4018				printk(KERN_INFO "%s:I: Density default disabled.\n", name);
4019			}
4020			else {
4021				STm->default_density = value & 0xff;
4022				printk(KERN_INFO "%s:I: Density default set to %x\n",
4023						  name, STm->default_density);
4024			}
4025		}
4026		else if (code == MT_ST_DEF_DRVBUFFER) {
4027			if (value == MT_ST_CLEAR_DEFAULT) {
4028				STp->default_drvbuffer = 0xff;
4029				printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
4030			}
4031			else {
4032				STp->default_drvbuffer = value & 7;
4033				printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
4034						  name, STp->default_drvbuffer);
4035			}
4036		}
4037		else if (code == MT_ST_DEF_COMPRESSION) {
4038			if (value == MT_ST_CLEAR_DEFAULT) {
4039				STm->default_compression = ST_DONT_TOUCH;
4040				printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
4041			}
4042			else {
4043				STm->default_compression = (value & 1 ? ST_YES : ST_NO);
4044				printk(KERN_INFO "%s:I: Compression default set to %x\n",
4045						  name, (value & 1));
4046			}
4047		}
4048	}
4049	else
4050		return (-EIO);
4051
4052	return 0;
4053}
4054
4055
4056/* Internal ioctl function */
4057static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
4058			     unsigned int cmd_in, unsigned long arg)
4059{
4060	int			timeout;
4061	long			ltmp;
4062	int			i, ioctl_result;
4063	int			chg_eof = 1;
4064	unsigned char		cmd[MAX_COMMAND_SIZE];
4065	struct osst_request   * SRpnt = * aSRpnt;
4066	struct st_partstat    * STps;
4067	int			fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
4068	int			datalen = 0, direction = DMA_NONE;
4069	char		      * name = tape_name(STp);
4070
4071	if (STp->ready != ST_READY && cmd_in != MTLOAD) {
4072		if (STp->ready == ST_NO_TAPE)
4073			return (-ENOMEDIUM);
4074		else
4075			return (-EIO);
4076	}
4077	timeout = STp->long_timeout;
4078	STps = &(STp->ps[STp->partition]);
4079	fileno = STps->drv_file;
4080	blkno = STps->drv_block;
4081	at_sm = STps->at_sm;
4082	frame_seq_numbr = STp->frame_seq_number;
4083	logical_blk_num = STp->logical_blk_num;
4084
4085	memset(cmd, 0, MAX_COMMAND_SIZE);
4086	switch (cmd_in) {
4087	 case MTFSFM:
4088		chg_eof = 0; /* Changed from the FSF after this */
4089	 case MTFSF:
4090		if (STp->raw)
4091		   return (-EIO);
4092		if (STp->linux_media)
4093		   ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4094		else
4095		   ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4096		if (fileno >= 0)
4097		   fileno += arg;
4098		blkno = 0;
4099		at_sm &= (arg == 0);
4100		goto os_bypass;
4101
4102	 case MTBSF:
4103		chg_eof = 0; /* Changed from the FSF after this */
4104	 case MTBSFM:
4105		if (STp->raw)
4106		   return (-EIO);
4107		ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4108		if (fileno >= 0)
4109		   fileno -= arg;
4110		blkno = (-1);  /* We can't know the block number */
4111		at_sm &= (arg == 0);
4112		goto os_bypass;
4113
4114	 case MTFSR:
4115	 case MTBSR:
4116#if DEBUG
4117		if (debugging)
4118		   printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4119				name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4120#endif
4121		if (cmd_in == MTFSR) {
4122		   logical_blk_num += arg;
4123		   if (blkno >= 0) blkno += arg;
4124		}
4125		else {
4126		   logical_blk_num -= arg;
4127		   if (blkno >= 0) blkno -= arg;
4128		}
4129		ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4130		fileno = STps->drv_file;
4131		blkno  = STps->drv_block;
4132		at_sm &= (arg == 0);
4133		goto os_bypass;
4134
4135	 case MTFSS:
4136		cmd[0] = SPACE;
4137		cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4138		cmd[2] = (arg >> 16);
4139		cmd[3] = (arg >> 8);
4140		cmd[4] = arg;
4141#if DEBUG
4142		if (debugging)
4143			printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4144		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4145#endif
4146		if (arg != 0) {
4147			blkno = fileno = (-1);
4148			at_sm = 1;
4149		}
4150		break;
4151	 case MTBSS:
4152		cmd[0] = SPACE;
4153		cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4154		ltmp = (-arg);
4155		cmd[2] = (ltmp >> 16);
4156		cmd[3] = (ltmp >> 8);
4157		cmd[4] = ltmp;
4158#if DEBUG
4159		if (debugging) {
4160			if (cmd[2] & 0x80)
4161			   ltmp = 0xff000000;
4162			ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4163			printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4164						name, (-ltmp));
4165		 }
4166#endif
4167		 if (arg != 0) {
4168			blkno = fileno = (-1);
4169			at_sm = 1;
4170		 }
4171		 break;
4172	 case MTWEOF:
4173		 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4174			STp->write_type = OS_WRITE_DATA;
4175			ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4176		 } else
4177			ioctl_result = 0;
4178#if DEBUG
4179		 if (debugging) 
4180			   printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4181#endif
4182		 for (i=0; i<arg; i++)
4183			ioctl_result |= osst_write_filemark(STp, &SRpnt);
4184		 if (fileno >= 0) fileno += arg;
4185		 if (blkno  >= 0) blkno   = 0;
4186		 goto os_bypass;
4187
4188	 case MTWSM:
4189		 if (STp->write_prot)
4190			return (-EACCES);
4191		 if (!STp->raw)
4192			return 0;
4193		 cmd[0] = WRITE_FILEMARKS;   /* FIXME -- need OS version */
4194		 if (cmd_in == MTWSM)
4195			 cmd[1] = 2;
4196		 cmd[2] = (arg >> 16);
4197		 cmd[3] = (arg >> 8);
4198		 cmd[4] = arg;
4199		 timeout = STp->timeout;
4200#if DEBUG
4201		 if (debugging) 
4202			   printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4203				  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4204#endif
4205		 if (fileno >= 0)
4206			fileno += arg;
4207		 blkno = 0;
4208		 at_sm = (cmd_in == MTWSM);
4209		 break;
4210	 case MTOFFL:
4211	 case MTLOAD:
4212	 case MTUNLOAD:
4213	 case MTRETEN:
4214		 cmd[0] = START_STOP;
4215		 cmd[1] = 1;			/* Don't wait for completion */
4216		 if (cmd_in == MTLOAD) {
4217		     if (STp->ready == ST_NO_TAPE)
4218			 cmd[4] = 4;		/* open tray */
4219		      else
4220			 cmd[4] = 1;		/* load */
4221		 }
4222		 if (cmd_in == MTRETEN)
4223			 cmd[4] = 3;		/* retension then mount */
4224		 if (cmd_in == MTOFFL)
4225			 cmd[4] = 4;		/* rewind then eject */
4226		 timeout = STp->timeout;
4227#if DEBUG
4228		 if (debugging) {
4229			 switch (cmd_in) {
4230				 case MTUNLOAD:
4231					 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4232					 break;
4233				 case MTLOAD:
4234					 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4235					 break;
4236				 case MTRETEN:
4237					 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4238					 break;
4239				 case MTOFFL:
4240					 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4241					 break;
4242			 }
4243		 }
4244#endif
4245       fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4246		 break;
4247	 case MTNOP:
4248#if DEBUG
4249		 if (debugging)
4250			 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4251#endif
4252		 return 0;  /* Should do something ? */
4253		 break;
4254	 case MTEOM:
4255#if DEBUG
4256		if (debugging)
4257		   printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4258#endif
4259		if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4260			    (osst_get_logical_frame(STp, &SRpnt, -1, 0)               < 0)) {
4261		   ioctl_result = -EIO;
4262		   goto os_bypass;
4263		}
4264		if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4265#if DEBUG
4266		   printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4267#endif
4268		   ioctl_result = -EIO;
4269		   goto os_bypass;
4270		}
4271		ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4272		fileno = STp->filemark_cnt;
4273		blkno  = at_sm = 0;
4274		goto os_bypass;
4275
4276	 case MTERASE:
4277		if (STp->write_prot)
4278		   return (-EACCES);
4279		ioctl_result = osst_reset_header(STp, &SRpnt);
4280		i = osst_write_eod(STp, &SRpnt);
4281		if (i < ioctl_result) ioctl_result = i;
4282		i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4283		if (i < ioctl_result) ioctl_result = i;
4284		fileno = blkno = at_sm = 0 ;
4285		goto os_bypass;
4286
4287	 case MTREW:
4288		cmd[0] = REZERO_UNIT; /* rewind */
4289		cmd[1] = 1;
4290#if DEBUG
4291		if (debugging)
4292		   printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4293#endif
4294		fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4295		break;
4296
4297	 case MTSETBLK:           /* Set block length */
4298		 if ((STps->drv_block == 0 )			  &&
4299		     !STp->dirty				  &&
4300		     ((STp->buffer)->buffer_bytes == 0)		  &&
4301		     ((arg & MT_ST_BLKSIZE_MASK) >= 512 )	  && 
4302		     ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4303		     !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))  ) {
4304			 /*
4305			  * Only allowed to change the block size if you opened the
4306			  * device at the beginning of a file before writing anything.
4307			  * Note, that when reading, changing block_size is futile,
4308			  * as the size used when writing overrides it.
4309			  */
4310			 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4311			 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4312					   name, STp->block_size);
4313			 return 0;
4314		 }
4315	 case MTSETDENSITY:       /* Set tape density */
4316	 case MTSETDRVBUFFER:     /* Set drive buffering */
4317	 case SET_DENS_AND_BLK:   /* Set density and block size */
4318		 chg_eof = 0;
4319		 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4320			 return (-EIO);       /* Not allowed if data in buffer */
4321		 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4322		     (arg & MT_ST_BLKSIZE_MASK) != 0                    &&
4323		     (arg & MT_ST_BLKSIZE_MASK) != STp->block_size       ) {
4324			 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4325						name, (int)(arg & MT_ST_BLKSIZE_MASK),
4326						(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4327			 return (-EINVAL);
4328		 }
4329		 return 0;  /* FIXME silently ignore if block size didn't change */
4330
4331	 default:
4332		return (-ENOSYS);
4333	}
4334
4335	SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4336
4337	ioctl_result = (STp->buffer)->syscall_result;
4338
4339	if (!SRpnt) {
4340#if DEBUG
4341		printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4342#endif
4343		return ioctl_result;
4344	}
4345
4346	if (!ioctl_result) {  /* SCSI command successful */
4347		STp->frame_seq_number = frame_seq_numbr;
4348		STp->logical_blk_num  = logical_blk_num;
4349	}
4350
4351os_bypass:
4352#if DEBUG
4353	if (debugging)
4354		printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4355#endif
4356
4357	if (!ioctl_result) {				/* success */
4358
4359		if (cmd_in == MTFSFM) {
4360			 fileno--;
4361			 blkno--;
4362		}
4363		if (cmd_in == MTBSFM) {
4364			 fileno++;
4365			 blkno++;
4366		}
4367		STps->drv_block = blkno;
4368		STps->drv_file = fileno;
4369		STps->at_sm = at_sm;
4370
4371		if (cmd_in == MTEOM)
4372			STps->eof = ST_EOD;
4373		else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4374			ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4375			STps->drv_block++;
4376			STp->logical_blk_num++;
4377			STp->frame_seq_number++;
4378			STp->frame_in_buffer = 0;
4379			STp->buffer->read_pointer = 0;
4380		}
4381		else if (cmd_in == MTFSF)
4382			STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4383		else if (chg_eof)
4384			STps->eof = ST_NOEOF;
4385
4386		if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4387			STp->rew_at_close = 0;
4388		else if (cmd_in == MTLOAD) {
4389			for (i=0; i < ST_NBR_PARTITIONS; i++) {
4390			    STp->ps[i].rw = ST_IDLE;
4391			    STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4392			}
4393			STp->partition = 0;
4394		}
4395
4396		if (cmd_in == MTREW) {
4397			ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos); 
4398			if (ioctl_result > 0)
4399				ioctl_result = 0;
4400		}
4401
4402	} else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4403		if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4404			STps->drv_file = STps->drv_block = -1;
4405		else
4406			STps->drv_file = STps->drv_block = 0;
4407		STps->eof = ST_NOEOF;
4408	} else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4409		if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4410			STps->drv_file = STps->drv_block = -1;
4411		else {
4412			STps->drv_file  = STp->filemark_cnt;
4413			STps->drv_block = 0;
4414		}
4415		STps->eof = ST_EOD;
4416	} else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4417		STps->drv_file = STps->drv_block = (-1);
4418		STps->eof = ST_NOEOF;
4419		STp->header_ok = 0;
4420	} else if (cmd_in == MTERASE) {
4421		STp->header_ok = 0;
4422	} else if (SRpnt) {  /* SCSI command was not completely successful. */
4423		if (SRpnt->sense[2] & 0x40) {
4424			STps->eof = ST_EOM_OK;
4425			STps->drv_block = 0;
4426		}
4427		if (chg_eof)
4428			STps->eof = ST_NOEOF;
4429
4430		if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4431			STps->eof = ST_EOD;
4432
4433		if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4434			ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4435	}
4436	*aSRpnt = SRpnt;
4437
4438	return ioctl_result;
4439}
4440
4441
4442/* Open the device */
4443static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4444{
4445	unsigned short	      flags;
4446	int		      i, b_size, new_session = 0, retval = 0;
4447	unsigned char	      cmd[MAX_COMMAND_SIZE];
4448	struct osst_request * SRpnt = NULL;
4449	struct osst_tape    * STp;
4450	struct st_modedef   * STm;
4451	struct st_partstat  * STps;
4452	char		    * name;
4453	int		      dev  = TAPE_NR(inode);
4454	int		      mode = TAPE_MODE(inode);
4455
4456	/*
4457	 * We really want to do nonseekable_open(inode, filp); here, but some
4458	 * versions of tar incorrectly call lseek on tapes and bail out if that
4459	 * fails.  So we disallow pread() and pwrite(), but permit lseeks.
4460	 */
4461	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4462
4463	write_lock(&os_scsi_tapes_lock);
4464	if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4465	    (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4466		write_unlock(&os_scsi_tapes_lock);
4467		return (-ENXIO);
4468	}
4469
4470	name = tape_name(STp);
4471
4472	if (STp->in_use) {
4473		write_unlock(&os_scsi_tapes_lock);
4474#if DEBUG
4475		printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4476#endif
4477		return (-EBUSY);
4478	}
4479	if (scsi_device_get(STp->device)) {
4480		write_unlock(&os_scsi_tapes_lock);
4481#if DEBUG
4482                printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4483#endif
4484		return (-ENXIO);
4485	}
4486	filp->private_data = STp;
4487	STp->in_use = 1;
4488	write_unlock(&os_scsi_tapes_lock);
4489	STp->rew_at_close = TAPE_REWIND(inode);
4490
4491	if( !scsi_block_when_processing_errors(STp->device) ) {
4492		return -ENXIO;
4493	}
4494
4495	if (mode != STp->current_mode) {
4496#if DEBUG
4497		if (debugging)
4498			printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4499					       name, STp->current_mode, mode);
4500#endif
4501		new_session = 1;
4502		STp->current_mode = mode;
4503	}
4504	STm = &(STp->modes[STp->current_mode]);
4505
4506	flags = filp->f_flags;
4507	STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4508
4509	STp->raw = TAPE_IS_RAW(inode);
4510	if (STp->raw)
4511		STp->header_ok = 0;
4512
4513	/* Allocate data segments for this device's tape buffer */
4514	if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4515		printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4516		retval = (-EOVERFLOW);
4517		goto err_out;
4518	}
4519	if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4520		for (i = 0, b_size = 0; 
4521		     (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE); 
4522		     b_size += STp->buffer->sg[i++].length);
4523		STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4524#if DEBUG
4525		printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4526			STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4527		printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4528			 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4529#endif
4530	} else {
4531		STp->buffer->aux = NULL; /* this had better never happen! */
4532		printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4533		retval = (-EIO);
4534		goto err_out;
4535	}
4536	STp->buffer->writing = 0;
4537	STp->buffer->syscall_result = 0;
4538	STp->dirty = 0;
4539	for (i=0; i < ST_NBR_PARTITIONS; i++) {
4540		STps = &(STp->ps[i]);
4541		STps->rw = ST_IDLE;
4542	}
4543	STp->ready = ST_READY;
4544#if DEBUG
4545	STp->nbr_waits = STp->nbr_finished = 0;
4546#endif
4547
4548	memset (cmd, 0, MAX_COMMAND_SIZE);
4549	cmd[0] = TEST_UNIT_READY;
4550
4551	SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4552	if (!SRpnt) {
4553		retval = (STp->buffer)->syscall_result;		/* FIXME - valid? */
4554		goto err_out;
4555	}
4556	if ((SRpnt->sense[0] & 0x70) == 0x70      &&
4557	    (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4558	     SRpnt->sense[12]        == 4         ) {
4559#if DEBUG
4560		printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4561#endif
4562		if (filp->f_flags & O_NONBLOCK) {
4563			retval = -EAGAIN;
4564			goto err_out;
4565		}
4566		if (SRpnt->sense[13] == 2) {	/* initialize command required (LOAD) */
4567			memset (cmd, 0, MAX_COMMAND_SIZE);
4568        		cmd[0] = START_STOP;
4569			cmd[1] = 1;
4570			cmd[4] = 1;
4571			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4572					     STp->timeout, MAX_RETRIES, 1);
4573		}
4574		osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4575	}
4576	if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4577	    (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4578#if DEBUG
4579		printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4580#endif
4581		STp->header_ok = 0;
4582
4583		for (i=0; i < 10; i++) {
4584
4585			memset (cmd, 0, MAX_COMMAND_SIZE);
4586			cmd[0] = TEST_UNIT_READY;
4587
4588			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4589					     STp->timeout, MAX_RETRIES, 1);
4590			if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4591			    (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4592				break;
4593		}
4594
4595		STp->pos_unknown = 0;
4596		STp->partition = STp->new_partition = 0;
4597		if (STp->can_partitions)
4598			STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4599		for (i=0; i < ST_NBR_PARTITIONS; i++) {
4600			STps = &(STp->ps[i]);
4601			STps->rw = ST_IDLE;		/* FIXME - seems to be redundant... */
4602			STps->eof = ST_NOEOF;
4603			STps->at_sm = 0;
4604			STps->last_block_valid = 0;
4605			STps->drv_block = 0;
4606			STps->drv_file = 0 ;
4607		}
4608		new_session = 1;
4609		STp->recover_count = 0;
4610		STp->abort_count = 0;
4611	}
4612	/*
4613	 * if we have valid headers from before, and the drive/tape seem untouched,
4614	 * open without reconfiguring and re-reading the headers
4615	 */
4616	if (!STp->buffer->syscall_result && STp->header_ok &&
4617	    !SRpnt->result && SRpnt->sense[0] == 0) {
4618
4619		memset(cmd, 0, MAX_COMMAND_SIZE);
4620		cmd[0] = MODE_SENSE;
4621		cmd[1] = 8;
4622		cmd[2] = VENDOR_IDENT_PAGE;
4623		cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4624
4625		SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4626
4627		if (STp->buffer->syscall_result                     ||
4628		    STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4629		    STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4630		    STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4631		    STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4'  ) {
4632#if DEBUG
4633			printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4634			  STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4635			  STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4636			  STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4637			  STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4638#endif
4639			STp->header_ok = 0;
4640		}
4641		i = STp->first_frame_position;
4642		if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4643			if (STp->door_locked == ST_UNLOCKED) {
4644				if (do_door_lock(STp, 1))
4645					printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4646				else
4647					STp->door_locked = ST_LOCKED_AUTO;
4648			}
4649			if (!STp->frame_in_buffer) {
4650				STp->block_size = (STm->default_blksize > 0) ?
4651							STm->default_blksize : OS_DATA_SIZE;
4652				STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4653			}
4654			STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4655			STp->fast_open = 1;
4656			osst_release_request(SRpnt);
4657			return 0;
4658		}
4659#if DEBUG
4660		if (i != STp->first_frame_position)
4661			printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4662						name, i, STp->first_frame_position);
4663#endif
4664		STp->header_ok = 0;
4665	}
4666	STp->fast_open = 0;
4667
4668	if ((STp->buffer)->syscall_result != 0 &&   /* in all error conditions except no medium */ 
4669	    (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4670
4671		memset(cmd, 0, MAX_COMMAND_SIZE);
4672		cmd[0] = MODE_SELECT;
4673		cmd[1] = 0x10;
4674		cmd[4] = 4 + MODE_HEADER_LENGTH;
4675
4676		(STp->buffer)->b_data[0] = cmd[4] - 1;
4677		(STp->buffer)->b_data[1] = 0;			/* Medium Type - ignoring */
4678		(STp->buffer)->b_data[2] = 0;			/* Reserved */
4679		(STp->buffer)->b_data[3] = 0;			/* Block Descriptor Length */
4680		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4681		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4682		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4683		(STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4684
4685#if DEBUG
4686		printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4687#endif
4688		SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4689
4690		STp->header_ok = 0;
4691
4692		for (i=0; i < 10; i++) {
4693
4694			memset (cmd, 0, MAX_COMMAND_SIZE);
4695			cmd[0] = TEST_UNIT_READY;
4696
4697			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4698						    STp->timeout, MAX_RETRIES, 1);
4699			if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4700			    (SRpnt->sense[2] & 0x0f) == NOT_READY)
4701			break;
4702
4703			if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4704				int j;
4705
4706				STp->pos_unknown = 0;
4707				STp->partition = STp->new_partition = 0;
4708				if (STp->can_partitions)
4709					STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4710				for (j = 0; j < ST_NBR_PARTITIONS; j++) {
4711					STps = &(STp->ps[j]);
4712					STps->rw = ST_IDLE;
4713					STps->eof = ST_NOEOF;
4714					STps->at_sm = 0;
4715					STps->last_block_valid = 0;
4716					STps->drv_block = 0;
4717					STps->drv_file = 0 ;
4718				}
4719				new_session = 1;
4720			}
4721		}
4722	}
4723
4724	if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))		/* FIXME - not allowed with NOBLOCK */
4725		 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4726
4727	if ((STp->buffer)->syscall_result != 0) {
4728		if ((STp->device)->scsi_level >= SCSI_2 &&
4729		    (SRpnt->sense[0] & 0x70) == 0x70 &&
4730		    (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4731		     SRpnt->sense[12] == 0x3a) { /* Check ASC */
4732			STp->ready = ST_NO_TAPE;
4733		} else
4734			STp->ready = ST_NOT_READY;
4735		osst_release_request(SRpnt);
4736		SRpnt = NULL;
4737		STp->density = 0;   	/* Clear the erroneous "residue" */
4738		STp->write_prot = 0;
4739		STp->block_size = 0;
4740		STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4741		STp->partition = STp->new_partition = 0;
4742		STp->door_locked = ST_UNLOCKED;
4743		return 0;
4744	}
4745
4746	osst_configure_onstream(STp, &SRpnt);
4747
4748	STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4749			     (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4750	STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4751	STp->buffer->buffer_bytes  =
4752	STp->buffer->read_pointer  =
4753	STp->frame_in_buffer       = 0;
4754
4755#if DEBUG
4756	if (debugging)
4757		printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4758		     name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4759		     (STp->buffer)->buffer_blocks);
4760#endif
4761
4762	if (STp->drv_write_prot) {
4763		STp->write_prot = 1;
4764#if DEBUG
4765		if (debugging)
4766			printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4767#endif
4768		if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4769			retval = (-EROFS);
4770			goto err_out;
4771		}
4772	}
4773
4774	if (new_session) {  /* Change the drive parameters for the new mode */
4775#if DEBUG
4776		if (debugging)
4777	printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4778#endif
4779		STp->density_changed = STp->blksize_changed = 0;
4780		STp->compression_changed = 0;
4781	}
4782
4783	/*
4784	 * properly position the tape and check the ADR headers
4785	 */
4786	if (STp->door_locked == ST_UNLOCKED) {
4787		 if (do_door_lock(STp, 1))
4788			printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4789		 else
4790			STp->door_locked = ST_LOCKED_AUTO;
4791	}
4792
4793	osst_analyze_headers(STp, &SRpnt);
4794
4795	osst_release_request(SRpnt);
4796	SRpnt = NULL;
4797
4798	return 0;
4799
4800err_out:
4801	if (SRpnt != NULL)
4802		osst_release_request(SRpnt);
4803	normalize_buffer(STp->buffer);
4804	STp->header_ok = 0;
4805	STp->in_use = 0;
4806	scsi_device_put(STp->device);
4807
4808	return retval;
4809}
4810
4811/* BKL pushdown: spaghetti avoidance wrapper */
4812static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4813{
4814	int ret;
4815
4816	mutex_lock(&osst_int_mutex);
4817	ret = __os_scsi_tape_open(inode, filp);
4818	mutex_unlock(&osst_int_mutex);
4819	return ret;
4820}
4821
4822
4823
4824/* Flush the tape buffer before close */
4825static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4826{
4827	int		      result = 0, result2;
4828	struct osst_tape    * STp    = filp->private_data;
4829	struct st_modedef   * STm    = &(STp->modes[STp->current_mode]);
4830	struct st_partstat  * STps   = &(STp->ps[STp->partition]);
4831	struct osst_request * SRpnt  = NULL;
4832	char		    * name   = tape_name(STp);
4833
4834	if (file_count(filp) > 1)
4835		return 0;
4836
4837	if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4838		STp->write_type = OS_WRITE_DATA;
4839		result = osst_flush_write_buffer(STp, &SRpnt);
4840		if (result != 0 && result != (-ENOSPC))
4841			goto out;
4842	}
4843	if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4844
4845#if DEBUG
4846		if (debugging) {
4847			printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4848					       name, (long)(filp->f_pos));
4849			printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4850					       name, STp->nbr_waits, STp->nbr_finished);
4851		}
4852#endif
4853		result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4854#if DEBUG
4855		if (debugging)
4856			printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4857					       name, 1+STp->two_fm);
4858#endif
4859	}
4860	else if (!STp->rew_at_close) {
4861		STps = &(STp->ps[STp->partition]);
4862		if (!STm->sysv || STps->rw != ST_READING) {
4863			if (STp->can_bsr)
4864				result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4865			else if (STps->eof == ST_FM_HIT) {
4866				result = cross_eof(STp, &SRpnt, 0);
4867					if (result) {
4868						if (STps->drv_file >= 0)
4869							STps->drv_file++;
4870						STps->drv_block = 0;
4871						STps->eof = ST_FM;
4872					}
4873					else
4874						STps->eof = ST_NOEOF;
4875			}
4876		}
4877		else if ((STps->eof == ST_NOEOF &&
4878			  !(result = cross_eof(STp, &SRpnt, 1))) ||
4879			 STps->eof == ST_FM_HIT) {
4880			if (STps->drv_file >= 0)
4881				STps->drv_file++;
4882			STps->drv_block = 0;
4883			STps->eof = ST_FM;
4884		}
4885	}
4886
4887out:
4888	if (STp->rew_at_close) {
4889		result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4890		STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4891		if (result == 0 && result2 < 0)
4892			result = result2;
4893	}
4894	if (SRpnt) osst_release_request(SRpnt);
4895
4896	if (STp->abort_count || STp->recover_count) {
4897		printk(KERN_INFO "%s:I:", name);
4898		if (STp->abort_count)
4899			printk(" %d unrecovered errors", STp->abort_count);
4900		if (STp->recover_count)
4901			printk(" %d recovered errors", STp->recover_count);
4902		if (STp->write_count)
4903			printk(" in %d frames written", STp->write_count);
4904		if (STp->read_count)
4905			printk(" in %d frames read", STp->read_count);
4906		printk("\n");
4907		STp->recover_count = 0;
4908		STp->abort_count   = 0;
4909	}
4910	STp->write_count = 0;
4911	STp->read_count  = 0;
4912
4913	return result;
4914}
4915
4916
4917/* Close the device and release it */
4918static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4919{
4920	int		      result = 0;
4921	struct osst_tape    * STp    = filp->private_data;
4922
4923	if (STp->door_locked == ST_LOCKED_AUTO)
4924		do_door_lock(STp, 0);
4925
4926	if (STp->raw)
4927		STp->header_ok = 0;
4928	
4929	normalize_buffer(STp->buffer);
4930	write_lock(&os_scsi_tapes_lock);
4931	STp->in_use = 0;
4932	write_unlock(&os_scsi_tapes_lock);
4933
4934	scsi_device_put(STp->device);
4935
4936	return result;
4937}
4938
4939
4940/* The ioctl command */
4941static long osst_ioctl(struct file * file,
4942	 unsigned int cmd_in, unsigned long arg)
4943{
4944	int		      i, cmd_nr, cmd_type, blk, retval = 0;
4945	struct st_modedef   * STm;
4946	struct st_partstat  * STps;
4947	struct osst_request * SRpnt = NULL;
4948	struct osst_tape    * STp   = file->private_data;
4949	char		    * name  = tape_name(STp);
4950	void	    __user  * p     = (void __user *)arg;
4951
4952	mutex_lock(&osst_int_mutex);
4953	if (mutex_lock_interruptible(&STp->lock)) {
4954		mutex_unlock(&osst_int_mutex);
4955		return -ERESTARTSYS;
4956	}
4957
4958#if DEBUG
4959	if (debugging && !STp->in_use) {
4960		printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4961		retval = (-EIO);
4962		goto out;
4963	}
4964#endif
4965	STm = &(STp->modes[STp->current_mode]);
4966	STps = &(STp->ps[STp->partition]);
4967
4968	/*
4969	 * If we are in the middle of error recovery, don't let anyone
4970	 * else try and use this device.  Also, if error recovery fails, it
4971	 * may try and take the device offline, in which case all further
4972	 * access to the device is prohibited.
4973	 */
4974	retval = scsi_ioctl_block_when_processing_errors(STp->device, cmd_in,
4975			file->f_flags & O_NDELAY);
4976	if (retval)
4977		goto out;
4978
4979	cmd_type = _IOC_TYPE(cmd_in);
4980	cmd_nr   = _IOC_NR(cmd_in);
4981#if DEBUG
4982	printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4983			    cmd_type, cmd_nr, STp->raw?"raw":"normal");
4984#endif
4985	if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4986		struct mtop mtc;
4987		int    auto_weof = 0;
4988
4989		if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4990			retval = (-EINVAL);
4991			goto out;
4992		}
4993
4994		i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4995		if (i) {
4996			retval = (-EFAULT);
4997			goto out;
4998		}
4999
5000		if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
5001			printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
5002			retval = (-EPERM);
5003			goto out;
5004		}
5005
5006		if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
5007			retval = (-ENXIO);
5008			goto out;
5009		}
5010
5011		if (!STp->pos_unknown) {
5012
5013			if (STps->eof == ST_FM_HIT) {
5014				if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
5015					mtc.mt_count -= 1;
5016					if (STps->drv_file >= 0)
5017						STps->drv_file += 1;
5018				}
5019				else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
5020					mtc.mt_count += 1;
5021					if (STps->drv_file >= 0)
5022						STps->drv_file += 1;
5023				}
5024			}
5025
5026			if (mtc.mt_op == MTSEEK) {
5027				/* Old position must be restored if partition will be changed */
5028				i = !STp->can_partitions || (STp->new_partition != STp->partition);
5029			}
5030			else {
5031				i = mtc.mt_op == MTREW   || mtc.mt_op == MTOFFL ||
5032				    mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM  ||
5033				    mtc.mt_op == MTLOCK  || mtc.mt_op == MTLOAD ||
5034				    mtc.mt_op == MTFSF   || mtc.mt_op == MTFSFM ||
5035				    mtc.mt_op == MTBSF   || mtc.mt_op == MTBSFM ||
5036				    mtc.mt_op == MTCOMPRESSION;
5037			}
5038			i = osst_flush_buffer(STp, &SRpnt, i);
5039			if (i < 0) {
5040				retval = i;
5041				goto out;
5042			}
5043		}
5044		else {
5045			/*
5046			 * If there was a bus reset, block further access
5047			 * to this device.  If the user wants to rewind the tape,
5048			 * then reset the flag and allow access again.
5049			 */
5050			if(mtc.mt_op != MTREW   &&
5051			   mtc.mt_op != MTOFFL  &&
5052			   mtc.mt_op != MTRETEN &&
5053			   mtc.mt_op != MTERASE &&
5054			   mtc.mt_op != MTSEEK  &&
5055			   mtc.mt_op != MTEOM)   {
5056				retval = (-EIO);
5057				goto out;
5058			}
5059			reset_state(STp);
5060			/* remove this when the midlevel properly clears was_reset */
5061			STp->device->was_reset = 0;
5062		}
5063
5064		if (mtc.mt_op != MTCOMPRESSION  && mtc.mt_op != MTLOCK         &&
5065		    mtc.mt_op != MTNOP          && mtc.mt_op != MTSETBLK       &&
5066		    mtc.mt_op != MTSETDENSITY   && mtc.mt_op != MTSETDRVBUFFER && 
5067		    mtc.mt_op != MTMKPART       && mtc.mt_op != MTSETPART      &&
5068		    mtc.mt_op != MTWEOF         && mtc.mt_op != MTWSM           ) {
5069
5070			/*
5071			 * The user tells us to move to another position on the tape.
5072			 * If we were appending to the tape content, that would leave
5073			 * the tape without proper end, in that case write EOD and
5074			 * update the header to reflect its position.
5075			 */
5076#if DEBUG
5077			printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
5078					STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
5079					STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
5080					STp->logical_blk_num, STps->drv_file, STps->drv_block );
5081#endif
5082			if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
5083				auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
5084							!(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5085				i = osst_write_trailer(STp, &SRpnt,
5086							!(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5087#if DEBUG
5088				printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5089						name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5090						STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5091#endif
5092				if (i < 0) {
5093					retval = i;
5094					goto out;
5095				}
5096			}
5097			STps->rw = ST_IDLE;
5098		}
5099
5100		if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5101			do_door_lock(STp, 0);  /* Ignore result! */
5102
5103		if (mtc.mt_op == MTSETDRVBUFFER &&
5104		   (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5105			retval = osst_set_options(STp, mtc.mt_count);
5106			goto out;
5107		}
5108
5109		if (mtc.mt_op == MTSETPART) {
5110			if (mtc.mt_count >= STp->nbr_partitions)
5111				retval = -EINVAL;
5112			else {
5113				STp->new_partition = mtc.mt_count;
5114				retval = 0;
5115			}
5116			goto out;
5117		}
5118
5119		if (mtc.mt_op == MTMKPART) {
5120			if (!STp->can_partitions) {
5121				retval = (-EINVAL);
5122				goto out;
5123			}
5124			if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5125			    (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5126				retval = i;
5127				goto out;
5128			}
5129			for (i=0; i < ST_NBR_PARTITIONS; i++) {
5130				STp->ps[i].rw = ST_IDLE;
5131				STp->ps[i].at_sm = 0;
5132				STp->ps[i].last_block_valid = 0;
5133			}
5134			STp->partition = STp->new_partition = 0;
5135			STp->nbr_partitions = 1;  /* Bad guess ?-) */
5136			STps->drv_block = STps->drv_file = 0;
5137			retval = 0;
5138			goto out;
5139	 	}
5140
5141		if (mtc.mt_op == MTSEEK) {
5142			if (STp->raw)
5143				i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5144			else
5145				i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5146			if (!STp->can_partitions)
5147				STp->ps[0].rw = ST_IDLE;
5148			retval = i;
5149			goto out;
5150		}
5151 
5152		if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5153			retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5154			goto out;
5155		}
5156
5157		if (auto_weof)
5158			cross_eof(STp, &SRpnt, 0);
5159
5160		if (mtc.mt_op == MTCOMPRESSION)
5161			retval = -EINVAL;       /* OnStream drives don't have compression hardware */
5162		else
5163			/* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5164			 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5165			retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5166		goto out;
5167	}
5168
5169	if (!STm->defined) {
5170		retval = (-ENXIO);
5171		goto out;
5172	}
5173
5174	if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5175		retval = i;
5176		goto out;
5177	}
5178
5179	if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5180		struct mtget mt_status;
5181
5182		if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5183			 retval = (-EINVAL);
5184			 goto out;
5185		}
5186
5187		mt_status.mt_type = MT_ISONSTREAM_SC;
5188		mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5189		mt_status.mt_dsreg =
5190			((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5191			((STp->density    << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5192		mt_status.mt_blkno = STps->drv_block;
5193		mt_status.mt_fileno = STps->drv_file;
5194		if (STp->block_size != 0) {
5195			if (STps->rw == ST_WRITING)
5196				mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5197			else if (STps->rw == ST_READING)
5198				mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5199							STp->block_size - 1) / STp->block_size;
5200		}
5201
5202		mt_status.mt_gstat = 0;
5203		if (STp->drv_write_prot)
5204			mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5205		if (mt_status.mt_blkno == 0) {
5206			if (mt_status.mt_fileno == 0)
5207				mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5208			else
5209				mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5210		}
5211		mt_status.mt_resid = STp->partition;
5212		if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5213			mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5214		else if (STps->eof >= ST_EOM_OK)
5215			mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5216		if (STp->density == 1)
5217			mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5218		else if (STp->density == 2)
5219			mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5220		else if (STp->density == 3)
5221			mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5222		if (STp->ready == ST_READY)
5223			mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5224		if (STp->ready == ST_NO_TAPE)
5225			mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5226		if (STps->at_sm)
5227			mt_status.mt_gstat |= GMT_SM(0xffffffff);
5228		if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5229		    STp->drv_buffer != 0)
5230			mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5231
5232		i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5233		if (i) {
5234			retval = (-EFAULT);
5235			goto out;
5236		}
5237
5238		STp->recover_erreg = 0;  /* Clear after read */
5239		retval = 0;
5240		goto out;
5241	} /* End of MTIOCGET */
5242
5243	if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5244		struct mtpos mt_pos;
5245
5246		if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5247			retval = (-EINVAL);
5248			goto out;
5249		}
5250		if (STp->raw)
5251			blk = osst_get_frame_position(STp, &SRpnt);
5252		else
5253			blk = osst_get_sector(STp, &SRpnt);
5254		if (blk < 0) {
5255			retval = blk;
5256			goto out;
5257		}
5258		mt_pos.mt_blkno = blk;
5259		i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5260		if (i)
5261			retval = -EFAULT;
5262		goto out;
5263	}
5264	if (SRpnt) osst_release_request(SRpnt);
5265
5266	mutex_unlock(&STp->lock);
5267
5268	retval = scsi_ioctl(STp->device, cmd_in, p);
5269	mutex_unlock(&osst_int_mutex);
5270	return retval;
5271
5272out:
5273	if (SRpnt) osst_release_request(SRpnt);
5274
5275	mutex_unlock(&STp->lock);
5276	mutex_unlock(&osst_int_mutex);
5277
5278	return retval;
5279}
5280
5281#ifdef CONFIG_COMPAT
5282static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5283{
5284	struct osst_tape *STp = file->private_data;
5285	struct scsi_device *sdev = STp->device;
5286	int ret = -ENOIOCTLCMD;
5287	if (sdev->host->hostt->compat_ioctl) {
5288
5289		ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5290
5291	}
5292	return ret;
5293}
5294#endif
5295
5296
5297
5298/* Memory handling routines */
5299
5300/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5301static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5302{
5303	int i;
5304	gfp_t priority;
5305	struct osst_buffer *tb;
5306
5307	if (from_initialization)
5308		priority = GFP_ATOMIC;
5309	else
5310		priority = GFP_KERNEL;
5311
5312	i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5313	tb = kzalloc(i, priority);
5314	if (!tb) {
5315		printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5316		return NULL;
5317	}
5318
5319	tb->sg_segs = tb->orig_sg_segs = 0;
5320	tb->use_sg = max_sg;
5321	tb->in_use = 1;
5322	tb->dma = need_dma;
5323	tb->buffer_size = 0;
5324#if DEBUG
5325	if (debugging) 
5326		printk(OSST_DEB_MSG
5327			"osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5328			   i, max_sg, need_dma);
5329#endif
5330	return tb;
5331}
5332
5333/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5334static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5335{
5336	int segs, nbr, max_segs, b_size, order, got;
5337	gfp_t priority;
5338
5339	if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5340		return 1;
5341
5342	if (STbuffer->sg_segs) {
5343		printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5344		normalize_buffer(STbuffer);
5345	}
5346	/* See how many segments we can use -- need at least two */
5347	nbr = max_segs = STbuffer->use_sg;
5348	if (nbr <= 2)
5349		return 0;
5350
5351	priority = GFP_KERNEL /* | __GFP_NOWARN */;
5352	if (need_dma)
5353		priority |= GFP_DMA;
5354
5355	/* Try to allocate the first segment up to OS_DATA_SIZE and the others
5356	   big enough to reach the goal (code assumes no segments in place) */
5357	for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5358		struct page *page = alloc_pages(priority, order);
5359
5360		STbuffer->sg[0].offset = 0;
5361		if (page != NULL) {
5362		    sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5363		    STbuffer->b_data = page_address(page);
5364		    break;
5365		}
5366	}
5367	if (sg_page(&STbuffer->sg[0]) == NULL) {
5368		printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5369		return 0;
5370	}
5371	/* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5372	for (segs=STbuffer->sg_segs=1, got=b_size;
5373	     segs < max_segs && got < OS_FRAME_SIZE; ) {
5374		struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5375		STbuffer->sg[segs].offset = 0;
5376		if (page == NULL) {
5377			printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5378						OS_FRAME_SIZE);
5379#if DEBUG
5380			STbuffer->buffer_size = got;
5381#endif
5382			normalize_buffer(STbuffer);
5383			return 0;
5384		}
5385		sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5386		got += STbuffer->sg[segs].length;
5387		STbuffer->buffer_size = got;
5388		STbuffer->sg_segs = ++segs;
5389	}
5390#if DEBUG
5391	if (debugging) {
5392		printk(OSST_DEB_MSG
5393			   "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5394			   got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5395		printk(OSST_DEB_MSG
5396			   "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5397			   STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5398			   STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5399	}
5400#endif
5401
5402	return 1;
5403}
5404
5405
5406/* Release the segments */
5407static void normalize_buffer(struct osst_buffer *STbuffer)
5408{
5409  int i, order, b_size;
5410
5411	for (i=0; i < STbuffer->sg_segs; i++) {
5412
5413		for (b_size = PAGE_SIZE, order = 0;
5414		     b_size < STbuffer->sg[i].length;
5415		     b_size *= 2, order++);
5416
5417		__free_pages(sg_page(&STbuffer->sg[i]), order);
5418		STbuffer->buffer_size -= STbuffer->sg[i].length;
5419	}
5420#if DEBUG
5421	if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5422		printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5423			     STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5424#endif
5425	STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5426}
5427
5428
5429/* Move data from the user buffer to the tape buffer. Returns zero (success) or
5430   negative error code. */
5431static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5432{
5433	int i, cnt, res, offset;
5434
5435	for (i=0, offset=st_bp->buffer_bytes;
5436	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5437		offset -= st_bp->sg[i].length;
5438	if (i == st_bp->sg_segs) {  /* Should never happen */
5439		printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5440		return (-EIO);
5441	}
5442	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5443		cnt = st_bp->sg[i].length - offset < do_count ?
5444		      st_bp->sg[i].length - offset : do_count;
5445		res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5446		if (res)
5447			return (-EFAULT);
5448		do_count -= cnt;
5449		st_bp->buffer_bytes += cnt;
5450		ubp += cnt;
5451		offset = 0;
5452	}
5453	if (do_count) {  /* Should never happen */
5454		printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5455		       do_count);
5456		return (-EIO);
5457	}
5458	return 0;
5459}
5460
5461
5462/* Move data from the tape buffer to the user buffer. Returns zero (success) or
5463   negative error code. */
5464static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5465{
5466	int i, cnt, res, offset;
5467
5468	for (i=0, offset=st_bp->read_pointer;
5469	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5470		offset -= st_bp->sg[i].length;
5471	if (i == st_bp->sg_segs) {  /* Should never happen */
5472		printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5473		return (-EIO);
5474	}
5475	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5476		cnt = st_bp->sg[i].length - offset < do_count ?
5477		      st_bp->sg[i].length - offset : do_count;
5478		res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5479		if (res)
5480			return (-EFAULT);
5481		do_count -= cnt;
5482		st_bp->buffer_bytes -= cnt;
5483		st_bp->read_pointer += cnt;
5484		ubp += cnt;
5485		offset = 0;
5486	}
5487	if (do_count) {  /* Should never happen */
5488		printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5489		return (-EIO);
5490	}
5491	return 0;
5492}
5493
5494/* Sets the tail of the buffer after fill point to zero.
5495   Returns zero (success) or negative error code.        */
5496static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5497{
5498	int	i, offset, do_count, cnt;
5499
5500	for (i = 0, offset = st_bp->buffer_bytes;
5501	     i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5502		offset -= st_bp->sg[i].length;
5503	if (i == st_bp->sg_segs) {  /* Should never happen */
5504		printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5505		return (-EIO);
5506	}
5507	for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5508	     i < st_bp->sg_segs && do_count > 0; i++) {
5509		cnt = st_bp->sg[i].length - offset < do_count ?
5510		      st_bp->sg[i].length - offset : do_count ;
5511		memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5512		do_count -= cnt;
5513		offset = 0;
5514	}
5515	if (do_count) {  /* Should never happen */
5516		printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5517		return (-EIO);
5518	}
5519	return 0;
5520}
5521
5522/* Copy a osst 32K chunk of memory into the buffer.
5523   Returns zero (success) or negative error code.  */
5524static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5525{
5526	int	i, cnt, do_count = OS_DATA_SIZE;
5527
5528	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5529		cnt = st_bp->sg[i].length < do_count ?
5530		      st_bp->sg[i].length : do_count ;
5531		memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5532		do_count -= cnt;
5533		ptr      += cnt;
5534	}
5535	if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5536		printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5537					 do_count, i);
5538		return (-EIO);
5539	}
5540	return 0;
5541}
5542
5543/* Copy a osst 32K chunk of memory from the buffer.
5544   Returns zero (success) or negative error code.  */
5545static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5546{
5547	int	i, cnt, do_count = OS_DATA_SIZE;
5548
5549	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5550		cnt = st_bp->sg[i].length < do_count ?
5551		      st_bp->sg[i].length : do_count ;
5552		memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5553		do_count -= cnt;
5554		ptr      += cnt;
5555	}
5556	if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5557		printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5558					 do_count, i);
5559		return (-EIO);
5560	}
5561	return 0;
5562}
5563
5564
5565/* Module housekeeping */
5566
5567static void validate_options (void)
5568{
5569  if (max_dev > 0)
5570		osst_max_dev = max_dev;  
5571  if (write_threshold_kbs > 0)
5572		osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5573  if (osst_write_threshold > osst_buffer_size)
5574		osst_write_threshold = osst_buffer_size;
5575  if (max_sg_segs >= OSST_FIRST_SG)
5576		osst_max_sg_segs = max_sg_segs;
5577#if DEBUG
5578  printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5579			   osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5580#endif
5581}
5582	
5583#ifndef MODULE
5584/* Set the boot options. Syntax: osst=xxx,yyy,...
5585   where xxx is write threshold in 1024 byte blocks,
5586   and   yyy is number of s/g segments to use. */
5587static int __init osst_setup (char *str)
5588{
5589  int i, ints[5];
5590  char *stp;
5591
5592  stp = get_options(str, ARRAY_SIZE(ints), ints);
5593
5594  if (ints[0] > 0) {
5595	for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5596		  *parms[i].val = ints[i + 1];
5597  } else {
5598	while (stp != NULL) {
5599		for (i = 0; i < ARRAY_SIZE(parms); i++) {
5600			int len = strlen(parms[i].name);
5601			if (!strncmp(stp, parms[i].name, len) &&
5602			    (*(stp + len) == ':' || *(stp + len) == '=')) {
5603				*parms[i].val =
5604					simple_strtoul(stp + len + 1, NULL, 0);
5605				break;
5606			}
5607		}
5608		if (i >= ARRAY_SIZE(parms))
5609			printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5610			       stp);
5611		stp = strchr(stp, ',');
5612		if (stp)
5613			stp++;
5614	}
5615  }
5616
5617  return 1;
5618}
5619
5620__setup("osst=", osst_setup);
5621
5622#endif
5623
5624static const struct file_operations osst_fops = {
5625	.owner =        THIS_MODULE,
5626	.read =         osst_read,
5627	.write =        osst_write,
5628	.unlocked_ioctl = osst_ioctl,
5629#ifdef CONFIG_COMPAT
5630	.compat_ioctl = osst_compat_ioctl,
5631#endif
5632	.open =         os_scsi_tape_open,
5633	.flush =        os_scsi_tape_flush,
5634	.release =      os_scsi_tape_close,
5635	.llseek =	noop_llseek,
5636};
5637
5638static int osst_supports(struct scsi_device * SDp)
5639{
5640	struct	osst_support_data {
5641		char *vendor;
5642		char *model;
5643		char *rev;
5644		char *driver_hint; /* Name of the correct driver, NULL if unknown */
5645	};
5646
5647static	struct	osst_support_data support_list[] = {
5648		/* {"XXX", "Yy-", "", NULL},  example */
5649		SIGS_FROM_OSST,
5650		{NULL, }};
5651
5652	struct	osst_support_data *rp;
5653
5654	/* We are willing to drive OnStream SC-x0 as well as the
5655	 * 	 * IDE, ParPort, FireWire, USB variants, if accessible by
5656	 * 	 	 * emulation layer (ide-scsi, usb-storage, ...) */
5657
5658	for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5659		if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5660		    !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5661		    !strncmp(rp->rev, SDp->rev, strlen(rp->rev))) 
5662			return 1;
5663	return 0;
5664}
5665
5666/*
5667 * sysfs support for osst driver parameter information
5668 */
5669
5670static ssize_t version_show(struct device_driver *ddd, char *buf)
5671{
5672	return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5673}
5674
5675static DRIVER_ATTR_RO(version);
5676
5677static int osst_create_sysfs_files(struct device_driver *sysfs)
5678{
5679	return driver_create_file(sysfs, &driver_attr_version);
5680}
5681
5682static void osst_remove_sysfs_files(struct device_driver *sysfs)
5683{
5684	driver_remove_file(sysfs, &driver_attr_version);
5685}
5686
5687/*
5688 * sysfs support for accessing ADR header information
5689 */
5690
5691static ssize_t osst_adr_rev_show(struct device *dev,
5692				 struct device_attribute *attr, char *buf)
5693{
5694	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5695	ssize_t l = 0;
5696
5697	if (STp && STp->header_ok && STp->linux_media)
5698		l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5699	return l;
5700}
5701
5702DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5703
5704static ssize_t osst_linux_media_version_show(struct device *dev,
5705					     struct device_attribute *attr,
5706					     char *buf)
5707{
5708	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5709	ssize_t l = 0;
5710
5711	if (STp && STp->header_ok && STp->linux_media)
5712		l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5713	return l;
5714}
5715
5716DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5717
5718static ssize_t osst_capacity_show(struct device *dev,
5719				  struct device_attribute *attr, char *buf)
5720{
5721	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5722	ssize_t l = 0;
5723
5724	if (STp && STp->header_ok && STp->linux_media)
5725		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5726	return l;
5727}
5728
5729DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5730
5731static ssize_t osst_first_data_ppos_show(struct device *dev,
5732					 struct device_attribute *attr,
5733					 char *buf)
5734{
5735	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5736	ssize_t l = 0;
5737
5738	if (STp && STp->header_ok && STp->linux_media)
5739		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5740	return l;
5741}
5742
5743DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5744
5745static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5746					struct device_attribute *attr,
5747					char *buf)
5748{
5749	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5750	ssize_t l = 0;
5751
5752	if (STp && STp->header_ok && STp->linux_media)
5753		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5754	return l;
5755}
5756
5757DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5758
5759static ssize_t osst_filemark_cnt_show(struct device *dev,
5760				      struct device_attribute *attr, char *buf)
5761{
5762	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5763	ssize_t l = 0;
5764
5765	if (STp && STp->header_ok && STp->linux_media)
5766		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5767	return l;
5768}
5769
5770DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5771
5772static struct class *osst_sysfs_class;
5773
5774static int osst_sysfs_init(void)
5775{
5776	osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5777	if (IS_ERR(osst_sysfs_class)) {
5778		printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5779		return PTR_ERR(osst_sysfs_class);
5780	}
5781
5782	return 0;
5783}
5784
5785static void osst_sysfs_destroy(dev_t dev)
5786{
5787	device_destroy(osst_sysfs_class, dev);
5788}
5789
5790static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5791{
5792	struct device *osst_member;
5793	int err;
5794
5795	osst_member = device_create(osst_sysfs_class, device, dev, STp,
5796				    "%s", name);
5797	if (IS_ERR(osst_member)) {
5798		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5799		return PTR_ERR(osst_member);
5800	}
5801
5802	err = device_create_file(osst_member, &dev_attr_ADR_rev);
5803	if (err)
5804		goto err_out;
5805	err = device_create_file(osst_member, &dev_attr_media_version);
5806	if (err)
5807		goto err_out;
5808	err = device_create_file(osst_member, &dev_attr_capacity);
5809	if (err)
5810		goto err_out;
5811	err = device_create_file(osst_member, &dev_attr_BOT_frame);
5812	if (err)
5813		goto err_out;
5814	err = device_create_file(osst_member, &dev_attr_EOD_frame);
5815	if (err)
5816		goto err_out;
5817	err = device_create_file(osst_member, &dev_attr_file_count);
5818	if (err)
5819		goto err_out;
5820
5821	return 0;
5822
5823err_out:
5824	osst_sysfs_destroy(dev);
5825	return err;
5826}
5827
5828static void osst_sysfs_cleanup(void)
5829{
5830	class_destroy(osst_sysfs_class);
5831}
5832
5833/*
5834 * osst startup / cleanup code
5835 */
5836
5837static int osst_probe(struct device *dev)
5838{
5839	struct scsi_device * SDp = to_scsi_device(dev);
5840	struct osst_tape   * tpnt;
5841	struct st_modedef  * STm;
5842	struct st_partstat * STps;
5843	struct osst_buffer * buffer;
5844	struct gendisk	   * drive;
5845	int		     i, dev_num, err = -ENODEV;
5846
5847	if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5848		return -ENODEV;
5849
5850	drive = alloc_disk(1);
5851	if (!drive) {
5852		printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5853		return -ENODEV;
5854	}
5855
5856	/* if this is the first attach, build the infrastructure */
5857	write_lock(&os_scsi_tapes_lock);
5858	if (os_scsi_tapes == NULL) {
5859		os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC);
5860		if (os_scsi_tapes == NULL) {
5861			write_unlock(&os_scsi_tapes_lock);
5862			printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5863			goto out_put_disk;
5864		}
5865		for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5866	}
5867	
5868	if (osst_nr_dev >= osst_max_dev) {
5869		write_unlock(&os_scsi_tapes_lock);
5870		printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5871		goto out_put_disk;
5872	}
5873
5874	/* find a free minor number */
5875	for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++)
5876		;
5877	if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5878	dev_num = i;
5879
5880	/* allocate a struct osst_tape for this device */
5881	tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5882	if (!tpnt) {
5883		write_unlock(&os_scsi_tapes_lock);
5884		printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5885		goto out_put_disk;
5886	}
5887
5888	/* allocate a buffer for this device */
5889	i = SDp->host->sg_tablesize;
5890	if (osst_max_sg_segs < i)
5891		i = osst_max_sg_segs;
5892	buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5893	if (buffer == NULL) {
5894		write_unlock(&os_scsi_tapes_lock);
5895		printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5896		kfree(tpnt);
5897		goto out_put_disk;
5898	}
5899	os_scsi_tapes[dev_num] = tpnt;
5900	tpnt->buffer = buffer;
5901	tpnt->device = SDp;
5902	drive->private_data = &tpnt->driver;
5903	sprintf(drive->disk_name, "osst%d", dev_num);
5904	tpnt->driver = &osst_template;
5905	tpnt->drive = drive;
5906	tpnt->in_use = 0;
5907	tpnt->capacity = 0xfffff;
5908	tpnt->dirty = 0;
5909	tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
5910	tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5911	tpnt->density = 0;
5912	tpnt->do_auto_lock = OSST_AUTO_LOCK;
5913	tpnt->can_bsr = OSST_IN_FILE_POS;
5914	tpnt->can_partitions = 0;
5915	tpnt->two_fm = OSST_TWO_FM;
5916	tpnt->fast_mteom = OSST_FAST_MTEOM;
5917	tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5918	tpnt->write_threshold = osst_write_threshold;
5919	tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5920	tpnt->partition = 0;
5921	tpnt->new_partition = 0;
5922	tpnt->nbr_partitions = 0;
5923	tpnt->min_block = 512;
5924	tpnt->max_block = OS_DATA_SIZE;
5925	tpnt->timeout = OSST_TIMEOUT;
5926	tpnt->long_timeout = OSST_LONG_TIMEOUT;
5927
5928	/* Recognize OnStream tapes */
5929	/* We don't need to test for OnStream, as this has been done in detect () */
5930	tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5931	tpnt->omit_blklims = 1;
5932
5933	tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || 
5934		     (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5935	tpnt->frame_in_buffer = 0;
5936	tpnt->header_ok = 0;
5937	tpnt->linux_media = 0;
5938	tpnt->header_cache = NULL;
5939
5940	for (i=0; i < ST_NBR_MODES; i++) {
5941		STm = &(tpnt->modes[i]);
5942		STm->defined = 0;
5943		STm->sysv = OSST_SYSV;
5944		STm->defaults_for_writes = 0;
5945		STm->do_async_writes = OSST_ASYNC_WRITES;
5946		STm->do_buffer_writes = OSST_BUFFER_WRITES;
5947		STm->do_read_ahead = OSST_READ_AHEAD;
5948		STm->default_compression = ST_DONT_TOUCH;
5949		STm->default_blksize = 512;
5950		STm->default_density = (-1);  /* No forced density */
5951	}
5952
5953	for (i=0; i < ST_NBR_PARTITIONS; i++) {
5954		STps = &(tpnt->ps[i]);
5955		STps->rw = ST_IDLE;
5956		STps->eof = ST_NOEOF;
5957		STps->at_sm = 0;
5958		STps->last_block_valid = 0;
5959		STps->drv_block = (-1);
5960		STps->drv_file = (-1);
5961	}
5962
5963	tpnt->current_mode = 0;
5964	tpnt->modes[0].defined = 1;
5965	tpnt->modes[2].defined = 1;
5966	tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5967
5968	mutex_init(&tpnt->lock);
5969	osst_nr_dev++;
5970	write_unlock(&os_scsi_tapes_lock);
5971
5972	{
5973		char name[8];
5974
5975		/*  Rewind entry  */
5976		err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5977		if (err)
5978			goto out_free_buffer;
5979
5980		/*  No-rewind entry  */
5981		snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5982		err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5983		if (err)
5984			goto out_free_sysfs1;
5985	}
5986
5987	sdev_printk(KERN_INFO, SDp,
5988		"osst :I: Attached OnStream %.5s tape as %s\n",
5989		SDp->model, tape_name(tpnt));
5990
5991	return 0;
5992
5993out_free_sysfs1:
5994	osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5995out_free_buffer:
5996	kfree(buffer);
5997out_put_disk:
5998        put_disk(drive);
5999        return err;
6000};
6001
6002static int osst_remove(struct device *dev)
6003{
6004	struct scsi_device * SDp = to_scsi_device(dev);
6005	struct osst_tape * tpnt;
6006	int i;
6007
6008	if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
6009		return 0;
6010
6011	write_lock(&os_scsi_tapes_lock);
6012	for(i=0; i < osst_max_dev; i++) {
6013		if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
6014			osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
6015			osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
6016			tpnt->device = NULL;
6017			put_disk(tpnt->drive);
6018			os_scsi_tapes[i] = NULL;
6019			osst_nr_dev--;
6020			write_unlock(&os_scsi_tapes_lock);
6021			vfree(tpnt->header_cache);
6022			if (tpnt->buffer) {
6023				normalize_buffer(tpnt->buffer);
6024				kfree(tpnt->buffer);
6025			}
6026			kfree(tpnt);
6027			return 0;
6028		}
6029	}
6030	write_unlock(&os_scsi_tapes_lock);
6031	return 0;
6032}
6033
6034static int __init init_osst(void) 
6035{
6036	int err;
6037
6038	printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
6039
6040	validate_options();
6041
6042	err = osst_sysfs_init();
6043	if (err)
6044		return err;
6045
6046	err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
6047	if (err < 0) {
6048		printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
6049		goto err_out;
6050	}
6051
6052	err = scsi_register_driver(&osst_template.gendrv);
6053	if (err)
6054		goto err_out_chrdev;
6055
6056	err = osst_create_sysfs_files(&osst_template.gendrv);
6057	if (err)
6058		goto err_out_scsidrv;
6059
6060	return 0;
6061
6062err_out_scsidrv:
6063	scsi_unregister_driver(&osst_template.gendrv);
6064err_out_chrdev:
6065	unregister_chrdev(OSST_MAJOR, "osst");
6066err_out:
6067	osst_sysfs_cleanup();
6068	return err;
6069}
6070
6071static void __exit exit_osst (void)
6072{
6073	int i;
6074	struct osst_tape * STp;
6075
6076	osst_remove_sysfs_files(&osst_template.gendrv);
6077	scsi_unregister_driver(&osst_template.gendrv);
6078	unregister_chrdev(OSST_MAJOR, "osst");
6079	osst_sysfs_cleanup();
6080
6081	if (os_scsi_tapes) {
6082		for (i=0; i < osst_max_dev; ++i) {
6083			if (!(STp = os_scsi_tapes[i])) continue;
6084			/* This is defensive, supposed to happen during detach */
6085			vfree(STp->header_cache);
6086			if (STp->buffer) {
6087				normalize_buffer(STp->buffer);
6088				kfree(STp->buffer);
6089			}
6090			put_disk(STp->drive);
6091			kfree(STp);
6092		}
6093		kfree(os_scsi_tapes);
6094	}
6095	printk(KERN_INFO "osst :I: Unloaded.\n");
6096}
6097
6098module_init(init_osst);
6099module_exit(exit_osst);