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