2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
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
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.
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid
= "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27 static const char * osst_version
= "0.99.4";
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)
34 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
41 #include <linux/init.h>
42 #include <linux/string.h>
43 #include <linux/errno.h>
44 #include <linux/mtio.h>
45 #include <linux/ioctl.h>
46 #include <linux/fcntl.h>
47 #include <linux/spinlock.h>
48 #include <linux/vmalloc.h>
49 #include <linux/blkdev.h>
50 #include <linux/moduleparam.h>
51 #include <linux/delay.h>
52 #include <linux/jiffies.h>
53 #include <linux/smp_lock.h>
54 #include <asm/uaccess.h>
56 #include <asm/system.h>
58 /* The driver prints some debugging information on the console if DEBUG
59 is defined and non-zero. */
62 /* The message level for the debug messages is currently set to KERN_NOTICE
63 so that people can easily see the messages. Later when the debugging messages
64 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
65 #define OSST_DEB_MSG KERN_NOTICE
67 #include <scsi/scsi.h>
68 #include <scsi/scsi_dbg.h>
69 #include <scsi/scsi_device.h>
70 #include <scsi/scsi_driver.h>
71 #include <scsi/scsi_eh.h>
72 #include <scsi/scsi_host.h>
73 #include <scsi/scsi_ioctl.h>
75 #define ST_KILOBYTE 1024
79 #include "osst_options.h"
80 #include "osst_detect.h"
82 static int max_dev
= 0;
83 static int write_threshold_kbs
= 0;
84 static int max_sg_segs
= 0;
87 MODULE_AUTHOR("Willem Riede");
88 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
89 MODULE_LICENSE("GPL");
90 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR
);
91 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE
);
93 module_param(max_dev
, int, 0444);
94 MODULE_PARM_DESC(max_dev
, "Maximum number of OnStream Tape Drives to attach (4)");
96 module_param(write_threshold_kbs
, int, 0644);
97 MODULE_PARM_DESC(write_threshold_kbs
, "Asynchronous write threshold (KB; 32)");
99 module_param(max_sg_segs
, int, 0644);
100 MODULE_PARM_DESC(max_sg_segs
, "Maximum number of scatter/gather segments to use (9)");
102 static struct osst_dev_parm
{
105 } parms
[] __initdata
= {
106 { "max_dev", &max_dev
},
107 { "write_threshold_kbs", &write_threshold_kbs
},
108 { "max_sg_segs", &max_sg_segs
}
112 /* Some default definitions have been moved to osst_options.h */
113 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
114 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116 /* The buffer size should fit into the 24 bits for length in the
117 6-byte SCSI read and write commands. */
118 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
119 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
123 static int debugging
= 1;
124 /* uncomment define below to test error recovery */
125 // #define OSST_INJECT_ERRORS 1
128 /* Do not retry! The drive firmware already retries when appropriate,
129 and when it tries to tell us something, we had better listen... */
130 #define MAX_RETRIES 0
132 #define NO_TAPE NOT_READY
134 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
135 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
136 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
138 #define OSST_TIMEOUT (200 * HZ)
139 #define OSST_LONG_TIMEOUT (1800 * HZ)
141 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
142 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
143 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
144 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
146 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
148 #define SET_DENS_AND_BLK 0x10001
150 static int osst_buffer_size
= OSST_BUFFER_SIZE
;
151 static int osst_write_threshold
= OSST_WRITE_THRESHOLD
;
152 static int osst_max_sg_segs
= OSST_MAX_SG
;
153 static int osst_max_dev
= OSST_MAX_TAPES
;
154 static int osst_nr_dev
;
156 static struct osst_tape
**os_scsi_tapes
= NULL
;
157 static DEFINE_RWLOCK(os_scsi_tapes_lock
);
159 static int modes_defined
= 0;
161 static struct osst_buffer
*new_tape_buffer(int, int, int);
162 static int enlarge_buffer(struct osst_buffer
*, int);
163 static void normalize_buffer(struct osst_buffer
*);
164 static int append_to_buffer(const char __user
*, struct osst_buffer
*, int);
165 static int from_buffer(struct osst_buffer
*, char __user
*, int);
166 static int osst_zero_buffer_tail(struct osst_buffer
*);
167 static int osst_copy_to_buffer(struct osst_buffer
*, unsigned char *);
168 static int osst_copy_from_buffer(struct osst_buffer
*, unsigned char *);
170 static int osst_probe(struct device
*);
171 static int osst_remove(struct device
*);
173 static struct scsi_driver osst_template
= {
174 .owner
= THIS_MODULE
,
178 .remove
= osst_remove
,
182 static int osst_int_ioctl(struct osst_tape
*STp
, struct osst_request
** aSRpnt
,
183 unsigned int cmd_in
, unsigned long arg
);
185 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int frame
, int skip
);
187 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
189 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
191 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
);
193 static inline char *tape_name(struct osst_tape
*tape
)
195 return tape
->drive
->disk_name
;
198 /* Routines that handle the interaction with mid-layer SCSI routines */
201 /* Normalize Sense */
202 static void osst_analyze_sense(struct osst_request
*SRpnt
, struct st_cmdstatus
*s
)
205 const u8
*sense
= SRpnt
->sense
;
207 s
->have_sense
= scsi_normalize_sense(SRpnt
->sense
,
208 SCSI_SENSE_BUFFERSIZE
, &s
->sense_hdr
);
214 scsi_get_sense_info_fld(sense
, SCSI_SENSE_BUFFERSIZE
, &s
->uremainder64
);
215 switch (sense
[0] & 0x7f) {
220 s
->flags
= sense
[2] & 0xe0;
226 ucp
= scsi_sense_desc_find(sense
, SCSI_SENSE_BUFFERSIZE
, 4);
227 s
->flags
= ucp
? (ucp
[3] & 0xe0) : 0;
233 /* Convert the result to success code */
234 static int osst_chk_result(struct osst_tape
* STp
, struct osst_request
* SRpnt
)
236 char *name
= tape_name(STp
);
237 int result
= SRpnt
->result
;
238 u8
* sense
= SRpnt
->sense
, scode
;
242 struct st_cmdstatus
*cmdstatp
;
247 cmdstatp
= &STp
->buffer
->cmdstat
;
248 osst_analyze_sense(SRpnt
, cmdstatp
);
250 if (cmdstatp
->have_sense
)
251 scode
= STp
->buffer
->cmdstat
.sense_hdr
.sense_key
;
256 printk(OSST_DEB_MSG
"%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
258 SRpnt
->cmd
[0], SRpnt
->cmd
[1], SRpnt
->cmd
[2],
259 SRpnt
->cmd
[3], SRpnt
->cmd
[4], SRpnt
->cmd
[5]);
260 if (scode
) printk(OSST_DEB_MSG
"%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
261 name
, scode
, sense
[12], sense
[13]);
262 if (cmdstatp
->have_sense
)
263 __scsi_print_sense("osst ", SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
267 if (cmdstatp
->have_sense
&& (
269 scode
!= RECOVERED_ERROR
&&
270 /* scode != UNIT_ATTENTION && */
271 scode
!= BLANK_CHECK
&&
272 scode
!= VOLUME_OVERFLOW
&&
273 SRpnt
->cmd
[0] != MODE_SENSE
&&
274 SRpnt
->cmd
[0] != TEST_UNIT_READY
)) { /* Abnormal conditions for tape */
275 if (cmdstatp
->have_sense
) {
276 printk(KERN_WARNING
"%s:W: Command with sense data:\n", name
);
277 __scsi_print_sense("osst ", SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
280 static int notyetprinted
= 1;
283 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
284 name
, result
, suggestion(result
), driver_byte(result
) & DRIVER_MASK
,
289 "%s:I: This warning may be caused by your scsi controller,\n", name
);
291 "%s:I: it has been reported with some Buslogic cards.\n", name
);
295 STp
->pos_unknown
|= STp
->device
->was_reset
;
297 if (cmdstatp
->have_sense
&& scode
== RECOVERED_ERROR
) {
298 STp
->recover_count
++;
299 STp
->recover_erreg
++;
302 if (SRpnt
->cmd
[0] == READ_6
)
304 else if (SRpnt
->cmd
[0] == WRITE_6
)
308 printk(OSST_DEB_MSG
"%s:D: Recovered %s error (%d).\n", name
, stp
,
312 if ((sense
[2] & 0xe0) == 0)
319 /* Wakeup from interrupt */
320 static void osst_sleep_done(void *data
, char *sense
, int result
, int resid
)
322 struct osst_request
*SRpnt
= data
;
323 struct osst_tape
*STp
= SRpnt
->stp
;
325 memcpy(SRpnt
->sense
, sense
, SCSI_SENSE_BUFFERSIZE
);
326 STp
->buffer
->cmdstat
.midlevel_result
= SRpnt
->result
= result
;
328 STp
->write_pending
= 0;
331 complete(SRpnt
->waiting
);
334 /* osst_request memory management */
335 static struct osst_request
*osst_allocate_request(void)
337 return kzalloc(sizeof(struct osst_request
), GFP_KERNEL
);
340 static void osst_release_request(struct osst_request
*streq
)
345 /* Do the scsi command. Waits until command performed if do_wait is true.
346 Otherwise osst_write_behind_check() is used to check that the command
348 static struct osst_request
* osst_do_scsi(struct osst_request
*SRpnt
, struct osst_tape
*STp
,
349 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
352 unsigned short use_sg
;
353 #ifdef OSST_INJECT_ERRORS
354 static int inject
= 0;
355 static int repeat
= 0;
357 struct completion
*waiting
;
359 /* if async, make sure there's no command outstanding */
360 if (!do_wait
&& ((STp
->buffer
)->last_SRpnt
)) {
361 printk(KERN_ERR
"%s: Async command already active.\n",
363 if (signal_pending(current
))
364 (STp
->buffer
)->syscall_result
= (-EINTR
);
366 (STp
->buffer
)->syscall_result
= (-EBUSY
);
371 SRpnt
= osst_allocate_request();
373 printk(KERN_ERR
"%s: Can't allocate SCSI request.\n",
375 if (signal_pending(current
))
376 (STp
->buffer
)->syscall_result
= (-EINTR
);
378 (STp
->buffer
)->syscall_result
= (-EBUSY
);
384 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
385 which IO is outstanding. It's nulled out when the IO completes. */
387 (STp
->buffer
)->last_SRpnt
= SRpnt
;
389 waiting
= &STp
->wait
;
390 init_completion(waiting
);
391 SRpnt
->waiting
= waiting
;
393 use_sg
= (bytes
> STp
->buffer
->sg
[0].length
) ? STp
->buffer
->use_sg
: 0;
395 bp
= (char *)&(STp
->buffer
->sg
[0]);
396 if (STp
->buffer
->sg_segs
< use_sg
)
397 use_sg
= STp
->buffer
->sg_segs
;
400 bp
= (STp
->buffer
)->b_data
;
402 memcpy(SRpnt
->cmd
, cmd
, sizeof(SRpnt
->cmd
));
403 STp
->buffer
->cmdstat
.have_sense
= 0;
404 STp
->buffer
->syscall_result
= 0;
406 if (scsi_execute_async(STp
->device
, cmd
, COMMAND_SIZE(cmd
[0]), direction
, bp
, bytes
,
407 use_sg
, timeout
, retries
, SRpnt
, osst_sleep_done
, GFP_KERNEL
))
408 /* could not allocate the buffer or request was too large */
409 (STp
->buffer
)->syscall_result
= (-EBUSY
);
411 wait_for_completion(waiting
);
412 SRpnt
->waiting
= NULL
;
413 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
414 #ifdef OSST_INJECT_ERRORS
415 if (STp
->buffer
->syscall_result
== 0 &&
418 ( (++ inject
% 83) == 29 ||
419 (STp
->first_frame_position
== 240
420 /* or STp->read_error_frame to fail again on the block calculated above */ &&
422 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
423 STp
->buffer
->last_result_fatal
= 1;
431 /* Handle the write-behind checking (downs the semaphore) */
432 static void osst_write_behind_check(struct osst_tape
*STp
)
434 struct osst_buffer
* STbuffer
;
436 STbuffer
= STp
->buffer
;
439 if (STp
->write_pending
)
444 wait_for_completion(&(STp
->wait
));
445 STp
->buffer
->last_SRpnt
->waiting
= NULL
;
447 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
449 if (STp
->buffer
->syscall_result
)
450 STp
->buffer
->syscall_result
=
451 osst_write_error_recovery(STp
, &(STp
->buffer
->last_SRpnt
), 1);
453 STp
->first_frame_position
++;
455 osst_release_request(STp
->buffer
->last_SRpnt
);
457 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
458 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
460 STbuffer
->last_SRpnt
= NULL
;
461 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
462 STbuffer
->writing
= 0;
469 /* Onstream specific Routines */
471 * Initialize the OnStream AUX
473 static void osst_init_aux(struct osst_tape
* STp
, int frame_type
, int frame_seq_number
,
474 int logical_blk_num
, int blk_sz
, int blk_cnt
)
476 os_aux_t
*aux
= STp
->buffer
->aux
;
477 os_partition_t
*par
= &aux
->partition
;
478 os_dat_t
*dat
= &aux
->dat
;
480 if (STp
->raw
) return;
482 memset(aux
, 0, sizeof(*aux
));
483 aux
->format_id
= htonl(0);
484 memcpy(aux
->application_sig
, "LIN4", 4);
485 aux
->hdwr
= htonl(0);
486 aux
->frame_type
= frame_type
;
488 switch (frame_type
) {
489 case OS_FRAME_TYPE_HEADER
:
490 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
491 par
->partition_num
= OS_CONFIG_PARTITION
;
492 par
->par_desc_ver
= OS_PARTITION_VERSION
;
493 par
->wrt_pass_cntr
= htons(0xffff);
494 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
495 par
->first_frame_ppos
= htonl(0);
496 par
->last_frame_ppos
= htonl(0xbb7);
497 aux
->frame_seq_num
= htonl(0);
498 aux
->logical_blk_num_high
= htonl(0);
499 aux
->logical_blk_num
= htonl(0);
500 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
502 case OS_FRAME_TYPE_DATA
:
503 case OS_FRAME_TYPE_MARKER
:
508 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
509 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
510 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
511 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
512 dat
->dat_list
[0].reserved
= 0;
513 case OS_FRAME_TYPE_EOD
:
514 aux
->update_frame_cntr
= htonl(0);
515 par
->partition_num
= OS_DATA_PARTITION
;
516 par
->par_desc_ver
= OS_PARTITION_VERSION
;
517 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
518 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
519 par
->last_frame_ppos
= htonl(STp
->capacity
);
520 aux
->frame_seq_num
= htonl(frame_seq_number
);
521 aux
->logical_blk_num_high
= htonl(0);
522 aux
->logical_blk_num
= htonl(logical_blk_num
);
524 default: ; /* probably FILL */
526 aux
->filemark_cnt
= htonl(STp
->filemark_cnt
);
527 aux
->phys_fm
= htonl(0xffffffff);
528 aux
->last_mark_ppos
= htonl(STp
->last_mark_ppos
);
529 aux
->last_mark_lbn
= htonl(STp
->last_mark_lbn
);
533 * Verify that we have the correct tape frame
535 static int osst_verify_frame(struct osst_tape
* STp
, int frame_seq_number
, int quiet
)
537 char * name
= tape_name(STp
);
538 os_aux_t
* aux
= STp
->buffer
->aux
;
539 os_partition_t
* par
= &(aux
->partition
);
540 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
541 int blk_cnt
, blk_sz
, i
;
544 if (STp
->buffer
->syscall_result
) {
545 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
546 memset(page_address(sg_page(&STp
->buffer
->sg
[i
])),
547 0, STp
->buffer
->sg
[i
].length
);
548 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
550 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
553 if (STp
->buffer
->syscall_result
) {
555 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
559 if (ntohl(aux
->format_id
) != 0) {
561 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
565 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
566 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
568 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
572 if (par
->partition_num
!= OS_DATA_PARTITION
) {
573 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
575 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
576 name
, par
->partition_num
);
581 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
583 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
587 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
589 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
590 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
594 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
595 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
596 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
599 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
604 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
605 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
606 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
607 STp
->first_frame_position
);
610 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
613 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
614 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
619 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
620 STps
->eof
= ST_FM_HIT
;
622 i
= ntohl(aux
->filemark_cnt
);
623 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
624 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
626 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
627 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
628 i
, STp
->first_frame_position
- 1);
630 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
631 if (i
>= STp
->filemark_cnt
)
632 STp
->filemark_cnt
= i
+1;
635 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
636 STps
->eof
= ST_EOD_1
;
637 STp
->frame_in_buffer
= 1;
639 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
640 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
641 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
642 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
643 STp
->buffer
->read_pointer
= 0;
644 STp
->frame_in_buffer
= 1;
646 /* See what block size was used to write file */
647 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
649 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
650 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
651 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
652 STp
->block_size
<1024?'b':'k');
653 STp
->block_size
= blk_sz
;
654 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
656 STps
->eof
= ST_NOEOF
;
658 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
659 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
663 if (STp
->read_error_frame
== 0)
664 STp
->read_error_frame
= STp
->first_frame_position
- 1;
669 * Wait for the unit to become Ready
671 static int osst_wait_ready(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
672 unsigned timeout
, int initial_delay
)
674 unsigned char cmd
[MAX_COMMAND_SIZE
];
675 struct osst_request
* SRpnt
;
676 unsigned long startwait
= jiffies
;
679 char * name
= tape_name(STp
);
681 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
684 if (initial_delay
> 0)
685 msleep(jiffies_to_msecs(initial_delay
));
687 memset(cmd
, 0, MAX_COMMAND_SIZE
);
688 cmd
[0] = TEST_UNIT_READY
;
690 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
692 if (!SRpnt
) return (-EBUSY
);
694 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
695 (( SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
696 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8) ) ||
697 ( SRpnt
->sense
[2] == 6 && SRpnt
->sense
[12] == 0x28 &&
698 SRpnt
->sense
[13] == 0 ) )) {
701 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
702 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
708 memset(cmd
, 0, MAX_COMMAND_SIZE
);
709 cmd
[0] = TEST_UNIT_READY
;
711 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
717 if ( STp
->buffer
->syscall_result
&&
718 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
720 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
721 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
722 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
723 SRpnt
->sense
[12], SRpnt
->sense
[13]);
728 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
734 * Wait for a tape to be inserted in the unit
736 static int osst_wait_for_medium(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, unsigned timeout
)
738 unsigned char cmd
[MAX_COMMAND_SIZE
];
739 struct osst_request
* SRpnt
;
740 unsigned long startwait
= jiffies
;
743 char * name
= tape_name(STp
);
745 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
748 memset(cmd
, 0, MAX_COMMAND_SIZE
);
749 cmd
[0] = TEST_UNIT_READY
;
751 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
753 if (!SRpnt
) return (-EBUSY
);
755 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
756 SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 0x3a && SRpnt
->sense
[13] == 0 ) {
759 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
760 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
766 memset(cmd
, 0, MAX_COMMAND_SIZE
);
767 cmd
[0] = TEST_UNIT_READY
;
769 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
775 if ( STp
->buffer
->syscall_result
&& SRpnt
->sense
[2] != 2 &&
776 SRpnt
->sense
[12] != 4 && SRpnt
->sense
[13] == 1) {
778 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
779 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
780 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
781 SRpnt
->sense
[12], SRpnt
->sense
[13]);
786 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
791 static int osst_position_tape_and_confirm(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int frame
)
795 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
796 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
797 if (retval
) return (retval
);
798 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
799 return (osst_get_frame_position(STp
, aSRpnt
));
803 * Wait for write(s) to complete
805 static int osst_flush_drive_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
807 unsigned char cmd
[MAX_COMMAND_SIZE
];
808 struct osst_request
* SRpnt
;
810 int delay
= OSST_WAIT_WRITE_COMPLETE
;
812 char * name
= tape_name(STp
);
814 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
817 memset(cmd
, 0, MAX_COMMAND_SIZE
);
818 cmd
[0] = WRITE_FILEMARKS
;
821 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
823 if (!SRpnt
) return (-EBUSY
);
824 if (STp
->buffer
->syscall_result
) {
825 if ((SRpnt
->sense
[2] & 0x0f) == 2 && SRpnt
->sense
[12] == 4) {
826 if (SRpnt
->sense
[13] == 8) {
827 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
830 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
832 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
833 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
838 #define OSST_POLL_PER_SEC 10
839 static int osst_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int curr
, int minlast
, int to
)
841 unsigned long startwait
= jiffies
;
842 char * name
= tape_name(STp
);
844 char notyetprinted
= 1;
846 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
847 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
849 while (time_before (jiffies
, startwait
+ to
*HZ
))
852 result
= osst_get_frame_position(STp
, aSRpnt
);
854 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
855 return 0; /* successful recovery leaves drive ready for frame */
856 if (result
< 0) break;
857 if (STp
->first_frame_position
== curr
&&
859 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
860 (minlast
>= 0 && STp
->cur_frames
> minlast
)
864 if (debugging
|| time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
))
866 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
867 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
868 STp
->last_frame_position
, STp
->cur_frames
,
869 result
, (jiffies
-startwait
)/HZ
,
870 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
875 if (time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
) && notyetprinted
)
877 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
878 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
879 STp
->last_frame_position
, STp
->cur_frames
, result
);
883 msleep(1000 / OSST_POLL_PER_SEC
);
886 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
887 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
888 STp
->last_frame_position
, STp
->cur_frames
,
889 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
894 static int osst_recover_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int writing
)
896 struct osst_request
* SRpnt
;
897 unsigned char cmd
[MAX_COMMAND_SIZE
];
898 unsigned long startwait
= jiffies
;
900 char * name
= tape_name(STp
);
904 char * olddata
= STp
->buffer
->b_data
;
905 int oldsize
= STp
->buffer
->buffer_size
;
907 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
909 memset(cmd
, 0, MAX_COMMAND_SIZE
);
910 cmd
[0] = WRITE_FILEMARKS
;
912 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
915 while (retval
&& time_before (jiffies
, startwait
+ 5*60*HZ
)) {
917 if (STp
->buffer
->syscall_result
&& (SRpnt
->sense
[2] & 0x0f) != 2) {
919 /* some failure - not just not-ready */
920 retval
= osst_write_error_recovery(STp
, aSRpnt
, 0);
923 schedule_timeout_interruptible(HZ
/ OSST_POLL_PER_SEC
);
925 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
926 memset(cmd
, 0, MAX_COMMAND_SIZE
);
927 cmd
[0] = READ_POSITION
;
929 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
932 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
933 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
936 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
938 /* TODO - figure out which error conditions can be handled */
939 if (STp
->buffer
->syscall_result
)
941 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
942 (*aSRpnt
)->sense
[ 2] & 0x0f,
943 (*aSRpnt
)->sense
[12],
944 (*aSRpnt
)->sense
[13]);
950 * Read the next OnStream tape frame at the current location
952 static int osst_read_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int timeout
)
954 unsigned char cmd
[MAX_COMMAND_SIZE
];
955 struct osst_request
* SRpnt
;
958 os_aux_t
* aux
= STp
->buffer
->aux
;
959 char * name
= tape_name(STp
);
963 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
964 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
966 memset(cmd
, 0, MAX_COMMAND_SIZE
);
973 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
975 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
976 STp
->timeout
, MAX_RETRIES
, 1);
981 if ((STp
->buffer
)->syscall_result
) {
983 if (STp
->read_error_frame
== 0) {
984 STp
->read_error_frame
= STp
->first_frame_position
;
986 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
991 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
993 SRpnt
->sense
[0], SRpnt
->sense
[1],
994 SRpnt
->sense
[2], SRpnt
->sense
[3],
995 SRpnt
->sense
[4], SRpnt
->sense
[5],
996 SRpnt
->sense
[6], SRpnt
->sense
[7]);
1000 STp
->first_frame_position
++;
1005 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
1008 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
1009 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
1010 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
1011 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
1012 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
1013 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
1014 if (aux
->frame_type
==2)
1015 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
1016 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
1017 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
1023 static int osst_initiate_read(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1025 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1026 struct osst_request
* SRpnt
;
1027 unsigned char cmd
[MAX_COMMAND_SIZE
];
1029 char * name
= tape_name(STp
);
1031 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
1032 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
1033 STp
->write_type
= OS_WRITE_DATA
;
1034 osst_flush_write_buffer(STp
, aSRpnt
);
1035 osst_flush_drive_buffer(STp
, aSRpnt
);
1037 STps
->rw
= ST_READING
;
1038 STp
->frame_in_buffer
= 0;
1041 * Issue a read 0 command to get the OnStream drive
1042 * read frames into its buffer.
1044 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1049 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
1051 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
1053 if ((retval
= STp
->buffer
->syscall_result
))
1054 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1060 static int osst_get_logical_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1061 int frame_seq_number
, int quiet
)
1063 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1064 char * name
= tape_name(STp
);
1072 * If we want just any frame (-1) and there is a frame in the buffer, return it
1074 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1076 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1081 * Search and wait for the next logical tape frame
1085 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1086 name
, frame_seq_number
);
1087 if (STp
->read_error_frame
) {
1088 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1090 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1091 name
, STp
->read_error_frame
);
1093 STp
->read_error_frame
= 0;
1100 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1101 name
, frame_seq_number
, cnt
);
1103 if ( osst_initiate_read(STp
, aSRpnt
)
1104 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1107 position
= osst_get_frame_position(STp
, aSRpnt
);
1108 if (position
>= 0xbae && position
< 0xbb8)
1110 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1111 position
= STp
->read_error_frame
- 1;
1119 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1122 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1125 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1127 if (osst_verify_frame(STp
, -1, quiet
)) {
1128 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1129 if (STp
->fast_open
) {
1131 "%s:W: Found logical frame %d instead of %d after fast open\n",
1132 name
, x
, frame_seq_number
);
1134 STp
->read_error_frame
= 0;
1137 if (x
> frame_seq_number
) {
1139 /* positioning backwards did not bring us to the desired frame */
1140 position
= STp
->read_error_frame
- 1;
1143 position
= osst_get_frame_position(STp
, aSRpnt
)
1144 + frame_seq_number
- x
- 1;
1146 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1151 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1152 name
, x
, frame_seq_number
,
1153 STp
->first_frame_position
- position
);
1155 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1161 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1163 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1165 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1168 STp
->frame_in_buffer
= 0;
1171 STp
->recover_count
++;
1172 STp
->recover_erreg
++;
1173 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1174 name
, STp
->read_error_frame
);
1179 if (debugging
|| STps
->eof
)
1181 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1182 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1185 STp
->read_error_frame
= 0;
1189 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int logical_blk_num
)
1191 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1192 char * name
= tape_name(STp
);
1194 int frame_seq_estimate
, ppos_estimate
, move
;
1196 if (logical_blk_num
< 0) logical_blk_num
= 0;
1198 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1199 name
, logical_blk_num
, STp
->logical_blk_num
,
1200 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1201 STp
->block_size
<1024?'b':'k');
1203 /* Do we know where we are? */
1204 if (STps
->drv_block
>= 0) {
1205 move
= logical_blk_num
- STp
->logical_blk_num
;
1206 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1207 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1208 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1210 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1212 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1213 else ppos_estimate
= frame_seq_estimate
+ 20;
1214 while (++retries
< 10) {
1215 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1216 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1217 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1219 if (frame_seq_estimate
< 0) {
1220 frame_seq_estimate
= 0;
1223 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1224 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1225 /* we've located the estimated frame, now does it have our block? */
1226 if (logical_blk_num
< STp
->logical_blk_num
||
1227 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1228 if (STps
->eof
== ST_FM_HIT
)
1229 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1231 move
= logical_blk_num
- STp
->logical_blk_num
;
1232 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1233 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1235 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1238 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1239 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1240 STp
->logical_blk_num
, logical_blk_num
, move
);
1242 frame_seq_estimate
+= move
;
1243 ppos_estimate
+= move
;
1246 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1247 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1248 STp
->logical_blk_num
= logical_blk_num
;
1251 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1252 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1253 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1256 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1257 if (STps
->eof
== ST_FM_HIT
) {
1259 STps
->drv_block
= 0;
1261 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1262 STp
->logical_blk_num
-
1263 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1266 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1270 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1272 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1274 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1275 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1276 STp
->logical_blk_num
, logical_blk_num
);
1278 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1279 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1284 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1285 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1289 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1290 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1291 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1292 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1294 #define OSST_FRAME_SHIFT 6
1295 #define OSST_SECTOR_SHIFT 9
1296 #define OSST_SECTOR_MASK 0x03F
1298 static int osst_get_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1302 char * name
= tape_name(STp
);
1305 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1306 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1307 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1308 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1309 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1310 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1312 /* do we know where we are inside a file? */
1313 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1314 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1315 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1316 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1317 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1319 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1321 sector
= osst_get_frame_position(STp
, aSRpnt
);
1323 sector
<<= OSST_FRAME_SHIFT
;
1328 static int osst_seek_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int sector
)
1330 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1331 int frame
= sector
>> OSST_FRAME_SHIFT
,
1332 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1335 char * name
= tape_name(STp
);
1337 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1338 name
, sector
, frame
, offset
);
1340 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1342 if (frame
<= STp
->first_data_ppos
) {
1343 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1344 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1346 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1347 if (r
< 0) return r
;
1349 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1350 if (r
< 0) return r
;
1352 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1355 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1356 STp
->buffer
->read_pointer
= offset
;
1357 STp
->buffer
->buffer_bytes
-= offset
;
1359 STp
->frame_seq_number
++;
1360 STp
->frame_in_buffer
= 0;
1361 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1362 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1364 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1365 if (STps
->eof
== ST_FM_HIT
) {
1367 STps
->drv_block
= 0;
1369 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1370 STp
->logical_blk_num
-
1371 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1374 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1377 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1378 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1379 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1385 * Read back the drive's internal buffer contents, as a part
1386 * of the write error recovery mechanism for old OnStream
1387 * firmware revisions.
1388 * Precondition for this function to work: all frames in the
1389 * drive's buffer must be of one type (DATA, MARK or EOD)!
1391 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1392 unsigned int frame
, unsigned int skip
, int pending
)
1394 struct osst_request
* SRpnt
= * aSRpnt
;
1395 unsigned char * buffer
, * p
;
1396 unsigned char cmd
[MAX_COMMAND_SIZE
];
1397 int flag
, new_frame
, i
;
1398 int nframes
= STp
->cur_frames
;
1399 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1400 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1401 - (nframes
+ pending
- 1);
1402 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1403 - (nframes
+ pending
- 1) * blks_per_frame
;
1404 char * name
= tape_name(STp
);
1405 unsigned long startwait
= jiffies
;
1407 int dbg
= debugging
;
1410 if ((buffer
= (unsigned char *)vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1413 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1414 name
, nframes
, pending
?" and one that was pending":"");
1416 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1418 if (pending
&& debugging
)
1419 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1420 name
, frame_seq_number
+ nframes
,
1421 logical_blk_num
+ nframes
* blks_per_frame
,
1422 p
[0], p
[1], p
[2], p
[3]);
1424 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1426 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1427 cmd
[0] = 0x3C; /* Buffer Read */
1428 cmd
[1] = 6; /* Retrieve Faulty Block */
1429 cmd
[7] = 32768 >> 8;
1430 cmd
[8] = 32768 & 0xff;
1432 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1433 STp
->timeout
, MAX_RETRIES
, 1);
1435 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1436 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1441 osst_copy_from_buffer(STp
->buffer
, p
);
1444 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1445 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1449 osst_get_frame_position(STp
, aSRpnt
);
1452 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1454 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1455 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1457 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1460 if (STp
->write_type
== OS_WRITE_HEADER
) {
1462 p
+= skip
* OS_DATA_SIZE
;
1464 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1469 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1470 name
, new_frame
+i
, frame_seq_number
+i
);
1472 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1473 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1474 osst_get_frame_position(STp
, aSRpnt
);
1477 if (new_frame
> frame
+ 1000) {
1478 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1482 if ( i
>= nframes
+ pending
) break;
1485 osst_copy_to_buffer(STp
->buffer
, p
);
1487 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1489 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1490 logical_blk_num
+ i
*blks_per_frame
,
1491 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1492 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1500 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1501 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1502 p
[0], p
[1], p
[2], p
[3]);
1504 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1505 STp
->timeout
, MAX_RETRIES
, 1);
1507 if (STp
->buffer
->syscall_result
)
1510 p
+= OS_DATA_SIZE
; i
++;
1512 /* if we just sent the last frame, wait till all successfully written */
1513 if ( i
== nframes
+ pending
) {
1515 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1517 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1518 cmd
[0] = WRITE_FILEMARKS
;
1520 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1521 STp
->timeout
, MAX_RETRIES
, 1);
1524 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1525 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1529 flag
= STp
->buffer
->syscall_result
;
1530 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1532 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1533 cmd
[0] = TEST_UNIT_READY
;
1535 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1538 if (SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
1539 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8)) {
1540 /* in the process of becoming ready */
1544 if (STp
->buffer
->syscall_result
)
1550 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1556 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1557 SRpnt
->sense
[12] == 0 &&
1558 SRpnt
->sense
[13] == 2) {
1559 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1561 return (-EIO
); /* hit end of tape = fail */
1563 i
= ((SRpnt
->sense
[3] << 24) |
1564 (SRpnt
->sense
[4] << 16) |
1565 (SRpnt
->sense
[5] << 8) |
1566 SRpnt
->sense
[6] ) - new_frame
;
1567 p
= &buffer
[i
* OS_DATA_SIZE
];
1569 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1571 osst_get_frame_position(STp
, aSRpnt
);
1573 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1574 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1579 /* error recovery did not successfully complete */
1580 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1581 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1584 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1589 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1590 unsigned int frame
, unsigned int skip
, int pending
)
1592 unsigned char cmd
[MAX_COMMAND_SIZE
];
1593 struct osst_request
* SRpnt
;
1594 char * name
= tape_name(STp
);
1596 int attempts
= 1000 / skip
;
1598 unsigned long startwait
= jiffies
;
1600 int dbg
= debugging
;
1603 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1608 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1610 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1612 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1613 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1615 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1618 schedule_timeout_interruptible(msecs_to_jiffies(100));
1620 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1622 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1623 name
, STp
->first_frame_position
,
1624 STp
->last_frame_position
, STp
->cur_frames
);
1626 frame
= STp
->last_frame_position
;
1630 if (pending
&& STp
->cur_frames
< 50) {
1632 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1637 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1638 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1640 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1641 STp
->timeout
, MAX_RETRIES
, 1);
1644 if (STp
->buffer
->syscall_result
) { /* additional write error */
1645 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1646 SRpnt
->sense
[12] == 0 &&
1647 SRpnt
->sense
[13] == 2) {
1649 "%s:E: Volume overflow in write error recovery\n",
1651 break; /* hit end of tape = fail */
1660 if (STp
->cur_frames
== 0) {
1663 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1665 if (STp
->first_frame_position
!= expected
) {
1666 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1667 name
, STp
->first_frame_position
, expected
);
1674 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1675 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1679 schedule_timeout_interruptible(msecs_to_jiffies(100));
1681 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1689 * Error recovery algorithm for the OnStream tape.
1692 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
)
1694 struct osst_request
* SRpnt
= * aSRpnt
;
1695 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1696 char * name
= tape_name(STp
);
1699 unsigned int frame
, skip
;
1701 rw_state
= STps
->rw
;
1703 if ((SRpnt
->sense
[ 2] & 0x0f) != 3
1704 || SRpnt
->sense
[12] != 12
1705 || SRpnt
->sense
[13] != 0) {
1707 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1708 SRpnt
->sense
[2], SRpnt
->sense
[12], SRpnt
->sense
[13]);
1712 frame
= (SRpnt
->sense
[3] << 24) |
1713 (SRpnt
->sense
[4] << 16) |
1714 (SRpnt
->sense
[5] << 8) |
1716 skip
= SRpnt
->sense
[9];
1719 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1721 osst_get_frame_position(STp
, aSRpnt
);
1723 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1724 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1726 switch (STp
->write_type
) {
1729 case OS_WRITE_NEW_MARK
:
1731 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1732 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1733 if (STp
->os_fw_rev
>= 10600)
1734 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1736 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1737 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1739 retval
?"" :"Don't worry, ",
1740 retval
?" not ":" ");
1742 case OS_WRITE_LAST_MARK
:
1743 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1744 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1747 case OS_WRITE_HEADER
:
1748 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1749 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1752 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1753 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1755 osst_get_frame_position(STp
, aSRpnt
);
1757 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1758 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1759 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1762 STp
->recover_count
++;
1763 STp
->recover_erreg
++;
1767 STps
->rw
= rw_state
;
1771 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1772 int mt_op
, int mt_count
)
1774 char * name
= tape_name(STp
);
1776 int last_mark_ppos
= -1;
1779 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1781 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1783 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1787 if (STp
->linux_media_version
>= 4) {
1789 * direct lookup in header filemark list
1791 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1792 if (STp
->header_ok
&&
1793 STp
->header_cache
!= NULL
&&
1794 (cnt
- mt_count
) >= 0 &&
1795 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1796 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1797 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1799 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1801 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1802 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1803 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1805 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1807 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1808 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1809 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1810 mt_count
, last_mark_ppos
);
1812 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1813 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1814 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1817 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1821 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1822 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1823 name
, last_mark_ppos
);
1829 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1833 while (cnt
!= mt_count
) {
1834 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1835 if (last_mark_ppos
== -1)
1838 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1840 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1842 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1844 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1848 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1849 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1850 name
, last_mark_ppos
);
1855 if (mt_op
== MTBSFM
) {
1856 STp
->frame_seq_number
++;
1857 STp
->frame_in_buffer
= 0;
1858 STp
->buffer
->buffer_bytes
= 0;
1859 STp
->buffer
->read_pointer
= 0;
1860 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1866 * ADRL 1.1 compatible "slow" space filemarks fwd version
1868 * Just scans for the filemark sequentially.
1870 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1871 int mt_op
, int mt_count
)
1875 char * name
= tape_name(STp
);
1877 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1879 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1881 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1886 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1888 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1892 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1894 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1896 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1898 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1900 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1901 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1903 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1907 if (cnt
== mt_count
)
1909 STp
->frame_in_buffer
= 0;
1911 if (mt_op
== MTFSF
) {
1912 STp
->frame_seq_number
++;
1913 STp
->frame_in_buffer
= 0;
1914 STp
->buffer
->buffer_bytes
= 0;
1915 STp
->buffer
->read_pointer
= 0;
1916 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1922 * Fast linux specific version of OnStream FSF
1924 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1925 int mt_op
, int mt_count
)
1927 char * name
= tape_name(STp
);
1929 next_mark_ppos
= -1;
1932 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
1934 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1936 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1941 if (STp
->linux_media_version
>= 4) {
1943 * direct lookup in header filemark list
1945 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
1946 if (STp
->header_ok
&&
1947 STp
->header_cache
!= NULL
&&
1948 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
1949 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
1950 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1951 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
1953 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
1955 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
1956 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1957 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1959 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1961 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1962 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
1963 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1964 mt_count
, next_mark_ppos
);
1966 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
1968 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1970 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
1972 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
1973 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1975 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
1980 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1981 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1982 name
, next_mark_ppos
);
1985 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
1986 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
1987 name
, cnt
+mt_count
, next_mark_ppos
,
1988 ntohl(STp
->buffer
->aux
->filemark_cnt
));
1994 * Find nearest (usually previous) marker, then jump from marker to marker
1997 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1999 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
2001 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
2005 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
2006 if (STp
->first_mark_ppos
== -1) {
2008 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2010 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2012 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
2013 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2016 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2021 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2022 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
2023 name
, STp
->first_mark_ppos
);
2027 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
2033 while (cnt
!= mt_count
) {
2034 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
2035 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
2037 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2039 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
2042 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
2044 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2046 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2048 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2053 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2054 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2055 name
, next_mark_ppos
);
2060 if (mt_op
== MTFSF
) {
2061 STp
->frame_seq_number
++;
2062 STp
->frame_in_buffer
= 0;
2063 STp
->buffer
->buffer_bytes
= 0;
2064 STp
->buffer
->read_pointer
= 0;
2065 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2071 * In debug mode, we want to see as many errors as possible
2072 * to test the error recovery mechanism.
2075 static void osst_set_retries(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int retries
)
2077 unsigned char cmd
[MAX_COMMAND_SIZE
];
2078 struct osst_request
* SRpnt
= * aSRpnt
;
2079 char * name
= tape_name(STp
);
2081 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2082 cmd
[0] = MODE_SELECT
;
2084 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2086 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2087 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2088 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2089 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2090 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2091 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2092 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2093 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2096 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2098 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2101 if ((STp
->buffer
)->syscall_result
)
2102 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2107 static int osst_write_filemark(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2110 int this_mark_ppos
= STp
->first_frame_position
;
2111 int this_mark_lbn
= STp
->logical_blk_num
;
2113 char * name
= tape_name(STp
);
2116 if (STp
->raw
) return 0;
2118 STp
->write_type
= OS_WRITE_NEW_MARK
;
2120 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2121 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2124 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2125 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2126 STp
->last_mark_ppos
= this_mark_ppos
;
2127 STp
->last_mark_lbn
= this_mark_lbn
;
2128 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2129 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2130 if (STp
->filemark_cnt
++ == 0)
2131 STp
->first_mark_ppos
= this_mark_ppos
;
2135 static int osst_write_eod(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2139 char * name
= tape_name(STp
);
2142 if (STp
->raw
) return 0;
2144 STp
->write_type
= OS_WRITE_EOD
;
2145 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2147 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2148 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2152 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2153 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2154 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2158 static int osst_write_filler(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2160 char * name
= tape_name(STp
);
2163 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2165 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2166 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2167 STp
->write_type
= OS_WRITE_FILLER
;
2169 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2170 STp
->buffer
->buffer_bytes
= 6;
2172 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2173 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2178 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2180 return osst_flush_drive_buffer(STp
, aSRpnt
);
2183 static int __osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2185 char * name
= tape_name(STp
);
2189 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2191 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2192 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2193 STp
->write_type
= OS_WRITE_HEADER
;
2195 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2196 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2198 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2199 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2203 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2205 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2210 static int osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int locate_eod
)
2212 os_header_t
* header
;
2214 char * name
= tape_name(STp
);
2217 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2219 if (STp
->raw
) return 0;
2221 if (STp
->header_cache
== NULL
) {
2222 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2223 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2226 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2228 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2231 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2232 else STp
->update_frame_cntr
= 0;
2234 header
= STp
->header_cache
;
2235 strcpy(header
->ident_str
, "ADR_SEQ");
2236 header
->major_rev
= 1;
2237 header
->minor_rev
= 4;
2238 header
->ext_trk_tb_off
= htons(17192);
2239 header
->pt_par_num
= 1;
2240 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2241 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2242 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2243 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2244 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2245 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2246 header
->cfg_col_width
= htonl(20);
2247 header
->dat_col_width
= htonl(1500);
2248 header
->qfa_col_width
= htonl(0);
2249 header
->ext_track_tb
.nr_stream_part
= 1;
2250 header
->ext_track_tb
.et_ent_sz
= 32;
2251 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2252 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2253 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2254 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2255 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2256 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2257 header
->dat_fm_tab
.fm_part_num
= 0;
2258 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2259 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2260 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2262 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2263 if (STp
->update_frame_cntr
== 0)
2264 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2265 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2269 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2271 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2274 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2276 memcpy(STp
->application_sig
, "LIN4", 4);
2277 STp
->linux_media
= 1;
2278 STp
->linux_media_version
= 4;
2284 static int osst_reset_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2286 if (STp
->header_cache
!= NULL
)
2287 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2289 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2290 STp
->frame_in_buffer
= 0;
2291 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2292 STp
->filemark_cnt
= 0;
2293 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2294 return osst_write_header(STp
, aSRpnt
, 1);
2297 static int __osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int ppos
)
2299 char * name
= tape_name(STp
);
2300 os_header_t
* header
;
2303 int linux_media_version
,
2309 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2310 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2311 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2312 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2313 if (osst_initiate_read (STp
, aSRpnt
)) {
2314 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2318 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2320 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2324 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2325 aux
= STp
->buffer
->aux
;
2326 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2328 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2332 if (ntohl(aux
->frame_seq_num
) != 0 ||
2333 ntohl(aux
->logical_blk_num
) != 0 ||
2334 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2335 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2336 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2338 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2339 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2340 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2341 ntohl(aux
->partition
.last_frame_ppos
));
2345 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2346 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2347 strlcpy(id_string
, header
->ident_str
, 8);
2349 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2353 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2354 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2356 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2357 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2361 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2363 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2364 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2365 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2366 header
->major_rev
, header
->minor_rev
);
2368 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2372 if (header
->pt_par_num
!= 1)
2373 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2374 name
, header
->pt_par_num
);
2376 memcpy(id_string
, aux
->application_sig
, 4);
2378 if (memcmp(id_string
, "LIN", 3) == 0) {
2379 STp
->linux_media
= 1;
2380 linux_media_version
= id_string
[3] - '0';
2381 if (linux_media_version
!= 4)
2382 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2383 name
, linux_media_version
);
2385 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2388 if (linux_media_version
< STp
->linux_media_version
) {
2390 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2391 name
, ppos
, linux_media_version
);
2395 if (linux_media_version
> STp
->linux_media_version
) {
2397 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2398 name
, ppos
, linux_media_version
);
2400 memcpy(STp
->application_sig
, id_string
, 5);
2401 STp
->linux_media_version
= linux_media_version
;
2402 STp
->update_frame_cntr
= -1;
2404 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2406 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2407 name
, ppos
, update_frame_cntr
);
2409 if (STp
->header_cache
== NULL
) {
2410 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2411 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2415 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2418 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2419 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2421 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2422 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2423 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2424 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2425 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2426 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2427 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2428 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2429 STp
->update_frame_cntr
= update_frame_cntr
;
2431 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2432 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2433 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2434 STp
->first_data_ppos
,
2435 ntohl(header
->partition
[0].last_frame_ppos
),
2436 ntohl(header
->partition
[0].eod_frame_ppos
));
2437 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2438 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2440 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2442 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2444 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2445 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2446 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2448 if (header
->minor_rev
== 4 &&
2449 (header
->ext_trk_tb_off
!= htons(17192) ||
2450 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2451 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2452 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2453 header
->cfg_col_width
!= htonl(20) ||
2454 header
->dat_col_width
!= htonl(1500) ||
2455 header
->qfa_col_width
!= htonl(0) ||
2456 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2457 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2458 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2459 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2460 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2461 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2462 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2463 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2464 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2465 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2466 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2467 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2474 static int osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2479 char * name
= tape_name(STp
);
2481 position
= osst_get_frame_position(STp
, aSRpnt
);
2484 STp
->header_ok
= STp
->linux_media
= 1;
2485 STp
->linux_media_version
= 0;
2488 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2489 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2490 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2491 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2493 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2496 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2497 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2499 first
= position
==10?0xbae: 5;
2500 last
= position
==10?0xbb3:10;
2502 for (ppos
= first
; ppos
< last
; ppos
++)
2503 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2506 first
= position
==10? 5:0xbae;
2507 last
= position
==10?10:0xbb3;
2509 for (ppos
= first
; ppos
< last
; ppos
++)
2510 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2514 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2515 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2516 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2519 if (position
<= STp
->first_data_ppos
) {
2520 position
= STp
->first_data_ppos
;
2521 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2523 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2529 static int osst_verify_position(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2531 int frame_position
= STp
->first_frame_position
;
2532 int frame_seq_numbr
= STp
->frame_seq_number
;
2533 int logical_blk_num
= STp
->logical_blk_num
;
2534 int halfway_frame
= STp
->frame_in_buffer
;
2535 int read_pointer
= STp
->buffer
->read_pointer
;
2536 int prev_mark_ppos
= -1;
2537 int actual_mark_ppos
, i
, n
;
2539 char * name
= tape_name(STp
);
2541 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2543 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2544 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2546 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2550 if (STp
->linux_media_version
>= 4) {
2551 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2552 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2555 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2556 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2557 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2558 if (frame_position
!= STp
->first_frame_position
||
2559 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2560 prev_mark_ppos
!= actual_mark_ppos
) {
2562 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2563 STp
->first_frame_position
, frame_position
,
2564 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2565 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2569 if (halfway_frame
) {
2570 /* prepare buffer for append and rewrite on top of original */
2571 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2572 STp
->buffer
->buffer_bytes
= read_pointer
;
2573 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2576 STp
->frame_in_buffer
= halfway_frame
;
2577 STp
->frame_seq_number
= frame_seq_numbr
;
2578 STp
->logical_blk_num
= logical_blk_num
;
2582 /* Acc. to OnStream, the vers. numbering is the following:
2583 * X.XX for released versions (X=digit),
2584 * XXXY for unreleased versions (Y=letter)
2585 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2586 * This fn makes monoton numbers out of this scheme ...
2588 static unsigned int osst_parse_firmware_rev (const char * str
)
2590 if (str
[1] == '.') {
2591 return (str
[0]-'0')*10000
2595 return (str
[0]-'0')*10000
2597 +(str
[2]-'0')*100 - 100
2603 * Configure the OnStream SCII tape drive for default operation
2605 static int osst_configure_onstream(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2607 unsigned char cmd
[MAX_COMMAND_SIZE
];
2608 char * name
= tape_name(STp
);
2609 struct osst_request
* SRpnt
= * aSRpnt
;
2610 osst_mode_parameter_header_t
* header
;
2611 osst_block_size_page_t
* bs
;
2612 osst_capabilities_page_t
* cp
;
2613 osst_tape_paramtr_page_t
* prm
;
2614 int drive_buffer_size
;
2616 if (STp
->ready
!= ST_READY
) {
2618 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2623 if (STp
->os_fw_rev
< 10600) {
2624 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2625 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2629 * Configure 32.5KB (data+aux) frame size.
2630 * Get the current frame size from the block size mode page
2632 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2633 cmd
[0] = MODE_SENSE
;
2635 cmd
[2] = BLOCK_SIZE_PAGE
;
2636 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2638 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2639 if (SRpnt
== NULL
) {
2641 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2646 if ((STp
->buffer
)->syscall_result
!= 0) {
2647 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2651 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2652 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2655 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2656 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2657 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2658 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2662 * Configure default auto columns mode, 32.5KB transfer mode
2670 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2671 cmd
[0] = MODE_SELECT
;
2673 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2675 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2677 if ((STp
->buffer
)->syscall_result
!= 0) {
2678 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2683 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2685 * In debug mode, we want to see as many errors as possible
2686 * to test the error recovery mechanism.
2688 osst_set_retries(STp
, aSRpnt
, 0);
2693 * Set vendor name to 'LIN4' for "Linux support version 4".
2696 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2697 cmd
[0] = MODE_SELECT
;
2699 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2701 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2702 header
->medium_type
= 0; /* Medium Type - ignoring */
2703 header
->dsp
= 0; /* Reserved */
2704 header
->bdl
= 0; /* Block Descriptor Length */
2706 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2707 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2708 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2709 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2710 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2711 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2712 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2713 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2715 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2718 if ((STp
->buffer
)->syscall_result
!= 0) {
2719 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2720 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2724 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2725 cmd
[0] = MODE_SENSE
;
2727 cmd
[2] = CAPABILITIES_PAGE
;
2728 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2730 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2733 if ((STp
->buffer
)->syscall_result
!= 0) {
2734 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2738 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2739 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2740 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2742 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2744 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2745 cmd
[0] = MODE_SENSE
;
2747 cmd
[2] = TAPE_PARAMTR_PAGE
;
2748 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2750 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2753 if ((STp
->buffer
)->syscall_result
!= 0) {
2754 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2758 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2759 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2760 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2762 STp
->density
= prm
->density
;
2763 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2765 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2766 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2774 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2775 it messes up the block number). */
2776 static int cross_eof(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int forward
)
2779 char * name
= tape_name(STp
);
2783 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2784 name
, forward
? "forward" : "backward");
2788 /* assumes that the filemark is already read by the drive, so this is low cost */
2789 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2792 /* assumes this is only called if we just read the filemark! */
2793 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2796 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2797 name
, forward
? "forward" : "backward");
2803 /* Get the tape position. */
2805 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2807 unsigned char scmd
[MAX_COMMAND_SIZE
];
2808 struct osst_request
* SRpnt
;
2810 char * name
= tape_name(STp
);
2812 /* KG: We want to be able to use it for checking Write Buffer availability
2813 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2815 char * olddata
= STp
->buffer
->b_data
;
2816 int oldsize
= STp
->buffer
->buffer_size
;
2818 if (STp
->ready
!= ST_READY
) return (-EIO
);
2820 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2821 scmd
[0] = READ_POSITION
;
2823 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2824 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2825 STp
->timeout
, MAX_RETRIES
, 1);
2827 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2832 if (STp
->buffer
->syscall_result
)
2833 result
= ((SRpnt
->sense
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2835 if (result
== -EINVAL
)
2836 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2838 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2839 unsigned char mysense
[16];
2840 memcpy (mysense
, SRpnt
->sense
, 16);
2841 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2842 scmd
[0] = READ_POSITION
;
2843 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2844 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2845 STp
->timeout
, MAX_RETRIES
, 1);
2847 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2848 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2849 SRpnt
->sense
[2],SRpnt
->sense
[12],SRpnt
->sense
[13]);
2851 if (!STp
->buffer
->syscall_result
)
2852 memcpy (SRpnt
->sense
, mysense
, 16);
2854 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2856 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2857 + ((STp
->buffer
)->b_data
[5] << 16)
2858 + ((STp
->buffer
)->b_data
[6] << 8)
2859 + (STp
->buffer
)->b_data
[7];
2860 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2861 + ((STp
->buffer
)->b_data
[ 9] << 16)
2862 + ((STp
->buffer
)->b_data
[10] << 8)
2863 + (STp
->buffer
)->b_data
[11];
2864 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2867 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2868 STp
->first_frame_position
, STp
->last_frame_position
,
2869 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2870 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2874 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2876 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2877 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2879 STp
->first_frame_position
= STp
->last_frame_position
;
2882 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2884 return (result
== 0 ? STp
->first_frame_position
: result
);
2888 /* Set the tape block */
2889 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int ppos
, int skip
)
2891 unsigned char scmd
[MAX_COMMAND_SIZE
];
2892 struct osst_request
* SRpnt
;
2893 struct st_partstat
* STps
;
2895 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2896 char * name
= tape_name(STp
);
2898 if (STp
->ready
!= ST_READY
) return (-EIO
);
2900 STps
= &(STp
->ps
[STp
->partition
]);
2902 if (ppos
< 0 || ppos
> STp
->capacity
) {
2903 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2904 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2911 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2913 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2916 scmd
[3] = (pp
>> 24);
2917 scmd
[4] = (pp
>> 16);
2918 scmd
[5] = (pp
>> 8);
2923 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
2929 if ((STp
->buffer
)->syscall_result
!= 0) {
2931 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
2932 name
, STp
->first_frame_position
, pp
);
2937 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
2938 } while ((pp
!= ppos
) && (pp
= ppos
));
2939 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
2940 STps
->eof
= ST_NOEOF
;
2943 STp
->frame_in_buffer
= 0;
2947 static int osst_write_trailer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int leave_at_EOT
)
2949 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
2952 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
2953 /* true unless the user wrote the filemark for us */
2954 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2955 if (result
< 0) goto out
;
2956 result
= osst_write_filemark(STp
, aSRpnt
);
2957 if (result
< 0) goto out
;
2959 if (STps
->drv_file
>= 0)
2961 STps
->drv_block
= 0;
2963 result
= osst_write_eod(STp
, aSRpnt
);
2964 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
2971 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2973 /* Flush the write buffer (never need to write if variable blocksize). */
2974 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2976 int offset
, transfer
, blks
= 0;
2978 unsigned char cmd
[MAX_COMMAND_SIZE
];
2979 struct osst_request
* SRpnt
= *aSRpnt
;
2980 struct st_partstat
* STps
;
2981 char * name
= tape_name(STp
);
2983 if ((STp
->buffer
)->writing
) {
2984 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
2986 { printk(OSST_DEB_MSG
2987 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name
);
2989 *aSRpnt
= SRpnt
= NULL
;
2993 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name
);
2995 osst_write_behind_check(STp
);
2996 if ((STp
->buffer
)->syscall_result
) {
2999 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
3000 name
, (STp
->buffer
)->midlevel_result
);
3002 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3009 if (STp
->dirty
== 1) {
3012 STps
= &(STp
->ps
[STp
->partition
]);
3013 STps
->rw
= ST_WRITING
;
3014 offset
= STp
->buffer
->buffer_bytes
;
3015 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
3016 transfer
= OS_FRAME_SIZE
;
3018 if (offset
< OS_DATA_SIZE
)
3019 osst_zero_buffer_tail(STp
->buffer
);
3022 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
3023 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
3025 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3030 switch (STp
->write_type
) {
3034 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3035 name
, blks
, STp
->frame_seq_number
,
3036 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3038 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3039 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3042 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
3043 STp
->logical_blk_num
, 0, 0);
3045 case OS_WRITE_NEW_MARK
:
3046 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
3047 STp
->logical_blk_num
++, 0, blks
=1);
3049 case OS_WRITE_HEADER
:
3050 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
3052 default: /* probably FILLER */
3053 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
3057 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3058 name
, offset
, transfer
, blks
);
3061 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3062 STp
->timeout
, MAX_RETRIES
, 1);
3067 if ((STp
->buffer
)->syscall_result
!= 0) {
3070 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3071 name
, SRpnt
->sense
[0], SRpnt
->sense
[2],
3072 SRpnt
->sense
[12], SRpnt
->sense
[13]);
3074 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3075 (SRpnt
->sense
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3076 (SRpnt
->sense
[2] & 0x0f) == NO_SENSE
) {
3078 (STp
->buffer
)->buffer_bytes
= 0;
3082 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3083 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3087 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3090 STp
->first_frame_position
++;
3092 (STp
->buffer
)->buffer_bytes
= 0;
3096 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3102 /* Flush the tape buffer. The tape will be positioned correctly unless
3103 seek_next is true. */
3104 static int osst_flush_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int seek_next
)
3106 struct st_partstat
* STps
;
3107 int backspace
= 0, result
= 0;
3109 char * name
= tape_name(STp
);
3113 * If there was a bus reset, block further access
3116 if( STp
->pos_unknown
)
3119 if (STp
->ready
!= ST_READY
)
3122 STps
= &(STp
->ps
[STp
->partition
]);
3123 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3124 STp
->write_type
= OS_WRITE_DATA
;
3125 return osst_flush_write_buffer(STp
, aSRpnt
);
3127 if (STp
->block_size
== 0)
3131 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3134 if (!STp
->can_bsr
) {
3135 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3136 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3137 (STp
->buffer
)->buffer_bytes
= 0;
3138 (STp
->buffer
)->read_pointer
= 0;
3139 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3143 if (STps
->eof
== ST_FM_HIT
) {
3144 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3146 STps
->eof
= ST_NOEOF
;
3148 if (STps
->drv_file
>= 0)
3150 STps
->drv_block
= 0;
3153 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3154 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3156 else if (STps
->eof
== ST_FM_HIT
) {
3157 if (STps
->drv_file
>= 0)
3159 STps
->drv_block
= 0;
3160 STps
->eof
= ST_NOEOF
;
3166 static int osst_write_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int synchronous
)
3168 unsigned char cmd
[MAX_COMMAND_SIZE
];
3169 struct osst_request
* SRpnt
;
3172 char * name
= tape_name(STp
);
3175 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3177 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3179 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3182 /* error recovery may have bumped us past the header partition */
3183 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3185 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3187 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3192 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3193 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3196 // osst_build_stats(STp, &SRpnt);
3198 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3199 STp
->write_type
= OS_WRITE_DATA
;
3201 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3204 cmd
[4] = 1; /* one frame at a time... */
3205 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3208 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3209 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3211 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3212 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3216 STp
->write_pending
= 1;
3218 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3219 MAX_RETRIES
, synchronous
);
3225 if (STp
->buffer
->syscall_result
!= 0) {
3228 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3230 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3231 (SRpnt
->sense
[2] & 0x40)) {
3232 if ((SRpnt
->sense
[2] & 0x0f) == VOLUME_OVERFLOW
)
3236 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3241 STp
->first_frame_position
++;
3249 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3250 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3254 cmd
= do_lock
? SCSI_IOCTL_DOORLOCK
: SCSI_IOCTL_DOORUNLOCK
;
3256 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3258 retval
= scsi_ioctl(STp
->device
, cmd
, NULL
);
3260 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3263 STp
->door_locked
= ST_LOCK_FAILS
;
3268 /* Set the internal state after reset */
3269 static void reset_state(struct osst_tape
*STp
)
3272 struct st_partstat
*STps
;
3274 STp
->pos_unknown
= 0;
3275 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3276 STps
= &(STp
->ps
[i
]);
3278 STps
->eof
= ST_NOEOF
;
3280 STps
->last_block_valid
= 0;
3281 STps
->drv_block
= -1;
3282 STps
->drv_file
= -1;
3287 /* Entry points to osst */
3290 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3292 ssize_t total
, retval
= 0;
3293 ssize_t i
, do_count
, blks
, transfer
;
3294 int write_threshold
;
3295 int doing_write
= 0;
3296 const char __user
* b_point
;
3297 struct osst_request
* SRpnt
= NULL
;
3298 struct st_modedef
* STm
;
3299 struct st_partstat
* STps
;
3300 struct osst_tape
* STp
= filp
->private_data
;
3301 char * name
= tape_name(STp
);
3304 if (mutex_lock_interruptible(&STp
->lock
))
3305 return (-ERESTARTSYS
);
3308 * If we are in the middle of error recovery, don't let anyone
3309 * else try and use this device. Also, if error recovery fails, it
3310 * may try and take the device offline, in which case all further
3311 * access to the device is prohibited.
3313 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3318 if (STp
->ready
!= ST_READY
) {
3319 if (STp
->ready
== ST_NO_TAPE
)
3320 retval
= (-ENOMEDIUM
);
3325 STm
= &(STp
->modes
[STp
->current_mode
]);
3326 if (!STm
->defined
) {
3334 * If there was a bus reset, block further access
3337 if (STp
->pos_unknown
) {
3344 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3350 if (STp
->write_prot
) {
3355 /* Write must be integral number of blocks */
3356 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3357 printk(KERN_ERR
"%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3358 name
, count
, STp
->block_size
<1024?
3359 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3364 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3365 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3366 name
, STp
->first_frame_position
);
3371 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3372 STp
->door_locked
= ST_LOCKED_AUTO
;
3374 STps
= &(STp
->ps
[STp
->partition
]);
3376 if (STps
->rw
== ST_READING
) {
3378 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3379 STps
->drv_file
, STps
->drv_block
);
3381 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3386 if (STps
->rw
!= ST_WRITING
) {
3387 /* Are we totally rewriting this tape? */
3388 if (!STp
->header_ok
||
3389 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3390 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3391 STp
->wrt_pass_cntr
++;
3393 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3394 name
, STp
->wrt_pass_cntr
);
3396 osst_reset_header(STp
, &SRpnt
);
3397 STps
->drv_file
= STps
->drv_block
= 0;
3399 /* Do we know where we'll be writing on the tape? */
3401 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3402 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3403 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3404 STps
->drv_file
= STp
->filemark_cnt
;
3405 STps
->drv_block
= 0;
3408 /* We have no idea where the tape is positioned - give up */
3411 "%s:D: Cannot write at indeterminate position.\n", name
);
3417 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3418 STp
->filemark_cnt
= STps
->drv_file
;
3419 STp
->last_mark_ppos
=
3420 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3422 "%s:W: Overwriting file %d with old write pass counter %d\n",
3423 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3425 "%s:W: may lead to stale data being accepted on reading back!\n",
3429 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3430 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3436 if (!STp
->header_ok
) {
3438 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3444 if ((STp
->buffer
)->writing
) {
3445 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3446 osst_write_behind_check(STp
);
3447 if ((STp
->buffer
)->syscall_result
) {
3450 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3451 (STp
->buffer
)->midlevel_result
);
3453 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3454 STps
->eof
= ST_EOM_OK
;
3456 STps
->eof
= ST_EOM_ERROR
;
3459 if (STps
->eof
== ST_EOM_OK
) {
3463 else if (STps
->eof
== ST_EOM_ERROR
) {
3468 /* Check the buffer readability in cases where copy_user might catch
3469 the problems after some tape movement. */
3470 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3471 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3476 if (!STm
->do_buffer_writes
) {
3477 write_threshold
= 1;
3480 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3481 if (!STm
->do_async_writes
)
3487 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3488 name
, (int) count
, STps
->drv_file
, STps
->drv_block
,
3489 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3492 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3495 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3496 (STp
->buffer
)->buffer_bytes
;
3497 if (do_count
> count
)
3500 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3506 blks
= do_count
/ STp
->block_size
;
3507 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3509 i
= osst_write_frame(STp
, &SRpnt
, 1);
3511 if (i
== (-ENOSPC
)) {
3512 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3513 if (transfer
<= do_count
) {
3514 filp
->f_pos
+= do_count
- transfer
;
3515 count
-= do_count
- transfer
;
3516 if (STps
->drv_block
>= 0) {
3517 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3519 STps
->eof
= ST_EOM_OK
;
3520 retval
= (-ENOSPC
); /* EOM within current request */
3523 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3524 name
, (int) transfer
);
3528 STps
->eof
= ST_EOM_ERROR
;
3529 STps
->drv_block
= (-1); /* Too cautious? */
3530 retval
= (-EIO
); /* EOM for old data */
3533 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3541 if (SRpnt
!= NULL
) {
3542 osst_release_request(SRpnt
);
3545 STp
->buffer
->buffer_bytes
= 0;
3548 retval
= total
- count
;
3552 filp
->f_pos
+= do_count
;
3553 b_point
+= do_count
;
3555 if (STps
->drv_block
>= 0) {
3556 STps
->drv_block
+= blks
;
3558 STp
->buffer
->buffer_bytes
= 0;
3560 } /* end while write threshold exceeded */
3564 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3569 blks
= count
/ STp
->block_size
;
3570 STp
->logical_blk_num
+= blks
;
3571 if (STps
->drv_block
>= 0) {
3572 STps
->drv_block
+= blks
;
3574 filp
->f_pos
+= count
;
3578 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3579 retval
= (STp
->buffer
)->syscall_result
;
3583 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3584 /* Schedule an asynchronous write */
3585 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3586 STp
->block_size
) * STp
->block_size
;
3587 STp
->dirty
= !((STp
->buffer
)->writing
==
3588 (STp
->buffer
)->buffer_bytes
);
3590 i
= osst_write_frame(STp
, &SRpnt
, 0);
3595 SRpnt
= NULL
; /* Prevent releasing this request! */
3597 STps
->at_sm
&= (total
== 0);
3599 STps
->eof
= ST_NOEOF
;
3604 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3606 mutex_unlock(&STp
->lock
);
3613 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3615 ssize_t total
, retval
= 0;
3616 ssize_t i
, transfer
;
3618 struct st_modedef
* STm
;
3619 struct st_partstat
* STps
;
3620 struct osst_request
* SRpnt
= NULL
;
3621 struct osst_tape
* STp
= filp
->private_data
;
3622 char * name
= tape_name(STp
);
3625 if (mutex_lock_interruptible(&STp
->lock
))
3626 return (-ERESTARTSYS
);
3629 * If we are in the middle of error recovery, don't let anyone
3630 * else try and use this device. Also, if error recovery fails, it
3631 * may try and take the device offline, in which case all further
3632 * access to the device is prohibited.
3634 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3639 if (STp
->ready
!= ST_READY
) {
3640 if (STp
->ready
== ST_NO_TAPE
)
3641 retval
= (-ENOMEDIUM
);
3646 STm
= &(STp
->modes
[STp
->current_mode
]);
3647 if (!STm
->defined
) {
3653 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3658 /* Must have initialized medium */
3659 if (!STp
->header_ok
) {
3664 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3665 STp
->door_locked
= ST_LOCKED_AUTO
;
3667 STps
= &(STp
->ps
[STp
->partition
]);
3668 if (STps
->rw
== ST_WRITING
) {
3669 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3673 /* FIXME -- this may leave the tape without EOD and up2date headers */
3676 if ((count
% STp
->block_size
) != 0) {
3678 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3679 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3683 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3684 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3685 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3687 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3688 STps
->eof
>= ST_EOD_1
) {
3689 if (STps
->eof
< ST_EOD
) {
3694 retval
= (-EIO
); /* EOM or Blank Check */
3698 /* Check the buffer writability before any tape movement. Don't alter
3700 if (copy_from_user(&i
, buf
, 1) != 0 ||
3701 copy_to_user (buf
, &i
, 1) != 0 ||
3702 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3703 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3708 /* Loop until enough data in buffer or a special condition found */
3709 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3711 /* Get new data if the buffer is empty */
3712 if ((STp
->buffer
)->buffer_bytes
== 0) {
3713 if (STps
->eof
== ST_FM_HIT
)
3715 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3716 if (special
< 0) { /* No need to continue read */
3717 STp
->frame_in_buffer
= 0;
3723 /* Move the data from driver buffer to user buffer */
3724 if ((STp
->buffer
)->buffer_bytes
> 0) {
3726 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3727 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3728 STps
->eof
, (STp
->buffer
)->buffer_bytes
, (int) (count
- total
));
3730 /* force multiple of block size, note block_size may have been adjusted */
3731 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3732 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3733 STp
->block_size
) * STp
->block_size
;
3735 if (transfer
== 0) {
3737 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3738 name
, count
, STp
->block_size
< 1024?
3739 STp
->block_size
:STp
->block_size
/1024,
3740 STp
->block_size
<1024?'b':'k');
3743 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3748 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3749 STps
->drv_block
+= transfer
/ STp
->block_size
;
3750 filp
->f_pos
+= transfer
;
3755 if ((STp
->buffer
)->buffer_bytes
== 0) {
3758 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3759 name
, STp
->frame_seq_number
);
3761 STp
->frame_in_buffer
= 0;
3762 STp
->frame_seq_number
++; /* frame to look for next time */
3764 } /* for (total = 0, special = 0; total < count && !special; ) */
3766 /* Change the eof state if no data from tape or buffer */
3768 if (STps
->eof
== ST_FM_HIT
) {
3769 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3770 STps
->drv_block
= 0;
3771 if (STps
->drv_file
>= 0)
3774 else if (STps
->eof
== ST_EOD_1
) {
3775 STps
->eof
= ST_EOD_2
;
3776 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3778 STps
->drv_block
= 0;
3780 else if (STps
->eof
== ST_EOD_2
)
3783 else if (STps
->eof
== ST_FM
)
3784 STps
->eof
= ST_NOEOF
;
3789 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3791 mutex_unlock(&STp
->lock
);
3797 /* Set the driver options */
3798 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3801 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3802 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3803 STm
->do_read_ahead
);
3805 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3806 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3808 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3809 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3810 STp
->scsi2_logical
);
3812 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3815 "%s:D: debugging: %d\n",
3821 static int osst_set_options(struct osst_tape
*STp
, long options
)
3825 struct st_modedef
* STm
;
3826 char * name
= tape_name(STp
);
3828 STm
= &(STp
->modes
[STp
->current_mode
]);
3829 if (!STm
->defined
) {
3830 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3834 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3835 name
, STp
->current_mode
);
3839 code
= options
& MT_ST_OPTIONS
;
3840 if (code
== MT_ST_BOOLEANS
) {
3841 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3842 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3843 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3844 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3845 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3846 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3847 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3848 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3849 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3850 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3851 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3852 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3853 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3855 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3857 osst_log_options(STp
, STm
, name
);
3859 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3860 value
= (code
== MT_ST_SETBOOLEANS
);
3861 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3862 STm
->do_buffer_writes
= value
;
3863 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3864 STm
->do_async_writes
= value
;
3865 if ((options
& MT_ST_DEF_WRITES
) != 0)
3866 STm
->defaults_for_writes
= value
;
3867 if ((options
& MT_ST_READ_AHEAD
) != 0)
3868 STm
->do_read_ahead
= value
;
3869 if ((options
& MT_ST_TWO_FM
) != 0)
3870 STp
->two_fm
= value
;
3871 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3872 STp
->fast_mteom
= value
;
3873 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3874 STp
->do_auto_lock
= value
;
3875 if ((options
& MT_ST_CAN_BSR
) != 0)
3876 STp
->can_bsr
= value
;
3877 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3878 STp
->omit_blklims
= value
;
3879 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3880 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3881 STp
->can_partitions
= value
;
3882 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3883 STp
->scsi2_logical
= value
;
3884 if ((options
& MT_ST_SYSV
) != 0)
3887 if ((options
& MT_ST_DEBUGGING
) != 0)
3890 osst_log_options(STp
, STm
, name
);
3892 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3893 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3894 if (value
< 1 || value
> osst_buffer_size
) {
3895 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3899 STp
->write_threshold
= value
;
3900 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3903 else if (code
== MT_ST_DEF_BLKSIZE
) {
3904 value
= (options
& ~MT_ST_OPTIONS
);
3905 if (value
== ~MT_ST_OPTIONS
) {
3906 STm
->default_blksize
= (-1);
3907 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3910 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3911 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3915 STm
->default_blksize
= value
;
3916 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3917 name
, STm
->default_blksize
);
3920 else if (code
== MT_ST_TIMEOUTS
) {
3921 value
= (options
& ~MT_ST_OPTIONS
);
3922 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
3923 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
3924 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
3925 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
3928 STp
->timeout
= value
* HZ
;
3929 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
3932 else if (code
== MT_ST_DEF_OPTIONS
) {
3933 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
3934 value
= (options
& MT_ST_CLEAR_DEFAULT
);
3935 if (code
== MT_ST_DEF_DENSITY
) {
3936 if (value
== MT_ST_CLEAR_DEFAULT
) {
3937 STm
->default_density
= (-1);
3938 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
3941 STm
->default_density
= value
& 0xff;
3942 printk(KERN_INFO
"%s:I: Density default set to %x\n",
3943 name
, STm
->default_density
);
3946 else if (code
== MT_ST_DEF_DRVBUFFER
) {
3947 if (value
== MT_ST_CLEAR_DEFAULT
) {
3948 STp
->default_drvbuffer
= 0xff;
3949 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
3952 STp
->default_drvbuffer
= value
& 7;
3953 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
3954 name
, STp
->default_drvbuffer
);
3957 else if (code
== MT_ST_DEF_COMPRESSION
) {
3958 if (value
== MT_ST_CLEAR_DEFAULT
) {
3959 STm
->default_compression
= ST_DONT_TOUCH
;
3960 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
3963 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
3964 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
3976 /* Internal ioctl function */
3977 static int osst_int_ioctl(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
3978 unsigned int cmd_in
, unsigned long arg
)
3982 int i
, ioctl_result
;
3984 unsigned char cmd
[MAX_COMMAND_SIZE
];
3985 struct osst_request
* SRpnt
= * aSRpnt
;
3986 struct st_partstat
* STps
;
3987 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
3988 int datalen
= 0, direction
= DMA_NONE
;
3989 char * name
= tape_name(STp
);
3991 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
3992 if (STp
->ready
== ST_NO_TAPE
)
3993 return (-ENOMEDIUM
);
3997 timeout
= STp
->long_timeout
;
3998 STps
= &(STp
->ps
[STp
->partition
]);
3999 fileno
= STps
->drv_file
;
4000 blkno
= STps
->drv_block
;
4001 at_sm
= STps
->at_sm
;
4002 frame_seq_numbr
= STp
->frame_seq_number
;
4003 logical_blk_num
= STp
->logical_blk_num
;
4005 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4008 chg_eof
= 0; /* Changed from the FSF after this */
4012 if (STp
->linux_media
)
4013 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
4015 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
4019 at_sm
&= (arg
== 0);
4023 chg_eof
= 0; /* Changed from the FSF after this */
4027 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
4030 blkno
= (-1); /* We can't know the block number */
4031 at_sm
&= (arg
== 0);
4038 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
4039 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
4041 if (cmd_in
== MTFSR
) {
4042 logical_blk_num
+= arg
;
4043 if (blkno
>= 0) blkno
+= arg
;
4046 logical_blk_num
-= arg
;
4047 if (blkno
>= 0) blkno
-= arg
;
4049 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
4050 fileno
= STps
->drv_file
;
4051 blkno
= STps
->drv_block
;
4052 at_sm
&= (arg
== 0);
4057 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4058 cmd
[2] = (arg
>> 16);
4059 cmd
[3] = (arg
>> 8);
4063 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4064 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4067 blkno
= fileno
= (-1);
4073 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4075 cmd
[2] = (ltmp
>> 16);
4076 cmd
[3] = (ltmp
>> 8);
4082 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4083 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4088 blkno
= fileno
= (-1);
4093 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4094 STp
->write_type
= OS_WRITE_DATA
;
4095 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4100 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4102 for (i
=0; i
<arg
; i
++)
4103 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4104 if (fileno
>= 0) fileno
+= arg
;
4105 if (blkno
>= 0) blkno
= 0;
4109 if (STp
->write_prot
)
4113 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4114 if (cmd_in
== MTWSM
)
4116 cmd
[2] = (arg
>> 16);
4117 cmd
[3] = (arg
>> 8);
4119 timeout
= STp
->timeout
;
4122 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4123 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4128 at_sm
= (cmd_in
== MTWSM
);
4134 cmd
[0] = START_STOP
;
4135 cmd
[1] = 1; /* Don't wait for completion */
4136 if (cmd_in
== MTLOAD
) {
4137 if (STp
->ready
== ST_NO_TAPE
)
4138 cmd
[4] = 4; /* open tray */
4140 cmd
[4] = 1; /* load */
4142 if (cmd_in
== MTRETEN
)
4143 cmd
[4] = 3; /* retension then mount */
4144 if (cmd_in
== MTOFFL
)
4145 cmd
[4] = 4; /* rewind then eject */
4146 timeout
= STp
->timeout
;
4151 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4154 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4157 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4160 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4165 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4170 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4172 return 0; /* Should do something ? */
4177 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4179 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4180 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4181 ioctl_result
= -EIO
;
4184 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4186 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4188 ioctl_result
= -EIO
;
4191 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4192 fileno
= STp
->filemark_cnt
;
4197 if (STp
->write_prot
)
4199 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4200 i
= osst_write_eod(STp
, &SRpnt
);
4201 if (i
< ioctl_result
) ioctl_result
= i
;
4202 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4203 if (i
< ioctl_result
) ioctl_result
= i
;
4204 fileno
= blkno
= at_sm
= 0 ;
4208 cmd
[0] = REZERO_UNIT
; /* rewind */
4212 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4214 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4217 case MTSETBLK
: /* Set block length */
4218 if ((STps
->drv_block
== 0 ) &&
4220 ((STp
->buffer
)->buffer_bytes
== 0) &&
4221 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4222 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4223 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4225 * Only allowed to change the block size if you opened the
4226 * device at the beginning of a file before writing anything.
4227 * Note, that when reading, changing block_size is futile,
4228 * as the size used when writing overrides it.
4230 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4231 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4232 name
, STp
->block_size
);
4235 case MTSETDENSITY
: /* Set tape density */
4236 case MTSETDRVBUFFER
: /* Set drive buffering */
4237 case SET_DENS_AND_BLK
: /* Set density and block size */
4239 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4240 return (-EIO
); /* Not allowed if data in buffer */
4241 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4242 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4243 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4244 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4245 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4246 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4249 return 0; /* FIXME silently ignore if block size didn't change */
4255 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4257 ioctl_result
= (STp
->buffer
)->syscall_result
;
4261 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4263 return ioctl_result
;
4266 if (!ioctl_result
) { /* SCSI command successful */
4267 STp
->frame_seq_number
= frame_seq_numbr
;
4268 STp
->logical_blk_num
= logical_blk_num
;
4274 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4277 if (!ioctl_result
) { /* success */
4279 if (cmd_in
== MTFSFM
) {
4283 if (cmd_in
== MTBSFM
) {
4287 STps
->drv_block
= blkno
;
4288 STps
->drv_file
= fileno
;
4289 STps
->at_sm
= at_sm
;
4291 if (cmd_in
== MTEOM
)
4293 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4294 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4296 STp
->logical_blk_num
++;
4297 STp
->frame_seq_number
++;
4298 STp
->frame_in_buffer
= 0;
4299 STp
->buffer
->read_pointer
= 0;
4301 else if (cmd_in
== MTFSF
)
4302 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4304 STps
->eof
= ST_NOEOF
;
4306 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4307 STp
->rew_at_close
= 0;
4308 else if (cmd_in
== MTLOAD
) {
4309 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4310 STp
->ps
[i
].rw
= ST_IDLE
;
4311 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4316 if (cmd_in
== MTREW
) {
4317 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4318 if (ioctl_result
> 0)
4322 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4323 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4324 STps
->drv_file
= STps
->drv_block
= -1;
4326 STps
->drv_file
= STps
->drv_block
= 0;
4327 STps
->eof
= ST_NOEOF
;
4328 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4329 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4330 STps
->drv_file
= STps
->drv_block
= -1;
4332 STps
->drv_file
= STp
->filemark_cnt
;
4333 STps
->drv_block
= 0;
4336 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4337 STps
->drv_file
= STps
->drv_block
= (-1);
4338 STps
->eof
= ST_NOEOF
;
4340 } else if (cmd_in
== MTERASE
) {
4342 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4343 if (SRpnt
->sense
[2] & 0x40) {
4344 STps
->eof
= ST_EOM_OK
;
4345 STps
->drv_block
= 0;
4348 STps
->eof
= ST_NOEOF
;
4350 if ((SRpnt
->sense
[2] & 0x0f) == BLANK_CHECK
)
4353 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4354 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4358 return ioctl_result
;
4362 /* Open the device */
4363 static int __os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4365 unsigned short flags
;
4366 int i
, b_size
, new_session
= 0, retval
= 0;
4367 unsigned char cmd
[MAX_COMMAND_SIZE
];
4368 struct osst_request
* SRpnt
= NULL
;
4369 struct osst_tape
* STp
;
4370 struct st_modedef
* STm
;
4371 struct st_partstat
* STps
;
4373 int dev
= TAPE_NR(inode
);
4374 int mode
= TAPE_MODE(inode
);
4377 * We really want to do nonseekable_open(inode, filp); here, but some
4378 * versions of tar incorrectly call lseek on tapes and bail out if that
4379 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4381 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4383 write_lock(&os_scsi_tapes_lock
);
4384 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4385 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4386 write_unlock(&os_scsi_tapes_lock
);
4390 name
= tape_name(STp
);
4393 write_unlock(&os_scsi_tapes_lock
);
4395 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4399 if (scsi_device_get(STp
->device
)) {
4400 write_unlock(&os_scsi_tapes_lock
);
4402 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4406 filp
->private_data
= STp
;
4408 write_unlock(&os_scsi_tapes_lock
);
4409 STp
->rew_at_close
= TAPE_REWIND(inode
);
4411 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4415 if (mode
!= STp
->current_mode
) {
4418 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4419 name
, STp
->current_mode
, mode
);
4422 STp
->current_mode
= mode
;
4424 STm
= &(STp
->modes
[STp
->current_mode
]);
4426 flags
= filp
->f_flags
;
4427 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4429 STp
->raw
= TAPE_IS_RAW(inode
);
4433 /* Allocate data segments for this device's tape buffer */
4434 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4435 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4436 retval
= (-EOVERFLOW
);
4439 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4440 for (i
= 0, b_size
= 0;
4441 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4442 b_size
+= STp
->buffer
->sg
[i
++].length
);
4443 STp
->buffer
->aux
= (os_aux_t
*) (page_address(sg_page(&STp
->buffer
->sg
[i
])) + OS_DATA_SIZE
- b_size
);
4445 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4446 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4447 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4448 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4451 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4452 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4456 STp
->buffer
->writing
= 0;
4457 STp
->buffer
->syscall_result
= 0;
4459 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4460 STps
= &(STp
->ps
[i
]);
4463 STp
->ready
= ST_READY
;
4465 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4468 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4469 cmd
[0] = TEST_UNIT_READY
;
4471 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4473 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4476 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4477 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4478 SRpnt
->sense
[12] == 4 ) {
4480 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sense
[13]);
4482 if (filp
->f_flags
& O_NONBLOCK
) {
4486 if (SRpnt
->sense
[13] == 2) { /* initialize command required (LOAD) */
4487 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4488 cmd
[0] = START_STOP
;
4491 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4492 STp
->timeout
, MAX_RETRIES
, 1);
4494 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sense
[13]==1?15:3) * 60, 0);
4496 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4497 (SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4499 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4503 for (i
=0; i
< 10; i
++) {
4505 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4506 cmd
[0] = TEST_UNIT_READY
;
4508 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4509 STp
->timeout
, MAX_RETRIES
, 1);
4510 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4511 (SRpnt
->sense
[2] & 0x0f) != UNIT_ATTENTION
)
4515 STp
->pos_unknown
= 0;
4516 STp
->partition
= STp
->new_partition
= 0;
4517 if (STp
->can_partitions
)
4518 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4519 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4520 STps
= &(STp
->ps
[i
]);
4521 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4522 STps
->eof
= ST_NOEOF
;
4524 STps
->last_block_valid
= 0;
4525 STps
->drv_block
= 0;
4526 STps
->drv_file
= 0 ;
4529 STp
->recover_count
= 0;
4530 STp
->abort_count
= 0;
4533 * if we have valid headers from before, and the drive/tape seem untouched,
4534 * open without reconfiguring and re-reading the headers
4536 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4537 !SRpnt
->result
&& SRpnt
->sense
[0] == 0) {
4539 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4540 cmd
[0] = MODE_SENSE
;
4542 cmd
[2] = VENDOR_IDENT_PAGE
;
4543 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4545 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4547 if (STp
->buffer
->syscall_result
||
4548 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4549 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4550 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4551 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4553 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4554 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4555 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4556 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4557 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4561 i
= STp
->first_frame_position
;
4562 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4563 if (STp
->door_locked
== ST_UNLOCKED
) {
4564 if (do_door_lock(STp
, 1))
4565 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4567 STp
->door_locked
= ST_LOCKED_AUTO
;
4569 if (!STp
->frame_in_buffer
) {
4570 STp
->block_size
= (STm
->default_blksize
> 0) ?
4571 STm
->default_blksize
: OS_DATA_SIZE
;
4572 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4574 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4576 osst_release_request(SRpnt
);
4580 if (i
!= STp
->first_frame_position
)
4581 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4582 name
, i
, STp
->first_frame_position
);
4588 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4589 (SRpnt
->sense
[2] != 2 || SRpnt
->sense
[12] != 0x3A) ) {
4591 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4592 cmd
[0] = MODE_SELECT
;
4594 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4596 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4597 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4598 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4599 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4600 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4601 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4602 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4603 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4606 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4608 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4612 for (i
=0; i
< 10; i
++) {
4614 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4615 cmd
[0] = TEST_UNIT_READY
;
4617 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4618 STp
->timeout
, MAX_RETRIES
, 1);
4619 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4620 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
)
4623 if ((SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) {
4624 STp
->pos_unknown
= 0;
4625 STp
->partition
= STp
->new_partition
= 0;
4626 if (STp
->can_partitions
)
4627 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4628 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4629 STps
= &(STp
->ps
[i
]);
4631 STps
->eof
= ST_NOEOF
;
4633 STps
->last_block_valid
= 0;
4634 STps
->drv_block
= 0;
4635 STps
->drv_file
= 0 ;
4642 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4643 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4645 if ((STp
->buffer
)->syscall_result
!= 0) {
4646 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4647 (SRpnt
->sense
[0] & 0x70) == 0x70 &&
4648 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4649 SRpnt
->sense
[12] == 0x3a) { /* Check ASC */
4650 STp
->ready
= ST_NO_TAPE
;
4652 STp
->ready
= ST_NOT_READY
;
4653 osst_release_request(SRpnt
);
4655 STp
->density
= 0; /* Clear the erroneous "residue" */
4656 STp
->write_prot
= 0;
4657 STp
->block_size
= 0;
4658 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4659 STp
->partition
= STp
->new_partition
= 0;
4660 STp
->door_locked
= ST_UNLOCKED
;
4664 osst_configure_onstream(STp
, &SRpnt
);
4666 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4667 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4668 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4669 STp
->buffer
->buffer_bytes
=
4670 STp
->buffer
->read_pointer
=
4671 STp
->frame_in_buffer
= 0;
4675 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4676 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4677 (STp
->buffer
)->buffer_blocks
);
4680 if (STp
->drv_write_prot
) {
4681 STp
->write_prot
= 1;
4684 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4686 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4692 if (new_session
) { /* Change the drive parameters for the new mode */
4695 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4697 STp
->density_changed
= STp
->blksize_changed
= 0;
4698 STp
->compression_changed
= 0;
4702 * properly position the tape and check the ADR headers
4704 if (STp
->door_locked
== ST_UNLOCKED
) {
4705 if (do_door_lock(STp
, 1))
4706 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4708 STp
->door_locked
= ST_LOCKED_AUTO
;
4711 osst_analyze_headers(STp
, &SRpnt
);
4713 osst_release_request(SRpnt
);
4720 osst_release_request(SRpnt
);
4721 normalize_buffer(STp
->buffer
);
4724 scsi_device_put(STp
->device
);
4729 /* BKL pushdown: spaghetti avoidance wrapper */
4730 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4735 ret
= __os_scsi_tape_open(inode
, filp
);
4742 /* Flush the tape buffer before close */
4743 static int os_scsi_tape_flush(struct file
* filp
, fl_owner_t id
)
4745 int result
= 0, result2
;
4746 struct osst_tape
* STp
= filp
->private_data
;
4747 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4748 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4749 struct osst_request
* SRpnt
= NULL
;
4750 char * name
= tape_name(STp
);
4752 if (file_count(filp
) > 1)
4755 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4756 STp
->write_type
= OS_WRITE_DATA
;
4757 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4758 if (result
!= 0 && result
!= (-ENOSPC
))
4761 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4765 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4766 name
, (long)(filp
->f_pos
));
4767 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4768 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4771 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4774 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4775 name
, 1+STp
->two_fm
);
4778 else if (!STp
->rew_at_close
) {
4779 STps
= &(STp
->ps
[STp
->partition
]);
4780 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4782 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4783 else if (STps
->eof
== ST_FM_HIT
) {
4784 result
= cross_eof(STp
, &SRpnt
, 0);
4786 if (STps
->drv_file
>= 0)
4788 STps
->drv_block
= 0;
4792 STps
->eof
= ST_NOEOF
;
4795 else if ((STps
->eof
== ST_NOEOF
&&
4796 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4797 STps
->eof
== ST_FM_HIT
) {
4798 if (STps
->drv_file
>= 0)
4800 STps
->drv_block
= 0;
4806 if (STp
->rew_at_close
) {
4807 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4808 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4809 if (result
== 0 && result2
< 0)
4812 if (SRpnt
) osst_release_request(SRpnt
);
4814 if (STp
->abort_count
|| STp
->recover_count
) {
4815 printk(KERN_INFO
"%s:I:", name
);
4816 if (STp
->abort_count
)
4817 printk(" %d unrecovered errors", STp
->abort_count
);
4818 if (STp
->recover_count
)
4819 printk(" %d recovered errors", STp
->recover_count
);
4820 if (STp
->write_count
)
4821 printk(" in %d frames written", STp
->write_count
);
4822 if (STp
->read_count
)
4823 printk(" in %d frames read", STp
->read_count
);
4825 STp
->recover_count
= 0;
4826 STp
->abort_count
= 0;
4828 STp
->write_count
= 0;
4829 STp
->read_count
= 0;
4835 /* Close the device and release it */
4836 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4839 struct osst_tape
* STp
= filp
->private_data
;
4841 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4842 do_door_lock(STp
, 0);
4847 normalize_buffer(STp
->buffer
);
4848 write_lock(&os_scsi_tapes_lock
);
4850 write_unlock(&os_scsi_tapes_lock
);
4852 scsi_device_put(STp
->device
);
4858 /* The ioctl command */
4859 static int osst_ioctl(struct inode
* inode
,struct file
* file
,
4860 unsigned int cmd_in
, unsigned long arg
)
4862 int i
, cmd_nr
, cmd_type
, blk
, retval
= 0;
4863 struct st_modedef
* STm
;
4864 struct st_partstat
* STps
;
4865 struct osst_request
* SRpnt
= NULL
;
4866 struct osst_tape
* STp
= file
->private_data
;
4867 char * name
= tape_name(STp
);
4868 void __user
* p
= (void __user
*)arg
;
4870 if (mutex_lock_interruptible(&STp
->lock
))
4871 return -ERESTARTSYS
;
4874 if (debugging
&& !STp
->in_use
) {
4875 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4880 STm
= &(STp
->modes
[STp
->current_mode
]);
4881 STps
= &(STp
->ps
[STp
->partition
]);
4884 * If we are in the middle of error recovery, don't let anyone
4885 * else try and use this device. Also, if error recovery fails, it
4886 * may try and take the device offline, in which case all further
4887 * access to the device is prohibited.
4889 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4894 cmd_type
= _IOC_TYPE(cmd_in
);
4895 cmd_nr
= _IOC_NR(cmd_in
);
4897 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4898 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4900 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4904 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4909 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
4915 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
4916 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
4921 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
4926 if (!STp
->pos_unknown
) {
4928 if (STps
->eof
== ST_FM_HIT
) {
4929 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
4931 if (STps
->drv_file
>= 0)
4932 STps
->drv_file
+= 1;
4934 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
4936 if (STps
->drv_file
>= 0)
4937 STps
->drv_file
+= 1;
4941 if (mtc
.mt_op
== MTSEEK
) {
4942 /* Old position must be restored if partition will be changed */
4943 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
4946 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
4947 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
4948 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
4949 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
4950 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
4951 mtc
.mt_op
== MTCOMPRESSION
;
4953 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
4961 * If there was a bus reset, block further access
4962 * to this device. If the user wants to rewind the tape,
4963 * then reset the flag and allow access again.
4965 if(mtc
.mt_op
!= MTREW
&&
4966 mtc
.mt_op
!= MTOFFL
&&
4967 mtc
.mt_op
!= MTRETEN
&&
4968 mtc
.mt_op
!= MTERASE
&&
4969 mtc
.mt_op
!= MTSEEK
&&
4970 mtc
.mt_op
!= MTEOM
) {
4975 /* remove this when the midlevel properly clears was_reset */
4976 STp
->device
->was_reset
= 0;
4979 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
4980 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
4981 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
4982 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
4983 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
4986 * The user tells us to move to another position on the tape.
4987 * If we were appending to the tape content, that would leave
4988 * the tape without proper end, in that case write EOD and
4989 * update the header to reflect its position.
4992 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
4993 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
4994 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
4995 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
4997 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
4998 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
4999 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5000 i
= osst_write_trailer(STp
, &SRpnt
,
5001 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5003 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5004 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
5005 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5015 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
5016 do_door_lock(STp
, 0); /* Ignore result! */
5018 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
5019 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
5020 retval
= osst_set_options(STp
, mtc
.mt_count
);
5024 if (mtc
.mt_op
== MTSETPART
) {
5025 if (mtc
.mt_count
>= STp
->nbr_partitions
)
5028 STp
->new_partition
= mtc
.mt_count
;
5034 if (mtc
.mt_op
== MTMKPART
) {
5035 if (!STp
->can_partitions
) {
5039 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
5040 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5044 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5045 STp
->ps
[i
].rw
= ST_IDLE
;
5046 STp
->ps
[i
].at_sm
= 0;
5047 STp
->ps
[i
].last_block_valid
= 0;
5049 STp
->partition
= STp
->new_partition
= 0;
5050 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
5051 STps
->drv_block
= STps
->drv_file
= 0;
5056 if (mtc
.mt_op
== MTSEEK
) {
5058 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
5060 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
5061 if (!STp
->can_partitions
)
5062 STp
->ps
[0].rw
= ST_IDLE
;
5067 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
5068 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5073 cross_eof(STp
, &SRpnt
, 0);
5075 if (mtc
.mt_op
== MTCOMPRESSION
)
5076 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5078 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5079 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5080 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5084 if (!STm
->defined
) {
5089 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5094 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5095 struct mtget mt_status
;
5097 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5102 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5103 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5104 mt_status
.mt_dsreg
=
5105 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5106 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5107 mt_status
.mt_blkno
= STps
->drv_block
;
5108 mt_status
.mt_fileno
= STps
->drv_file
;
5109 if (STp
->block_size
!= 0) {
5110 if (STps
->rw
== ST_WRITING
)
5111 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5112 else if (STps
->rw
== ST_READING
)
5113 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5114 STp
->block_size
- 1) / STp
->block_size
;
5117 mt_status
.mt_gstat
= 0;
5118 if (STp
->drv_write_prot
)
5119 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5120 if (mt_status
.mt_blkno
== 0) {
5121 if (mt_status
.mt_fileno
== 0)
5122 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5124 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5126 mt_status
.mt_resid
= STp
->partition
;
5127 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5128 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5129 else if (STps
->eof
>= ST_EOM_OK
)
5130 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5131 if (STp
->density
== 1)
5132 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5133 else if (STp
->density
== 2)
5134 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5135 else if (STp
->density
== 3)
5136 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5137 if (STp
->ready
== ST_READY
)
5138 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5139 if (STp
->ready
== ST_NO_TAPE
)
5140 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5142 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5143 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5144 STp
->drv_buffer
!= 0)
5145 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5147 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5153 STp
->recover_erreg
= 0; /* Clear after read */
5156 } /* End of MTIOCGET */
5158 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5159 struct mtpos mt_pos
;
5161 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5166 blk
= osst_get_frame_position(STp
, &SRpnt
);
5168 blk
= osst_get_sector(STp
, &SRpnt
);
5173 mt_pos
.mt_blkno
= blk
;
5174 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5179 if (SRpnt
) osst_release_request(SRpnt
);
5181 mutex_unlock(&STp
->lock
);
5183 return scsi_ioctl(STp
->device
, cmd_in
, p
);
5186 if (SRpnt
) osst_release_request(SRpnt
);
5188 mutex_unlock(&STp
->lock
);
5193 #ifdef CONFIG_COMPAT
5194 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5196 struct osst_tape
*STp
= file
->private_data
;
5197 struct scsi_device
*sdev
= STp
->device
;
5198 int ret
= -ENOIOCTLCMD
;
5199 if (sdev
->host
->hostt
->compat_ioctl
) {
5201 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5210 /* Memory handling routines */
5212 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5213 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5217 struct osst_buffer
*tb
;
5219 if (from_initialization
)
5220 priority
= GFP_ATOMIC
;
5222 priority
= GFP_KERNEL
;
5224 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5225 tb
= kzalloc(i
, priority
);
5227 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5231 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5232 tb
->use_sg
= max_sg
;
5235 tb
->buffer_size
= 0;
5239 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5240 i
, max_sg
, need_dma
);
5245 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5246 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5248 int segs
, nbr
, max_segs
, b_size
, order
, got
;
5251 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5254 if (STbuffer
->sg_segs
) {
5255 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5256 normalize_buffer(STbuffer
);
5258 /* See how many segments we can use -- need at least two */
5259 nbr
= max_segs
= STbuffer
->use_sg
;
5263 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5265 priority
|= GFP_DMA
;
5267 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5268 big enough to reach the goal (code assumes no segments in place) */
5269 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5270 struct page
*page
= alloc_pages(priority
, order
);
5272 STbuffer
->sg
[0].offset
= 0;
5274 sg_set_page(&STbuffer
->sg
[0], page
, b_size
, 0);
5275 STbuffer
->b_data
= page_address(page
);
5279 if (sg_page(&STbuffer
->sg
[0]) == NULL
) {
5280 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5283 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5284 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5285 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5286 struct page
*page
= alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5287 STbuffer
->sg
[segs
].offset
= 0;
5289 if (OS_FRAME_SIZE
- got
<= (max_segs
- segs
) * b_size
/ 2 && order
) {
5290 b_size
/= 2; /* Large enough for the rest of the buffers */
5294 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5297 STbuffer
->buffer_size
= got
;
5299 normalize_buffer(STbuffer
);
5302 sg_set_page(&STbuffer
->sg
[segs
], page
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
, 0);
5303 got
+= STbuffer
->sg
[segs
].length
;
5304 STbuffer
->buffer_size
= got
;
5305 STbuffer
->sg_segs
= ++segs
;
5310 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5311 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5313 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5314 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5315 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5323 /* Release the segments */
5324 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5326 int i
, order
, b_size
;
5328 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5330 for (b_size
= PAGE_SIZE
, order
= 0;
5331 b_size
< STbuffer
->sg
[i
].length
;
5332 b_size
*= 2, order
++);
5334 __free_pages(sg_page(&STbuffer
->sg
[i
]), order
);
5335 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5338 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5339 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5340 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5342 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5346 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5347 negative error code. */
5348 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5350 int i
, cnt
, res
, offset
;
5352 for (i
=0, offset
=st_bp
->buffer_bytes
;
5353 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5354 offset
-= st_bp
->sg
[i
].length
;
5355 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5356 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5359 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5360 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5361 st_bp
->sg
[i
].length
- offset
: do_count
;
5362 res
= copy_from_user(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, ubp
, cnt
);
5366 st_bp
->buffer_bytes
+= cnt
;
5370 if (do_count
) { /* Should never happen */
5371 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5379 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5380 negative error code. */
5381 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5383 int i
, cnt
, res
, offset
;
5385 for (i
=0, offset
=st_bp
->read_pointer
;
5386 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5387 offset
-= st_bp
->sg
[i
].length
;
5388 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5389 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5392 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5393 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5394 st_bp
->sg
[i
].length
- offset
: do_count
;
5395 res
= copy_to_user(ubp
, page_address(sg_page(&st_bp
->sg
[i
])) + offset
, cnt
);
5399 st_bp
->buffer_bytes
-= cnt
;
5400 st_bp
->read_pointer
+= cnt
;
5404 if (do_count
) { /* Should never happen */
5405 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5411 /* Sets the tail of the buffer after fill point to zero.
5412 Returns zero (success) or negative error code. */
5413 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5415 int i
, offset
, do_count
, cnt
;
5417 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5418 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5419 offset
-= st_bp
->sg
[i
].length
;
5420 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5421 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5424 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5425 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5426 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5427 st_bp
->sg
[i
].length
- offset
: do_count
;
5428 memset(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, 0, cnt
);
5432 if (do_count
) { /* Should never happen */
5433 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5439 /* Copy a osst 32K chunk of memory into the buffer.
5440 Returns zero (success) or negative error code. */
5441 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5443 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5445 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5446 cnt
= st_bp
->sg
[i
].length
< do_count
?
5447 st_bp
->sg
[i
].length
: do_count
;
5448 memcpy(page_address(sg_page(&st_bp
->sg
[i
])), ptr
, cnt
);
5452 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5453 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5460 /* Copy a osst 32K chunk of memory from the buffer.
5461 Returns zero (success) or negative error code. */
5462 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5464 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5466 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5467 cnt
= st_bp
->sg
[i
].length
< do_count
?
5468 st_bp
->sg
[i
].length
: do_count
;
5469 memcpy(ptr
, page_address(sg_page(&st_bp
->sg
[i
])), cnt
);
5473 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5474 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5482 /* Module housekeeping */
5484 static void validate_options (void)
5487 osst_max_dev
= max_dev
;
5488 if (write_threshold_kbs
> 0)
5489 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5490 if (osst_write_threshold
> osst_buffer_size
)
5491 osst_write_threshold
= osst_buffer_size
;
5492 if (max_sg_segs
>= OSST_FIRST_SG
)
5493 osst_max_sg_segs
= max_sg_segs
;
5495 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5496 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5501 /* Set the boot options. Syntax: osst=xxx,yyy,...
5502 where xxx is write threshold in 1024 byte blocks,
5503 and yyy is number of s/g segments to use. */
5504 static int __init
osst_setup (char *str
)
5509 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5512 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5513 *parms
[i
].val
= ints
[i
+ 1];
5515 while (stp
!= NULL
) {
5516 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5517 int len
= strlen(parms
[i
].name
);
5518 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5519 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5521 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5525 if (i
>= ARRAY_SIZE(parms
))
5526 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5528 stp
= strchr(stp
, ',');
5537 __setup("osst=", osst_setup
);
5541 static const struct file_operations osst_fops
= {
5542 .owner
= THIS_MODULE
,
5544 .write
= osst_write
,
5545 .ioctl
= osst_ioctl
,
5546 #ifdef CONFIG_COMPAT
5547 .compat_ioctl
= osst_compat_ioctl
,
5549 .open
= os_scsi_tape_open
,
5550 .flush
= os_scsi_tape_flush
,
5551 .release
= os_scsi_tape_close
,
5554 static int osst_supports(struct scsi_device
* SDp
)
5556 struct osst_support_data
{
5560 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5563 static struct osst_support_data support_list
[] = {
5564 /* {"XXX", "Yy-", "", NULL}, example */
5568 struct osst_support_data
*rp
;
5570 /* We are willing to drive OnStream SC-x0 as well as the
5571 * * IDE, ParPort, FireWire, USB variants, if accessible by
5572 * * emulation layer (ide-scsi, usb-storage, ...) */
5574 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5575 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5576 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5577 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5583 * sysfs support for osst driver parameter information
5586 static ssize_t
osst_version_show(struct device_driver
*ddd
, char *buf
)
5588 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5591 static DRIVER_ATTR(version
, S_IRUGO
, osst_version_show
, NULL
);
5593 static int osst_create_sysfs_files(struct device_driver
*sysfs
)
5595 return driver_create_file(sysfs
, &driver_attr_version
);
5598 static void osst_remove_sysfs_files(struct device_driver
*sysfs
)
5600 driver_remove_file(sysfs
, &driver_attr_version
);
5604 * sysfs support for accessing ADR header information
5607 static ssize_t
osst_adr_rev_show(struct device
*dev
,
5608 struct device_attribute
*attr
, char *buf
)
5610 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5613 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5614 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5618 DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5620 static ssize_t
osst_linux_media_version_show(struct device
*dev
,
5621 struct device_attribute
*attr
,
5624 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5627 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5628 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5632 DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5634 static ssize_t
osst_capacity_show(struct device
*dev
,
5635 struct device_attribute
*attr
, char *buf
)
5637 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5640 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5641 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5645 DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5647 static ssize_t
osst_first_data_ppos_show(struct device
*dev
,
5648 struct device_attribute
*attr
,
5651 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5654 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5655 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5659 DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5661 static ssize_t
osst_eod_frame_ppos_show(struct device
*dev
,
5662 struct device_attribute
*attr
,
5665 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5668 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5669 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5673 DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5675 static ssize_t
osst_filemark_cnt_show(struct device
*dev
,
5676 struct device_attribute
*attr
, char *buf
)
5678 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5681 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5682 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5686 DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5688 static struct class *osst_sysfs_class
;
5690 static int osst_sysfs_init(void)
5692 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5693 if (IS_ERR(osst_sysfs_class
)) {
5694 printk(KERN_ERR
"osst :W: Unable to register sysfs class\n");
5695 return PTR_ERR(osst_sysfs_class
);
5701 static void osst_sysfs_destroy(dev_t dev
)
5703 device_destroy(osst_sysfs_class
, dev
);
5706 static int osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5708 struct device
*osst_member
;
5711 osst_member
= device_create(osst_sysfs_class
, device
, dev
, STp
,
5713 if (IS_ERR(osst_member
)) {
5714 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5715 return PTR_ERR(osst_member
);
5718 err
= device_create_file(osst_member
, &dev_attr_ADR_rev
);
5721 err
= device_create_file(osst_member
, &dev_attr_media_version
);
5724 err
= device_create_file(osst_member
, &dev_attr_capacity
);
5727 err
= device_create_file(osst_member
, &dev_attr_BOT_frame
);
5730 err
= device_create_file(osst_member
, &dev_attr_EOD_frame
);
5733 err
= device_create_file(osst_member
, &dev_attr_file_count
);
5740 osst_sysfs_destroy(dev
);
5744 static void osst_sysfs_cleanup(void)
5746 class_destroy(osst_sysfs_class
);
5750 * osst startup / cleanup code
5753 static int osst_probe(struct device
*dev
)
5755 struct scsi_device
* SDp
= to_scsi_device(dev
);
5756 struct osst_tape
* tpnt
;
5757 struct st_modedef
* STm
;
5758 struct st_partstat
* STps
;
5759 struct osst_buffer
* buffer
;
5760 struct gendisk
* drive
;
5761 int i
, dev_num
, err
= -ENODEV
;
5763 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5766 drive
= alloc_disk(1);
5768 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5772 /* if this is the first attach, build the infrastructure */
5773 write_lock(&os_scsi_tapes_lock
);
5774 if (os_scsi_tapes
== NULL
) {
5776 (struct osst_tape
**)kmalloc(osst_max_dev
* sizeof(struct osst_tape
*),
5778 if (os_scsi_tapes
== NULL
) {
5779 write_unlock(&os_scsi_tapes_lock
);
5780 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5783 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5786 if (osst_nr_dev
>= osst_max_dev
) {
5787 write_unlock(&os_scsi_tapes_lock
);
5788 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5792 /* find a free minor number */
5793 for (i
=0; os_scsi_tapes
[i
] && i
<osst_max_dev
; i
++);
5794 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5797 /* allocate a struct osst_tape for this device */
5798 tpnt
= kzalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5800 write_unlock(&os_scsi_tapes_lock
);
5801 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5805 /* allocate a buffer for this device */
5806 i
= SDp
->host
->sg_tablesize
;
5807 if (osst_max_sg_segs
< i
)
5808 i
= osst_max_sg_segs
;
5809 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5810 if (buffer
== NULL
) {
5811 write_unlock(&os_scsi_tapes_lock
);
5812 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5816 os_scsi_tapes
[dev_num
] = tpnt
;
5817 tpnt
->buffer
= buffer
;
5819 drive
->private_data
= &tpnt
->driver
;
5820 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5821 tpnt
->driver
= &osst_template
;
5822 tpnt
->drive
= drive
;
5824 tpnt
->capacity
= 0xfffff;
5826 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5827 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5829 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5830 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5831 tpnt
->can_partitions
= 0;
5832 tpnt
->two_fm
= OSST_TWO_FM
;
5833 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5834 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5835 tpnt
->write_threshold
= osst_write_threshold
;
5836 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5837 tpnt
->partition
= 0;
5838 tpnt
->new_partition
= 0;
5839 tpnt
->nbr_partitions
= 0;
5840 tpnt
->min_block
= 512;
5841 tpnt
->max_block
= OS_DATA_SIZE
;
5842 tpnt
->timeout
= OSST_TIMEOUT
;
5843 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5845 /* Recognize OnStream tapes */
5846 /* We don't need to test for OnStream, as this has been done in detect () */
5847 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5848 tpnt
->omit_blklims
= 1;
5850 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5851 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5852 tpnt
->frame_in_buffer
= 0;
5853 tpnt
->header_ok
= 0;
5854 tpnt
->linux_media
= 0;
5855 tpnt
->header_cache
= NULL
;
5857 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5858 STm
= &(tpnt
->modes
[i
]);
5860 STm
->sysv
= OSST_SYSV
;
5861 STm
->defaults_for_writes
= 0;
5862 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5863 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5864 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5865 STm
->default_compression
= ST_DONT_TOUCH
;
5866 STm
->default_blksize
= 512;
5867 STm
->default_density
= (-1); /* No forced density */
5870 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5871 STps
= &(tpnt
->ps
[i
]);
5873 STps
->eof
= ST_NOEOF
;
5875 STps
->last_block_valid
= 0;
5876 STps
->drv_block
= (-1);
5877 STps
->drv_file
= (-1);
5880 tpnt
->current_mode
= 0;
5881 tpnt
->modes
[0].defined
= 1;
5882 tpnt
->modes
[2].defined
= 1;
5883 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5885 mutex_init(&tpnt
->lock
);
5887 write_unlock(&os_scsi_tapes_lock
);
5893 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5895 goto out_free_buffer
;
5897 /* No-rewind entry */
5898 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5899 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5901 goto out_free_sysfs1
;
5904 sdev_printk(KERN_INFO
, SDp
,
5905 "osst :I: Attached OnStream %.5s tape as %s\n",
5906 SDp
->model
, tape_name(tpnt
));
5911 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, dev_num
));
5919 static int osst_remove(struct device
*dev
)
5921 struct scsi_device
* SDp
= to_scsi_device(dev
);
5922 struct osst_tape
* tpnt
;
5925 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
5928 write_lock(&os_scsi_tapes_lock
);
5929 for(i
=0; i
< osst_max_dev
; i
++) {
5930 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
5931 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
5932 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
5933 tpnt
->device
= NULL
;
5934 put_disk(tpnt
->drive
);
5935 os_scsi_tapes
[i
] = NULL
;
5937 write_unlock(&os_scsi_tapes_lock
);
5938 vfree(tpnt
->header_cache
);
5940 normalize_buffer(tpnt
->buffer
);
5941 kfree(tpnt
->buffer
);
5947 write_unlock(&os_scsi_tapes_lock
);
5951 static int __init
init_osst(void)
5955 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
5959 err
= osst_sysfs_init();
5963 err
= register_chrdev(OSST_MAJOR
, "osst", &osst_fops
);
5965 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
5969 err
= scsi_register_driver(&osst_template
.gendrv
);
5971 goto err_out_chrdev
;
5973 err
= osst_create_sysfs_files(&osst_template
.gendrv
);
5975 goto err_out_scsidrv
;
5980 scsi_unregister_driver(&osst_template
.gendrv
);
5982 unregister_chrdev(OSST_MAJOR
, "osst");
5984 osst_sysfs_cleanup();
5988 static void __exit
exit_osst (void)
5991 struct osst_tape
* STp
;
5993 osst_remove_sysfs_files(&osst_template
.gendrv
);
5994 scsi_unregister_driver(&osst_template
.gendrv
);
5995 unregister_chrdev(OSST_MAJOR
, "osst");
5996 osst_sysfs_cleanup();
5998 if (os_scsi_tapes
) {
5999 for (i
=0; i
< osst_max_dev
; ++i
) {
6000 if (!(STp
= os_scsi_tapes
[i
])) continue;
6001 /* This is defensive, supposed to happen during detach */
6002 vfree(STp
->header_cache
);
6004 normalize_buffer(STp
->buffer
);
6007 put_disk(STp
->drive
);
6010 kfree(os_scsi_tapes
);
6012 printk(KERN_INFO
"osst :I: Unloaded.\n");
6015 module_init(init_osst
);
6016 module_exit(exit_osst
);