PageRenderTime 155ms CodeModel.GetById 26ms app.highlight 106ms RepoModel.GetById 2ms app.codeStats 1ms

/drivers/scsi/osst.c

http://github.com/mirrors/linux
C | 6096 lines | 5156 code | 631 blank | 309 comment | 1505 complexity | a9b3cc6e7aa97c372afc28aeafce0596 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2  SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
   3  file Documentation/scsi/st.txt for more information.
   4
   5  History:
   6
   7  OnStream SCSI Tape support (osst) cloned from st.c by
   8  Willem Riede (osst@riede.org) Feb 2000
   9  Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
  10
  11  Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
  12  Contribution and ideas from several people including (in alphabetical
  13  order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
  14  Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
  15
  16  Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
  17	 email osst@riede.org
  18
  19  $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
  20
  21  Microscopic alterations - Rik Ling, 2000/12/21
  22  Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
  23  Some small formal changes - aeb, 950809
  24*/
  25
  26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
  27static const char * osst_version = "0.99.4";
  28
  29/* The "failure to reconnect" firmware bug */
  30#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
  31#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
  32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
  33
  34#include <linux/module.h>
  35
  36#include <linux/fs.h>
  37#include <linux/kernel.h>
  38#include <linux/sched.h>
  39#include <linux/proc_fs.h>
  40#include <linux/mm.h>
  41#include <linux/slab.h>
  42#include <linux/init.h>
  43#include <linux/string.h>
  44#include <linux/errno.h>
  45#include <linux/mtio.h>
  46#include <linux/ioctl.h>
  47#include <linux/fcntl.h>
  48#include <linux/spinlock.h>
  49#include <linux/vmalloc.h>
  50#include <linux/blkdev.h>
  51#include <linux/moduleparam.h>
  52#include <linux/delay.h>
  53#include <linux/jiffies.h>
  54#include <linux/mutex.h>
  55#include <asm/uaccess.h>
  56#include <asm/dma.h>
  57
  58/* The driver prints some debugging information on the console if DEBUG
  59   is defined and non-zero. */
  60#define DEBUG 0
  61
  62/* The message level for the debug messages is currently set to KERN_NOTICE
  63   so that people can easily see the messages. Later when the debugging messages
  64   in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
  65#define OSST_DEB_MSG  KERN_NOTICE
  66
  67#include <scsi/scsi.h>
  68#include <scsi/scsi_dbg.h>
  69#include <scsi/scsi_device.h>
  70#include <scsi/scsi_driver.h>
  71#include <scsi/scsi_eh.h>
  72#include <scsi/scsi_host.h>
  73#include <scsi/scsi_ioctl.h>
  74
  75#define ST_KILOBYTE 1024
  76
  77#include "st.h"
  78#include "osst.h"
  79#include "osst_options.h"
  80#include "osst_detect.h"
  81
  82static DEFINE_MUTEX(osst_int_mutex);
  83static int max_dev = 0;
  84static int write_threshold_kbs = 0;
  85static int max_sg_segs = 0;
  86
  87#ifdef MODULE
  88MODULE_AUTHOR("Willem Riede");
  89MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
  90MODULE_LICENSE("GPL");
  91MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
  92MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
  93
  94module_param(max_dev, int, 0444);
  95MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
  96
  97module_param(write_threshold_kbs, int, 0644);
  98MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
  99
 100module_param(max_sg_segs, int, 0644);
 101MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
 102#else
 103static struct osst_dev_parm {
 104       char   *name;
 105       int    *val;
 106} parms[] __initdata = {
 107       { "max_dev",             &max_dev             },
 108       { "write_threshold_kbs", &write_threshold_kbs },
 109       { "max_sg_segs",         &max_sg_segs         }
 110};
 111#endif
 112
 113/* Some default definitions have been moved to osst_options.h */
 114#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
 115#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
 116
 117/* The buffer size should fit into the 24 bits for length in the
 118   6-byte SCSI read and write commands. */
 119#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
 120#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
 121#endif
 122
 123#if DEBUG
 124static int debugging = 1;
 125/* uncomment define below to test error recovery */
 126// #define OSST_INJECT_ERRORS 1 
 127#endif
 128
 129/* Do not retry! The drive firmware already retries when appropriate,
 130   and when it tries to tell us something, we had better listen... */
 131#define MAX_RETRIES 0
 132
 133#define NO_TAPE  NOT_READY
 134
 135#define OSST_WAIT_POSITION_COMPLETE   (HZ > 200 ? HZ / 200 : 1)
 136#define OSST_WAIT_WRITE_COMPLETE      (HZ / 12)
 137#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
 138	
 139#define OSST_TIMEOUT (200 * HZ)
 140#define OSST_LONG_TIMEOUT (1800 * HZ)
 141
 142#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
 143#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
 144#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
 145#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
 146
 147/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
 148   24 bits) */
 149#define SET_DENS_AND_BLK 0x10001
 150
 151static int osst_buffer_size       = OSST_BUFFER_SIZE;
 152static int osst_write_threshold   = OSST_WRITE_THRESHOLD;
 153static int osst_max_sg_segs       = OSST_MAX_SG;
 154static int osst_max_dev           = OSST_MAX_TAPES;
 155static int osst_nr_dev;
 156
 157static struct osst_tape **os_scsi_tapes = NULL;
 158static DEFINE_RWLOCK(os_scsi_tapes_lock);
 159
 160static int modes_defined = 0;
 161
 162static struct osst_buffer *new_tape_buffer(int, int, int);
 163static int enlarge_buffer(struct osst_buffer *, int);
 164static void normalize_buffer(struct osst_buffer *);
 165static int append_to_buffer(const char __user *, struct osst_buffer *, int);
 166static int from_buffer(struct osst_buffer *, char __user *, int);
 167static int osst_zero_buffer_tail(struct osst_buffer *);
 168static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
 169static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
 170
 171static int osst_probe(struct device *);
 172static int osst_remove(struct device *);
 173
 174static struct scsi_driver osst_template = {
 175	.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, int update)
 324{
 325	struct osst_request *SRpnt = req->end_io_data;
 326	struct osst_tape *STp = SRpnt->stp;
 327	struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
 328
 329	STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
 330#if DEBUG
 331	STp->write_pending = 0;
 332#endif
 333	if (SRpnt->waiting)
 334		complete(SRpnt->waiting);
 335
 336	if (SRpnt->bio) {
 337		kfree(mdata->pages);
 338		blk_rq_unmap_user(SRpnt->bio);
 339	}
 340
 341	__blk_put_request(req->q, req);
 342}
 343
 344/* osst_request memory management */
 345static struct osst_request *osst_allocate_request(void)
 346{
 347	return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
 348}
 349
 350static void osst_release_request(struct osst_request *streq)
 351{
 352	kfree(streq);
 353}
 354
 355static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
 356			int cmd_len, int data_direction, void *buffer, unsigned bufflen,
 357			int use_sg, int timeout, int retries)
 358{
 359	struct request *req;
 360	struct page **pages = NULL;
 361	struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
 362
 363	int err = 0;
 364	int write = (data_direction == DMA_TO_DEVICE);
 365
 366	req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
 367	if (IS_ERR(req))
 368		return DRIVER_ERROR << 24;
 369
 370	blk_rq_set_block_pc(req);
 371	req->cmd_flags |= REQ_QUIET;
 372
 373	SRpnt->bio = NULL;
 374
 375	if (use_sg) {
 376		struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
 377		int i;
 378
 379		pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
 380		if (!pages)
 381			goto free_req;
 382
 383		for_each_sg(sgl, sg, use_sg, i)
 384			pages[i] = sg_page(sg);
 385
 386		mdata->null_mapped = 1;
 387
 388		mdata->page_order = get_order(sgl[0].length);
 389		mdata->nr_entries =
 390			DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
 391		mdata->offset = 0;
 392
 393		err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
 394		if (err) {
 395			kfree(pages);
 396			goto free_req;
 397		}
 398		SRpnt->bio = req->bio;
 399		mdata->pages = pages;
 400
 401	} else if (bufflen) {
 402		err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
 403		if (err)
 404			goto free_req;
 405	}
 406
 407	req->cmd_len = cmd_len;
 408	memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
 409	memcpy(req->cmd, cmd, req->cmd_len);
 410	req->sense = SRpnt->sense;
 411	req->sense_len = 0;
 412	req->timeout = timeout;
 413	req->retries = retries;
 414	req->end_io_data = SRpnt;
 415
 416	blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
 417	return 0;
 418free_req:
 419	blk_put_request(req);
 420	return DRIVER_ERROR << 24;
 421}
 422
 423/* Do the scsi command. Waits until command performed if do_wait is true.
 424   Otherwise osst_write_behind_check() is used to check that the command
 425   has finished. */
 426static	struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp, 
 427	unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
 428{
 429	unsigned char *bp;
 430	unsigned short use_sg;
 431#ifdef OSST_INJECT_ERRORS
 432	static   int   inject = 0;
 433	static   int   repeat = 0;
 434#endif
 435	struct completion *waiting;
 436
 437	/* if async, make sure there's no command outstanding */
 438	if (!do_wait && ((STp->buffer)->last_SRpnt)) {
 439		printk(KERN_ERR "%s: Async command already active.\n",
 440		       tape_name(STp));
 441		if (signal_pending(current))
 442			(STp->buffer)->syscall_result = (-EINTR);
 443		else
 444			(STp->buffer)->syscall_result = (-EBUSY);
 445		return NULL;
 446	}
 447
 448	if (SRpnt == NULL) {
 449		SRpnt = osst_allocate_request();
 450		if (SRpnt == NULL) {
 451			printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
 452				     tape_name(STp));
 453			if (signal_pending(current))
 454				(STp->buffer)->syscall_result = (-EINTR);
 455			else
 456				(STp->buffer)->syscall_result = (-EBUSY);
 457			return NULL;
 458		}
 459		SRpnt->stp = STp;
 460	}
 461
 462	/* If async IO, set last_SRpnt. This ptr tells write_behind_check
 463	   which IO is outstanding. It's nulled out when the IO completes. */
 464	if (!do_wait)
 465		(STp->buffer)->last_SRpnt = SRpnt;
 466
 467	waiting = &STp->wait;
 468	init_completion(waiting);
 469	SRpnt->waiting = waiting;
 470
 471	use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
 472	if (use_sg) {
 473		bp = (char *)&(STp->buffer->sg[0]);
 474		if (STp->buffer->sg_segs < use_sg)
 475			use_sg = STp->buffer->sg_segs;
 476	}
 477	else
 478		bp = (STp->buffer)->b_data;
 479
 480	memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
 481	STp->buffer->cmdstat.have_sense = 0;
 482	STp->buffer->syscall_result = 0;
 483
 484	if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
 485			 use_sg, timeout, retries))
 486		/* could not allocate the buffer or request was too large */
 487		(STp->buffer)->syscall_result = (-EBUSY);
 488	else if (do_wait) {
 489		wait_for_completion(waiting);
 490		SRpnt->waiting = NULL;
 491		STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
 492#ifdef OSST_INJECT_ERRORS
 493		if (STp->buffer->syscall_result == 0 &&
 494		    cmd[0] == READ_6 &&
 495		    cmd[4] && 
 496		    ( (++ inject % 83) == 29  ||
 497		      (STp->first_frame_position == 240 
 498			         /* or STp->read_error_frame to fail again on the block calculated above */ &&
 499				 ++repeat < 3))) {
 500			printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
 501			STp->buffer->last_result_fatal = 1;
 502		}
 503#endif
 504	}
 505	return SRpnt;
 506}
 507
 508
 509/* Handle the write-behind checking (downs the semaphore) */
 510static void osst_write_behind_check(struct osst_tape *STp)
 511{
 512	struct osst_buffer * STbuffer;
 513
 514	STbuffer = STp->buffer;
 515
 516#if DEBUG
 517	if (STp->write_pending)
 518		STp->nbr_waits++;
 519	else
 520		STp->nbr_finished++;
 521#endif
 522	wait_for_completion(&(STp->wait));
 523	STp->buffer->last_SRpnt->waiting = NULL;
 524
 525	STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
 526
 527	if (STp->buffer->syscall_result)
 528		STp->buffer->syscall_result =
 529			osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
 530	else
 531		STp->first_frame_position++;
 532
 533	osst_release_request(STp->buffer->last_SRpnt);
 534
 535	if (STbuffer->writing < STbuffer->buffer_bytes)
 536		printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
 537
 538	STbuffer->last_SRpnt = NULL;
 539	STbuffer->buffer_bytes -= STbuffer->writing;
 540	STbuffer->writing = 0;
 541
 542	return;
 543}
 544
 545
 546
 547/* Onstream specific Routines */
 548/*
 549 * Initialize the OnStream AUX
 550 */
 551static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
 552					 int logical_blk_num, int blk_sz, int blk_cnt)
 553{
 554	os_aux_t       *aux = STp->buffer->aux;
 555	os_partition_t *par = &aux->partition;
 556	os_dat_t       *dat = &aux->dat;
 557
 558	if (STp->raw) return;
 559
 560	memset(aux, 0, sizeof(*aux));
 561	aux->format_id = htonl(0);
 562	memcpy(aux->application_sig, "LIN4", 4);
 563	aux->hdwr = htonl(0);
 564	aux->frame_type = frame_type;
 565
 566	switch (frame_type) {
 567	  case	OS_FRAME_TYPE_HEADER:
 568		aux->update_frame_cntr    = htonl(STp->update_frame_cntr);
 569		par->partition_num        = OS_CONFIG_PARTITION;
 570		par->par_desc_ver         = OS_PARTITION_VERSION;
 571		par->wrt_pass_cntr        = htons(0xffff);
 572		/* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
 573		par->first_frame_ppos     = htonl(0);
 574		par->last_frame_ppos      = htonl(0xbb7);
 575		aux->frame_seq_num        = htonl(0);
 576		aux->logical_blk_num_high = htonl(0);
 577		aux->logical_blk_num      = htonl(0);
 578		aux->next_mark_ppos       = htonl(STp->first_mark_ppos);
 579		break;
 580	  case	OS_FRAME_TYPE_DATA:
 581	  case	OS_FRAME_TYPE_MARKER:
 582		dat->dat_sz = 8;
 583		dat->reserved1 = 0;
 584		dat->entry_cnt = 1;
 585		dat->reserved3 = 0;
 586		dat->dat_list[0].blk_sz   = htonl(blk_sz);
 587		dat->dat_list[0].blk_cnt  = htons(blk_cnt);
 588		dat->dat_list[0].flags    = frame_type==OS_FRAME_TYPE_MARKER?
 589							OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
 590		dat->dat_list[0].reserved = 0;
 591	  case	OS_FRAME_TYPE_EOD:
 592		aux->update_frame_cntr    = htonl(0);
 593		par->partition_num        = OS_DATA_PARTITION;
 594		par->par_desc_ver         = OS_PARTITION_VERSION;
 595		par->wrt_pass_cntr        = htons(STp->wrt_pass_cntr);
 596		par->first_frame_ppos     = htonl(STp->first_data_ppos);
 597		par->last_frame_ppos      = htonl(STp->capacity);
 598		aux->frame_seq_num        = htonl(frame_seq_number);
 599		aux->logical_blk_num_high = htonl(0);
 600		aux->logical_blk_num      = htonl(logical_blk_num);
 601		break;
 602	  default: ; /* probably FILL */
 603	}
 604	aux->filemark_cnt = htonl(STp->filemark_cnt);
 605	aux->phys_fm = htonl(0xffffffff);
 606	aux->last_mark_ppos = htonl(STp->last_mark_ppos);
 607	aux->last_mark_lbn  = htonl(STp->last_mark_lbn);
 608}
 609
 610/*
 611 * Verify that we have the correct tape frame
 612 */
 613static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
 614{
 615	char               * name = tape_name(STp);
 616	os_aux_t           * aux  = STp->buffer->aux;
 617	os_partition_t     * par  = &(aux->partition);
 618	struct st_partstat * STps = &(STp->ps[STp->partition]);
 619	int		     blk_cnt, blk_sz, i;
 620
 621	if (STp->raw) {
 622		if (STp->buffer->syscall_result) {
 623			for (i=0; i < STp->buffer->sg_segs; i++)
 624				memset(page_address(sg_page(&STp->buffer->sg[i])),
 625				       0, STp->buffer->sg[i].length);
 626			strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
 627                } else
 628			STp->buffer->buffer_bytes = OS_FRAME_SIZE;
 629		return 1;
 630	}
 631	if (STp->buffer->syscall_result) {
 632#if DEBUG
 633		printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
 634#endif
 635		return 0;
 636	}
 637	if (ntohl(aux->format_id) != 0) {
 638#if DEBUG
 639		printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
 640#endif
 641		goto err_out;
 642	}
 643	if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
 644	    (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
 645#if DEBUG
 646		printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
 647#endif
 648		goto err_out;
 649	}
 650	if (par->partition_num != OS_DATA_PARTITION) {
 651		if (!STp->linux_media || STp->linux_media_version != 2) {
 652#if DEBUG
 653			printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
 654					    name, par->partition_num);
 655#endif
 656			goto err_out;
 657		}
 658	}
 659	if (par->par_desc_ver != OS_PARTITION_VERSION) {
 660#if DEBUG
 661		printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
 662#endif
 663		goto err_out;
 664	}
 665	if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
 666#if DEBUG
 667		printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", 
 668				    name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
 669#endif
 670		goto err_out;
 671	}
 672	if (aux->frame_type != OS_FRAME_TYPE_DATA &&
 673	    aux->frame_type != OS_FRAME_TYPE_EOD &&
 674	    aux->frame_type != OS_FRAME_TYPE_MARKER) {
 675		if (!quiet) {
 676#if DEBUG
 677			printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
 678#endif
 679		}
 680		goto err_out;
 681	}
 682	if (aux->frame_type == OS_FRAME_TYPE_EOD &&
 683	    STp->first_frame_position < STp->eod_frame_ppos) {
 684		printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
 685				 STp->first_frame_position);
 686		goto err_out;
 687	}
 688        if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
 689		if (!quiet) {
 690#if DEBUG
 691			printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n", 
 692					    name, ntohl(aux->frame_seq_num), frame_seq_number);
 693#endif
 694		}
 695		goto err_out;
 696	}
 697	if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
 698		STps->eof = ST_FM_HIT;
 699
 700		i = ntohl(aux->filemark_cnt);
 701		if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
 702		    STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
 703#if DEBUG
 704			printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
 705				  STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
 706				  i, STp->first_frame_position - 1);
 707#endif
 708			STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
 709			if (i >= STp->filemark_cnt)
 710				 STp->filemark_cnt = i+1;
 711		}
 712	}
 713	if (aux->frame_type == OS_FRAME_TYPE_EOD) {
 714		STps->eof = ST_EOD_1;
 715		STp->frame_in_buffer = 1;
 716	}
 717	if (aux->frame_type == OS_FRAME_TYPE_DATA) {
 718                blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
 719		blk_sz  = ntohl(aux->dat.dat_list[0].blk_sz);
 720		STp->buffer->buffer_bytes = blk_cnt * blk_sz;
 721		STp->buffer->read_pointer = 0;
 722		STp->frame_in_buffer = 1;
 723
 724		/* See what block size was used to write file */
 725		if (STp->block_size != blk_sz && blk_sz > 0) {
 726			printk(KERN_INFO
 727	    	"%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
 728       				name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
 729				STp->block_size<1024?STp->block_size:STp->block_size/1024,
 730				STp->block_size<1024?'b':'k');
 731			STp->block_size            = blk_sz;
 732			STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
 733		}
 734		STps->eof = ST_NOEOF;
 735	}
 736        STp->frame_seq_number = ntohl(aux->frame_seq_num);
 737	STp->logical_blk_num  = ntohl(aux->logical_blk_num);
 738	return 1;
 739
 740err_out:
 741	if (STp->read_error_frame == 0)
 742		STp->read_error_frame = STp->first_frame_position - 1;
 743	return 0;
 744}
 745
 746/*
 747 * Wait for the unit to become Ready
 748 */
 749static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
 750				 unsigned timeout, int initial_delay)
 751{
 752	unsigned char		cmd[MAX_COMMAND_SIZE];
 753	struct osst_request   * SRpnt;
 754	unsigned long		startwait = jiffies;
 755#if DEBUG
 756	int			dbg  = debugging;
 757	char    	      * name = tape_name(STp);
 758
 759	printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
 760#endif
 761
 762	if (initial_delay > 0)
 763		msleep(jiffies_to_msecs(initial_delay));
 764
 765	memset(cmd, 0, MAX_COMMAND_SIZE);
 766	cmd[0] = TEST_UNIT_READY;
 767
 768	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 769	*aSRpnt = SRpnt;
 770	if (!SRpnt) return (-EBUSY);
 771
 772	while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 773	       (( SRpnt->sense[2]  == 2 && SRpnt->sense[12] == 4    &&
 774		 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)    ) ||
 775		( SRpnt->sense[2]  == 6 && SRpnt->sense[12] == 0x28 &&
 776		  SRpnt->sense[13] == 0                                        )  )) {
 777#if DEBUG
 778	    if (debugging) {
 779		printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
 780		printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 781		debugging = 0;
 782	    }
 783#endif
 784	    msleep(100);
 785
 786	    memset(cmd, 0, MAX_COMMAND_SIZE);
 787	    cmd[0] = TEST_UNIT_READY;
 788
 789	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 790	}
 791	*aSRpnt = SRpnt;
 792#if DEBUG
 793	debugging = dbg;
 794#endif
 795	if ( STp->buffer->syscall_result &&
 796	     osst_write_error_recovery(STp, aSRpnt, 0) ) {
 797#if DEBUG
 798	    printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
 799	    printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 800			STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 801			SRpnt->sense[12], SRpnt->sense[13]);
 802#endif
 803	    return (-EIO);
 804	}
 805#if DEBUG
 806	printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
 807#endif
 808	return 0;
 809}
 810
 811/*
 812 * Wait for a tape to be inserted in the unit
 813 */
 814static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
 815{
 816	unsigned char		cmd[MAX_COMMAND_SIZE];
 817	struct osst_request   * SRpnt;
 818	unsigned long		startwait = jiffies;
 819#if DEBUG
 820	int			dbg = debugging;
 821	char    	      * name = tape_name(STp);
 822
 823	printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
 824#endif
 825
 826	memset(cmd, 0, MAX_COMMAND_SIZE);
 827	cmd[0] = TEST_UNIT_READY;
 828
 829	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 830	*aSRpnt = SRpnt;
 831	if (!SRpnt) return (-EBUSY);
 832
 833	while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 834		SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0  ) {
 835#if DEBUG
 836	    if (debugging) {
 837		printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
 838		printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 839		debugging = 0;
 840	    }
 841#endif
 842	    msleep(100);
 843
 844	    memset(cmd, 0, MAX_COMMAND_SIZE);
 845	    cmd[0] = TEST_UNIT_READY;
 846
 847	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 848	}
 849	*aSRpnt = SRpnt;
 850#if DEBUG
 851	debugging = dbg;
 852#endif
 853	if ( STp->buffer->syscall_result     && SRpnt->sense[2]  != 2 &&
 854	     SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
 855#if DEBUG
 856	    printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
 857	    printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 858			STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 859			SRpnt->sense[12], SRpnt->sense[13]);
 860#endif
 861	    return 0;
 862	}
 863#if DEBUG
 864	printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
 865#endif
 866	return 1;
 867}
 868
 869static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
 870{
 871	int	retval;
 872
 873	osst_wait_ready(STp, aSRpnt, 15 * 60, 0);			/* TODO - can this catch a write error? */
 874	retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
 875	if (retval) return (retval);
 876	osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
 877	return (osst_get_frame_position(STp, aSRpnt));
 878}
 879
 880/*
 881 * Wait for write(s) to complete
 882 */
 883static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
 884{
 885	unsigned char		cmd[MAX_COMMAND_SIZE];
 886	struct osst_request   * SRpnt;
 887	int			result = 0;
 888	int			delay  = OSST_WAIT_WRITE_COMPLETE;
 889#if DEBUG
 890	char		      * name = tape_name(STp);
 891
 892	printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
 893#endif
 894
 895	memset(cmd, 0, MAX_COMMAND_SIZE);
 896	cmd[0] = WRITE_FILEMARKS;
 897	cmd[1] = 1;
 898
 899	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 900	*aSRpnt = SRpnt;
 901	if (!SRpnt) return (-EBUSY);
 902	if (STp->buffer->syscall_result) {
 903		if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
 904			if (SRpnt->sense[13] == 8) {
 905				delay = OSST_WAIT_LONG_WRITE_COMPLETE;
 906			}
 907		} else
 908			result = osst_write_error_recovery(STp, aSRpnt, 0);
 909	}
 910	result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
 911	STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
 912
 913	return (result);
 914}
 915
 916#define OSST_POLL_PER_SEC 10
 917static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
 918{
 919	unsigned long	startwait = jiffies;
 920	char	      * name      = tape_name(STp);
 921#if DEBUG
 922	char	   notyetprinted  = 1;
 923#endif
 924	if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
 925		printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
 926
 927	while (time_before (jiffies, startwait + to*HZ))
 928	{ 
 929		int result;
 930		result = osst_get_frame_position(STp, aSRpnt);
 931		if (result == -EIO)
 932			if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
 933				return 0;	/* successful recovery leaves drive ready for frame */
 934		if (result < 0) break;
 935		if (STp->first_frame_position == curr &&
 936		    ((minlast < 0 &&
 937		      (signed)STp->last_frame_position > (signed)curr + minlast) ||
 938		     (minlast >= 0 && STp->cur_frames > minlast)
 939		    ) && result >= 0)
 940		{
 941#if DEBUG			
 942			if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
 943				printk (OSST_DEB_MSG
 944					"%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
 945					name, curr, curr+minlast, STp->first_frame_position,
 946					STp->last_frame_position, STp->cur_frames,
 947					result, (jiffies-startwait)/HZ, 
 948					(((jiffies-startwait)%HZ)*10)/HZ);
 949#endif
 950			return 0;
 951		}
 952#if DEBUG
 953		if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
 954		{
 955			printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
 956				name, curr, curr+minlast, STp->first_frame_position,
 957				STp->last_frame_position, STp->cur_frames, result);
 958			notyetprinted--;
 959		}
 960#endif
 961		msleep(1000 / OSST_POLL_PER_SEC);
 962	}
 963#if DEBUG
 964	printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
 965		name, curr, curr+minlast, STp->first_frame_position,
 966		STp->last_frame_position, STp->cur_frames,
 967		(jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
 968#endif	
 969	return -EBUSY;
 970}
 971
 972static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
 973{
 974	struct osst_request   * SRpnt;
 975	unsigned char		cmd[MAX_COMMAND_SIZE];
 976	unsigned long   	startwait = jiffies;
 977	int			retval    = 1;
 978        char		      * name      = tape_name(STp);
 979                                                                                                                                
 980	if (writing) {
 981		char	mybuf[24];
 982		char  * olddata = STp->buffer->b_data;
 983		int	oldsize = STp->buffer->buffer_size;
 984
 985		/* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
 986
 987		memset(cmd, 0, MAX_COMMAND_SIZE);
 988		cmd[0] = WRITE_FILEMARKS;
 989		cmd[1] = 1;
 990		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
 991								MAX_RETRIES, 1);
 992
 993		while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
 994
 995			if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
 996
 997				/* some failure - not just not-ready */
 998				retval = osst_write_error_recovery(STp, aSRpnt, 0);
 999				break;
1000			}
1001			schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
1002
1003			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1004			memset(cmd, 0, MAX_COMMAND_SIZE);
1005			cmd[0] = READ_POSITION;
1006
1007			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1008										MAX_RETRIES, 1);
1009
1010			retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1011			STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1012		}
1013		if (retval)
1014			printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1015	} else
1016		/* TODO - figure out which error conditions can be handled */
1017		if (STp->buffer->syscall_result)
1018			printk(KERN_WARNING
1019				"%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1020					(*aSRpnt)->sense[ 2] & 0x0f,
1021					(*aSRpnt)->sense[12],
1022					(*aSRpnt)->sense[13]);
1023
1024	return retval;
1025}
1026
1027/*
1028 * Read the next OnStream tape frame at the current location
1029 */
1030static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1031{
1032	unsigned char		cmd[MAX_COMMAND_SIZE];
1033	struct osst_request   * SRpnt;
1034	int			retval = 0;
1035#if DEBUG
1036	os_aux_t	      * aux    = STp->buffer->aux;
1037	char		      * name   = tape_name(STp);
1038#endif
1039
1040	if (STp->poll)
1041		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1042			retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1043
1044	memset(cmd, 0, MAX_COMMAND_SIZE);
1045	cmd[0] = READ_6;
1046	cmd[1] = 1;
1047	cmd[4] = 1;
1048
1049#if DEBUG
1050	if (debugging)
1051		printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1052#endif
1053	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1054				      STp->timeout, MAX_RETRIES, 1);
1055	*aSRpnt = SRpnt;
1056	if (!SRpnt)
1057		return (-EBUSY);
1058
1059	if ((STp->buffer)->syscall_result) {
1060	    retval = 1;
1061	    if (STp->read_error_frame == 0) {
1062		STp->read_error_frame = STp->first_frame_position;
1063#if DEBUG
1064		printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1065#endif
1066	    }
1067#if DEBUG
1068	    if (debugging)
1069		printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1070		   name,
1071		   SRpnt->sense[0], SRpnt->sense[1],
1072		   SRpnt->sense[2], SRpnt->sense[3],
1073		   SRpnt->sense[4], SRpnt->sense[5],
1074		   SRpnt->sense[6], SRpnt->sense[7]);
1075#endif
1076	}
1077	else
1078	    STp->first_frame_position++;
1079#if DEBUG
1080	if (debugging) {
1081	   char sig[8]; int i;
1082	   for (i=0;i<4;i++)
1083		   sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1084	   sig[4] = '\0';
1085	   printk(OSST_DEB_MSG 
1086		"%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1087			ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1088			aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1089			aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", 
1090			ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1091			ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1092	   if (aux->frame_type==2)
1093		printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1094			ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1095	   printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1096	}
1097#endif
1098	return (retval);
1099}
1100
1101static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1102{
1103	struct st_partstat    * STps   = &(STp->ps[STp->partition]);
1104	struct osst_request   * SRpnt  ;
1105	unsigned char		cmd[MAX_COMMAND_SIZE];
1106	int			retval = 0;
1107	char		      * name   = tape_name(STp);
1108
1109	if (STps->rw != ST_READING) {         /* Initialize read operation */
1110		if (STps->rw == ST_WRITING || STp->dirty) {
1111			STp->write_type = OS_WRITE_DATA;
1112                        osst_flush_write_buffer(STp, aSRpnt);
1113			osst_flush_drive_buffer(STp, aSRpnt);
1114		}
1115		STps->rw = ST_READING;
1116		STp->frame_in_buffer = 0;
1117
1118		/*
1119		 *      Issue a read 0 command to get the OnStream drive
1120                 *      read frames into its buffer.
1121		 */
1122		memset(cmd, 0, MAX_COMMAND_SIZE);
1123		cmd[0] = READ_6;
1124		cmd[1] = 1;
1125
1126#if DEBUG
1127		printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1128#endif
1129		SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1130		*aSRpnt = SRpnt;
1131		if ((retval = STp->buffer->syscall_result))
1132			printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1133	}
1134
1135	return retval;
1136}
1137
1138static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1139						int frame_seq_number, int quiet)
1140{
1141	struct st_partstat * STps  = &(STp->ps[STp->partition]);
1142	char		   * name  = tape_name(STp);
1143	int		     cnt   = 0,
1144			     bad   = 0,
1145			     past  = 0,
1146			     x,
1147			     position;
1148
1149	/*
1150	 * If we want just any frame (-1) and there is a frame in the buffer, return it
1151	 */
1152	if (frame_seq_number == -1 && STp->frame_in_buffer) {
1153#if DEBUG
1154		printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1155#endif
1156		return (STps->eof);
1157	}
1158	/*
1159         * Search and wait for the next logical tape frame
1160	 */
1161	while (1) {
1162		if (cnt++ > 400) {
1163                        printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1164					    name, frame_seq_number);
1165			if (STp->read_error_frame) {
1166				osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1167#if DEBUG
1168                        	printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1169						    name, STp->read_error_frame);
1170#endif
1171				STp->read_error_frame = 0;
1172				STp->abort_count++;
1173			}
1174			return (-EIO);
1175		}
1176#if DEBUG
1177		if (debugging)
1178			printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1179					  name, frame_seq_number, cnt);
1180#endif
1181		if ( osst_initiate_read(STp, aSRpnt)
1182                || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1183			if (STp->raw)
1184				return (-EIO);
1185			position = osst_get_frame_position(STp, aSRpnt);
1186			if (position >= 0xbae && position < 0xbb8)
1187				position = 0xbb8;
1188			else if (position > STp->eod_frame_ppos || ++bad == 10) {
1189				position = STp->read_error_frame - 1;
1190				bad = 0;
1191			}
1192			else {
1193				position += 29;
1194				cnt      += 19;
1195			}
1196#if DEBUG
1197			printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1198					 name, position);
1199#endif
1200			osst_set_frame_position(STp, aSRpnt, position, 0);
1201			continue;
1202		}
1203		if (osst_verify_frame(STp, frame_seq_number, quiet))
1204			break;
1205		if (osst_verify_frame(STp, -1, quiet)) {
1206			x = ntohl(STp->buffer->aux->frame_seq_num);
1207			if (STp->fast_open) {
1208				printk(KERN_WARNING
1209				       "%s:W: Found logical frame %d instead of %d after fast open\n",
1210				       name, x, frame_seq_number);
1211				STp->header_ok = 0;
1212				STp->read_error_frame = 0;
1213				return (-EIO);
1214			}
1215			if (x > frame_seq_number) {
1216				if (++past > 3) {
1217					/* positioning backwards did not bring us to the desired frame */
1218					position = STp->read_error_frame - 1;
1219				}
1220				else {
1221			        	position = osst_get_frame_position(STp, aSRpnt)
1222					         + frame_seq_number - x - 1;
1223
1224					if (STp->first_frame_position >= 3000 && position < 3000)
1225						position -= 10;
1226				}
1227#if DEBUG
1228                                printk(OSST_DEB_MSG
1229				       "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1230						name, x, frame_seq_number,
1231					       	STp->first_frame_position - position);
1232#endif
1233                        	osst_set_frame_position(STp, aSRpnt, position, 0);
1234				cnt += 10;
1235			}
1236			else
1237				past = 0;
1238		}
1239		if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1240#if DEBUG
1241			printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1242#endif
1243			osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1244			cnt--;
1245		}
1246		STp->frame_in_buffer = 0;
1247	}
1248	if (cnt > 1) {
1249		STp->recover_count++;
1250		STp->recover_erreg++;
1251		printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n", 
1252					name, STp->read_error_frame);
1253 	}
1254	STp->read_count++;
1255
1256#if DEBUG
1257	if (debugging || STps->eof)
1258		printk(OSST_DEB_MSG
1259			"%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1260			name, frame_seq_number, STp->frame_seq_number, STps->eof);
1261#endif
1262	STp->fast_open = 0;
1263	STp->read_error_frame = 0;
1264	return (STps->eof);
1265}
1266
1267static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1268{
1269        struct st_partstat * STps = &(STp->ps[STp->partition]);
1270	char		   * name = tape_name(STp);
1271	int	retries    = 0;
1272	int	frame_seq_estimate, ppos_estimate, move;
1273	
1274	if (logical_blk_num < 0) logical_blk_num = 0;
1275#if DEBUG
1276	printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1277				name, logical_blk_num, STp->logical_blk_num, 
1278				STp->block_size<1024?STp->block_size:STp->block_size/1024,
1279				STp->block_size<1024?'b':'k');
1280#endif
1281	/* Do we know where we are? */
1282	if (STps->drv_block >= 0) {
1283		move                = logical_blk_num - STp->logical_blk_num;
1284		if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1285		move               /= (OS_DATA_SIZE / STp->block_size);
1286		frame_seq_estimate  = STp->frame_seq_number + move;
1287	} else
1288		frame_seq_estimate  = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1289
1290	if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1291	else			       ppos_estimate = frame_seq_estimate + 20;
1292	while (++retries < 10) {
1293	   if (ppos_estimate > STp->eod_frame_ppos-2) {
1294	       frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1295	       ppos_estimate       = STp->eod_frame_ppos - 2;
1296	   }
1297	   if (frame_seq_estimate < 0) {
1298	       frame_seq_estimate = 0;
1299	       ppos_estimate      = 10;
1300	   }
1301	   osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1302	   if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1303	      /* we've located the estimated frame, now does it have our block? */
1304	      if (logical_blk_num <  STp->logical_blk_num ||
1305	          logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1306		 if (STps->eof == ST_FM_HIT)
1307		    move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1308		 else {
1309		    move                = logical_blk_num - STp->logical_blk_num;
1310		    if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1311		    move               /= (OS_DATA_SIZE / STp->block_size);
1312		 }
1313		 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1314#if DEBUG
1315		 printk(OSST_DEB_MSG
1316			"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1317				name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1318				STp->logical_blk_num, logical_blk_num, move);
1319#endif
1320		 frame_seq_estimate += move;
1321		 ppos_estimate      += move;
1322		 continue;
1323	      } else {
1324		 STp->buffer->read_pointer  = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1325		 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1326		 STp->logical_blk_num       =  logical_blk_num;
1327#if DEBUG
1328		 printk(OSST_DEB_MSG 
1329			"%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1330				name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer, 
1331				STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size, 
1332				STp->block_size);
1333#endif
1334		 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1335		 if (STps->eof == ST_FM_HIT) {
1336		     STps->drv_file++;
1337		     STps->drv_block = 0;
1338		 } else {
1339		     STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1340					  STp->logical_blk_num -
1341					     (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1342					-1;
1343		 }
1344		 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1345		 return 0;
1346	      }
1347	   }
1348	   if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1349	      goto error;
1350	   /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1351#if DEBUG
1352	   printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n", 
1353			   name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1354			   STp->logical_blk_num, logical_blk_num);
1355#endif
1356	   if (frame_seq_estimate != STp->frame_seq_number)
1357	      ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1358	   else
1359	      break;
1360	}
1361error:
1362	printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n", 
1363			    name, logical_blk_num, STp->logical_blk_num, retries);
1364	return (-EIO);
1365}
1366
1367/* The values below are based on the OnStream frame payload size of 32K == 2**15,
1368 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1369 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1370 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1371 */
1372#define OSST_FRAME_SHIFT  6
1373#define OSST_SECTOR_SHIFT 9
1374#define OSST_SECTOR_MASK  0x03F
1375
1376static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1377{
1378	int	sector;
1379#if DEBUG
1380	char  * name = tape_name(STp);
1381	
1382	printk(OSST_DEB_MSG 
1383		"%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1384		name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1385		STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block, 
1386		STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1387		STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1388		STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1389#endif
1390	/* do we know where we are inside a file? */
1391	if (STp->ps[STp->partition].drv_block >= 0) {
1392		sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1393				STp->first_frame_position) << OSST_FRAME_SHIFT;
1394		if (STp->ps[STp->partition].rw == ST_WRITING)
1395		       	sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1396		else
1397	       		sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1398	} else {
1399		sector = osst_get_frame_position(STp, aSRpnt);
1400		if (sector > 0)
1401			sector <<= OSST_FRAME_SHIFT;
1402	}
1403	return sector;
1404}
1405
1406static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1407{
1408        struct st_partstat * STps   = &(STp->ps[STp->partition]);
1409	int		     frame  = sector >> OSST_FRAME_SHIFT,
1410			     offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
1411			     r;
1412#if DEBUG
1413	char          * name = tape_name(STp);
1414
1415	printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1416				name, sector, frame, offset);
1417#endif
1418	if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1419
1420	if (frame <= STp->first_data_ppos) {
1421		STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1422		return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1423	}
1424	r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1425	if (r < 0) return r;
1426
1427	r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1428	if (r < 0) return r;
1429
1430	if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1431
1432	if (offset) {
1433		STp->logical_blk_num      += offset / STp->block_size;
1434		STp->buffer->read_pointer  = offset;
1435		STp->buffer->buffer_bytes -= offset;
1436	} else {
1437		STp->frame_seq_number++;
1438		STp->frame_in_buffer       = 0;
1439		STp->logical_blk_num      += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1440		STp->buffer->buffer_bytes  = STp->buffer->read_pointer = 0;
1441	}
1442	STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1443	if (STps->eof == ST_FM_HIT) {
1444		STps->drv_file++;
1445		STps->drv_block = 0;
1446	} else {
1447		STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1448				    STp->logical_blk_num -
1449					(STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1450				  -1;
1451	}
1452	STps->eof       = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1453#if DEBUG
1454	printk(OSST_DEB_MSG 
1455		"%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1456		name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1457		STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1458#endif
1459	return 0;
1460}
1461
1462/*
1463 * Read back the drive's internal buffer contents, as a part
1464 * of the write error recovery mechanism for old OnStream
1465 * firmware revisions.
1466 * Precondition for this function to work: all frames in the
1467 * drive's buffer must be of one type (DATA, MARK or EOD)!
1468 */
1469static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1470						unsigned int frame, unsigned int skip, int pending)
1471{
1472	struct osst_request   * SRpnt = * aSRpnt;
1473	unsigned char	      * buffer, * p;
1474	unsigned char		cmd[MAX_COMMAND_SIZE];
1475	int			flag, new_frame, i;
1476	int			nframes          = STp->cur_frames;
1477	int			blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1478	int			frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1479						- (nframes + pending - 1);
1480	int			logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
1481						- (nframes + pending - 1) * blks_per_frame;
1482	char		      * name             = tape_name(STp);
1483	unsigned long		startwait        = jiffies;
1484#if DEBUG
1485	int			dbg              = debugging;
1486#endif
1487
1488	if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1489		return (-EIO);
1490
1491	printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1492			 name, nframes, pending?" and one that was pending":"");
1493
1494	osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1495#if DEBUG
1496	if (pending && debugging)
1497		printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1498				name, frame_seq_number + nframes,
1499			       	logical_blk_num + nframes * blks_per_frame,
1500			       	p[0], p[1], p[2], p[3]);
1501#endif
1502	for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1503
1504		memset(cmd, 0, MAX_COMMAND_SIZE);
1505		cmd[0] = 0x3C;		/* Buffer Read           */
1506		cmd[1] = 6;		/* Retrieve Faulty Block */
1507		cmd[7] = 32768 >> 8;
1508		cmd[8] = 32768 & 0xff;
1509
1510		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1511					    STp->timeout, MAX_RETRIES, 1);
1512	
1513		if ((STp->buffer)->syscall_result || !SRpnt) {
1514			printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1515			vfree(buffer);
1516			*aSRpnt = SRpnt;
1517			return (-EIO);
1518		}
1519		osst_copy_from_buffer(STp->buffer, p);
1520#if DEBUG
1521		if (debugging)
1522			printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1523					  name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1524#endif
1525	}
1526	*aSRpnt = SRpnt;
1527	osst_get_frame_position(STp, aSRpnt);
1528
1529#if DEBUG
1530	printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1531#endif
1532	/* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1533	/* In the header we don't actually re-write the frames that fail, just the ones after them */
1534
1535	for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1536
1537		if (flag) {
1538			if (STp->write_type == OS_WRITE_HEADER) {
1539				i += skip;
1540				p += skip * OS_DATA_SIZE;
1541			}
1542			else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1543				new_frame = 3000-i;
1544			else
1545				new_frame += skip;
1546#if DEBUG
1547			printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1548						name, new_frame+i, frame_seq_number+i);
1549#endif
1550			osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1551			osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1552			osst_get_frame_position(STp, aSRpnt);
1553			SRpnt = * aSRpnt;
1554
1555			if (new_frame > frame + 1000) {
1556				printk(KERN_ERR "%s:E: Failed to find writable tape media\n", nam

Large files files are truncated, but you can click here to view the full file