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