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