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