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/slab.h>
42 #include <linux/init.h>
43 #include <linux/string.h>
44 #include <linux/errno.h>
45 #include <linux/mtio.h>
46 #include <linux/ioctl.h>
47 #include <linux/fcntl.h>
48 #include <linux/spinlock.h>
49 #include <linux/vmalloc.h>
50 #include <linux/blkdev.h>
51 #include <linux/moduleparam.h>
52 #include <linux/delay.h>
53 #include <linux/jiffies.h>
54 #include <linux/smp_lock.h>
55 #include <asm/uaccess.h>
57 #include <asm/system.h>
59 /* The driver prints some debugging information on the console if DEBUG
60 is defined and non-zero. */
63 /* The message level for the debug messages is currently set to KERN_NOTICE
64 so that people can easily see the messages. Later when the debugging messages
65 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
66 #define OSST_DEB_MSG KERN_NOTICE
68 #include <scsi/scsi.h>
69 #include <scsi/scsi_dbg.h>
70 #include <scsi/scsi_device.h>
71 #include <scsi/scsi_driver.h>
72 #include <scsi/scsi_eh.h>
73 #include <scsi/scsi_host.h>
74 #include <scsi/scsi_ioctl.h>
76 #define ST_KILOBYTE 1024
80 #include "osst_options.h"
81 #include "osst_detect.h"
83 static int max_dev
= 0;
84 static int write_threshold_kbs
= 0;
85 static int max_sg_segs
= 0;
88 MODULE_AUTHOR("Willem Riede");
89 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
90 MODULE_LICENSE("GPL");
91 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR
);
92 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE
);
94 module_param(max_dev
, int, 0444);
95 MODULE_PARM_DESC(max_dev
, "Maximum number of OnStream Tape Drives to attach (4)");
97 module_param(write_threshold_kbs
, int, 0644);
98 MODULE_PARM_DESC(write_threshold_kbs
, "Asynchronous write threshold (KB; 32)");
100 module_param(max_sg_segs
, int, 0644);
101 MODULE_PARM_DESC(max_sg_segs
, "Maximum number of scatter/gather segments to use (9)");
103 static struct osst_dev_parm
{
106 } parms
[] __initdata
= {
107 { "max_dev", &max_dev
},
108 { "write_threshold_kbs", &write_threshold_kbs
},
109 { "max_sg_segs", &max_sg_segs
}
113 /* Some default definitions have been moved to osst_options.h */
114 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
115 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
117 /* The buffer size should fit into the 24 bits for length in the
118 6-byte SCSI read and write commands. */
119 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
120 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
124 static int debugging
= 1;
125 /* uncomment define below to test error recovery */
126 // #define OSST_INJECT_ERRORS 1
129 /* Do not retry! The drive firmware already retries when appropriate,
130 and when it tries to tell us something, we had better listen... */
131 #define MAX_RETRIES 0
133 #define NO_TAPE NOT_READY
135 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
136 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
137 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
139 #define OSST_TIMEOUT (200 * HZ)
140 #define OSST_LONG_TIMEOUT (1800 * HZ)
142 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
143 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
144 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
145 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
147 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
149 #define SET_DENS_AND_BLK 0x10001
151 static int osst_buffer_size
= OSST_BUFFER_SIZE
;
152 static int osst_write_threshold
= OSST_WRITE_THRESHOLD
;
153 static int osst_max_sg_segs
= OSST_MAX_SG
;
154 static int osst_max_dev
= OSST_MAX_TAPES
;
155 static int osst_nr_dev
;
157 static struct osst_tape
**os_scsi_tapes
= NULL
;
158 static DEFINE_RWLOCK(os_scsi_tapes_lock
);
160 static int modes_defined
= 0;
162 static struct osst_buffer
*new_tape_buffer(int, int, int);
163 static int enlarge_buffer(struct osst_buffer
*, int);
164 static void normalize_buffer(struct osst_buffer
*);
165 static int append_to_buffer(const char __user
*, struct osst_buffer
*, int);
166 static int from_buffer(struct osst_buffer
*, char __user
*, int);
167 static int osst_zero_buffer_tail(struct osst_buffer
*);
168 static int osst_copy_to_buffer(struct osst_buffer
*, unsigned char *);
169 static int osst_copy_from_buffer(struct osst_buffer
*, unsigned char *);
171 static int osst_probe(struct device
*);
172 static int osst_remove(struct device
*);
174 static struct scsi_driver osst_template
= {
175 .owner
= THIS_MODULE
,
179 .remove
= osst_remove
,
183 static int osst_int_ioctl(struct osst_tape
*STp
, struct osst_request
** aSRpnt
,
184 unsigned int cmd_in
, unsigned long arg
);
186 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int frame
, int skip
);
188 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
190 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
192 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
);
194 static inline char *tape_name(struct osst_tape
*tape
)
196 return tape
->drive
->disk_name
;
199 /* Routines that handle the interaction with mid-layer SCSI routines */
202 /* Normalize Sense */
203 static void osst_analyze_sense(struct osst_request
*SRpnt
, struct st_cmdstatus
*s
)
206 const u8
*sense
= SRpnt
->sense
;
208 s
->have_sense
= scsi_normalize_sense(SRpnt
->sense
,
209 SCSI_SENSE_BUFFERSIZE
, &s
->sense_hdr
);
215 scsi_get_sense_info_fld(sense
, SCSI_SENSE_BUFFERSIZE
, &s
->uremainder64
);
216 switch (sense
[0] & 0x7f) {
221 s
->flags
= sense
[2] & 0xe0;
227 ucp
= scsi_sense_desc_find(sense
, SCSI_SENSE_BUFFERSIZE
, 4);
228 s
->flags
= ucp
? (ucp
[3] & 0xe0) : 0;
234 /* Convert the result to success code */
235 static int osst_chk_result(struct osst_tape
* STp
, struct osst_request
* SRpnt
)
237 char *name
= tape_name(STp
);
238 int result
= SRpnt
->result
;
239 u8
* sense
= SRpnt
->sense
, scode
;
243 struct st_cmdstatus
*cmdstatp
;
248 cmdstatp
= &STp
->buffer
->cmdstat
;
249 osst_analyze_sense(SRpnt
, cmdstatp
);
251 if (cmdstatp
->have_sense
)
252 scode
= STp
->buffer
->cmdstat
.sense_hdr
.sense_key
;
257 printk(OSST_DEB_MSG
"%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
259 SRpnt
->cmd
[0], SRpnt
->cmd
[1], SRpnt
->cmd
[2],
260 SRpnt
->cmd
[3], SRpnt
->cmd
[4], SRpnt
->cmd
[5]);
261 if (scode
) printk(OSST_DEB_MSG
"%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
262 name
, scode
, sense
[12], sense
[13]);
263 if (cmdstatp
->have_sense
)
264 __scsi_print_sense("osst ", SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
268 if (cmdstatp
->have_sense
&& (
270 scode
!= RECOVERED_ERROR
&&
271 /* scode != UNIT_ATTENTION && */
272 scode
!= BLANK_CHECK
&&
273 scode
!= VOLUME_OVERFLOW
&&
274 SRpnt
->cmd
[0] != MODE_SENSE
&&
275 SRpnt
->cmd
[0] != TEST_UNIT_READY
)) { /* Abnormal conditions for tape */
276 if (cmdstatp
->have_sense
) {
277 printk(KERN_WARNING
"%s:W: Command with sense data:\n", name
);
278 __scsi_print_sense("osst ", SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
281 static int notyetprinted
= 1;
284 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
285 name
, result
, driver_byte(result
),
290 "%s:I: This warning may be caused by your scsi controller,\n", name
);
292 "%s:I: it has been reported with some Buslogic cards.\n", name
);
296 STp
->pos_unknown
|= STp
->device
->was_reset
;
298 if (cmdstatp
->have_sense
&& scode
== RECOVERED_ERROR
) {
299 STp
->recover_count
++;
300 STp
->recover_erreg
++;
303 if (SRpnt
->cmd
[0] == READ_6
)
305 else if (SRpnt
->cmd
[0] == WRITE_6
)
309 printk(OSST_DEB_MSG
"%s:D: Recovered %s error (%d).\n", name
, stp
,
313 if ((sense
[2] & 0xe0) == 0)
320 /* Wakeup from interrupt */
321 static void osst_end_async(struct request
*req
, int update
)
323 struct osst_request
*SRpnt
= req
->end_io_data
;
324 struct osst_tape
*STp
= SRpnt
->stp
;
325 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
327 STp
->buffer
->cmdstat
.midlevel_result
= SRpnt
->result
= req
->errors
;
329 STp
->write_pending
= 0;
332 complete(SRpnt
->waiting
);
336 blk_rq_unmap_user(SRpnt
->bio
);
339 __blk_put_request(req
->q
, req
);
342 /* osst_request memory management */
343 static struct osst_request
*osst_allocate_request(void)
345 return kzalloc(sizeof(struct osst_request
), GFP_KERNEL
);
348 static void osst_release_request(struct osst_request
*streq
)
353 static int osst_execute(struct osst_request
*SRpnt
, const unsigned char *cmd
,
354 int cmd_len
, int data_direction
, void *buffer
, unsigned bufflen
,
355 int use_sg
, int timeout
, int retries
)
358 struct page
**pages
= NULL
;
359 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
362 int write
= (data_direction
== DMA_TO_DEVICE
);
364 req
= blk_get_request(SRpnt
->stp
->device
->request_queue
, write
, GFP_KERNEL
);
366 return DRIVER_ERROR
<< 24;
368 req
->cmd_type
= REQ_TYPE_BLOCK_PC
;
369 req
->cmd_flags
|= REQ_QUIET
;
374 struct scatterlist
*sg
, *sgl
= (struct scatterlist
*)buffer
;
377 pages
= kzalloc(use_sg
* sizeof(struct page
*), GFP_KERNEL
);
381 for_each_sg(sgl
, sg
, use_sg
, i
)
382 pages
[i
] = sg_page(sg
);
384 mdata
->null_mapped
= 1;
386 mdata
->page_order
= get_order(sgl
[0].length
);
388 DIV_ROUND_UP(bufflen
, PAGE_SIZE
<< mdata
->page_order
);
391 err
= blk_rq_map_user(req
->q
, req
, mdata
, NULL
, bufflen
, GFP_KERNEL
);
396 SRpnt
->bio
= req
->bio
;
397 mdata
->pages
= pages
;
399 } else if (bufflen
) {
400 err
= blk_rq_map_kern(req
->q
, req
, buffer
, bufflen
, GFP_KERNEL
);
405 req
->cmd_len
= cmd_len
;
406 memset(req
->cmd
, 0, BLK_MAX_CDB
); /* ATAPI hates garbage after CDB */
407 memcpy(req
->cmd
, cmd
, req
->cmd_len
);
408 req
->sense
= SRpnt
->sense
;
410 req
->timeout
= timeout
;
411 req
->retries
= retries
;
412 req
->end_io_data
= SRpnt
;
414 blk_execute_rq_nowait(req
->q
, NULL
, req
, 1, osst_end_async
);
417 blk_put_request(req
);
418 return DRIVER_ERROR
<< 24;
421 /* Do the scsi command. Waits until command performed if do_wait is true.
422 Otherwise osst_write_behind_check() is used to check that the command
424 static struct osst_request
* osst_do_scsi(struct osst_request
*SRpnt
, struct osst_tape
*STp
,
425 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
428 unsigned short use_sg
;
429 #ifdef OSST_INJECT_ERRORS
430 static int inject
= 0;
431 static int repeat
= 0;
433 struct completion
*waiting
;
435 /* if async, make sure there's no command outstanding */
436 if (!do_wait
&& ((STp
->buffer
)->last_SRpnt
)) {
437 printk(KERN_ERR
"%s: Async command already active.\n",
439 if (signal_pending(current
))
440 (STp
->buffer
)->syscall_result
= (-EINTR
);
442 (STp
->buffer
)->syscall_result
= (-EBUSY
);
447 SRpnt
= osst_allocate_request();
449 printk(KERN_ERR
"%s: Can't allocate SCSI request.\n",
451 if (signal_pending(current
))
452 (STp
->buffer
)->syscall_result
= (-EINTR
);
454 (STp
->buffer
)->syscall_result
= (-EBUSY
);
460 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
461 which IO is outstanding. It's nulled out when the IO completes. */
463 (STp
->buffer
)->last_SRpnt
= SRpnt
;
465 waiting
= &STp
->wait
;
466 init_completion(waiting
);
467 SRpnt
->waiting
= waiting
;
469 use_sg
= (bytes
> STp
->buffer
->sg
[0].length
) ? STp
->buffer
->use_sg
: 0;
471 bp
= (char *)&(STp
->buffer
->sg
[0]);
472 if (STp
->buffer
->sg_segs
< use_sg
)
473 use_sg
= STp
->buffer
->sg_segs
;
476 bp
= (STp
->buffer
)->b_data
;
478 memcpy(SRpnt
->cmd
, cmd
, sizeof(SRpnt
->cmd
));
479 STp
->buffer
->cmdstat
.have_sense
= 0;
480 STp
->buffer
->syscall_result
= 0;
482 if (osst_execute(SRpnt
, cmd
, COMMAND_SIZE(cmd
[0]), direction
, bp
, bytes
,
483 use_sg
, timeout
, retries
))
484 /* could not allocate the buffer or request was too large */
485 (STp
->buffer
)->syscall_result
= (-EBUSY
);
487 wait_for_completion(waiting
);
488 SRpnt
->waiting
= NULL
;
489 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
490 #ifdef OSST_INJECT_ERRORS
491 if (STp
->buffer
->syscall_result
== 0 &&
494 ( (++ inject
% 83) == 29 ||
495 (STp
->first_frame_position
== 240
496 /* or STp->read_error_frame to fail again on the block calculated above */ &&
498 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
499 STp
->buffer
->last_result_fatal
= 1;
507 /* Handle the write-behind checking (downs the semaphore) */
508 static void osst_write_behind_check(struct osst_tape
*STp
)
510 struct osst_buffer
* STbuffer
;
512 STbuffer
= STp
->buffer
;
515 if (STp
->write_pending
)
520 wait_for_completion(&(STp
->wait
));
521 STp
->buffer
->last_SRpnt
->waiting
= NULL
;
523 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
525 if (STp
->buffer
->syscall_result
)
526 STp
->buffer
->syscall_result
=
527 osst_write_error_recovery(STp
, &(STp
->buffer
->last_SRpnt
), 1);
529 STp
->first_frame_position
++;
531 osst_release_request(STp
->buffer
->last_SRpnt
);
533 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
534 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
536 STbuffer
->last_SRpnt
= NULL
;
537 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
538 STbuffer
->writing
= 0;
545 /* Onstream specific Routines */
547 * Initialize the OnStream AUX
549 static void osst_init_aux(struct osst_tape
* STp
, int frame_type
, int frame_seq_number
,
550 int logical_blk_num
, int blk_sz
, int blk_cnt
)
552 os_aux_t
*aux
= STp
->buffer
->aux
;
553 os_partition_t
*par
= &aux
->partition
;
554 os_dat_t
*dat
= &aux
->dat
;
556 if (STp
->raw
) return;
558 memset(aux
, 0, sizeof(*aux
));
559 aux
->format_id
= htonl(0);
560 memcpy(aux
->application_sig
, "LIN4", 4);
561 aux
->hdwr
= htonl(0);
562 aux
->frame_type
= frame_type
;
564 switch (frame_type
) {
565 case OS_FRAME_TYPE_HEADER
:
566 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
567 par
->partition_num
= OS_CONFIG_PARTITION
;
568 par
->par_desc_ver
= OS_PARTITION_VERSION
;
569 par
->wrt_pass_cntr
= htons(0xffff);
570 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
571 par
->first_frame_ppos
= htonl(0);
572 par
->last_frame_ppos
= htonl(0xbb7);
573 aux
->frame_seq_num
= htonl(0);
574 aux
->logical_blk_num_high
= htonl(0);
575 aux
->logical_blk_num
= htonl(0);
576 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
578 case OS_FRAME_TYPE_DATA
:
579 case OS_FRAME_TYPE_MARKER
:
584 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
585 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
586 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
587 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
588 dat
->dat_list
[0].reserved
= 0;
589 case OS_FRAME_TYPE_EOD
:
590 aux
->update_frame_cntr
= htonl(0);
591 par
->partition_num
= OS_DATA_PARTITION
;
592 par
->par_desc_ver
= OS_PARTITION_VERSION
;
593 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
594 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
595 par
->last_frame_ppos
= htonl(STp
->capacity
);
596 aux
->frame_seq_num
= htonl(frame_seq_number
);
597 aux
->logical_blk_num_high
= htonl(0);
598 aux
->logical_blk_num
= htonl(logical_blk_num
);
600 default: ; /* probably FILL */
602 aux
->filemark_cnt
= htonl(STp
->filemark_cnt
);
603 aux
->phys_fm
= htonl(0xffffffff);
604 aux
->last_mark_ppos
= htonl(STp
->last_mark_ppos
);
605 aux
->last_mark_lbn
= htonl(STp
->last_mark_lbn
);
609 * Verify that we have the correct tape frame
611 static int osst_verify_frame(struct osst_tape
* STp
, int frame_seq_number
, int quiet
)
613 char * name
= tape_name(STp
);
614 os_aux_t
* aux
= STp
->buffer
->aux
;
615 os_partition_t
* par
= &(aux
->partition
);
616 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
617 int blk_cnt
, blk_sz
, i
;
620 if (STp
->buffer
->syscall_result
) {
621 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
622 memset(page_address(sg_page(&STp
->buffer
->sg
[i
])),
623 0, STp
->buffer
->sg
[i
].length
);
624 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
626 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
629 if (STp
->buffer
->syscall_result
) {
631 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
635 if (ntohl(aux
->format_id
) != 0) {
637 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
641 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
642 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
644 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
648 if (par
->partition_num
!= OS_DATA_PARTITION
) {
649 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
651 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
652 name
, par
->partition_num
);
657 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
659 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
663 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
665 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
666 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
670 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
671 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
672 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
675 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
680 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
681 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
682 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
683 STp
->first_frame_position
);
686 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
689 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
690 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
695 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
696 STps
->eof
= ST_FM_HIT
;
698 i
= ntohl(aux
->filemark_cnt
);
699 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
700 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
702 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
703 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
704 i
, STp
->first_frame_position
- 1);
706 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
707 if (i
>= STp
->filemark_cnt
)
708 STp
->filemark_cnt
= i
+1;
711 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
712 STps
->eof
= ST_EOD_1
;
713 STp
->frame_in_buffer
= 1;
715 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
716 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
717 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
718 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
719 STp
->buffer
->read_pointer
= 0;
720 STp
->frame_in_buffer
= 1;
722 /* See what block size was used to write file */
723 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
725 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
726 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
727 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
728 STp
->block_size
<1024?'b':'k');
729 STp
->block_size
= blk_sz
;
730 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
732 STps
->eof
= ST_NOEOF
;
734 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
735 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
739 if (STp
->read_error_frame
== 0)
740 STp
->read_error_frame
= STp
->first_frame_position
- 1;
745 * Wait for the unit to become Ready
747 static int osst_wait_ready(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
748 unsigned timeout
, int initial_delay
)
750 unsigned char cmd
[MAX_COMMAND_SIZE
];
751 struct osst_request
* SRpnt
;
752 unsigned long startwait
= jiffies
;
755 char * name
= tape_name(STp
);
757 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
760 if (initial_delay
> 0)
761 msleep(jiffies_to_msecs(initial_delay
));
763 memset(cmd
, 0, MAX_COMMAND_SIZE
);
764 cmd
[0] = TEST_UNIT_READY
;
766 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
768 if (!SRpnt
) return (-EBUSY
);
770 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
771 (( SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
772 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8) ) ||
773 ( SRpnt
->sense
[2] == 6 && SRpnt
->sense
[12] == 0x28 &&
774 SRpnt
->sense
[13] == 0 ) )) {
777 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
778 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
784 memset(cmd
, 0, MAX_COMMAND_SIZE
);
785 cmd
[0] = TEST_UNIT_READY
;
787 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
793 if ( STp
->buffer
->syscall_result
&&
794 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
796 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
797 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
798 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
799 SRpnt
->sense
[12], SRpnt
->sense
[13]);
804 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
810 * Wait for a tape to be inserted in the unit
812 static int osst_wait_for_medium(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, unsigned timeout
)
814 unsigned char cmd
[MAX_COMMAND_SIZE
];
815 struct osst_request
* SRpnt
;
816 unsigned long startwait
= jiffies
;
819 char * name
= tape_name(STp
);
821 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
824 memset(cmd
, 0, MAX_COMMAND_SIZE
);
825 cmd
[0] = TEST_UNIT_READY
;
827 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
829 if (!SRpnt
) return (-EBUSY
);
831 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
832 SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 0x3a && SRpnt
->sense
[13] == 0 ) {
835 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
836 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
842 memset(cmd
, 0, MAX_COMMAND_SIZE
);
843 cmd
[0] = TEST_UNIT_READY
;
845 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
851 if ( STp
->buffer
->syscall_result
&& SRpnt
->sense
[2] != 2 &&
852 SRpnt
->sense
[12] != 4 && SRpnt
->sense
[13] == 1) {
854 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
855 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
856 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
857 SRpnt
->sense
[12], SRpnt
->sense
[13]);
862 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
867 static int osst_position_tape_and_confirm(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int frame
)
871 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
872 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
873 if (retval
) return (retval
);
874 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
875 return (osst_get_frame_position(STp
, aSRpnt
));
879 * Wait for write(s) to complete
881 static int osst_flush_drive_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
883 unsigned char cmd
[MAX_COMMAND_SIZE
];
884 struct osst_request
* SRpnt
;
886 int delay
= OSST_WAIT_WRITE_COMPLETE
;
888 char * name
= tape_name(STp
);
890 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
893 memset(cmd
, 0, MAX_COMMAND_SIZE
);
894 cmd
[0] = WRITE_FILEMARKS
;
897 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
899 if (!SRpnt
) return (-EBUSY
);
900 if (STp
->buffer
->syscall_result
) {
901 if ((SRpnt
->sense
[2] & 0x0f) == 2 && SRpnt
->sense
[12] == 4) {
902 if (SRpnt
->sense
[13] == 8) {
903 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
906 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
908 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
909 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
914 #define OSST_POLL_PER_SEC 10
915 static int osst_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int curr
, int minlast
, int to
)
917 unsigned long startwait
= jiffies
;
918 char * name
= tape_name(STp
);
920 char notyetprinted
= 1;
922 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
923 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
925 while (time_before (jiffies
, startwait
+ to
*HZ
))
928 result
= osst_get_frame_position(STp
, aSRpnt
);
930 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
931 return 0; /* successful recovery leaves drive ready for frame */
932 if (result
< 0) break;
933 if (STp
->first_frame_position
== curr
&&
935 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
936 (minlast
>= 0 && STp
->cur_frames
> minlast
)
940 if (debugging
|| time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
))
942 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
943 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
944 STp
->last_frame_position
, STp
->cur_frames
,
945 result
, (jiffies
-startwait
)/HZ
,
946 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
951 if (time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
) && notyetprinted
)
953 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
954 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
955 STp
->last_frame_position
, STp
->cur_frames
, result
);
959 msleep(1000 / OSST_POLL_PER_SEC
);
962 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
963 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
964 STp
->last_frame_position
, STp
->cur_frames
,
965 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
970 static int osst_recover_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int writing
)
972 struct osst_request
* SRpnt
;
973 unsigned char cmd
[MAX_COMMAND_SIZE
];
974 unsigned long startwait
= jiffies
;
976 char * name
= tape_name(STp
);
980 char * olddata
= STp
->buffer
->b_data
;
981 int oldsize
= STp
->buffer
->buffer_size
;
983 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
985 memset(cmd
, 0, MAX_COMMAND_SIZE
);
986 cmd
[0] = WRITE_FILEMARKS
;
988 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
991 while (retval
&& time_before (jiffies
, startwait
+ 5*60*HZ
)) {
993 if (STp
->buffer
->syscall_result
&& (SRpnt
->sense
[2] & 0x0f) != 2) {
995 /* some failure - not just not-ready */
996 retval
= osst_write_error_recovery(STp
, aSRpnt
, 0);
999 schedule_timeout_interruptible(HZ
/ OSST_POLL_PER_SEC
);
1001 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
1002 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1003 cmd
[0] = READ_POSITION
;
1005 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
1008 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
1009 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
1012 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
1014 /* TODO - figure out which error conditions can be handled */
1015 if (STp
->buffer
->syscall_result
)
1017 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
1018 (*aSRpnt
)->sense
[ 2] & 0x0f,
1019 (*aSRpnt
)->sense
[12],
1020 (*aSRpnt
)->sense
[13]);
1026 * Read the next OnStream tape frame at the current location
1028 static int osst_read_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int timeout
)
1030 unsigned char cmd
[MAX_COMMAND_SIZE
];
1031 struct osst_request
* SRpnt
;
1034 os_aux_t
* aux
= STp
->buffer
->aux
;
1035 char * name
= tape_name(STp
);
1039 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
1040 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
1042 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1049 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
1051 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1052 STp
->timeout
, MAX_RETRIES
, 1);
1057 if ((STp
->buffer
)->syscall_result
) {
1059 if (STp
->read_error_frame
== 0) {
1060 STp
->read_error_frame
= STp
->first_frame_position
;
1062 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
1067 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1069 SRpnt
->sense
[0], SRpnt
->sense
[1],
1070 SRpnt
->sense
[2], SRpnt
->sense
[3],
1071 SRpnt
->sense
[4], SRpnt
->sense
[5],
1072 SRpnt
->sense
[6], SRpnt
->sense
[7]);
1076 STp
->first_frame_position
++;
1081 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
1084 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
1085 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
1086 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
1087 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
1088 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
1089 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
1090 if (aux
->frame_type
==2)
1091 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
1092 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
1093 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
1099 static int osst_initiate_read(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1101 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1102 struct osst_request
* SRpnt
;
1103 unsigned char cmd
[MAX_COMMAND_SIZE
];
1105 char * name
= tape_name(STp
);
1107 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
1108 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
1109 STp
->write_type
= OS_WRITE_DATA
;
1110 osst_flush_write_buffer(STp
, aSRpnt
);
1111 osst_flush_drive_buffer(STp
, aSRpnt
);
1113 STps
->rw
= ST_READING
;
1114 STp
->frame_in_buffer
= 0;
1117 * Issue a read 0 command to get the OnStream drive
1118 * read frames into its buffer.
1120 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1125 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
1127 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
1129 if ((retval
= STp
->buffer
->syscall_result
))
1130 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1136 static int osst_get_logical_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1137 int frame_seq_number
, int quiet
)
1139 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1140 char * name
= tape_name(STp
);
1148 * If we want just any frame (-1) and there is a frame in the buffer, return it
1150 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1152 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1157 * Search and wait for the next logical tape frame
1161 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1162 name
, frame_seq_number
);
1163 if (STp
->read_error_frame
) {
1164 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1166 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1167 name
, STp
->read_error_frame
);
1169 STp
->read_error_frame
= 0;
1176 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1177 name
, frame_seq_number
, cnt
);
1179 if ( osst_initiate_read(STp
, aSRpnt
)
1180 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1183 position
= osst_get_frame_position(STp
, aSRpnt
);
1184 if (position
>= 0xbae && position
< 0xbb8)
1186 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1187 position
= STp
->read_error_frame
- 1;
1195 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1198 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1201 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1203 if (osst_verify_frame(STp
, -1, quiet
)) {
1204 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1205 if (STp
->fast_open
) {
1207 "%s:W: Found logical frame %d instead of %d after fast open\n",
1208 name
, x
, frame_seq_number
);
1210 STp
->read_error_frame
= 0;
1213 if (x
> frame_seq_number
) {
1215 /* positioning backwards did not bring us to the desired frame */
1216 position
= STp
->read_error_frame
- 1;
1219 position
= osst_get_frame_position(STp
, aSRpnt
)
1220 + frame_seq_number
- x
- 1;
1222 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1227 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1228 name
, x
, frame_seq_number
,
1229 STp
->first_frame_position
- position
);
1231 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1237 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1239 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1241 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1244 STp
->frame_in_buffer
= 0;
1247 STp
->recover_count
++;
1248 STp
->recover_erreg
++;
1249 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1250 name
, STp
->read_error_frame
);
1255 if (debugging
|| STps
->eof
)
1257 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1258 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1261 STp
->read_error_frame
= 0;
1265 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int logical_blk_num
)
1267 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1268 char * name
= tape_name(STp
);
1270 int frame_seq_estimate
, ppos_estimate
, move
;
1272 if (logical_blk_num
< 0) logical_blk_num
= 0;
1274 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1275 name
, logical_blk_num
, STp
->logical_blk_num
,
1276 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1277 STp
->block_size
<1024?'b':'k');
1279 /* Do we know where we are? */
1280 if (STps
->drv_block
>= 0) {
1281 move
= logical_blk_num
- STp
->logical_blk_num
;
1282 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1283 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1284 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1286 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1288 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1289 else ppos_estimate
= frame_seq_estimate
+ 20;
1290 while (++retries
< 10) {
1291 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1292 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1293 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1295 if (frame_seq_estimate
< 0) {
1296 frame_seq_estimate
= 0;
1299 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1300 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1301 /* we've located the estimated frame, now does it have our block? */
1302 if (logical_blk_num
< STp
->logical_blk_num
||
1303 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1304 if (STps
->eof
== ST_FM_HIT
)
1305 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1307 move
= logical_blk_num
- STp
->logical_blk_num
;
1308 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1309 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1311 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1314 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1315 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1316 STp
->logical_blk_num
, logical_blk_num
, move
);
1318 frame_seq_estimate
+= move
;
1319 ppos_estimate
+= move
;
1322 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1323 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1324 STp
->logical_blk_num
= logical_blk_num
;
1327 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1328 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1329 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1332 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1333 if (STps
->eof
== ST_FM_HIT
) {
1335 STps
->drv_block
= 0;
1337 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1338 STp
->logical_blk_num
-
1339 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1342 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1346 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1348 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1350 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1351 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1352 STp
->logical_blk_num
, logical_blk_num
);
1354 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1355 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1360 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1361 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1365 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1366 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1367 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1368 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1370 #define OSST_FRAME_SHIFT 6
1371 #define OSST_SECTOR_SHIFT 9
1372 #define OSST_SECTOR_MASK 0x03F
1374 static int osst_get_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1378 char * name
= tape_name(STp
);
1381 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1382 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1383 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1384 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1385 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1386 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1388 /* do we know where we are inside a file? */
1389 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1390 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1391 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1392 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1393 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1395 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1397 sector
= osst_get_frame_position(STp
, aSRpnt
);
1399 sector
<<= OSST_FRAME_SHIFT
;
1404 static int osst_seek_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int sector
)
1406 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1407 int frame
= sector
>> OSST_FRAME_SHIFT
,
1408 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1411 char * name
= tape_name(STp
);
1413 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1414 name
, sector
, frame
, offset
);
1416 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1418 if (frame
<= STp
->first_data_ppos
) {
1419 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1420 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1422 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1423 if (r
< 0) return r
;
1425 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1426 if (r
< 0) return r
;
1428 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1431 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1432 STp
->buffer
->read_pointer
= offset
;
1433 STp
->buffer
->buffer_bytes
-= offset
;
1435 STp
->frame_seq_number
++;
1436 STp
->frame_in_buffer
= 0;
1437 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1438 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1440 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1441 if (STps
->eof
== ST_FM_HIT
) {
1443 STps
->drv_block
= 0;
1445 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1446 STp
->logical_blk_num
-
1447 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1450 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1453 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1454 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1455 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1461 * Read back the drive's internal buffer contents, as a part
1462 * of the write error recovery mechanism for old OnStream
1463 * firmware revisions.
1464 * Precondition for this function to work: all frames in the
1465 * drive's buffer must be of one type (DATA, MARK or EOD)!
1467 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1468 unsigned int frame
, unsigned int skip
, int pending
)
1470 struct osst_request
* SRpnt
= * aSRpnt
;
1471 unsigned char * buffer
, * p
;
1472 unsigned char cmd
[MAX_COMMAND_SIZE
];
1473 int flag
, new_frame
, i
;
1474 int nframes
= STp
->cur_frames
;
1475 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1476 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1477 - (nframes
+ pending
- 1);
1478 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1479 - (nframes
+ pending
- 1) * blks_per_frame
;
1480 char * name
= tape_name(STp
);
1481 unsigned long startwait
= jiffies
;
1483 int dbg
= debugging
;
1486 if ((buffer
= (unsigned char *)vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1489 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1490 name
, nframes
, pending
?" and one that was pending":"");
1492 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1494 if (pending
&& debugging
)
1495 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1496 name
, frame_seq_number
+ nframes
,
1497 logical_blk_num
+ nframes
* blks_per_frame
,
1498 p
[0], p
[1], p
[2], p
[3]);
1500 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1502 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1503 cmd
[0] = 0x3C; /* Buffer Read */
1504 cmd
[1] = 6; /* Retrieve Faulty Block */
1505 cmd
[7] = 32768 >> 8;
1506 cmd
[8] = 32768 & 0xff;
1508 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1509 STp
->timeout
, MAX_RETRIES
, 1);
1511 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1512 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1517 osst_copy_from_buffer(STp
->buffer
, p
);
1520 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1521 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1525 osst_get_frame_position(STp
, aSRpnt
);
1528 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1530 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1531 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1533 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1536 if (STp
->write_type
== OS_WRITE_HEADER
) {
1538 p
+= skip
* OS_DATA_SIZE
;
1540 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1545 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1546 name
, new_frame
+i
, frame_seq_number
+i
);
1548 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1549 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1550 osst_get_frame_position(STp
, aSRpnt
);
1553 if (new_frame
> frame
+ 1000) {
1554 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1558 if ( i
>= nframes
+ pending
) break;
1561 osst_copy_to_buffer(STp
->buffer
, p
);
1563 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1565 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1566 logical_blk_num
+ i
*blks_per_frame
,
1567 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1568 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1576 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1577 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1578 p
[0], p
[1], p
[2], p
[3]);
1580 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1581 STp
->timeout
, MAX_RETRIES
, 1);
1583 if (STp
->buffer
->syscall_result
)
1586 p
+= OS_DATA_SIZE
; i
++;
1588 /* if we just sent the last frame, wait till all successfully written */
1589 if ( i
== nframes
+ pending
) {
1591 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1593 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1594 cmd
[0] = WRITE_FILEMARKS
;
1596 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1597 STp
->timeout
, MAX_RETRIES
, 1);
1600 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1601 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1605 flag
= STp
->buffer
->syscall_result
;
1606 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1608 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1609 cmd
[0] = TEST_UNIT_READY
;
1611 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1614 if (SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
1615 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8)) {
1616 /* in the process of becoming ready */
1620 if (STp
->buffer
->syscall_result
)
1626 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1632 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1633 SRpnt
->sense
[12] == 0 &&
1634 SRpnt
->sense
[13] == 2) {
1635 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1637 return (-EIO
); /* hit end of tape = fail */
1639 i
= ((SRpnt
->sense
[3] << 24) |
1640 (SRpnt
->sense
[4] << 16) |
1641 (SRpnt
->sense
[5] << 8) |
1642 SRpnt
->sense
[6] ) - new_frame
;
1643 p
= &buffer
[i
* OS_DATA_SIZE
];
1645 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1647 osst_get_frame_position(STp
, aSRpnt
);
1649 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1650 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1655 /* error recovery did not successfully complete */
1656 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1657 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1660 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1665 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1666 unsigned int frame
, unsigned int skip
, int pending
)
1668 unsigned char cmd
[MAX_COMMAND_SIZE
];
1669 struct osst_request
* SRpnt
;
1670 char * name
= tape_name(STp
);
1672 int attempts
= 1000 / skip
;
1674 unsigned long startwait
= jiffies
;
1676 int dbg
= debugging
;
1679 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1684 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1686 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1688 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1689 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1691 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1694 schedule_timeout_interruptible(msecs_to_jiffies(100));
1696 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1698 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1699 name
, STp
->first_frame_position
,
1700 STp
->last_frame_position
, STp
->cur_frames
);
1702 frame
= STp
->last_frame_position
;
1706 if (pending
&& STp
->cur_frames
< 50) {
1708 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1713 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1714 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1716 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1717 STp
->timeout
, MAX_RETRIES
, 1);
1720 if (STp
->buffer
->syscall_result
) { /* additional write error */
1721 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1722 SRpnt
->sense
[12] == 0 &&
1723 SRpnt
->sense
[13] == 2) {
1725 "%s:E: Volume overflow in write error recovery\n",
1727 break; /* hit end of tape = fail */
1736 if (STp
->cur_frames
== 0) {
1739 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1741 if (STp
->first_frame_position
!= expected
) {
1742 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1743 name
, STp
->first_frame_position
, expected
);
1750 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1751 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1755 schedule_timeout_interruptible(msecs_to_jiffies(100));
1757 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1765 * Error recovery algorithm for the OnStream tape.
1768 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
)
1770 struct osst_request
* SRpnt
= * aSRpnt
;
1771 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1772 char * name
= tape_name(STp
);
1775 unsigned int frame
, skip
;
1777 rw_state
= STps
->rw
;
1779 if ((SRpnt
->sense
[ 2] & 0x0f) != 3
1780 || SRpnt
->sense
[12] != 12
1781 || SRpnt
->sense
[13] != 0) {
1783 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1784 SRpnt
->sense
[2], SRpnt
->sense
[12], SRpnt
->sense
[13]);
1788 frame
= (SRpnt
->sense
[3] << 24) |
1789 (SRpnt
->sense
[4] << 16) |
1790 (SRpnt
->sense
[5] << 8) |
1792 skip
= SRpnt
->sense
[9];
1795 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1797 osst_get_frame_position(STp
, aSRpnt
);
1799 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1800 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1802 switch (STp
->write_type
) {
1805 case OS_WRITE_NEW_MARK
:
1807 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1808 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1809 if (STp
->os_fw_rev
>= 10600)
1810 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1812 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1813 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1815 retval
?"" :"Don't worry, ",
1816 retval
?" not ":" ");
1818 case OS_WRITE_LAST_MARK
:
1819 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1820 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1823 case OS_WRITE_HEADER
:
1824 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1825 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1828 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1829 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1831 osst_get_frame_position(STp
, aSRpnt
);
1833 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1834 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1835 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1838 STp
->recover_count
++;
1839 STp
->recover_erreg
++;
1843 STps
->rw
= rw_state
;
1847 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1848 int mt_op
, int mt_count
)
1850 char * name
= tape_name(STp
);
1852 int last_mark_ppos
= -1;
1855 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1857 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1859 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1863 if (STp
->linux_media_version
>= 4) {
1865 * direct lookup in header filemark list
1867 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1868 if (STp
->header_ok
&&
1869 STp
->header_cache
!= NULL
&&
1870 (cnt
- mt_count
) >= 0 &&
1871 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1872 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1873 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1875 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1877 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1878 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1879 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1881 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1883 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1884 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1885 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1886 mt_count
, last_mark_ppos
);
1888 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1889 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1890 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1893 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1897 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1898 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1899 name
, last_mark_ppos
);
1905 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1909 while (cnt
!= mt_count
) {
1910 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1911 if (last_mark_ppos
== -1)
1914 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1916 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1918 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1920 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1924 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1925 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1926 name
, last_mark_ppos
);
1931 if (mt_op
== MTBSFM
) {
1932 STp
->frame_seq_number
++;
1933 STp
->frame_in_buffer
= 0;
1934 STp
->buffer
->buffer_bytes
= 0;
1935 STp
->buffer
->read_pointer
= 0;
1936 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1942 * ADRL 1.1 compatible "slow" space filemarks fwd version
1944 * Just scans for the filemark sequentially.
1946 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1947 int mt_op
, int mt_count
)
1951 char * name
= tape_name(STp
);
1953 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1955 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1957 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1962 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1964 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1968 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1970 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1972 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1974 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1976 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1977 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1979 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1983 if (cnt
== mt_count
)
1985 STp
->frame_in_buffer
= 0;
1987 if (mt_op
== MTFSF
) {
1988 STp
->frame_seq_number
++;
1989 STp
->frame_in_buffer
= 0;
1990 STp
->buffer
->buffer_bytes
= 0;
1991 STp
->buffer
->read_pointer
= 0;
1992 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1998 * Fast linux specific version of OnStream FSF
2000 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
2001 int mt_op
, int mt_count
)
2003 char * name
= tape_name(STp
);
2005 next_mark_ppos
= -1;
2008 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
2010 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2012 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
2017 if (STp
->linux_media_version
>= 4) {
2019 * direct lookup in header filemark list
2021 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
2022 if (STp
->header_ok
&&
2023 STp
->header_cache
!= NULL
&&
2024 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
2025 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
2026 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2027 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
2029 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
2031 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
2032 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
2033 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
2035 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2037 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2038 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
2039 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
2040 mt_count
, next_mark_ppos
);
2042 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
2044 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2046 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2048 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2049 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2051 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2056 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2057 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2058 name
, next_mark_ppos
);
2061 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
2062 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
2063 name
, cnt
+mt_count
, next_mark_ppos
,
2064 ntohl(STp
->buffer
->aux
->filemark_cnt
));
2070 * Find nearest (usually previous) marker, then jump from marker to marker
2073 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
2075 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
2077 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
2081 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
2082 if (STp
->first_mark_ppos
== -1) {
2084 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2086 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2088 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
2089 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2092 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2097 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2098 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
2099 name
, STp
->first_mark_ppos
);
2103 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
2109 while (cnt
!= mt_count
) {
2110 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
2111 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
2113 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2115 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
2118 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
2120 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2122 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2124 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2129 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2130 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2131 name
, next_mark_ppos
);
2136 if (mt_op
== MTFSF
) {
2137 STp
->frame_seq_number
++;
2138 STp
->frame_in_buffer
= 0;
2139 STp
->buffer
->buffer_bytes
= 0;
2140 STp
->buffer
->read_pointer
= 0;
2141 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2147 * In debug mode, we want to see as many errors as possible
2148 * to test the error recovery mechanism.
2151 static void osst_set_retries(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int retries
)
2153 unsigned char cmd
[MAX_COMMAND_SIZE
];
2154 struct osst_request
* SRpnt
= * aSRpnt
;
2155 char * name
= tape_name(STp
);
2157 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2158 cmd
[0] = MODE_SELECT
;
2160 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2162 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2163 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2164 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2165 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2166 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2167 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2168 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2169 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2172 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2174 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2177 if ((STp
->buffer
)->syscall_result
)
2178 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2183 static int osst_write_filemark(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2186 int this_mark_ppos
= STp
->first_frame_position
;
2187 int this_mark_lbn
= STp
->logical_blk_num
;
2189 char * name
= tape_name(STp
);
2192 if (STp
->raw
) return 0;
2194 STp
->write_type
= OS_WRITE_NEW_MARK
;
2196 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2197 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2200 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2201 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2202 STp
->last_mark_ppos
= this_mark_ppos
;
2203 STp
->last_mark_lbn
= this_mark_lbn
;
2204 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2205 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2206 if (STp
->filemark_cnt
++ == 0)
2207 STp
->first_mark_ppos
= this_mark_ppos
;
2211 static int osst_write_eod(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2215 char * name
= tape_name(STp
);
2218 if (STp
->raw
) return 0;
2220 STp
->write_type
= OS_WRITE_EOD
;
2221 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2223 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2224 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2228 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2229 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2230 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2234 static int osst_write_filler(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2236 char * name
= tape_name(STp
);
2239 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2241 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2242 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2243 STp
->write_type
= OS_WRITE_FILLER
;
2245 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2246 STp
->buffer
->buffer_bytes
= 6;
2248 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2249 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2254 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2256 return osst_flush_drive_buffer(STp
, aSRpnt
);
2259 static int __osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2261 char * name
= tape_name(STp
);
2265 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2267 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2268 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2269 STp
->write_type
= OS_WRITE_HEADER
;
2271 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2272 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2274 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2275 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2279 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2281 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2286 static int osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int locate_eod
)
2288 os_header_t
* header
;
2290 char * name
= tape_name(STp
);
2293 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2295 if (STp
->raw
) return 0;
2297 if (STp
->header_cache
== NULL
) {
2298 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2299 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2302 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2304 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2307 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2308 else STp
->update_frame_cntr
= 0;
2310 header
= STp
->header_cache
;
2311 strcpy(header
->ident_str
, "ADR_SEQ");
2312 header
->major_rev
= 1;
2313 header
->minor_rev
= 4;
2314 header
->ext_trk_tb_off
= htons(17192);
2315 header
->pt_par_num
= 1;
2316 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2317 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2318 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2319 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2320 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2321 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2322 header
->cfg_col_width
= htonl(20);
2323 header
->dat_col_width
= htonl(1500);
2324 header
->qfa_col_width
= htonl(0);
2325 header
->ext_track_tb
.nr_stream_part
= 1;
2326 header
->ext_track_tb
.et_ent_sz
= 32;
2327 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2328 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2329 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2330 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2331 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2332 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2333 header
->dat_fm_tab
.fm_part_num
= 0;
2334 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2335 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2336 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2338 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2339 if (STp
->update_frame_cntr
== 0)
2340 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2341 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2345 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2347 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2350 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2352 memcpy(STp
->application_sig
, "LIN4", 4);
2353 STp
->linux_media
= 1;
2354 STp
->linux_media_version
= 4;
2360 static int osst_reset_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2362 if (STp
->header_cache
!= NULL
)
2363 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2365 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2366 STp
->frame_in_buffer
= 0;
2367 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2368 STp
->filemark_cnt
= 0;
2369 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2370 return osst_write_header(STp
, aSRpnt
, 1);
2373 static int __osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int ppos
)
2375 char * name
= tape_name(STp
);
2376 os_header_t
* header
;
2379 int linux_media_version
,
2385 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2386 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2387 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2388 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2389 if (osst_initiate_read (STp
, aSRpnt
)) {
2390 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2394 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2396 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2400 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2401 aux
= STp
->buffer
->aux
;
2402 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2404 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2408 if (ntohl(aux
->frame_seq_num
) != 0 ||
2409 ntohl(aux
->logical_blk_num
) != 0 ||
2410 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2411 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2412 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2414 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2415 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2416 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2417 ntohl(aux
->partition
.last_frame_ppos
));
2421 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2422 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2423 strlcpy(id_string
, header
->ident_str
, 8);
2425 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2429 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2430 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2432 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2433 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2437 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2439 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2440 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2441 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2442 header
->major_rev
, header
->minor_rev
);
2444 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2448 if (header
->pt_par_num
!= 1)
2449 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2450 name
, header
->pt_par_num
);
2452 memcpy(id_string
, aux
->application_sig
, 4);
2454 if (memcmp(id_string
, "LIN", 3) == 0) {
2455 STp
->linux_media
= 1;
2456 linux_media_version
= id_string
[3] - '0';
2457 if (linux_media_version
!= 4)
2458 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2459 name
, linux_media_version
);
2461 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2464 if (linux_media_version
< STp
->linux_media_version
) {
2466 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2467 name
, ppos
, linux_media_version
);
2471 if (linux_media_version
> STp
->linux_media_version
) {
2473 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2474 name
, ppos
, linux_media_version
);
2476 memcpy(STp
->application_sig
, id_string
, 5);
2477 STp
->linux_media_version
= linux_media_version
;
2478 STp
->update_frame_cntr
= -1;
2480 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2482 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2483 name
, ppos
, update_frame_cntr
);
2485 if (STp
->header_cache
== NULL
) {
2486 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2487 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2491 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2494 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2495 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2497 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2498 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2499 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2500 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2501 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2502 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2503 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2504 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2505 STp
->update_frame_cntr
= update_frame_cntr
;
2507 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2508 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2509 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2510 STp
->first_data_ppos
,
2511 ntohl(header
->partition
[0].last_frame_ppos
),
2512 ntohl(header
->partition
[0].eod_frame_ppos
));
2513 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2514 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2516 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2518 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2520 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2521 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2522 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2524 if (header
->minor_rev
== 4 &&
2525 (header
->ext_trk_tb_off
!= htons(17192) ||
2526 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2527 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2528 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2529 header
->cfg_col_width
!= htonl(20) ||
2530 header
->dat_col_width
!= htonl(1500) ||
2531 header
->qfa_col_width
!= htonl(0) ||
2532 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2533 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2534 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2535 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2536 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2537 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2538 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2539 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2540 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2541 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2542 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2543 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2550 static int osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2555 char * name
= tape_name(STp
);
2557 position
= osst_get_frame_position(STp
, aSRpnt
);
2560 STp
->header_ok
= STp
->linux_media
= 1;
2561 STp
->linux_media_version
= 0;
2564 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2565 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2566 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2567 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2569 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2572 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2573 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2575 first
= position
==10?0xbae: 5;
2576 last
= position
==10?0xbb3:10;
2578 for (ppos
= first
; ppos
< last
; ppos
++)
2579 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2582 first
= position
==10? 5:0xbae;
2583 last
= position
==10?10:0xbb3;
2585 for (ppos
= first
; ppos
< last
; ppos
++)
2586 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2590 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2591 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2592 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2595 if (position
<= STp
->first_data_ppos
) {
2596 position
= STp
->first_data_ppos
;
2597 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2599 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2605 static int osst_verify_position(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2607 int frame_position
= STp
->first_frame_position
;
2608 int frame_seq_numbr
= STp
->frame_seq_number
;
2609 int logical_blk_num
= STp
->logical_blk_num
;
2610 int halfway_frame
= STp
->frame_in_buffer
;
2611 int read_pointer
= STp
->buffer
->read_pointer
;
2612 int prev_mark_ppos
= -1;
2613 int actual_mark_ppos
, i
, n
;
2615 char * name
= tape_name(STp
);
2617 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2619 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2620 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2622 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2626 if (STp
->linux_media_version
>= 4) {
2627 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2628 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2631 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2632 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2633 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2634 if (frame_position
!= STp
->first_frame_position
||
2635 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2636 prev_mark_ppos
!= actual_mark_ppos
) {
2638 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2639 STp
->first_frame_position
, frame_position
,
2640 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2641 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2645 if (halfway_frame
) {
2646 /* prepare buffer for append and rewrite on top of original */
2647 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2648 STp
->buffer
->buffer_bytes
= read_pointer
;
2649 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2652 STp
->frame_in_buffer
= halfway_frame
;
2653 STp
->frame_seq_number
= frame_seq_numbr
;
2654 STp
->logical_blk_num
= logical_blk_num
;
2658 /* Acc. to OnStream, the vers. numbering is the following:
2659 * X.XX for released versions (X=digit),
2660 * XXXY for unreleased versions (Y=letter)
2661 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2662 * This fn makes monoton numbers out of this scheme ...
2664 static unsigned int osst_parse_firmware_rev (const char * str
)
2666 if (str
[1] == '.') {
2667 return (str
[0]-'0')*10000
2671 return (str
[0]-'0')*10000
2673 +(str
[2]-'0')*100 - 100
2679 * Configure the OnStream SCII tape drive for default operation
2681 static int osst_configure_onstream(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2683 unsigned char cmd
[MAX_COMMAND_SIZE
];
2684 char * name
= tape_name(STp
);
2685 struct osst_request
* SRpnt
= * aSRpnt
;
2686 osst_mode_parameter_header_t
* header
;
2687 osst_block_size_page_t
* bs
;
2688 osst_capabilities_page_t
* cp
;
2689 osst_tape_paramtr_page_t
* prm
;
2690 int drive_buffer_size
;
2692 if (STp
->ready
!= ST_READY
) {
2694 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2699 if (STp
->os_fw_rev
< 10600) {
2700 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2701 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2705 * Configure 32.5KB (data+aux) frame size.
2706 * Get the current frame size from the block size mode page
2708 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2709 cmd
[0] = MODE_SENSE
;
2711 cmd
[2] = BLOCK_SIZE_PAGE
;
2712 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2714 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2715 if (SRpnt
== NULL
) {
2717 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2722 if ((STp
->buffer
)->syscall_result
!= 0) {
2723 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2727 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2728 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2731 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2732 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2733 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2734 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2738 * Configure default auto columns mode, 32.5KB transfer mode
2746 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2747 cmd
[0] = MODE_SELECT
;
2749 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2751 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2753 if ((STp
->buffer
)->syscall_result
!= 0) {
2754 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2759 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2761 * In debug mode, we want to see as many errors as possible
2762 * to test the error recovery mechanism.
2764 osst_set_retries(STp
, aSRpnt
, 0);
2769 * Set vendor name to 'LIN4' for "Linux support version 4".
2772 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2773 cmd
[0] = MODE_SELECT
;
2775 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2777 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2778 header
->medium_type
= 0; /* Medium Type - ignoring */
2779 header
->dsp
= 0; /* Reserved */
2780 header
->bdl
= 0; /* Block Descriptor Length */
2782 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2783 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2784 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2785 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2786 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2787 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2788 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2789 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2791 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2794 if ((STp
->buffer
)->syscall_result
!= 0) {
2795 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2796 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2800 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2801 cmd
[0] = MODE_SENSE
;
2803 cmd
[2] = CAPABILITIES_PAGE
;
2804 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2806 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2809 if ((STp
->buffer
)->syscall_result
!= 0) {
2810 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2814 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2815 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2816 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2818 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2820 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2821 cmd
[0] = MODE_SENSE
;
2823 cmd
[2] = TAPE_PARAMTR_PAGE
;
2824 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2826 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2829 if ((STp
->buffer
)->syscall_result
!= 0) {
2830 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2834 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2835 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2836 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2838 STp
->density
= prm
->density
;
2839 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2841 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2842 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2850 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2851 it messes up the block number). */
2852 static int cross_eof(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int forward
)
2855 char * name
= tape_name(STp
);
2859 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2860 name
, forward
? "forward" : "backward");
2864 /* assumes that the filemark is already read by the drive, so this is low cost */
2865 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2868 /* assumes this is only called if we just read the filemark! */
2869 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2872 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2873 name
, forward
? "forward" : "backward");
2879 /* Get the tape position. */
2881 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2883 unsigned char scmd
[MAX_COMMAND_SIZE
];
2884 struct osst_request
* SRpnt
;
2886 char * name
= tape_name(STp
);
2888 /* KG: We want to be able to use it for checking Write Buffer availability
2889 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2891 char * olddata
= STp
->buffer
->b_data
;
2892 int oldsize
= STp
->buffer
->buffer_size
;
2894 if (STp
->ready
!= ST_READY
) return (-EIO
);
2896 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2897 scmd
[0] = READ_POSITION
;
2899 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2900 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2901 STp
->timeout
, MAX_RETRIES
, 1);
2903 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2908 if (STp
->buffer
->syscall_result
)
2909 result
= ((SRpnt
->sense
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2911 if (result
== -EINVAL
)
2912 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2914 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2915 unsigned char mysense
[16];
2916 memcpy (mysense
, SRpnt
->sense
, 16);
2917 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2918 scmd
[0] = READ_POSITION
;
2919 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2920 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2921 STp
->timeout
, MAX_RETRIES
, 1);
2923 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2924 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2925 SRpnt
->sense
[2],SRpnt
->sense
[12],SRpnt
->sense
[13]);
2927 if (!STp
->buffer
->syscall_result
)
2928 memcpy (SRpnt
->sense
, mysense
, 16);
2930 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2932 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2933 + ((STp
->buffer
)->b_data
[5] << 16)
2934 + ((STp
->buffer
)->b_data
[6] << 8)
2935 + (STp
->buffer
)->b_data
[7];
2936 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2937 + ((STp
->buffer
)->b_data
[ 9] << 16)
2938 + ((STp
->buffer
)->b_data
[10] << 8)
2939 + (STp
->buffer
)->b_data
[11];
2940 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2943 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2944 STp
->first_frame_position
, STp
->last_frame_position
,
2945 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2946 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2950 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2952 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2953 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2955 STp
->first_frame_position
= STp
->last_frame_position
;
2958 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2960 return (result
== 0 ? STp
->first_frame_position
: result
);
2964 /* Set the tape block */
2965 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int ppos
, int skip
)
2967 unsigned char scmd
[MAX_COMMAND_SIZE
];
2968 struct osst_request
* SRpnt
;
2969 struct st_partstat
* STps
;
2971 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2972 char * name
= tape_name(STp
);
2974 if (STp
->ready
!= ST_READY
) return (-EIO
);
2976 STps
= &(STp
->ps
[STp
->partition
]);
2978 if (ppos
< 0 || ppos
> STp
->capacity
) {
2979 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2980 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2987 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2989 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2992 scmd
[3] = (pp
>> 24);
2993 scmd
[4] = (pp
>> 16);
2994 scmd
[5] = (pp
>> 8);
2999 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
3005 if ((STp
->buffer
)->syscall_result
!= 0) {
3007 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
3008 name
, STp
->first_frame_position
, pp
);
3013 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
3014 } while ((pp
!= ppos
) && (pp
= ppos
));
3015 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
3016 STps
->eof
= ST_NOEOF
;
3019 STp
->frame_in_buffer
= 0;
3023 static int osst_write_trailer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int leave_at_EOT
)
3025 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
3028 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
3029 /* true unless the user wrote the filemark for us */
3030 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
3031 if (result
< 0) goto out
;
3032 result
= osst_write_filemark(STp
, aSRpnt
);
3033 if (result
< 0) goto out
;
3035 if (STps
->drv_file
>= 0)
3037 STps
->drv_block
= 0;
3039 result
= osst_write_eod(STp
, aSRpnt
);
3040 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
3047 /* osst versions of st functions - augmented and stripped to suit OnStream only */
3049 /* Flush the write buffer (never need to write if variable blocksize). */
3050 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
3052 int offset
, transfer
, blks
= 0;
3054 unsigned char cmd
[MAX_COMMAND_SIZE
];
3055 struct osst_request
* SRpnt
= *aSRpnt
;
3056 struct st_partstat
* STps
;
3057 char * name
= tape_name(STp
);
3059 if ((STp
->buffer
)->writing
) {
3060 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
3062 { printk(OSST_DEB_MSG
3063 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name
);
3065 *aSRpnt
= SRpnt
= NULL
;
3069 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name
);
3071 osst_write_behind_check(STp
);
3072 if ((STp
->buffer
)->syscall_result
) {
3075 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
3076 name
, (STp
->buffer
)->midlevel_result
);
3078 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3085 if (STp
->dirty
== 1) {
3088 STps
= &(STp
->ps
[STp
->partition
]);
3089 STps
->rw
= ST_WRITING
;
3090 offset
= STp
->buffer
->buffer_bytes
;
3091 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
3092 transfer
= OS_FRAME_SIZE
;
3094 if (offset
< OS_DATA_SIZE
)
3095 osst_zero_buffer_tail(STp
->buffer
);
3098 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
3099 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
3101 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3106 switch (STp
->write_type
) {
3110 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3111 name
, blks
, STp
->frame_seq_number
,
3112 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3114 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3115 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3118 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
3119 STp
->logical_blk_num
, 0, 0);
3121 case OS_WRITE_NEW_MARK
:
3122 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
3123 STp
->logical_blk_num
++, 0, blks
=1);
3125 case OS_WRITE_HEADER
:
3126 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
3128 default: /* probably FILLER */
3129 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
3133 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3134 name
, offset
, transfer
, blks
);
3137 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3138 STp
->timeout
, MAX_RETRIES
, 1);
3143 if ((STp
->buffer
)->syscall_result
!= 0) {
3146 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3147 name
, SRpnt
->sense
[0], SRpnt
->sense
[2],
3148 SRpnt
->sense
[12], SRpnt
->sense
[13]);
3150 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3151 (SRpnt
->sense
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3152 (SRpnt
->sense
[2] & 0x0f) == NO_SENSE
) {
3154 (STp
->buffer
)->buffer_bytes
= 0;
3158 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3159 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3163 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3166 STp
->first_frame_position
++;
3168 (STp
->buffer
)->buffer_bytes
= 0;
3172 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3178 /* Flush the tape buffer. The tape will be positioned correctly unless
3179 seek_next is true. */
3180 static int osst_flush_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int seek_next
)
3182 struct st_partstat
* STps
;
3183 int backspace
= 0, result
= 0;
3185 char * name
= tape_name(STp
);
3189 * If there was a bus reset, block further access
3192 if( STp
->pos_unknown
)
3195 if (STp
->ready
!= ST_READY
)
3198 STps
= &(STp
->ps
[STp
->partition
]);
3199 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3200 STp
->write_type
= OS_WRITE_DATA
;
3201 return osst_flush_write_buffer(STp
, aSRpnt
);
3203 if (STp
->block_size
== 0)
3207 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3210 if (!STp
->can_bsr
) {
3211 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3212 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3213 (STp
->buffer
)->buffer_bytes
= 0;
3214 (STp
->buffer
)->read_pointer
= 0;
3215 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3219 if (STps
->eof
== ST_FM_HIT
) {
3220 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3222 STps
->eof
= ST_NOEOF
;
3224 if (STps
->drv_file
>= 0)
3226 STps
->drv_block
= 0;
3229 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3230 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3232 else if (STps
->eof
== ST_FM_HIT
) {
3233 if (STps
->drv_file
>= 0)
3235 STps
->drv_block
= 0;
3236 STps
->eof
= ST_NOEOF
;
3242 static int osst_write_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int synchronous
)
3244 unsigned char cmd
[MAX_COMMAND_SIZE
];
3245 struct osst_request
* SRpnt
;
3248 char * name
= tape_name(STp
);
3251 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3253 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3255 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3258 /* error recovery may have bumped us past the header partition */
3259 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3261 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3263 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3268 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3269 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3272 // osst_build_stats(STp, &SRpnt);
3274 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3275 STp
->write_type
= OS_WRITE_DATA
;
3277 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3280 cmd
[4] = 1; /* one frame at a time... */
3281 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3284 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3285 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3287 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3288 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3292 STp
->write_pending
= 1;
3294 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3295 MAX_RETRIES
, synchronous
);
3301 if (STp
->buffer
->syscall_result
!= 0) {
3304 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3306 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3307 (SRpnt
->sense
[2] & 0x40)) {
3308 if ((SRpnt
->sense
[2] & 0x0f) == VOLUME_OVERFLOW
)
3312 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3317 STp
->first_frame_position
++;
3325 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3326 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3330 cmd
= do_lock
? SCSI_IOCTL_DOORLOCK
: SCSI_IOCTL_DOORUNLOCK
;
3332 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3334 retval
= scsi_ioctl(STp
->device
, cmd
, NULL
);
3336 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3339 STp
->door_locked
= ST_LOCK_FAILS
;
3344 /* Set the internal state after reset */
3345 static void reset_state(struct osst_tape
*STp
)
3348 struct st_partstat
*STps
;
3350 STp
->pos_unknown
= 0;
3351 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3352 STps
= &(STp
->ps
[i
]);
3354 STps
->eof
= ST_NOEOF
;
3356 STps
->last_block_valid
= 0;
3357 STps
->drv_block
= -1;
3358 STps
->drv_file
= -1;
3363 /* Entry points to osst */
3366 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3368 ssize_t total
, retval
= 0;
3369 ssize_t i
, do_count
, blks
, transfer
;
3370 int write_threshold
;
3371 int doing_write
= 0;
3372 const char __user
* b_point
;
3373 struct osst_request
* SRpnt
= NULL
;
3374 struct st_modedef
* STm
;
3375 struct st_partstat
* STps
;
3376 struct osst_tape
* STp
= filp
->private_data
;
3377 char * name
= tape_name(STp
);
3380 if (mutex_lock_interruptible(&STp
->lock
))
3381 return (-ERESTARTSYS
);
3384 * If we are in the middle of error recovery, don't let anyone
3385 * else try and use this device. Also, if error recovery fails, it
3386 * may try and take the device offline, in which case all further
3387 * access to the device is prohibited.
3389 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3394 if (STp
->ready
!= ST_READY
) {
3395 if (STp
->ready
== ST_NO_TAPE
)
3396 retval
= (-ENOMEDIUM
);
3401 STm
= &(STp
->modes
[STp
->current_mode
]);
3402 if (!STm
->defined
) {
3410 * If there was a bus reset, block further access
3413 if (STp
->pos_unknown
) {
3420 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3426 if (STp
->write_prot
) {
3431 /* Write must be integral number of blocks */
3432 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3433 printk(KERN_ERR
"%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3434 name
, count
, STp
->block_size
<1024?
3435 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3440 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3441 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3442 name
, STp
->first_frame_position
);
3447 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3448 STp
->door_locked
= ST_LOCKED_AUTO
;
3450 STps
= &(STp
->ps
[STp
->partition
]);
3452 if (STps
->rw
== ST_READING
) {
3454 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3455 STps
->drv_file
, STps
->drv_block
);
3457 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3462 if (STps
->rw
!= ST_WRITING
) {
3463 /* Are we totally rewriting this tape? */
3464 if (!STp
->header_ok
||
3465 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3466 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3467 STp
->wrt_pass_cntr
++;
3469 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3470 name
, STp
->wrt_pass_cntr
);
3472 osst_reset_header(STp
, &SRpnt
);
3473 STps
->drv_file
= STps
->drv_block
= 0;
3475 /* Do we know where we'll be writing on the tape? */
3477 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3478 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3479 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3480 STps
->drv_file
= STp
->filemark_cnt
;
3481 STps
->drv_block
= 0;
3484 /* We have no idea where the tape is positioned - give up */
3487 "%s:D: Cannot write at indeterminate position.\n", name
);
3493 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3494 STp
->filemark_cnt
= STps
->drv_file
;
3495 STp
->last_mark_ppos
=
3496 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3498 "%s:W: Overwriting file %d with old write pass counter %d\n",
3499 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3501 "%s:W: may lead to stale data being accepted on reading back!\n",
3505 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3506 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3512 if (!STp
->header_ok
) {
3514 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3520 if ((STp
->buffer
)->writing
) {
3521 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3522 osst_write_behind_check(STp
);
3523 if ((STp
->buffer
)->syscall_result
) {
3526 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3527 (STp
->buffer
)->midlevel_result
);
3529 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3530 STps
->eof
= ST_EOM_OK
;
3532 STps
->eof
= ST_EOM_ERROR
;
3535 if (STps
->eof
== ST_EOM_OK
) {
3539 else if (STps
->eof
== ST_EOM_ERROR
) {
3544 /* Check the buffer readability in cases where copy_user might catch
3545 the problems after some tape movement. */
3546 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3547 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3552 if (!STm
->do_buffer_writes
) {
3553 write_threshold
= 1;
3556 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3557 if (!STm
->do_async_writes
)
3563 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3564 name
, (int) count
, STps
->drv_file
, STps
->drv_block
,
3565 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3568 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3571 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3572 (STp
->buffer
)->buffer_bytes
;
3573 if (do_count
> count
)
3576 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3582 blks
= do_count
/ STp
->block_size
;
3583 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3585 i
= osst_write_frame(STp
, &SRpnt
, 1);
3587 if (i
== (-ENOSPC
)) {
3588 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3589 if (transfer
<= do_count
) {
3590 *ppos
+= do_count
- transfer
;
3591 count
-= do_count
- transfer
;
3592 if (STps
->drv_block
>= 0) {
3593 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3595 STps
->eof
= ST_EOM_OK
;
3596 retval
= (-ENOSPC
); /* EOM within current request */
3599 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3600 name
, (int) transfer
);
3604 STps
->eof
= ST_EOM_ERROR
;
3605 STps
->drv_block
= (-1); /* Too cautious? */
3606 retval
= (-EIO
); /* EOM for old data */
3609 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3617 if (SRpnt
!= NULL
) {
3618 osst_release_request(SRpnt
);
3621 STp
->buffer
->buffer_bytes
= 0;
3624 retval
= total
- count
;
3629 b_point
+= do_count
;
3631 if (STps
->drv_block
>= 0) {
3632 STps
->drv_block
+= blks
;
3634 STp
->buffer
->buffer_bytes
= 0;
3636 } /* end while write threshold exceeded */
3640 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3645 blks
= count
/ STp
->block_size
;
3646 STp
->logical_blk_num
+= blks
;
3647 if (STps
->drv_block
>= 0) {
3648 STps
->drv_block
+= blks
;
3654 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3655 retval
= (STp
->buffer
)->syscall_result
;
3659 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3660 /* Schedule an asynchronous write */
3661 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3662 STp
->block_size
) * STp
->block_size
;
3663 STp
->dirty
= !((STp
->buffer
)->writing
==
3664 (STp
->buffer
)->buffer_bytes
);
3666 i
= osst_write_frame(STp
, &SRpnt
, 0);
3671 SRpnt
= NULL
; /* Prevent releasing this request! */
3673 STps
->at_sm
&= (total
== 0);
3675 STps
->eof
= ST_NOEOF
;
3680 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3682 mutex_unlock(&STp
->lock
);
3689 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3691 ssize_t total
, retval
= 0;
3692 ssize_t i
, transfer
;
3694 struct st_modedef
* STm
;
3695 struct st_partstat
* STps
;
3696 struct osst_request
* SRpnt
= NULL
;
3697 struct osst_tape
* STp
= filp
->private_data
;
3698 char * name
= tape_name(STp
);
3701 if (mutex_lock_interruptible(&STp
->lock
))
3702 return (-ERESTARTSYS
);
3705 * If we are in the middle of error recovery, don't let anyone
3706 * else try and use this device. Also, if error recovery fails, it
3707 * may try and take the device offline, in which case all further
3708 * access to the device is prohibited.
3710 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3715 if (STp
->ready
!= ST_READY
) {
3716 if (STp
->ready
== ST_NO_TAPE
)
3717 retval
= (-ENOMEDIUM
);
3722 STm
= &(STp
->modes
[STp
->current_mode
]);
3723 if (!STm
->defined
) {
3729 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3734 /* Must have initialized medium */
3735 if (!STp
->header_ok
) {
3740 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3741 STp
->door_locked
= ST_LOCKED_AUTO
;
3743 STps
= &(STp
->ps
[STp
->partition
]);
3744 if (STps
->rw
== ST_WRITING
) {
3745 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3749 /* FIXME -- this may leave the tape without EOD and up2date headers */
3752 if ((count
% STp
->block_size
) != 0) {
3754 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3755 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3759 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3760 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3761 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3763 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3764 STps
->eof
>= ST_EOD_1
) {
3765 if (STps
->eof
< ST_EOD
) {
3770 retval
= (-EIO
); /* EOM or Blank Check */
3774 /* Check the buffer writability before any tape movement. Don't alter
3776 if (copy_from_user(&i
, buf
, 1) != 0 ||
3777 copy_to_user (buf
, &i
, 1) != 0 ||
3778 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3779 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3784 /* Loop until enough data in buffer or a special condition found */
3785 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3787 /* Get new data if the buffer is empty */
3788 if ((STp
->buffer
)->buffer_bytes
== 0) {
3789 if (STps
->eof
== ST_FM_HIT
)
3791 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3792 if (special
< 0) { /* No need to continue read */
3793 STp
->frame_in_buffer
= 0;
3799 /* Move the data from driver buffer to user buffer */
3800 if ((STp
->buffer
)->buffer_bytes
> 0) {
3802 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3803 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3804 STps
->eof
, (STp
->buffer
)->buffer_bytes
, (int) (count
- total
));
3806 /* force multiple of block size, note block_size may have been adjusted */
3807 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3808 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3809 STp
->block_size
) * STp
->block_size
;
3811 if (transfer
== 0) {
3813 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3814 name
, count
, STp
->block_size
< 1024?
3815 STp
->block_size
:STp
->block_size
/1024,
3816 STp
->block_size
<1024?'b':'k');
3819 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3824 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3825 STps
->drv_block
+= transfer
/ STp
->block_size
;
3831 if ((STp
->buffer
)->buffer_bytes
== 0) {
3834 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3835 name
, STp
->frame_seq_number
);
3837 STp
->frame_in_buffer
= 0;
3838 STp
->frame_seq_number
++; /* frame to look for next time */
3840 } /* for (total = 0, special = 0; total < count && !special; ) */
3842 /* Change the eof state if no data from tape or buffer */
3844 if (STps
->eof
== ST_FM_HIT
) {
3845 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3846 STps
->drv_block
= 0;
3847 if (STps
->drv_file
>= 0)
3850 else if (STps
->eof
== ST_EOD_1
) {
3851 STps
->eof
= ST_EOD_2
;
3852 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3854 STps
->drv_block
= 0;
3856 else if (STps
->eof
== ST_EOD_2
)
3859 else if (STps
->eof
== ST_FM
)
3860 STps
->eof
= ST_NOEOF
;
3865 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3867 mutex_unlock(&STp
->lock
);
3873 /* Set the driver options */
3874 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3877 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3878 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3879 STm
->do_read_ahead
);
3881 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3882 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3884 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3885 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3886 STp
->scsi2_logical
);
3888 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3891 "%s:D: debugging: %d\n",
3897 static int osst_set_options(struct osst_tape
*STp
, long options
)
3901 struct st_modedef
* STm
;
3902 char * name
= tape_name(STp
);
3904 STm
= &(STp
->modes
[STp
->current_mode
]);
3905 if (!STm
->defined
) {
3906 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3910 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3911 name
, STp
->current_mode
);
3915 code
= options
& MT_ST_OPTIONS
;
3916 if (code
== MT_ST_BOOLEANS
) {
3917 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3918 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3919 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3920 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3921 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3922 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3923 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3924 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3925 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3926 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3927 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3928 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3929 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3931 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3933 osst_log_options(STp
, STm
, name
);
3935 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3936 value
= (code
== MT_ST_SETBOOLEANS
);
3937 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3938 STm
->do_buffer_writes
= value
;
3939 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3940 STm
->do_async_writes
= value
;
3941 if ((options
& MT_ST_DEF_WRITES
) != 0)
3942 STm
->defaults_for_writes
= value
;
3943 if ((options
& MT_ST_READ_AHEAD
) != 0)
3944 STm
->do_read_ahead
= value
;
3945 if ((options
& MT_ST_TWO_FM
) != 0)
3946 STp
->two_fm
= value
;
3947 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3948 STp
->fast_mteom
= value
;
3949 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3950 STp
->do_auto_lock
= value
;
3951 if ((options
& MT_ST_CAN_BSR
) != 0)
3952 STp
->can_bsr
= value
;
3953 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3954 STp
->omit_blklims
= value
;
3955 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3956 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3957 STp
->can_partitions
= value
;
3958 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3959 STp
->scsi2_logical
= value
;
3960 if ((options
& MT_ST_SYSV
) != 0)
3963 if ((options
& MT_ST_DEBUGGING
) != 0)
3966 osst_log_options(STp
, STm
, name
);
3968 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3969 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3970 if (value
< 1 || value
> osst_buffer_size
) {
3971 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3975 STp
->write_threshold
= value
;
3976 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3979 else if (code
== MT_ST_DEF_BLKSIZE
) {
3980 value
= (options
& ~MT_ST_OPTIONS
);
3981 if (value
== ~MT_ST_OPTIONS
) {
3982 STm
->default_blksize
= (-1);
3983 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3986 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3987 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3991 STm
->default_blksize
= value
;
3992 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3993 name
, STm
->default_blksize
);
3996 else if (code
== MT_ST_TIMEOUTS
) {
3997 value
= (options
& ~MT_ST_OPTIONS
);
3998 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
3999 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
4000 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
4001 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
4004 STp
->timeout
= value
* HZ
;
4005 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
4008 else if (code
== MT_ST_DEF_OPTIONS
) {
4009 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
4010 value
= (options
& MT_ST_CLEAR_DEFAULT
);
4011 if (code
== MT_ST_DEF_DENSITY
) {
4012 if (value
== MT_ST_CLEAR_DEFAULT
) {
4013 STm
->default_density
= (-1);
4014 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
4017 STm
->default_density
= value
& 0xff;
4018 printk(KERN_INFO
"%s:I: Density default set to %x\n",
4019 name
, STm
->default_density
);
4022 else if (code
== MT_ST_DEF_DRVBUFFER
) {
4023 if (value
== MT_ST_CLEAR_DEFAULT
) {
4024 STp
->default_drvbuffer
= 0xff;
4025 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
4028 STp
->default_drvbuffer
= value
& 7;
4029 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
4030 name
, STp
->default_drvbuffer
);
4033 else if (code
== MT_ST_DEF_COMPRESSION
) {
4034 if (value
== MT_ST_CLEAR_DEFAULT
) {
4035 STm
->default_compression
= ST_DONT_TOUCH
;
4036 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
4039 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
4040 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
4052 /* Internal ioctl function */
4053 static int osst_int_ioctl(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
4054 unsigned int cmd_in
, unsigned long arg
)
4058 int i
, ioctl_result
;
4060 unsigned char cmd
[MAX_COMMAND_SIZE
];
4061 struct osst_request
* SRpnt
= * aSRpnt
;
4062 struct st_partstat
* STps
;
4063 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
4064 int datalen
= 0, direction
= DMA_NONE
;
4065 char * name
= tape_name(STp
);
4067 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
4068 if (STp
->ready
== ST_NO_TAPE
)
4069 return (-ENOMEDIUM
);
4073 timeout
= STp
->long_timeout
;
4074 STps
= &(STp
->ps
[STp
->partition
]);
4075 fileno
= STps
->drv_file
;
4076 blkno
= STps
->drv_block
;
4077 at_sm
= STps
->at_sm
;
4078 frame_seq_numbr
= STp
->frame_seq_number
;
4079 logical_blk_num
= STp
->logical_blk_num
;
4081 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4084 chg_eof
= 0; /* Changed from the FSF after this */
4088 if (STp
->linux_media
)
4089 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
4091 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
4095 at_sm
&= (arg
== 0);
4099 chg_eof
= 0; /* Changed from the FSF after this */
4103 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
4106 blkno
= (-1); /* We can't know the block number */
4107 at_sm
&= (arg
== 0);
4114 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
4115 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
4117 if (cmd_in
== MTFSR
) {
4118 logical_blk_num
+= arg
;
4119 if (blkno
>= 0) blkno
+= arg
;
4122 logical_blk_num
-= arg
;
4123 if (blkno
>= 0) blkno
-= arg
;
4125 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
4126 fileno
= STps
->drv_file
;
4127 blkno
= STps
->drv_block
;
4128 at_sm
&= (arg
== 0);
4133 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4134 cmd
[2] = (arg
>> 16);
4135 cmd
[3] = (arg
>> 8);
4139 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4140 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4143 blkno
= fileno
= (-1);
4149 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4151 cmd
[2] = (ltmp
>> 16);
4152 cmd
[3] = (ltmp
>> 8);
4158 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4159 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4164 blkno
= fileno
= (-1);
4169 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4170 STp
->write_type
= OS_WRITE_DATA
;
4171 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4176 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4178 for (i
=0; i
<arg
; i
++)
4179 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4180 if (fileno
>= 0) fileno
+= arg
;
4181 if (blkno
>= 0) blkno
= 0;
4185 if (STp
->write_prot
)
4189 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4190 if (cmd_in
== MTWSM
)
4192 cmd
[2] = (arg
>> 16);
4193 cmd
[3] = (arg
>> 8);
4195 timeout
= STp
->timeout
;
4198 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4199 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4204 at_sm
= (cmd_in
== MTWSM
);
4210 cmd
[0] = START_STOP
;
4211 cmd
[1] = 1; /* Don't wait for completion */
4212 if (cmd_in
== MTLOAD
) {
4213 if (STp
->ready
== ST_NO_TAPE
)
4214 cmd
[4] = 4; /* open tray */
4216 cmd
[4] = 1; /* load */
4218 if (cmd_in
== MTRETEN
)
4219 cmd
[4] = 3; /* retension then mount */
4220 if (cmd_in
== MTOFFL
)
4221 cmd
[4] = 4; /* rewind then eject */
4222 timeout
= STp
->timeout
;
4227 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4230 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4233 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4236 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4241 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4246 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4248 return 0; /* Should do something ? */
4253 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4255 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4256 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4257 ioctl_result
= -EIO
;
4260 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4262 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4264 ioctl_result
= -EIO
;
4267 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4268 fileno
= STp
->filemark_cnt
;
4273 if (STp
->write_prot
)
4275 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4276 i
= osst_write_eod(STp
, &SRpnt
);
4277 if (i
< ioctl_result
) ioctl_result
= i
;
4278 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4279 if (i
< ioctl_result
) ioctl_result
= i
;
4280 fileno
= blkno
= at_sm
= 0 ;
4284 cmd
[0] = REZERO_UNIT
; /* rewind */
4288 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4290 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4293 case MTSETBLK
: /* Set block length */
4294 if ((STps
->drv_block
== 0 ) &&
4296 ((STp
->buffer
)->buffer_bytes
== 0) &&
4297 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4298 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4299 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4301 * Only allowed to change the block size if you opened the
4302 * device at the beginning of a file before writing anything.
4303 * Note, that when reading, changing block_size is futile,
4304 * as the size used when writing overrides it.
4306 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4307 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4308 name
, STp
->block_size
);
4311 case MTSETDENSITY
: /* Set tape density */
4312 case MTSETDRVBUFFER
: /* Set drive buffering */
4313 case SET_DENS_AND_BLK
: /* Set density and block size */
4315 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4316 return (-EIO
); /* Not allowed if data in buffer */
4317 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4318 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4319 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4320 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4321 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4322 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4325 return 0; /* FIXME silently ignore if block size didn't change */
4331 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4333 ioctl_result
= (STp
->buffer
)->syscall_result
;
4337 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4339 return ioctl_result
;
4342 if (!ioctl_result
) { /* SCSI command successful */
4343 STp
->frame_seq_number
= frame_seq_numbr
;
4344 STp
->logical_blk_num
= logical_blk_num
;
4350 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4353 if (!ioctl_result
) { /* success */
4355 if (cmd_in
== MTFSFM
) {
4359 if (cmd_in
== MTBSFM
) {
4363 STps
->drv_block
= blkno
;
4364 STps
->drv_file
= fileno
;
4365 STps
->at_sm
= at_sm
;
4367 if (cmd_in
== MTEOM
)
4369 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4370 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4372 STp
->logical_blk_num
++;
4373 STp
->frame_seq_number
++;
4374 STp
->frame_in_buffer
= 0;
4375 STp
->buffer
->read_pointer
= 0;
4377 else if (cmd_in
== MTFSF
)
4378 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4380 STps
->eof
= ST_NOEOF
;
4382 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4383 STp
->rew_at_close
= 0;
4384 else if (cmd_in
== MTLOAD
) {
4385 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4386 STp
->ps
[i
].rw
= ST_IDLE
;
4387 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4392 if (cmd_in
== MTREW
) {
4393 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4394 if (ioctl_result
> 0)
4398 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4399 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4400 STps
->drv_file
= STps
->drv_block
= -1;
4402 STps
->drv_file
= STps
->drv_block
= 0;
4403 STps
->eof
= ST_NOEOF
;
4404 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4405 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4406 STps
->drv_file
= STps
->drv_block
= -1;
4408 STps
->drv_file
= STp
->filemark_cnt
;
4409 STps
->drv_block
= 0;
4412 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4413 STps
->drv_file
= STps
->drv_block
= (-1);
4414 STps
->eof
= ST_NOEOF
;
4416 } else if (cmd_in
== MTERASE
) {
4418 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4419 if (SRpnt
->sense
[2] & 0x40) {
4420 STps
->eof
= ST_EOM_OK
;
4421 STps
->drv_block
= 0;
4424 STps
->eof
= ST_NOEOF
;
4426 if ((SRpnt
->sense
[2] & 0x0f) == BLANK_CHECK
)
4429 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4430 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4434 return ioctl_result
;
4438 /* Open the device */
4439 static int __os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4441 unsigned short flags
;
4442 int i
, b_size
, new_session
= 0, retval
= 0;
4443 unsigned char cmd
[MAX_COMMAND_SIZE
];
4444 struct osst_request
* SRpnt
= NULL
;
4445 struct osst_tape
* STp
;
4446 struct st_modedef
* STm
;
4447 struct st_partstat
* STps
;
4449 int dev
= TAPE_NR(inode
);
4450 int mode
= TAPE_MODE(inode
);
4453 * We really want to do nonseekable_open(inode, filp); here, but some
4454 * versions of tar incorrectly call lseek on tapes and bail out if that
4455 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4457 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4459 write_lock(&os_scsi_tapes_lock
);
4460 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4461 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4462 write_unlock(&os_scsi_tapes_lock
);
4466 name
= tape_name(STp
);
4469 write_unlock(&os_scsi_tapes_lock
);
4471 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4475 if (scsi_device_get(STp
->device
)) {
4476 write_unlock(&os_scsi_tapes_lock
);
4478 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4482 filp
->private_data
= STp
;
4484 write_unlock(&os_scsi_tapes_lock
);
4485 STp
->rew_at_close
= TAPE_REWIND(inode
);
4487 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4491 if (mode
!= STp
->current_mode
) {
4494 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4495 name
, STp
->current_mode
, mode
);
4498 STp
->current_mode
= mode
;
4500 STm
= &(STp
->modes
[STp
->current_mode
]);
4502 flags
= filp
->f_flags
;
4503 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4505 STp
->raw
= TAPE_IS_RAW(inode
);
4509 /* Allocate data segments for this device's tape buffer */
4510 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4511 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4512 retval
= (-EOVERFLOW
);
4515 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4516 for (i
= 0, b_size
= 0;
4517 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4518 b_size
+= STp
->buffer
->sg
[i
++].length
);
4519 STp
->buffer
->aux
= (os_aux_t
*) (page_address(sg_page(&STp
->buffer
->sg
[i
])) + OS_DATA_SIZE
- b_size
);
4521 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4522 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4523 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4524 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4527 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4528 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4532 STp
->buffer
->writing
= 0;
4533 STp
->buffer
->syscall_result
= 0;
4535 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4536 STps
= &(STp
->ps
[i
]);
4539 STp
->ready
= ST_READY
;
4541 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4544 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4545 cmd
[0] = TEST_UNIT_READY
;
4547 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4549 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4552 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4553 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4554 SRpnt
->sense
[12] == 4 ) {
4556 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sense
[13]);
4558 if (filp
->f_flags
& O_NONBLOCK
) {
4562 if (SRpnt
->sense
[13] == 2) { /* initialize command required (LOAD) */
4563 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4564 cmd
[0] = START_STOP
;
4567 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4568 STp
->timeout
, MAX_RETRIES
, 1);
4570 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sense
[13]==1?15:3) * 60, 0);
4572 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4573 (SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4575 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4579 for (i
=0; i
< 10; i
++) {
4581 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4582 cmd
[0] = TEST_UNIT_READY
;
4584 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4585 STp
->timeout
, MAX_RETRIES
, 1);
4586 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4587 (SRpnt
->sense
[2] & 0x0f) != UNIT_ATTENTION
)
4591 STp
->pos_unknown
= 0;
4592 STp
->partition
= STp
->new_partition
= 0;
4593 if (STp
->can_partitions
)
4594 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4595 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4596 STps
= &(STp
->ps
[i
]);
4597 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4598 STps
->eof
= ST_NOEOF
;
4600 STps
->last_block_valid
= 0;
4601 STps
->drv_block
= 0;
4602 STps
->drv_file
= 0 ;
4605 STp
->recover_count
= 0;
4606 STp
->abort_count
= 0;
4609 * if we have valid headers from before, and the drive/tape seem untouched,
4610 * open without reconfiguring and re-reading the headers
4612 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4613 !SRpnt
->result
&& SRpnt
->sense
[0] == 0) {
4615 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4616 cmd
[0] = MODE_SENSE
;
4618 cmd
[2] = VENDOR_IDENT_PAGE
;
4619 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4621 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4623 if (STp
->buffer
->syscall_result
||
4624 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4625 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4626 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4627 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4629 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4630 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4631 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4632 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4633 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4637 i
= STp
->first_frame_position
;
4638 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4639 if (STp
->door_locked
== ST_UNLOCKED
) {
4640 if (do_door_lock(STp
, 1))
4641 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4643 STp
->door_locked
= ST_LOCKED_AUTO
;
4645 if (!STp
->frame_in_buffer
) {
4646 STp
->block_size
= (STm
->default_blksize
> 0) ?
4647 STm
->default_blksize
: OS_DATA_SIZE
;
4648 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4650 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4652 osst_release_request(SRpnt
);
4656 if (i
!= STp
->first_frame_position
)
4657 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4658 name
, i
, STp
->first_frame_position
);
4664 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4665 (SRpnt
->sense
[2] != 2 || SRpnt
->sense
[12] != 0x3A) ) {
4667 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4668 cmd
[0] = MODE_SELECT
;
4670 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4672 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4673 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4674 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4675 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4676 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4677 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4678 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4679 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4682 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4684 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4688 for (i
=0; i
< 10; i
++) {
4690 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4691 cmd
[0] = TEST_UNIT_READY
;
4693 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4694 STp
->timeout
, MAX_RETRIES
, 1);
4695 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4696 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
)
4699 if ((SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) {
4700 STp
->pos_unknown
= 0;
4701 STp
->partition
= STp
->new_partition
= 0;
4702 if (STp
->can_partitions
)
4703 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4704 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4705 STps
= &(STp
->ps
[i
]);
4707 STps
->eof
= ST_NOEOF
;
4709 STps
->last_block_valid
= 0;
4710 STps
->drv_block
= 0;
4711 STps
->drv_file
= 0 ;
4718 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4719 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4721 if ((STp
->buffer
)->syscall_result
!= 0) {
4722 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4723 (SRpnt
->sense
[0] & 0x70) == 0x70 &&
4724 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4725 SRpnt
->sense
[12] == 0x3a) { /* Check ASC */
4726 STp
->ready
= ST_NO_TAPE
;
4728 STp
->ready
= ST_NOT_READY
;
4729 osst_release_request(SRpnt
);
4731 STp
->density
= 0; /* Clear the erroneous "residue" */
4732 STp
->write_prot
= 0;
4733 STp
->block_size
= 0;
4734 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4735 STp
->partition
= STp
->new_partition
= 0;
4736 STp
->door_locked
= ST_UNLOCKED
;
4740 osst_configure_onstream(STp
, &SRpnt
);
4742 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4743 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4744 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4745 STp
->buffer
->buffer_bytes
=
4746 STp
->buffer
->read_pointer
=
4747 STp
->frame_in_buffer
= 0;
4751 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4752 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4753 (STp
->buffer
)->buffer_blocks
);
4756 if (STp
->drv_write_prot
) {
4757 STp
->write_prot
= 1;
4760 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4762 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4768 if (new_session
) { /* Change the drive parameters for the new mode */
4771 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4773 STp
->density_changed
= STp
->blksize_changed
= 0;
4774 STp
->compression_changed
= 0;
4778 * properly position the tape and check the ADR headers
4780 if (STp
->door_locked
== ST_UNLOCKED
) {
4781 if (do_door_lock(STp
, 1))
4782 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4784 STp
->door_locked
= ST_LOCKED_AUTO
;
4787 osst_analyze_headers(STp
, &SRpnt
);
4789 osst_release_request(SRpnt
);
4796 osst_release_request(SRpnt
);
4797 normalize_buffer(STp
->buffer
);
4800 scsi_device_put(STp
->device
);
4805 /* BKL pushdown: spaghetti avoidance wrapper */
4806 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4811 ret
= __os_scsi_tape_open(inode
, filp
);
4818 /* Flush the tape buffer before close */
4819 static int os_scsi_tape_flush(struct file
* filp
, fl_owner_t id
)
4821 int result
= 0, result2
;
4822 struct osst_tape
* STp
= filp
->private_data
;
4823 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4824 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4825 struct osst_request
* SRpnt
= NULL
;
4826 char * name
= tape_name(STp
);
4828 if (file_count(filp
) > 1)
4831 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4832 STp
->write_type
= OS_WRITE_DATA
;
4833 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4834 if (result
!= 0 && result
!= (-ENOSPC
))
4837 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4841 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4842 name
, (long)(filp
->f_pos
));
4843 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4844 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4847 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4850 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4851 name
, 1+STp
->two_fm
);
4854 else if (!STp
->rew_at_close
) {
4855 STps
= &(STp
->ps
[STp
->partition
]);
4856 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4858 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4859 else if (STps
->eof
== ST_FM_HIT
) {
4860 result
= cross_eof(STp
, &SRpnt
, 0);
4862 if (STps
->drv_file
>= 0)
4864 STps
->drv_block
= 0;
4868 STps
->eof
= ST_NOEOF
;
4871 else if ((STps
->eof
== ST_NOEOF
&&
4872 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4873 STps
->eof
== ST_FM_HIT
) {
4874 if (STps
->drv_file
>= 0)
4876 STps
->drv_block
= 0;
4882 if (STp
->rew_at_close
) {
4883 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4884 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4885 if (result
== 0 && result2
< 0)
4888 if (SRpnt
) osst_release_request(SRpnt
);
4890 if (STp
->abort_count
|| STp
->recover_count
) {
4891 printk(KERN_INFO
"%s:I:", name
);
4892 if (STp
->abort_count
)
4893 printk(" %d unrecovered errors", STp
->abort_count
);
4894 if (STp
->recover_count
)
4895 printk(" %d recovered errors", STp
->recover_count
);
4896 if (STp
->write_count
)
4897 printk(" in %d frames written", STp
->write_count
);
4898 if (STp
->read_count
)
4899 printk(" in %d frames read", STp
->read_count
);
4901 STp
->recover_count
= 0;
4902 STp
->abort_count
= 0;
4904 STp
->write_count
= 0;
4905 STp
->read_count
= 0;
4911 /* Close the device and release it */
4912 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4915 struct osst_tape
* STp
= filp
->private_data
;
4917 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4918 do_door_lock(STp
, 0);
4923 normalize_buffer(STp
->buffer
);
4924 write_lock(&os_scsi_tapes_lock
);
4926 write_unlock(&os_scsi_tapes_lock
);
4928 scsi_device_put(STp
->device
);
4934 /* The ioctl command */
4935 static long osst_ioctl(struct file
* file
,
4936 unsigned int cmd_in
, unsigned long arg
)
4938 int i
, cmd_nr
, cmd_type
, blk
, retval
= 0;
4939 struct st_modedef
* STm
;
4940 struct st_partstat
* STps
;
4941 struct osst_request
* SRpnt
= NULL
;
4942 struct osst_tape
* STp
= file
->private_data
;
4943 char * name
= tape_name(STp
);
4944 void __user
* p
= (void __user
*)arg
;
4947 if (mutex_lock_interruptible(&STp
->lock
)) {
4949 return -ERESTARTSYS
;
4953 if (debugging
&& !STp
->in_use
) {
4954 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4959 STm
= &(STp
->modes
[STp
->current_mode
]);
4960 STps
= &(STp
->ps
[STp
->partition
]);
4963 * If we are in the middle of error recovery, don't let anyone
4964 * else try and use this device. Also, if error recovery fails, it
4965 * may try and take the device offline, in which case all further
4966 * access to the device is prohibited.
4968 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4973 cmd_type
= _IOC_TYPE(cmd_in
);
4974 cmd_nr
= _IOC_NR(cmd_in
);
4976 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4977 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4979 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4983 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4988 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
4994 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
4995 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
5000 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
5005 if (!STp
->pos_unknown
) {
5007 if (STps
->eof
== ST_FM_HIT
) {
5008 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
5010 if (STps
->drv_file
>= 0)
5011 STps
->drv_file
+= 1;
5013 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
5015 if (STps
->drv_file
>= 0)
5016 STps
->drv_file
+= 1;
5020 if (mtc
.mt_op
== MTSEEK
) {
5021 /* Old position must be restored if partition will be changed */
5022 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
5025 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
5026 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
5027 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
5028 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
5029 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
5030 mtc
.mt_op
== MTCOMPRESSION
;
5032 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
5040 * If there was a bus reset, block further access
5041 * to this device. If the user wants to rewind the tape,
5042 * then reset the flag and allow access again.
5044 if(mtc
.mt_op
!= MTREW
&&
5045 mtc
.mt_op
!= MTOFFL
&&
5046 mtc
.mt_op
!= MTRETEN
&&
5047 mtc
.mt_op
!= MTERASE
&&
5048 mtc
.mt_op
!= MTSEEK
&&
5049 mtc
.mt_op
!= MTEOM
) {
5054 /* remove this when the midlevel properly clears was_reset */
5055 STp
->device
->was_reset
= 0;
5058 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
5059 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
5060 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
5061 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
5062 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
5065 * The user tells us to move to another position on the tape.
5066 * If we were appending to the tape content, that would leave
5067 * the tape without proper end, in that case write EOD and
5068 * update the header to reflect its position.
5071 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
5072 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
5073 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
5074 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5076 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
5077 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
5078 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5079 i
= osst_write_trailer(STp
, &SRpnt
,
5080 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5082 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5083 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
5084 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5094 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
5095 do_door_lock(STp
, 0); /* Ignore result! */
5097 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
5098 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
5099 retval
= osst_set_options(STp
, mtc
.mt_count
);
5103 if (mtc
.mt_op
== MTSETPART
) {
5104 if (mtc
.mt_count
>= STp
->nbr_partitions
)
5107 STp
->new_partition
= mtc
.mt_count
;
5113 if (mtc
.mt_op
== MTMKPART
) {
5114 if (!STp
->can_partitions
) {
5118 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
5119 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5123 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5124 STp
->ps
[i
].rw
= ST_IDLE
;
5125 STp
->ps
[i
].at_sm
= 0;
5126 STp
->ps
[i
].last_block_valid
= 0;
5128 STp
->partition
= STp
->new_partition
= 0;
5129 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
5130 STps
->drv_block
= STps
->drv_file
= 0;
5135 if (mtc
.mt_op
== MTSEEK
) {
5137 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
5139 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
5140 if (!STp
->can_partitions
)
5141 STp
->ps
[0].rw
= ST_IDLE
;
5146 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
5147 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5152 cross_eof(STp
, &SRpnt
, 0);
5154 if (mtc
.mt_op
== MTCOMPRESSION
)
5155 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5157 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5158 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5159 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5163 if (!STm
->defined
) {
5168 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5173 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5174 struct mtget mt_status
;
5176 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5181 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5182 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5183 mt_status
.mt_dsreg
=
5184 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5185 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5186 mt_status
.mt_blkno
= STps
->drv_block
;
5187 mt_status
.mt_fileno
= STps
->drv_file
;
5188 if (STp
->block_size
!= 0) {
5189 if (STps
->rw
== ST_WRITING
)
5190 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5191 else if (STps
->rw
== ST_READING
)
5192 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5193 STp
->block_size
- 1) / STp
->block_size
;
5196 mt_status
.mt_gstat
= 0;
5197 if (STp
->drv_write_prot
)
5198 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5199 if (mt_status
.mt_blkno
== 0) {
5200 if (mt_status
.mt_fileno
== 0)
5201 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5203 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5205 mt_status
.mt_resid
= STp
->partition
;
5206 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5207 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5208 else if (STps
->eof
>= ST_EOM_OK
)
5209 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5210 if (STp
->density
== 1)
5211 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5212 else if (STp
->density
== 2)
5213 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5214 else if (STp
->density
== 3)
5215 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5216 if (STp
->ready
== ST_READY
)
5217 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5218 if (STp
->ready
== ST_NO_TAPE
)
5219 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5221 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5222 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5223 STp
->drv_buffer
!= 0)
5224 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5226 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5232 STp
->recover_erreg
= 0; /* Clear after read */
5235 } /* End of MTIOCGET */
5237 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5238 struct mtpos mt_pos
;
5240 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5245 blk
= osst_get_frame_position(STp
, &SRpnt
);
5247 blk
= osst_get_sector(STp
, &SRpnt
);
5252 mt_pos
.mt_blkno
= blk
;
5253 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5258 if (SRpnt
) osst_release_request(SRpnt
);
5260 mutex_unlock(&STp
->lock
);
5262 retval
= scsi_ioctl(STp
->device
, cmd_in
, p
);
5267 if (SRpnt
) osst_release_request(SRpnt
);
5269 mutex_unlock(&STp
->lock
);
5275 #ifdef CONFIG_COMPAT
5276 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5278 struct osst_tape
*STp
= file
->private_data
;
5279 struct scsi_device
*sdev
= STp
->device
;
5280 int ret
= -ENOIOCTLCMD
;
5281 if (sdev
->host
->hostt
->compat_ioctl
) {
5283 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5292 /* Memory handling routines */
5294 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5295 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5299 struct osst_buffer
*tb
;
5301 if (from_initialization
)
5302 priority
= GFP_ATOMIC
;
5304 priority
= GFP_KERNEL
;
5306 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5307 tb
= kzalloc(i
, priority
);
5309 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5313 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5314 tb
->use_sg
= max_sg
;
5317 tb
->buffer_size
= 0;
5321 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5322 i
, max_sg
, need_dma
);
5327 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5328 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5330 int segs
, nbr
, max_segs
, b_size
, order
, got
;
5333 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5336 if (STbuffer
->sg_segs
) {
5337 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5338 normalize_buffer(STbuffer
);
5340 /* See how many segments we can use -- need at least two */
5341 nbr
= max_segs
= STbuffer
->use_sg
;
5345 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5347 priority
|= GFP_DMA
;
5349 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5350 big enough to reach the goal (code assumes no segments in place) */
5351 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5352 struct page
*page
= alloc_pages(priority
, order
);
5354 STbuffer
->sg
[0].offset
= 0;
5356 sg_set_page(&STbuffer
->sg
[0], page
, b_size
, 0);
5357 STbuffer
->b_data
= page_address(page
);
5361 if (sg_page(&STbuffer
->sg
[0]) == NULL
) {
5362 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5365 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5366 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5367 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5368 struct page
*page
= alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5369 STbuffer
->sg
[segs
].offset
= 0;
5371 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5374 STbuffer
->buffer_size
= got
;
5376 normalize_buffer(STbuffer
);
5379 sg_set_page(&STbuffer
->sg
[segs
], page
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
, 0);
5380 got
+= STbuffer
->sg
[segs
].length
;
5381 STbuffer
->buffer_size
= got
;
5382 STbuffer
->sg_segs
= ++segs
;
5387 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5388 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5390 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5391 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5392 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5400 /* Release the segments */
5401 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5403 int i
, order
, b_size
;
5405 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5407 for (b_size
= PAGE_SIZE
, order
= 0;
5408 b_size
< STbuffer
->sg
[i
].length
;
5409 b_size
*= 2, order
++);
5411 __free_pages(sg_page(&STbuffer
->sg
[i
]), order
);
5412 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5415 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5416 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5417 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5419 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5423 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5424 negative error code. */
5425 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5427 int i
, cnt
, res
, offset
;
5429 for (i
=0, offset
=st_bp
->buffer_bytes
;
5430 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5431 offset
-= st_bp
->sg
[i
].length
;
5432 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5433 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5436 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5437 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5438 st_bp
->sg
[i
].length
- offset
: do_count
;
5439 res
= copy_from_user(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, ubp
, cnt
);
5443 st_bp
->buffer_bytes
+= cnt
;
5447 if (do_count
) { /* Should never happen */
5448 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5456 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5457 negative error code. */
5458 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5460 int i
, cnt
, res
, offset
;
5462 for (i
=0, offset
=st_bp
->read_pointer
;
5463 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5464 offset
-= st_bp
->sg
[i
].length
;
5465 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5466 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5469 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5470 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5471 st_bp
->sg
[i
].length
- offset
: do_count
;
5472 res
= copy_to_user(ubp
, page_address(sg_page(&st_bp
->sg
[i
])) + offset
, cnt
);
5476 st_bp
->buffer_bytes
-= cnt
;
5477 st_bp
->read_pointer
+= cnt
;
5481 if (do_count
) { /* Should never happen */
5482 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5488 /* Sets the tail of the buffer after fill point to zero.
5489 Returns zero (success) or negative error code. */
5490 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5492 int i
, offset
, do_count
, cnt
;
5494 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5495 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5496 offset
-= st_bp
->sg
[i
].length
;
5497 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5498 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5501 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5502 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5503 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5504 st_bp
->sg
[i
].length
- offset
: do_count
;
5505 memset(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, 0, cnt
);
5509 if (do_count
) { /* Should never happen */
5510 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5516 /* Copy a osst 32K chunk of memory into the buffer.
5517 Returns zero (success) or negative error code. */
5518 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5520 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5522 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5523 cnt
= st_bp
->sg
[i
].length
< do_count
?
5524 st_bp
->sg
[i
].length
: do_count
;
5525 memcpy(page_address(sg_page(&st_bp
->sg
[i
])), ptr
, cnt
);
5529 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5530 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5537 /* Copy a osst 32K chunk of memory from the buffer.
5538 Returns zero (success) or negative error code. */
5539 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5541 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5543 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5544 cnt
= st_bp
->sg
[i
].length
< do_count
?
5545 st_bp
->sg
[i
].length
: do_count
;
5546 memcpy(ptr
, page_address(sg_page(&st_bp
->sg
[i
])), cnt
);
5550 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5551 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5559 /* Module housekeeping */
5561 static void validate_options (void)
5564 osst_max_dev
= max_dev
;
5565 if (write_threshold_kbs
> 0)
5566 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5567 if (osst_write_threshold
> osst_buffer_size
)
5568 osst_write_threshold
= osst_buffer_size
;
5569 if (max_sg_segs
>= OSST_FIRST_SG
)
5570 osst_max_sg_segs
= max_sg_segs
;
5572 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5573 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5578 /* Set the boot options. Syntax: osst=xxx,yyy,...
5579 where xxx is write threshold in 1024 byte blocks,
5580 and yyy is number of s/g segments to use. */
5581 static int __init
osst_setup (char *str
)
5586 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5589 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5590 *parms
[i
].val
= ints
[i
+ 1];
5592 while (stp
!= NULL
) {
5593 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5594 int len
= strlen(parms
[i
].name
);
5595 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5596 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5598 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5602 if (i
>= ARRAY_SIZE(parms
))
5603 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5605 stp
= strchr(stp
, ',');
5614 __setup("osst=", osst_setup
);
5618 static const struct file_operations osst_fops
= {
5619 .owner
= THIS_MODULE
,
5621 .write
= osst_write
,
5622 .unlocked_ioctl
= osst_ioctl
,
5623 #ifdef CONFIG_COMPAT
5624 .compat_ioctl
= osst_compat_ioctl
,
5626 .open
= os_scsi_tape_open
,
5627 .flush
= os_scsi_tape_flush
,
5628 .release
= os_scsi_tape_close
,
5629 .llseek
= noop_llseek
,
5632 static int osst_supports(struct scsi_device
* SDp
)
5634 struct osst_support_data
{
5638 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5641 static struct osst_support_data support_list
[] = {
5642 /* {"XXX", "Yy-", "", NULL}, example */
5646 struct osst_support_data
*rp
;
5648 /* We are willing to drive OnStream SC-x0 as well as the
5649 * * IDE, ParPort, FireWire, USB variants, if accessible by
5650 * * emulation layer (ide-scsi, usb-storage, ...) */
5652 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5653 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5654 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5655 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5661 * sysfs support for osst driver parameter information
5664 static ssize_t
osst_version_show(struct device_driver
*ddd
, char *buf
)
5666 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5669 static DRIVER_ATTR(version
, S_IRUGO
, osst_version_show
, NULL
);
5671 static int osst_create_sysfs_files(struct device_driver
*sysfs
)
5673 return driver_create_file(sysfs
, &driver_attr_version
);
5676 static void osst_remove_sysfs_files(struct device_driver
*sysfs
)
5678 driver_remove_file(sysfs
, &driver_attr_version
);
5682 * sysfs support for accessing ADR header information
5685 static ssize_t
osst_adr_rev_show(struct device
*dev
,
5686 struct device_attribute
*attr
, char *buf
)
5688 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5691 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5692 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5696 DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5698 static ssize_t
osst_linux_media_version_show(struct device
*dev
,
5699 struct device_attribute
*attr
,
5702 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5705 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5706 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5710 DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5712 static ssize_t
osst_capacity_show(struct device
*dev
,
5713 struct device_attribute
*attr
, char *buf
)
5715 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5718 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5719 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5723 DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5725 static ssize_t
osst_first_data_ppos_show(struct device
*dev
,
5726 struct device_attribute
*attr
,
5729 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5732 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5733 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5737 DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5739 static ssize_t
osst_eod_frame_ppos_show(struct device
*dev
,
5740 struct device_attribute
*attr
,
5743 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5746 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5747 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5751 DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5753 static ssize_t
osst_filemark_cnt_show(struct device
*dev
,
5754 struct device_attribute
*attr
, char *buf
)
5756 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5759 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5760 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5764 DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5766 static struct class *osst_sysfs_class
;
5768 static int osst_sysfs_init(void)
5770 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5771 if (IS_ERR(osst_sysfs_class
)) {
5772 printk(KERN_ERR
"osst :W: Unable to register sysfs class\n");
5773 return PTR_ERR(osst_sysfs_class
);
5779 static void osst_sysfs_destroy(dev_t dev
)
5781 device_destroy(osst_sysfs_class
, dev
);
5784 static int osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5786 struct device
*osst_member
;
5789 osst_member
= device_create(osst_sysfs_class
, device
, dev
, STp
,
5791 if (IS_ERR(osst_member
)) {
5792 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5793 return PTR_ERR(osst_member
);
5796 err
= device_create_file(osst_member
, &dev_attr_ADR_rev
);
5799 err
= device_create_file(osst_member
, &dev_attr_media_version
);
5802 err
= device_create_file(osst_member
, &dev_attr_capacity
);
5805 err
= device_create_file(osst_member
, &dev_attr_BOT_frame
);
5808 err
= device_create_file(osst_member
, &dev_attr_EOD_frame
);
5811 err
= device_create_file(osst_member
, &dev_attr_file_count
);
5818 osst_sysfs_destroy(dev
);
5822 static void osst_sysfs_cleanup(void)
5824 class_destroy(osst_sysfs_class
);
5828 * osst startup / cleanup code
5831 static int osst_probe(struct device
*dev
)
5833 struct scsi_device
* SDp
= to_scsi_device(dev
);
5834 struct osst_tape
* tpnt
;
5835 struct st_modedef
* STm
;
5836 struct st_partstat
* STps
;
5837 struct osst_buffer
* buffer
;
5838 struct gendisk
* drive
;
5839 int i
, dev_num
, err
= -ENODEV
;
5841 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5844 drive
= alloc_disk(1);
5846 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5850 /* if this is the first attach, build the infrastructure */
5851 write_lock(&os_scsi_tapes_lock
);
5852 if (os_scsi_tapes
== NULL
) {
5854 (struct osst_tape
**)kmalloc(osst_max_dev
* sizeof(struct osst_tape
*),
5856 if (os_scsi_tapes
== NULL
) {
5857 write_unlock(&os_scsi_tapes_lock
);
5858 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5861 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5864 if (osst_nr_dev
>= osst_max_dev
) {
5865 write_unlock(&os_scsi_tapes_lock
);
5866 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5870 /* find a free minor number */
5871 for (i
=0; os_scsi_tapes
[i
] && i
<osst_max_dev
; i
++);
5872 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5875 /* allocate a struct osst_tape for this device */
5876 tpnt
= kzalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5878 write_unlock(&os_scsi_tapes_lock
);
5879 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5883 /* allocate a buffer for this device */
5884 i
= SDp
->host
->sg_tablesize
;
5885 if (osst_max_sg_segs
< i
)
5886 i
= osst_max_sg_segs
;
5887 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5888 if (buffer
== NULL
) {
5889 write_unlock(&os_scsi_tapes_lock
);
5890 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5894 os_scsi_tapes
[dev_num
] = tpnt
;
5895 tpnt
->buffer
= buffer
;
5897 drive
->private_data
= &tpnt
->driver
;
5898 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5899 tpnt
->driver
= &osst_template
;
5900 tpnt
->drive
= drive
;
5902 tpnt
->capacity
= 0xfffff;
5904 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5905 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5907 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5908 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5909 tpnt
->can_partitions
= 0;
5910 tpnt
->two_fm
= OSST_TWO_FM
;
5911 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5912 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5913 tpnt
->write_threshold
= osst_write_threshold
;
5914 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5915 tpnt
->partition
= 0;
5916 tpnt
->new_partition
= 0;
5917 tpnt
->nbr_partitions
= 0;
5918 tpnt
->min_block
= 512;
5919 tpnt
->max_block
= OS_DATA_SIZE
;
5920 tpnt
->timeout
= OSST_TIMEOUT
;
5921 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5923 /* Recognize OnStream tapes */
5924 /* We don't need to test for OnStream, as this has been done in detect () */
5925 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5926 tpnt
->omit_blklims
= 1;
5928 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5929 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5930 tpnt
->frame_in_buffer
= 0;
5931 tpnt
->header_ok
= 0;
5932 tpnt
->linux_media
= 0;
5933 tpnt
->header_cache
= NULL
;
5935 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5936 STm
= &(tpnt
->modes
[i
]);
5938 STm
->sysv
= OSST_SYSV
;
5939 STm
->defaults_for_writes
= 0;
5940 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5941 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5942 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5943 STm
->default_compression
= ST_DONT_TOUCH
;
5944 STm
->default_blksize
= 512;
5945 STm
->default_density
= (-1); /* No forced density */
5948 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5949 STps
= &(tpnt
->ps
[i
]);
5951 STps
->eof
= ST_NOEOF
;
5953 STps
->last_block_valid
= 0;
5954 STps
->drv_block
= (-1);
5955 STps
->drv_file
= (-1);
5958 tpnt
->current_mode
= 0;
5959 tpnt
->modes
[0].defined
= 1;
5960 tpnt
->modes
[2].defined
= 1;
5961 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5963 mutex_init(&tpnt
->lock
);
5965 write_unlock(&os_scsi_tapes_lock
);
5971 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5973 goto out_free_buffer
;
5975 /* No-rewind entry */
5976 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5977 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5979 goto out_free_sysfs1
;
5982 sdev_printk(KERN_INFO
, SDp
,
5983 "osst :I: Attached OnStream %.5s tape as %s\n",
5984 SDp
->model
, tape_name(tpnt
));
5989 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, dev_num
));
5997 static int osst_remove(struct device
*dev
)
5999 struct scsi_device
* SDp
= to_scsi_device(dev
);
6000 struct osst_tape
* tpnt
;
6003 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
6006 write_lock(&os_scsi_tapes_lock
);
6007 for(i
=0; i
< osst_max_dev
; i
++) {
6008 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
6009 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
6010 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
6011 tpnt
->device
= NULL
;
6012 put_disk(tpnt
->drive
);
6013 os_scsi_tapes
[i
] = NULL
;
6015 write_unlock(&os_scsi_tapes_lock
);
6016 vfree(tpnt
->header_cache
);
6018 normalize_buffer(tpnt
->buffer
);
6019 kfree(tpnt
->buffer
);
6025 write_unlock(&os_scsi_tapes_lock
);
6029 static int __init
init_osst(void)
6033 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
6037 err
= osst_sysfs_init();
6041 err
= register_chrdev(OSST_MAJOR
, "osst", &osst_fops
);
6043 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
6047 err
= scsi_register_driver(&osst_template
.gendrv
);
6049 goto err_out_chrdev
;
6051 err
= osst_create_sysfs_files(&osst_template
.gendrv
);
6053 goto err_out_scsidrv
;
6058 scsi_unregister_driver(&osst_template
.gendrv
);
6060 unregister_chrdev(OSST_MAJOR
, "osst");
6062 osst_sysfs_cleanup();
6066 static void __exit
exit_osst (void)
6069 struct osst_tape
* STp
;
6071 osst_remove_sysfs_files(&osst_template
.gendrv
);
6072 scsi_unregister_driver(&osst_template
.gendrv
);
6073 unregister_chrdev(OSST_MAJOR
, "osst");
6074 osst_sysfs_cleanup();
6076 if (os_scsi_tapes
) {
6077 for (i
=0; i
< osst_max_dev
; ++i
) {
6078 if (!(STp
= os_scsi_tapes
[i
])) continue;
6079 /* This is defensive, supposed to happen during detach */
6080 vfree(STp
->header_cache
);
6082 normalize_buffer(STp
->buffer
);
6085 put_disk(STp
->drive
);
6088 kfree(os_scsi_tapes
);
6090 printk(KERN_INFO
"osst :I: Unloaded.\n");
6093 module_init(init_osst
);
6094 module_exit(exit_osst
);