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