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