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