2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid
= "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27 static const char * osst_version
= "0.99.4";
29 /* The "failure to reconnect" firmware bug */
30 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31 #define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
34 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
41 #include <linux/init.h>
42 #include <linux/string.h>
43 #include <linux/errno.h>
44 #include <linux/mtio.h>
45 #include <linux/ioctl.h>
46 #include <linux/fcntl.h>
47 #include <linux/spinlock.h>
48 #include <linux/vmalloc.h>
49 #include <linux/blkdev.h>
50 #include <linux/moduleparam.h>
51 #include <linux/delay.h>
52 #include <linux/jiffies.h>
53 #include <linux/smp_lock.h>
54 #include <asm/uaccess.h>
56 #include <asm/system.h>
58 /* The driver prints some debugging information on the console if DEBUG
59 is defined and non-zero. */
62 /* The message level for the debug messages is currently set to KERN_NOTICE
63 so that people can easily see the messages. Later when the debugging messages
64 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
65 #define OSST_DEB_MSG KERN_NOTICE
67 #include <scsi/scsi.h>
68 #include <scsi/scsi_dbg.h>
69 #include <scsi/scsi_device.h>
70 #include <scsi/scsi_driver.h>
71 #include <scsi/scsi_eh.h>
72 #include <scsi/scsi_host.h>
73 #include <scsi/scsi_ioctl.h>
75 #define ST_KILOBYTE 1024
79 #include "osst_options.h"
80 #include "osst_detect.h"
82 static int max_dev
= 0;
83 static int write_threshold_kbs
= 0;
84 static int max_sg_segs
= 0;
87 MODULE_AUTHOR("Willem Riede");
88 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
89 MODULE_LICENSE("GPL");
90 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR
);
91 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE
);
93 module_param(max_dev
, int, 0444);
94 MODULE_PARM_DESC(max_dev
, "Maximum number of OnStream Tape Drives to attach (4)");
96 module_param(write_threshold_kbs
, int, 0644);
97 MODULE_PARM_DESC(write_threshold_kbs
, "Asynchronous write threshold (KB; 32)");
99 module_param(max_sg_segs
, int, 0644);
100 MODULE_PARM_DESC(max_sg_segs
, "Maximum number of scatter/gather segments to use (9)");
102 static struct osst_dev_parm
{
105 } parms
[] __initdata
= {
106 { "max_dev", &max_dev
},
107 { "write_threshold_kbs", &write_threshold_kbs
},
108 { "max_sg_segs", &max_sg_segs
}
112 /* Some default definitions have been moved to osst_options.h */
113 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
114 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116 /* The buffer size should fit into the 24 bits for length in the
117 6-byte SCSI read and write commands. */
118 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
119 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
123 static int debugging
= 1;
124 /* uncomment define below to test error recovery */
125 // #define OSST_INJECT_ERRORS 1
128 /* Do not retry! The drive firmware already retries when appropriate,
129 and when it tries to tell us something, we had better listen... */
130 #define MAX_RETRIES 0
132 #define NO_TAPE NOT_READY
134 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
135 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
136 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
138 #define OSST_TIMEOUT (200 * HZ)
139 #define OSST_LONG_TIMEOUT (1800 * HZ)
141 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
142 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
143 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
144 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
146 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
148 #define SET_DENS_AND_BLK 0x10001
150 static int osst_buffer_size
= OSST_BUFFER_SIZE
;
151 static int osst_write_threshold
= OSST_WRITE_THRESHOLD
;
152 static int osst_max_sg_segs
= OSST_MAX_SG
;
153 static int osst_max_dev
= OSST_MAX_TAPES
;
154 static int osst_nr_dev
;
156 static struct osst_tape
**os_scsi_tapes
= NULL
;
157 static DEFINE_RWLOCK(os_scsi_tapes_lock
);
159 static int modes_defined
= 0;
161 static struct osst_buffer
*new_tape_buffer(int, int, int);
162 static int enlarge_buffer(struct osst_buffer
*, int);
163 static void normalize_buffer(struct osst_buffer
*);
164 static int append_to_buffer(const char __user
*, struct osst_buffer
*, int);
165 static int from_buffer(struct osst_buffer
*, char __user
*, int);
166 static int osst_zero_buffer_tail(struct osst_buffer
*);
167 static int osst_copy_to_buffer(struct osst_buffer
*, unsigned char *);
168 static int osst_copy_from_buffer(struct osst_buffer
*, unsigned char *);
170 static int osst_probe(struct device
*);
171 static int osst_remove(struct device
*);
173 static struct scsi_driver osst_template
= {
174 .owner
= THIS_MODULE
,
178 .remove
= osst_remove
,
182 static int osst_int_ioctl(struct osst_tape
*STp
, struct osst_request
** aSRpnt
,
183 unsigned int cmd_in
, unsigned long arg
);
185 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int frame
, int skip
);
187 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
189 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
191 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
);
193 static inline char *tape_name(struct osst_tape
*tape
)
195 return tape
->drive
->disk_name
;
198 /* Routines that handle the interaction with mid-layer SCSI routines */
201 /* Normalize Sense */
202 static void osst_analyze_sense(struct osst_request
*SRpnt
, struct st_cmdstatus
*s
)
205 const u8
*sense
= SRpnt
->sense
;
207 s
->have_sense
= scsi_normalize_sense(SRpnt
->sense
,
208 SCSI_SENSE_BUFFERSIZE
, &s
->sense_hdr
);
214 scsi_get_sense_info_fld(sense
, SCSI_SENSE_BUFFERSIZE
, &s
->uremainder64
);
215 switch (sense
[0] & 0x7f) {
220 s
->flags
= sense
[2] & 0xe0;
226 ucp
= scsi_sense_desc_find(sense
, SCSI_SENSE_BUFFERSIZE
, 4);
227 s
->flags
= ucp
? (ucp
[3] & 0xe0) : 0;
233 /* Convert the result to success code */
234 static int osst_chk_result(struct osst_tape
* STp
, struct osst_request
* SRpnt
)
236 char *name
= tape_name(STp
);
237 int result
= SRpnt
->result
;
238 u8
* sense
= SRpnt
->sense
, scode
;
242 struct st_cmdstatus
*cmdstatp
;
247 cmdstatp
= &STp
->buffer
->cmdstat
;
248 osst_analyze_sense(SRpnt
, cmdstatp
);
250 if (cmdstatp
->have_sense
)
251 scode
= STp
->buffer
->cmdstat
.sense_hdr
.sense_key
;
256 printk(OSST_DEB_MSG
"%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
258 SRpnt
->cmd
[0], SRpnt
->cmd
[1], SRpnt
->cmd
[2],
259 SRpnt
->cmd
[3], SRpnt
->cmd
[4], SRpnt
->cmd
[5]);
260 if (scode
) printk(OSST_DEB_MSG
"%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
261 name
, scode
, sense
[12], sense
[13]);
262 if (cmdstatp
->have_sense
)
263 __scsi_print_sense("osst ", SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
267 if (cmdstatp
->have_sense
&& (
269 scode
!= RECOVERED_ERROR
&&
270 /* scode != UNIT_ATTENTION && */
271 scode
!= BLANK_CHECK
&&
272 scode
!= VOLUME_OVERFLOW
&&
273 SRpnt
->cmd
[0] != MODE_SENSE
&&
274 SRpnt
->cmd
[0] != TEST_UNIT_READY
)) { /* Abnormal conditions for tape */
275 if (cmdstatp
->have_sense
) {
276 printk(KERN_WARNING
"%s:W: Command with sense data:\n", name
);
277 __scsi_print_sense("osst ", SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
280 static int notyetprinted
= 1;
283 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
284 name
, result
, driver_byte(result
),
289 "%s:I: This warning may be caused by your scsi controller,\n", name
);
291 "%s:I: it has been reported with some Buslogic cards.\n", name
);
295 STp
->pos_unknown
|= STp
->device
->was_reset
;
297 if (cmdstatp
->have_sense
&& scode
== RECOVERED_ERROR
) {
298 STp
->recover_count
++;
299 STp
->recover_erreg
++;
302 if (SRpnt
->cmd
[0] == READ_6
)
304 else if (SRpnt
->cmd
[0] == WRITE_6
)
308 printk(OSST_DEB_MSG
"%s:D: Recovered %s error (%d).\n", name
, stp
,
312 if ((sense
[2] & 0xe0) == 0)
319 /* Wakeup from interrupt */
320 static void osst_end_async(struct request
*req
, int update
)
322 struct osst_request
*SRpnt
= req
->end_io_data
;
323 struct osst_tape
*STp
= SRpnt
->stp
;
324 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
326 STp
->buffer
->cmdstat
.midlevel_result
= SRpnt
->result
= req
->errors
;
328 STp
->write_pending
= 0;
331 complete(SRpnt
->waiting
);
335 blk_rq_unmap_user(SRpnt
->bio
);
338 __blk_put_request(req
->q
, req
);
341 /* osst_request memory management */
342 static struct osst_request
*osst_allocate_request(void)
344 return kzalloc(sizeof(struct osst_request
), GFP_KERNEL
);
347 static void osst_release_request(struct osst_request
*streq
)
352 static int osst_execute(struct osst_request
*SRpnt
, const unsigned char *cmd
,
353 int cmd_len
, int data_direction
, void *buffer
, unsigned bufflen
,
354 int use_sg
, int timeout
, int retries
)
357 struct page
**pages
= NULL
;
358 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
361 int write
= (data_direction
== DMA_TO_DEVICE
);
363 req
= blk_get_request(SRpnt
->stp
->device
->request_queue
, write
, GFP_KERNEL
);
365 return DRIVER_ERROR
<< 24;
367 req
->cmd_type
= REQ_TYPE_BLOCK_PC
;
368 req
->cmd_flags
|= REQ_QUIET
;
373 struct scatterlist
*sg
, *sgl
= (struct scatterlist
*)buffer
;
376 pages
= kzalloc(use_sg
* sizeof(struct page
*), GFP_KERNEL
);
380 for_each_sg(sgl
, sg
, use_sg
, i
)
381 pages
[i
] = sg_page(sg
);
383 mdata
->null_mapped
= 1;
385 mdata
->page_order
= get_order(sgl
[0].length
);
387 DIV_ROUND_UP(bufflen
, PAGE_SIZE
<< mdata
->page_order
);
390 err
= blk_rq_map_user(req
->q
, req
, mdata
, NULL
, bufflen
, GFP_KERNEL
);
395 SRpnt
->bio
= req
->bio
;
396 mdata
->pages
= pages
;
398 } else if (bufflen
) {
399 err
= blk_rq_map_kern(req
->q
, req
, buffer
, bufflen
, GFP_KERNEL
);
404 req
->cmd_len
= cmd_len
;
405 memset(req
->cmd
, 0, BLK_MAX_CDB
); /* ATAPI hates garbage after CDB */
406 memcpy(req
->cmd
, cmd
, req
->cmd_len
);
407 req
->sense
= SRpnt
->sense
;
409 req
->timeout
= timeout
;
410 req
->retries
= retries
;
411 req
->end_io_data
= SRpnt
;
413 blk_execute_rq_nowait(req
->q
, NULL
, req
, 1, osst_end_async
);
416 blk_put_request(req
);
417 return DRIVER_ERROR
<< 24;
420 /* Do the scsi command. Waits until command performed if do_wait is true.
421 Otherwise osst_write_behind_check() is used to check that the command
423 static struct osst_request
* osst_do_scsi(struct osst_request
*SRpnt
, struct osst_tape
*STp
,
424 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
427 unsigned short use_sg
;
428 #ifdef OSST_INJECT_ERRORS
429 static int inject
= 0;
430 static int repeat
= 0;
432 struct completion
*waiting
;
434 /* if async, make sure there's no command outstanding */
435 if (!do_wait
&& ((STp
->buffer
)->last_SRpnt
)) {
436 printk(KERN_ERR
"%s: Async command already active.\n",
438 if (signal_pending(current
))
439 (STp
->buffer
)->syscall_result
= (-EINTR
);
441 (STp
->buffer
)->syscall_result
= (-EBUSY
);
446 SRpnt
= osst_allocate_request();
448 printk(KERN_ERR
"%s: Can't allocate SCSI request.\n",
450 if (signal_pending(current
))
451 (STp
->buffer
)->syscall_result
= (-EINTR
);
453 (STp
->buffer
)->syscall_result
= (-EBUSY
);
459 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
460 which IO is outstanding. It's nulled out when the IO completes. */
462 (STp
->buffer
)->last_SRpnt
= SRpnt
;
464 waiting
= &STp
->wait
;
465 init_completion(waiting
);
466 SRpnt
->waiting
= waiting
;
468 use_sg
= (bytes
> STp
->buffer
->sg
[0].length
) ? STp
->buffer
->use_sg
: 0;
470 bp
= (char *)&(STp
->buffer
->sg
[0]);
471 if (STp
->buffer
->sg_segs
< use_sg
)
472 use_sg
= STp
->buffer
->sg_segs
;
475 bp
= (STp
->buffer
)->b_data
;
477 memcpy(SRpnt
->cmd
, cmd
, sizeof(SRpnt
->cmd
));
478 STp
->buffer
->cmdstat
.have_sense
= 0;
479 STp
->buffer
->syscall_result
= 0;
481 if (osst_execute(SRpnt
, cmd
, COMMAND_SIZE(cmd
[0]), direction
, bp
, bytes
,
482 use_sg
, timeout
, retries
))
483 /* could not allocate the buffer or request was too large */
484 (STp
->buffer
)->syscall_result
= (-EBUSY
);
486 wait_for_completion(waiting
);
487 SRpnt
->waiting
= NULL
;
488 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
489 #ifdef OSST_INJECT_ERRORS
490 if (STp
->buffer
->syscall_result
== 0 &&
493 ( (++ inject
% 83) == 29 ||
494 (STp
->first_frame_position
== 240
495 /* or STp->read_error_frame to fail again on the block calculated above */ &&
497 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
498 STp
->buffer
->last_result_fatal
= 1;
506 /* Handle the write-behind checking (downs the semaphore) */
507 static void osst_write_behind_check(struct osst_tape
*STp
)
509 struct osst_buffer
* STbuffer
;
511 STbuffer
= STp
->buffer
;
514 if (STp
->write_pending
)
519 wait_for_completion(&(STp
->wait
));
520 STp
->buffer
->last_SRpnt
->waiting
= NULL
;
522 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
524 if (STp
->buffer
->syscall_result
)
525 STp
->buffer
->syscall_result
=
526 osst_write_error_recovery(STp
, &(STp
->buffer
->last_SRpnt
), 1);
528 STp
->first_frame_position
++;
530 osst_release_request(STp
->buffer
->last_SRpnt
);
532 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
533 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
535 STbuffer
->last_SRpnt
= NULL
;
536 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
537 STbuffer
->writing
= 0;
544 /* Onstream specific Routines */
546 * Initialize the OnStream AUX
548 static void osst_init_aux(struct osst_tape
* STp
, int frame_type
, int frame_seq_number
,
549 int logical_blk_num
, int blk_sz
, int blk_cnt
)
551 os_aux_t
*aux
= STp
->buffer
->aux
;
552 os_partition_t
*par
= &aux
->partition
;
553 os_dat_t
*dat
= &aux
->dat
;
555 if (STp
->raw
) return;
557 memset(aux
, 0, sizeof(*aux
));
558 aux
->format_id
= htonl(0);
559 memcpy(aux
->application_sig
, "LIN4", 4);
560 aux
->hdwr
= htonl(0);
561 aux
->frame_type
= frame_type
;
563 switch (frame_type
) {
564 case OS_FRAME_TYPE_HEADER
:
565 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
566 par
->partition_num
= OS_CONFIG_PARTITION
;
567 par
->par_desc_ver
= OS_PARTITION_VERSION
;
568 par
->wrt_pass_cntr
= htons(0xffff);
569 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
570 par
->first_frame_ppos
= htonl(0);
571 par
->last_frame_ppos
= htonl(0xbb7);
572 aux
->frame_seq_num
= htonl(0);
573 aux
->logical_blk_num_high
= htonl(0);
574 aux
->logical_blk_num
= htonl(0);
575 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
577 case OS_FRAME_TYPE_DATA
:
578 case OS_FRAME_TYPE_MARKER
:
583 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
584 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
585 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
586 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
587 dat
->dat_list
[0].reserved
= 0;
588 case OS_FRAME_TYPE_EOD
:
589 aux
->update_frame_cntr
= htonl(0);
590 par
->partition_num
= OS_DATA_PARTITION
;
591 par
->par_desc_ver
= OS_PARTITION_VERSION
;
592 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
593 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
594 par
->last_frame_ppos
= htonl(STp
->capacity
);
595 aux
->frame_seq_num
= htonl(frame_seq_number
);
596 aux
->logical_blk_num_high
= htonl(0);
597 aux
->logical_blk_num
= htonl(logical_blk_num
);
599 default: ; /* probably FILL */
601 aux
->filemark_cnt
= htonl(STp
->filemark_cnt
);
602 aux
->phys_fm
= htonl(0xffffffff);
603 aux
->last_mark_ppos
= htonl(STp
->last_mark_ppos
);
604 aux
->last_mark_lbn
= htonl(STp
->last_mark_lbn
);
608 * Verify that we have the correct tape frame
610 static int osst_verify_frame(struct osst_tape
* STp
, int frame_seq_number
, int quiet
)
612 char * name
= tape_name(STp
);
613 os_aux_t
* aux
= STp
->buffer
->aux
;
614 os_partition_t
* par
= &(aux
->partition
);
615 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
616 int blk_cnt
, blk_sz
, i
;
619 if (STp
->buffer
->syscall_result
) {
620 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
621 memset(page_address(sg_page(&STp
->buffer
->sg
[i
])),
622 0, STp
->buffer
->sg
[i
].length
);
623 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
625 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
628 if (STp
->buffer
->syscall_result
) {
630 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
634 if (ntohl(aux
->format_id
) != 0) {
636 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
640 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
641 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
643 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
647 if (par
->partition_num
!= OS_DATA_PARTITION
) {
648 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
650 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
651 name
, par
->partition_num
);
656 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
658 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
662 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
664 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
665 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
669 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
670 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
671 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
674 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
679 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
680 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
681 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
682 STp
->first_frame_position
);
685 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
688 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
689 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
694 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
695 STps
->eof
= ST_FM_HIT
;
697 i
= ntohl(aux
->filemark_cnt
);
698 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
699 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
701 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
702 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
703 i
, STp
->first_frame_position
- 1);
705 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
706 if (i
>= STp
->filemark_cnt
)
707 STp
->filemark_cnt
= i
+1;
710 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
711 STps
->eof
= ST_EOD_1
;
712 STp
->frame_in_buffer
= 1;
714 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
715 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
716 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
717 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
718 STp
->buffer
->read_pointer
= 0;
719 STp
->frame_in_buffer
= 1;
721 /* See what block size was used to write file */
722 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
724 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
725 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
726 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
727 STp
->block_size
<1024?'b':'k');
728 STp
->block_size
= blk_sz
;
729 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
731 STps
->eof
= ST_NOEOF
;
733 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
734 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
738 if (STp
->read_error_frame
== 0)
739 STp
->read_error_frame
= STp
->first_frame_position
- 1;
744 * Wait for the unit to become Ready
746 static int osst_wait_ready(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
747 unsigned timeout
, int initial_delay
)
749 unsigned char cmd
[MAX_COMMAND_SIZE
];
750 struct osst_request
* SRpnt
;
751 unsigned long startwait
= jiffies
;
754 char * name
= tape_name(STp
);
756 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
759 if (initial_delay
> 0)
760 msleep(jiffies_to_msecs(initial_delay
));
762 memset(cmd
, 0, MAX_COMMAND_SIZE
);
763 cmd
[0] = TEST_UNIT_READY
;
765 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
767 if (!SRpnt
) return (-EBUSY
);
769 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
770 (( SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
771 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8) ) ||
772 ( SRpnt
->sense
[2] == 6 && SRpnt
->sense
[12] == 0x28 &&
773 SRpnt
->sense
[13] == 0 ) )) {
776 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
777 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
783 memset(cmd
, 0, MAX_COMMAND_SIZE
);
784 cmd
[0] = TEST_UNIT_READY
;
786 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
792 if ( STp
->buffer
->syscall_result
&&
793 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
795 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
796 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
797 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
798 SRpnt
->sense
[12], SRpnt
->sense
[13]);
803 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
809 * Wait for a tape to be inserted in the unit
811 static int osst_wait_for_medium(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, unsigned timeout
)
813 unsigned char cmd
[MAX_COMMAND_SIZE
];
814 struct osst_request
* SRpnt
;
815 unsigned long startwait
= jiffies
;
818 char * name
= tape_name(STp
);
820 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
823 memset(cmd
, 0, MAX_COMMAND_SIZE
);
824 cmd
[0] = TEST_UNIT_READY
;
826 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
828 if (!SRpnt
) return (-EBUSY
);
830 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
831 SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 0x3a && SRpnt
->sense
[13] == 0 ) {
834 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
835 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
841 memset(cmd
, 0, MAX_COMMAND_SIZE
);
842 cmd
[0] = TEST_UNIT_READY
;
844 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
850 if ( STp
->buffer
->syscall_result
&& SRpnt
->sense
[2] != 2 &&
851 SRpnt
->sense
[12] != 4 && SRpnt
->sense
[13] == 1) {
853 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
854 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
855 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
856 SRpnt
->sense
[12], SRpnt
->sense
[13]);
861 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
866 static int osst_position_tape_and_confirm(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int frame
)
870 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
871 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
872 if (retval
) return (retval
);
873 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
874 return (osst_get_frame_position(STp
, aSRpnt
));
878 * Wait for write(s) to complete
880 static int osst_flush_drive_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
882 unsigned char cmd
[MAX_COMMAND_SIZE
];
883 struct osst_request
* SRpnt
;
885 int delay
= OSST_WAIT_WRITE_COMPLETE
;
887 char * name
= tape_name(STp
);
889 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
892 memset(cmd
, 0, MAX_COMMAND_SIZE
);
893 cmd
[0] = WRITE_FILEMARKS
;
896 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
898 if (!SRpnt
) return (-EBUSY
);
899 if (STp
->buffer
->syscall_result
) {
900 if ((SRpnt
->sense
[2] & 0x0f) == 2 && SRpnt
->sense
[12] == 4) {
901 if (SRpnt
->sense
[13] == 8) {
902 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
905 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
907 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
908 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
913 #define OSST_POLL_PER_SEC 10
914 static int osst_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int curr
, int minlast
, int to
)
916 unsigned long startwait
= jiffies
;
917 char * name
= tape_name(STp
);
919 char notyetprinted
= 1;
921 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
922 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
924 while (time_before (jiffies
, startwait
+ to
*HZ
))
927 result
= osst_get_frame_position(STp
, aSRpnt
);
929 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
930 return 0; /* successful recovery leaves drive ready for frame */
931 if (result
< 0) break;
932 if (STp
->first_frame_position
== curr
&&
934 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
935 (minlast
>= 0 && STp
->cur_frames
> minlast
)
939 if (debugging
|| time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
))
941 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
942 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
943 STp
->last_frame_position
, STp
->cur_frames
,
944 result
, (jiffies
-startwait
)/HZ
,
945 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
950 if (time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
) && notyetprinted
)
952 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
953 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
954 STp
->last_frame_position
, STp
->cur_frames
, result
);
958 msleep(1000 / OSST_POLL_PER_SEC
);
961 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
962 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
963 STp
->last_frame_position
, STp
->cur_frames
,
964 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
969 static int osst_recover_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int writing
)
971 struct osst_request
* SRpnt
;
972 unsigned char cmd
[MAX_COMMAND_SIZE
];
973 unsigned long startwait
= jiffies
;
975 char * name
= tape_name(STp
);
979 char * olddata
= STp
->buffer
->b_data
;
980 int oldsize
= STp
->buffer
->buffer_size
;
982 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
984 memset(cmd
, 0, MAX_COMMAND_SIZE
);
985 cmd
[0] = WRITE_FILEMARKS
;
987 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
990 while (retval
&& time_before (jiffies
, startwait
+ 5*60*HZ
)) {
992 if (STp
->buffer
->syscall_result
&& (SRpnt
->sense
[2] & 0x0f) != 2) {
994 /* some failure - not just not-ready */
995 retval
= osst_write_error_recovery(STp
, aSRpnt
, 0);
998 schedule_timeout_interruptible(HZ
/ OSST_POLL_PER_SEC
);
1000 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
1001 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1002 cmd
[0] = READ_POSITION
;
1004 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
1007 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
1008 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
1011 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
1013 /* TODO - figure out which error conditions can be handled */
1014 if (STp
->buffer
->syscall_result
)
1016 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
1017 (*aSRpnt
)->sense
[ 2] & 0x0f,
1018 (*aSRpnt
)->sense
[12],
1019 (*aSRpnt
)->sense
[13]);
1025 * Read the next OnStream tape frame at the current location
1027 static int osst_read_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int timeout
)
1029 unsigned char cmd
[MAX_COMMAND_SIZE
];
1030 struct osst_request
* SRpnt
;
1033 os_aux_t
* aux
= STp
->buffer
->aux
;
1034 char * name
= tape_name(STp
);
1038 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
1039 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
1041 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1048 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
1050 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1051 STp
->timeout
, MAX_RETRIES
, 1);
1056 if ((STp
->buffer
)->syscall_result
) {
1058 if (STp
->read_error_frame
== 0) {
1059 STp
->read_error_frame
= STp
->first_frame_position
;
1061 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
1066 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1068 SRpnt
->sense
[0], SRpnt
->sense
[1],
1069 SRpnt
->sense
[2], SRpnt
->sense
[3],
1070 SRpnt
->sense
[4], SRpnt
->sense
[5],
1071 SRpnt
->sense
[6], SRpnt
->sense
[7]);
1075 STp
->first_frame_position
++;
1080 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
1083 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
1084 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
1085 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
1086 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
1087 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
1088 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
1089 if (aux
->frame_type
==2)
1090 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
1091 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
1092 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
1098 static int osst_initiate_read(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1100 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1101 struct osst_request
* SRpnt
;
1102 unsigned char cmd
[MAX_COMMAND_SIZE
];
1104 char * name
= tape_name(STp
);
1106 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
1107 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
1108 STp
->write_type
= OS_WRITE_DATA
;
1109 osst_flush_write_buffer(STp
, aSRpnt
);
1110 osst_flush_drive_buffer(STp
, aSRpnt
);
1112 STps
->rw
= ST_READING
;
1113 STp
->frame_in_buffer
= 0;
1116 * Issue a read 0 command to get the OnStream drive
1117 * read frames into its buffer.
1119 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1124 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
1126 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
1128 if ((retval
= STp
->buffer
->syscall_result
))
1129 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1135 static int osst_get_logical_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1136 int frame_seq_number
, int quiet
)
1138 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1139 char * name
= tape_name(STp
);
1147 * If we want just any frame (-1) and there is a frame in the buffer, return it
1149 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1151 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1156 * Search and wait for the next logical tape frame
1160 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1161 name
, frame_seq_number
);
1162 if (STp
->read_error_frame
) {
1163 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1165 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1166 name
, STp
->read_error_frame
);
1168 STp
->read_error_frame
= 0;
1175 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1176 name
, frame_seq_number
, cnt
);
1178 if ( osst_initiate_read(STp
, aSRpnt
)
1179 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1182 position
= osst_get_frame_position(STp
, aSRpnt
);
1183 if (position
>= 0xbae && position
< 0xbb8)
1185 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1186 position
= STp
->read_error_frame
- 1;
1194 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1197 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1200 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1202 if (osst_verify_frame(STp
, -1, quiet
)) {
1203 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1204 if (STp
->fast_open
) {
1206 "%s:W: Found logical frame %d instead of %d after fast open\n",
1207 name
, x
, frame_seq_number
);
1209 STp
->read_error_frame
= 0;
1212 if (x
> frame_seq_number
) {
1214 /* positioning backwards did not bring us to the desired frame */
1215 position
= STp
->read_error_frame
- 1;
1218 position
= osst_get_frame_position(STp
, aSRpnt
)
1219 + frame_seq_number
- x
- 1;
1221 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1226 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1227 name
, x
, frame_seq_number
,
1228 STp
->first_frame_position
- position
);
1230 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1236 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1238 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1240 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1243 STp
->frame_in_buffer
= 0;
1246 STp
->recover_count
++;
1247 STp
->recover_erreg
++;
1248 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1249 name
, STp
->read_error_frame
);
1254 if (debugging
|| STps
->eof
)
1256 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1257 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1260 STp
->read_error_frame
= 0;
1264 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int logical_blk_num
)
1266 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1267 char * name
= tape_name(STp
);
1269 int frame_seq_estimate
, ppos_estimate
, move
;
1271 if (logical_blk_num
< 0) logical_blk_num
= 0;
1273 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1274 name
, logical_blk_num
, STp
->logical_blk_num
,
1275 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1276 STp
->block_size
<1024?'b':'k');
1278 /* Do we know where we are? */
1279 if (STps
->drv_block
>= 0) {
1280 move
= logical_blk_num
- STp
->logical_blk_num
;
1281 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1282 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1283 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1285 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1287 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1288 else ppos_estimate
= frame_seq_estimate
+ 20;
1289 while (++retries
< 10) {
1290 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1291 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1292 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1294 if (frame_seq_estimate
< 0) {
1295 frame_seq_estimate
= 0;
1298 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1299 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1300 /* we've located the estimated frame, now does it have our block? */
1301 if (logical_blk_num
< STp
->logical_blk_num
||
1302 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1303 if (STps
->eof
== ST_FM_HIT
)
1304 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1306 move
= logical_blk_num
- STp
->logical_blk_num
;
1307 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1308 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1310 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1313 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1314 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1315 STp
->logical_blk_num
, logical_blk_num
, move
);
1317 frame_seq_estimate
+= move
;
1318 ppos_estimate
+= move
;
1321 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1322 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1323 STp
->logical_blk_num
= logical_blk_num
;
1326 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1327 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1328 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1331 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1332 if (STps
->eof
== ST_FM_HIT
) {
1334 STps
->drv_block
= 0;
1336 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1337 STp
->logical_blk_num
-
1338 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1341 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1345 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1347 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1349 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1350 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1351 STp
->logical_blk_num
, logical_blk_num
);
1353 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1354 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1359 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1360 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1364 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1365 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1366 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1367 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1369 #define OSST_FRAME_SHIFT 6
1370 #define OSST_SECTOR_SHIFT 9
1371 #define OSST_SECTOR_MASK 0x03F
1373 static int osst_get_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1377 char * name
= tape_name(STp
);
1380 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1381 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1382 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1383 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1384 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1385 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1387 /* do we know where we are inside a file? */
1388 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1389 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1390 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1391 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1392 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1394 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1396 sector
= osst_get_frame_position(STp
, aSRpnt
);
1398 sector
<<= OSST_FRAME_SHIFT
;
1403 static int osst_seek_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int sector
)
1405 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1406 int frame
= sector
>> OSST_FRAME_SHIFT
,
1407 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1410 char * name
= tape_name(STp
);
1412 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1413 name
, sector
, frame
, offset
);
1415 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1417 if (frame
<= STp
->first_data_ppos
) {
1418 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1419 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1421 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1422 if (r
< 0) return r
;
1424 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1425 if (r
< 0) return r
;
1427 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1430 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1431 STp
->buffer
->read_pointer
= offset
;
1432 STp
->buffer
->buffer_bytes
-= offset
;
1434 STp
->frame_seq_number
++;
1435 STp
->frame_in_buffer
= 0;
1436 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1437 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1439 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1440 if (STps
->eof
== ST_FM_HIT
) {
1442 STps
->drv_block
= 0;
1444 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1445 STp
->logical_blk_num
-
1446 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1449 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1452 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1453 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1454 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1460 * Read back the drive's internal buffer contents, as a part
1461 * of the write error recovery mechanism for old OnStream
1462 * firmware revisions.
1463 * Precondition for this function to work: all frames in the
1464 * drive's buffer must be of one type (DATA, MARK or EOD)!
1466 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1467 unsigned int frame
, unsigned int skip
, int pending
)
1469 struct osst_request
* SRpnt
= * aSRpnt
;
1470 unsigned char * buffer
, * p
;
1471 unsigned char cmd
[MAX_COMMAND_SIZE
];
1472 int flag
, new_frame
, i
;
1473 int nframes
= STp
->cur_frames
;
1474 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1475 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1476 - (nframes
+ pending
- 1);
1477 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1478 - (nframes
+ pending
- 1) * blks_per_frame
;
1479 char * name
= tape_name(STp
);
1480 unsigned long startwait
= jiffies
;
1482 int dbg
= debugging
;
1485 if ((buffer
= (unsigned char *)vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1488 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1489 name
, nframes
, pending
?" and one that was pending":"");
1491 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1493 if (pending
&& debugging
)
1494 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1495 name
, frame_seq_number
+ nframes
,
1496 logical_blk_num
+ nframes
* blks_per_frame
,
1497 p
[0], p
[1], p
[2], p
[3]);
1499 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1501 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1502 cmd
[0] = 0x3C; /* Buffer Read */
1503 cmd
[1] = 6; /* Retrieve Faulty Block */
1504 cmd
[7] = 32768 >> 8;
1505 cmd
[8] = 32768 & 0xff;
1507 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1508 STp
->timeout
, MAX_RETRIES
, 1);
1510 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1511 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1516 osst_copy_from_buffer(STp
->buffer
, p
);
1519 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1520 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1524 osst_get_frame_position(STp
, aSRpnt
);
1527 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1529 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1530 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1532 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1535 if (STp
->write_type
== OS_WRITE_HEADER
) {
1537 p
+= skip
* OS_DATA_SIZE
;
1539 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1544 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1545 name
, new_frame
+i
, frame_seq_number
+i
);
1547 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1548 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1549 osst_get_frame_position(STp
, aSRpnt
);
1552 if (new_frame
> frame
+ 1000) {
1553 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1557 if ( i
>= nframes
+ pending
) break;
1560 osst_copy_to_buffer(STp
->buffer
, p
);
1562 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1564 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1565 logical_blk_num
+ i
*blks_per_frame
,
1566 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1567 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1575 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1576 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1577 p
[0], p
[1], p
[2], p
[3]);
1579 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1580 STp
->timeout
, MAX_RETRIES
, 1);
1582 if (STp
->buffer
->syscall_result
)
1585 p
+= OS_DATA_SIZE
; i
++;
1587 /* if we just sent the last frame, wait till all successfully written */
1588 if ( i
== nframes
+ pending
) {
1590 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1592 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1593 cmd
[0] = WRITE_FILEMARKS
;
1595 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1596 STp
->timeout
, MAX_RETRIES
, 1);
1599 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1600 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1604 flag
= STp
->buffer
->syscall_result
;
1605 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1607 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1608 cmd
[0] = TEST_UNIT_READY
;
1610 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1613 if (SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
1614 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8)) {
1615 /* in the process of becoming ready */
1619 if (STp
->buffer
->syscall_result
)
1625 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1631 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1632 SRpnt
->sense
[12] == 0 &&
1633 SRpnt
->sense
[13] == 2) {
1634 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1636 return (-EIO
); /* hit end of tape = fail */
1638 i
= ((SRpnt
->sense
[3] << 24) |
1639 (SRpnt
->sense
[4] << 16) |
1640 (SRpnt
->sense
[5] << 8) |
1641 SRpnt
->sense
[6] ) - new_frame
;
1642 p
= &buffer
[i
* OS_DATA_SIZE
];
1644 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1646 osst_get_frame_position(STp
, aSRpnt
);
1648 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1649 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1654 /* error recovery did not successfully complete */
1655 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1656 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1659 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1664 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1665 unsigned int frame
, unsigned int skip
, int pending
)
1667 unsigned char cmd
[MAX_COMMAND_SIZE
];
1668 struct osst_request
* SRpnt
;
1669 char * name
= tape_name(STp
);
1671 int attempts
= 1000 / skip
;
1673 unsigned long startwait
= jiffies
;
1675 int dbg
= debugging
;
1678 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1683 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1685 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1687 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1688 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1690 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1693 schedule_timeout_interruptible(msecs_to_jiffies(100));
1695 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1697 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1698 name
, STp
->first_frame_position
,
1699 STp
->last_frame_position
, STp
->cur_frames
);
1701 frame
= STp
->last_frame_position
;
1705 if (pending
&& STp
->cur_frames
< 50) {
1707 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1712 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1713 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1715 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1716 STp
->timeout
, MAX_RETRIES
, 1);
1719 if (STp
->buffer
->syscall_result
) { /* additional write error */
1720 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1721 SRpnt
->sense
[12] == 0 &&
1722 SRpnt
->sense
[13] == 2) {
1724 "%s:E: Volume overflow in write error recovery\n",
1726 break; /* hit end of tape = fail */
1735 if (STp
->cur_frames
== 0) {
1738 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1740 if (STp
->first_frame_position
!= expected
) {
1741 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1742 name
, STp
->first_frame_position
, expected
);
1749 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1750 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1754 schedule_timeout_interruptible(msecs_to_jiffies(100));
1756 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1764 * Error recovery algorithm for the OnStream tape.
1767 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
)
1769 struct osst_request
* SRpnt
= * aSRpnt
;
1770 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1771 char * name
= tape_name(STp
);
1774 unsigned int frame
, skip
;
1776 rw_state
= STps
->rw
;
1778 if ((SRpnt
->sense
[ 2] & 0x0f) != 3
1779 || SRpnt
->sense
[12] != 12
1780 || SRpnt
->sense
[13] != 0) {
1782 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1783 SRpnt
->sense
[2], SRpnt
->sense
[12], SRpnt
->sense
[13]);
1787 frame
= (SRpnt
->sense
[3] << 24) |
1788 (SRpnt
->sense
[4] << 16) |
1789 (SRpnt
->sense
[5] << 8) |
1791 skip
= SRpnt
->sense
[9];
1794 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1796 osst_get_frame_position(STp
, aSRpnt
);
1798 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1799 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1801 switch (STp
->write_type
) {
1804 case OS_WRITE_NEW_MARK
:
1806 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1807 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1808 if (STp
->os_fw_rev
>= 10600)
1809 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1811 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1812 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1814 retval
?"" :"Don't worry, ",
1815 retval
?" not ":" ");
1817 case OS_WRITE_LAST_MARK
:
1818 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1819 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1822 case OS_WRITE_HEADER
:
1823 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1824 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1827 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1828 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1830 osst_get_frame_position(STp
, aSRpnt
);
1832 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1833 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1834 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1837 STp
->recover_count
++;
1838 STp
->recover_erreg
++;
1842 STps
->rw
= rw_state
;
1846 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1847 int mt_op
, int mt_count
)
1849 char * name
= tape_name(STp
);
1851 int last_mark_ppos
= -1;
1854 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1856 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1858 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1862 if (STp
->linux_media_version
>= 4) {
1864 * direct lookup in header filemark list
1866 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1867 if (STp
->header_ok
&&
1868 STp
->header_cache
!= NULL
&&
1869 (cnt
- mt_count
) >= 0 &&
1870 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1871 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1872 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1874 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1876 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1877 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1878 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1880 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1882 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1883 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1884 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1885 mt_count
, last_mark_ppos
);
1887 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1888 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1889 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1892 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1896 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1897 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1898 name
, last_mark_ppos
);
1904 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1908 while (cnt
!= mt_count
) {
1909 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1910 if (last_mark_ppos
== -1)
1913 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1915 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1917 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1919 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1923 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1924 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1925 name
, last_mark_ppos
);
1930 if (mt_op
== MTBSFM
) {
1931 STp
->frame_seq_number
++;
1932 STp
->frame_in_buffer
= 0;
1933 STp
->buffer
->buffer_bytes
= 0;
1934 STp
->buffer
->read_pointer
= 0;
1935 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1941 * ADRL 1.1 compatible "slow" space filemarks fwd version
1943 * Just scans for the filemark sequentially.
1945 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1946 int mt_op
, int mt_count
)
1950 char * name
= tape_name(STp
);
1952 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1954 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1956 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1961 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1963 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1967 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1969 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1971 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1973 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1975 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1976 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1978 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1982 if (cnt
== mt_count
)
1984 STp
->frame_in_buffer
= 0;
1986 if (mt_op
== MTFSF
) {
1987 STp
->frame_seq_number
++;
1988 STp
->frame_in_buffer
= 0;
1989 STp
->buffer
->buffer_bytes
= 0;
1990 STp
->buffer
->read_pointer
= 0;
1991 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1997 * Fast linux specific version of OnStream FSF
1999 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
2000 int mt_op
, int mt_count
)
2002 char * name
= tape_name(STp
);
2004 next_mark_ppos
= -1;
2007 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
2009 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2011 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
2016 if (STp
->linux_media_version
>= 4) {
2018 * direct lookup in header filemark list
2020 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
2021 if (STp
->header_ok
&&
2022 STp
->header_cache
!= NULL
&&
2023 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
2024 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
2025 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2026 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
2028 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
2030 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
2031 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
2032 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
2034 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2036 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2037 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
2038 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
2039 mt_count
, next_mark_ppos
);
2041 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
2043 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2045 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2047 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2048 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2050 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2055 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2056 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2057 name
, next_mark_ppos
);
2060 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
2061 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
2062 name
, cnt
+mt_count
, next_mark_ppos
,
2063 ntohl(STp
->buffer
->aux
->filemark_cnt
));
2069 * Find nearest (usually previous) marker, then jump from marker to marker
2072 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
2074 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
2076 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
2080 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
2081 if (STp
->first_mark_ppos
== -1) {
2083 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2085 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2087 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
2088 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2091 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2096 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2097 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
2098 name
, STp
->first_mark_ppos
);
2102 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
2108 while (cnt
!= mt_count
) {
2109 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
2110 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
2112 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2114 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
2117 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
2119 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2121 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2123 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2128 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2129 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2130 name
, next_mark_ppos
);
2135 if (mt_op
== MTFSF
) {
2136 STp
->frame_seq_number
++;
2137 STp
->frame_in_buffer
= 0;
2138 STp
->buffer
->buffer_bytes
= 0;
2139 STp
->buffer
->read_pointer
= 0;
2140 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2146 * In debug mode, we want to see as many errors as possible
2147 * to test the error recovery mechanism.
2150 static void osst_set_retries(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int retries
)
2152 unsigned char cmd
[MAX_COMMAND_SIZE
];
2153 struct osst_request
* SRpnt
= * aSRpnt
;
2154 char * name
= tape_name(STp
);
2156 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2157 cmd
[0] = MODE_SELECT
;
2159 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2161 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2162 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2163 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2164 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2165 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2166 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2167 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2168 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2171 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2173 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2176 if ((STp
->buffer
)->syscall_result
)
2177 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2182 static int osst_write_filemark(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2185 int this_mark_ppos
= STp
->first_frame_position
;
2186 int this_mark_lbn
= STp
->logical_blk_num
;
2188 char * name
= tape_name(STp
);
2191 if (STp
->raw
) return 0;
2193 STp
->write_type
= OS_WRITE_NEW_MARK
;
2195 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2196 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2199 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2200 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2201 STp
->last_mark_ppos
= this_mark_ppos
;
2202 STp
->last_mark_lbn
= this_mark_lbn
;
2203 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2204 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2205 if (STp
->filemark_cnt
++ == 0)
2206 STp
->first_mark_ppos
= this_mark_ppos
;
2210 static int osst_write_eod(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2214 char * name
= tape_name(STp
);
2217 if (STp
->raw
) return 0;
2219 STp
->write_type
= OS_WRITE_EOD
;
2220 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2222 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2223 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2227 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2228 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2229 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2233 static int osst_write_filler(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2235 char * name
= tape_name(STp
);
2238 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2240 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2241 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2242 STp
->write_type
= OS_WRITE_FILLER
;
2244 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2245 STp
->buffer
->buffer_bytes
= 6;
2247 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2248 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2253 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2255 return osst_flush_drive_buffer(STp
, aSRpnt
);
2258 static int __osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2260 char * name
= tape_name(STp
);
2264 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2266 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2267 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2268 STp
->write_type
= OS_WRITE_HEADER
;
2270 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2271 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2273 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2274 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2278 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2280 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2285 static int osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int locate_eod
)
2287 os_header_t
* header
;
2289 char * name
= tape_name(STp
);
2292 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2294 if (STp
->raw
) return 0;
2296 if (STp
->header_cache
== NULL
) {
2297 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2298 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2301 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2303 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2306 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2307 else STp
->update_frame_cntr
= 0;
2309 header
= STp
->header_cache
;
2310 strcpy(header
->ident_str
, "ADR_SEQ");
2311 header
->major_rev
= 1;
2312 header
->minor_rev
= 4;
2313 header
->ext_trk_tb_off
= htons(17192);
2314 header
->pt_par_num
= 1;
2315 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2316 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2317 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2318 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2319 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2320 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2321 header
->cfg_col_width
= htonl(20);
2322 header
->dat_col_width
= htonl(1500);
2323 header
->qfa_col_width
= htonl(0);
2324 header
->ext_track_tb
.nr_stream_part
= 1;
2325 header
->ext_track_tb
.et_ent_sz
= 32;
2326 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2327 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2328 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2329 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2330 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2331 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2332 header
->dat_fm_tab
.fm_part_num
= 0;
2333 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2334 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2335 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2337 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2338 if (STp
->update_frame_cntr
== 0)
2339 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2340 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2344 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2346 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2349 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2351 memcpy(STp
->application_sig
, "LIN4", 4);
2352 STp
->linux_media
= 1;
2353 STp
->linux_media_version
= 4;
2359 static int osst_reset_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2361 if (STp
->header_cache
!= NULL
)
2362 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2364 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2365 STp
->frame_in_buffer
= 0;
2366 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2367 STp
->filemark_cnt
= 0;
2368 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2369 return osst_write_header(STp
, aSRpnt
, 1);
2372 static int __osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int ppos
)
2374 char * name
= tape_name(STp
);
2375 os_header_t
* header
;
2378 int linux_media_version
,
2384 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2385 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2386 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2387 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2388 if (osst_initiate_read (STp
, aSRpnt
)) {
2389 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2393 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2395 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2399 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2400 aux
= STp
->buffer
->aux
;
2401 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2403 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2407 if (ntohl(aux
->frame_seq_num
) != 0 ||
2408 ntohl(aux
->logical_blk_num
) != 0 ||
2409 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2410 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2411 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2413 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2414 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2415 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2416 ntohl(aux
->partition
.last_frame_ppos
));
2420 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2421 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2422 strlcpy(id_string
, header
->ident_str
, 8);
2424 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2428 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2429 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2431 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2432 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2436 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2438 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2439 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2440 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2441 header
->major_rev
, header
->minor_rev
);
2443 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2447 if (header
->pt_par_num
!= 1)
2448 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2449 name
, header
->pt_par_num
);
2451 memcpy(id_string
, aux
->application_sig
, 4);
2453 if (memcmp(id_string
, "LIN", 3) == 0) {
2454 STp
->linux_media
= 1;
2455 linux_media_version
= id_string
[3] - '0';
2456 if (linux_media_version
!= 4)
2457 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2458 name
, linux_media_version
);
2460 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2463 if (linux_media_version
< STp
->linux_media_version
) {
2465 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2466 name
, ppos
, linux_media_version
);
2470 if (linux_media_version
> STp
->linux_media_version
) {
2472 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2473 name
, ppos
, linux_media_version
);
2475 memcpy(STp
->application_sig
, id_string
, 5);
2476 STp
->linux_media_version
= linux_media_version
;
2477 STp
->update_frame_cntr
= -1;
2479 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2481 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2482 name
, ppos
, update_frame_cntr
);
2484 if (STp
->header_cache
== NULL
) {
2485 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2486 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2490 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2493 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2494 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2496 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2497 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2498 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2499 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2500 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2501 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2502 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2503 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2504 STp
->update_frame_cntr
= update_frame_cntr
;
2506 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2507 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2508 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2509 STp
->first_data_ppos
,
2510 ntohl(header
->partition
[0].last_frame_ppos
),
2511 ntohl(header
->partition
[0].eod_frame_ppos
));
2512 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2513 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2515 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2517 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2519 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2520 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2521 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2523 if (header
->minor_rev
== 4 &&
2524 (header
->ext_trk_tb_off
!= htons(17192) ||
2525 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2526 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2527 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2528 header
->cfg_col_width
!= htonl(20) ||
2529 header
->dat_col_width
!= htonl(1500) ||
2530 header
->qfa_col_width
!= htonl(0) ||
2531 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2532 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2533 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2534 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2535 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2536 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2537 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2538 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2539 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2540 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2541 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2542 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2549 static int osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2554 char * name
= tape_name(STp
);
2556 position
= osst_get_frame_position(STp
, aSRpnt
);
2559 STp
->header_ok
= STp
->linux_media
= 1;
2560 STp
->linux_media_version
= 0;
2563 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2564 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2565 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2566 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2568 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2571 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2572 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2574 first
= position
==10?0xbae: 5;
2575 last
= position
==10?0xbb3:10;
2577 for (ppos
= first
; ppos
< last
; ppos
++)
2578 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2581 first
= position
==10? 5:0xbae;
2582 last
= position
==10?10:0xbb3;
2584 for (ppos
= first
; ppos
< last
; ppos
++)
2585 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2589 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2590 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2591 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2594 if (position
<= STp
->first_data_ppos
) {
2595 position
= STp
->first_data_ppos
;
2596 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2598 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2604 static int osst_verify_position(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2606 int frame_position
= STp
->first_frame_position
;
2607 int frame_seq_numbr
= STp
->frame_seq_number
;
2608 int logical_blk_num
= STp
->logical_blk_num
;
2609 int halfway_frame
= STp
->frame_in_buffer
;
2610 int read_pointer
= STp
->buffer
->read_pointer
;
2611 int prev_mark_ppos
= -1;
2612 int actual_mark_ppos
, i
, n
;
2614 char * name
= tape_name(STp
);
2616 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2618 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2619 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2621 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2625 if (STp
->linux_media_version
>= 4) {
2626 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2627 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2630 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2631 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2632 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2633 if (frame_position
!= STp
->first_frame_position
||
2634 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2635 prev_mark_ppos
!= actual_mark_ppos
) {
2637 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2638 STp
->first_frame_position
, frame_position
,
2639 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2640 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2644 if (halfway_frame
) {
2645 /* prepare buffer for append and rewrite on top of original */
2646 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2647 STp
->buffer
->buffer_bytes
= read_pointer
;
2648 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2651 STp
->frame_in_buffer
= halfway_frame
;
2652 STp
->frame_seq_number
= frame_seq_numbr
;
2653 STp
->logical_blk_num
= logical_blk_num
;
2657 /* Acc. to OnStream, the vers. numbering is the following:
2658 * X.XX for released versions (X=digit),
2659 * XXXY for unreleased versions (Y=letter)
2660 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2661 * This fn makes monoton numbers out of this scheme ...
2663 static unsigned int osst_parse_firmware_rev (const char * str
)
2665 if (str
[1] == '.') {
2666 return (str
[0]-'0')*10000
2670 return (str
[0]-'0')*10000
2672 +(str
[2]-'0')*100 - 100
2678 * Configure the OnStream SCII tape drive for default operation
2680 static int osst_configure_onstream(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2682 unsigned char cmd
[MAX_COMMAND_SIZE
];
2683 char * name
= tape_name(STp
);
2684 struct osst_request
* SRpnt
= * aSRpnt
;
2685 osst_mode_parameter_header_t
* header
;
2686 osst_block_size_page_t
* bs
;
2687 osst_capabilities_page_t
* cp
;
2688 osst_tape_paramtr_page_t
* prm
;
2689 int drive_buffer_size
;
2691 if (STp
->ready
!= ST_READY
) {
2693 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2698 if (STp
->os_fw_rev
< 10600) {
2699 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2700 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2704 * Configure 32.5KB (data+aux) frame size.
2705 * Get the current frame size from the block size mode page
2707 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2708 cmd
[0] = MODE_SENSE
;
2710 cmd
[2] = BLOCK_SIZE_PAGE
;
2711 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2713 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2714 if (SRpnt
== NULL
) {
2716 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2721 if ((STp
->buffer
)->syscall_result
!= 0) {
2722 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2726 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2727 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2730 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2731 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2732 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2733 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2737 * Configure default auto columns mode, 32.5KB transfer mode
2745 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2746 cmd
[0] = MODE_SELECT
;
2748 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2750 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2752 if ((STp
->buffer
)->syscall_result
!= 0) {
2753 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2758 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2760 * In debug mode, we want to see as many errors as possible
2761 * to test the error recovery mechanism.
2763 osst_set_retries(STp
, aSRpnt
, 0);
2768 * Set vendor name to 'LIN4' for "Linux support version 4".
2771 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2772 cmd
[0] = MODE_SELECT
;
2774 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2776 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2777 header
->medium_type
= 0; /* Medium Type - ignoring */
2778 header
->dsp
= 0; /* Reserved */
2779 header
->bdl
= 0; /* Block Descriptor Length */
2781 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2782 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2783 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2784 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2785 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2786 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2787 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2788 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2790 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2793 if ((STp
->buffer
)->syscall_result
!= 0) {
2794 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2795 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2799 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2800 cmd
[0] = MODE_SENSE
;
2802 cmd
[2] = CAPABILITIES_PAGE
;
2803 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2805 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2808 if ((STp
->buffer
)->syscall_result
!= 0) {
2809 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2813 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2814 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2815 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2817 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2819 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2820 cmd
[0] = MODE_SENSE
;
2822 cmd
[2] = TAPE_PARAMTR_PAGE
;
2823 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2825 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2828 if ((STp
->buffer
)->syscall_result
!= 0) {
2829 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2833 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2834 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2835 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2837 STp
->density
= prm
->density
;
2838 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2840 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2841 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2849 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2850 it messes up the block number). */
2851 static int cross_eof(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int forward
)
2854 char * name
= tape_name(STp
);
2858 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2859 name
, forward
? "forward" : "backward");
2863 /* assumes that the filemark is already read by the drive, so this is low cost */
2864 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2867 /* assumes this is only called if we just read the filemark! */
2868 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2871 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2872 name
, forward
? "forward" : "backward");
2878 /* Get the tape position. */
2880 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2882 unsigned char scmd
[MAX_COMMAND_SIZE
];
2883 struct osst_request
* SRpnt
;
2885 char * name
= tape_name(STp
);
2887 /* KG: We want to be able to use it for checking Write Buffer availability
2888 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2890 char * olddata
= STp
->buffer
->b_data
;
2891 int oldsize
= STp
->buffer
->buffer_size
;
2893 if (STp
->ready
!= ST_READY
) return (-EIO
);
2895 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2896 scmd
[0] = READ_POSITION
;
2898 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2899 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2900 STp
->timeout
, MAX_RETRIES
, 1);
2902 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2907 if (STp
->buffer
->syscall_result
)
2908 result
= ((SRpnt
->sense
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2910 if (result
== -EINVAL
)
2911 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2913 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2914 unsigned char mysense
[16];
2915 memcpy (mysense
, SRpnt
->sense
, 16);
2916 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2917 scmd
[0] = READ_POSITION
;
2918 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2919 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2920 STp
->timeout
, MAX_RETRIES
, 1);
2922 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2923 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2924 SRpnt
->sense
[2],SRpnt
->sense
[12],SRpnt
->sense
[13]);
2926 if (!STp
->buffer
->syscall_result
)
2927 memcpy (SRpnt
->sense
, mysense
, 16);
2929 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2931 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2932 + ((STp
->buffer
)->b_data
[5] << 16)
2933 + ((STp
->buffer
)->b_data
[6] << 8)
2934 + (STp
->buffer
)->b_data
[7];
2935 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2936 + ((STp
->buffer
)->b_data
[ 9] << 16)
2937 + ((STp
->buffer
)->b_data
[10] << 8)
2938 + (STp
->buffer
)->b_data
[11];
2939 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2942 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2943 STp
->first_frame_position
, STp
->last_frame_position
,
2944 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2945 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2949 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2951 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2952 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2954 STp
->first_frame_position
= STp
->last_frame_position
;
2957 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2959 return (result
== 0 ? STp
->first_frame_position
: result
);
2963 /* Set the tape block */
2964 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int ppos
, int skip
)
2966 unsigned char scmd
[MAX_COMMAND_SIZE
];
2967 struct osst_request
* SRpnt
;
2968 struct st_partstat
* STps
;
2970 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2971 char * name
= tape_name(STp
);
2973 if (STp
->ready
!= ST_READY
) return (-EIO
);
2975 STps
= &(STp
->ps
[STp
->partition
]);
2977 if (ppos
< 0 || ppos
> STp
->capacity
) {
2978 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2979 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2986 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2988 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2991 scmd
[3] = (pp
>> 24);
2992 scmd
[4] = (pp
>> 16);
2993 scmd
[5] = (pp
>> 8);
2998 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
3004 if ((STp
->buffer
)->syscall_result
!= 0) {
3006 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
3007 name
, STp
->first_frame_position
, pp
);
3012 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
3013 } while ((pp
!= ppos
) && (pp
= ppos
));
3014 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
3015 STps
->eof
= ST_NOEOF
;
3018 STp
->frame_in_buffer
= 0;
3022 static int osst_write_trailer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int leave_at_EOT
)
3024 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
3027 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
3028 /* true unless the user wrote the filemark for us */
3029 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
3030 if (result
< 0) goto out
;
3031 result
= osst_write_filemark(STp
, aSRpnt
);
3032 if (result
< 0) goto out
;
3034 if (STps
->drv_file
>= 0)
3036 STps
->drv_block
= 0;
3038 result
= osst_write_eod(STp
, aSRpnt
);
3039 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
3046 /* osst versions of st functions - augmented and stripped to suit OnStream only */
3048 /* Flush the write buffer (never need to write if variable blocksize). */
3049 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
3051 int offset
, transfer
, blks
= 0;
3053 unsigned char cmd
[MAX_COMMAND_SIZE
];
3054 struct osst_request
* SRpnt
= *aSRpnt
;
3055 struct st_partstat
* STps
;
3056 char * name
= tape_name(STp
);
3058 if ((STp
->buffer
)->writing
) {
3059 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
3061 { printk(OSST_DEB_MSG
3062 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name
);
3064 *aSRpnt
= SRpnt
= NULL
;
3068 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name
);
3070 osst_write_behind_check(STp
);
3071 if ((STp
->buffer
)->syscall_result
) {
3074 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
3075 name
, (STp
->buffer
)->midlevel_result
);
3077 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3084 if (STp
->dirty
== 1) {
3087 STps
= &(STp
->ps
[STp
->partition
]);
3088 STps
->rw
= ST_WRITING
;
3089 offset
= STp
->buffer
->buffer_bytes
;
3090 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
3091 transfer
= OS_FRAME_SIZE
;
3093 if (offset
< OS_DATA_SIZE
)
3094 osst_zero_buffer_tail(STp
->buffer
);
3097 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
3098 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
3100 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3105 switch (STp
->write_type
) {
3109 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3110 name
, blks
, STp
->frame_seq_number
,
3111 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3113 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3114 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3117 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
3118 STp
->logical_blk_num
, 0, 0);
3120 case OS_WRITE_NEW_MARK
:
3121 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
3122 STp
->logical_blk_num
++, 0, blks
=1);
3124 case OS_WRITE_HEADER
:
3125 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
3127 default: /* probably FILLER */
3128 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
3132 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3133 name
, offset
, transfer
, blks
);
3136 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3137 STp
->timeout
, MAX_RETRIES
, 1);
3142 if ((STp
->buffer
)->syscall_result
!= 0) {
3145 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3146 name
, SRpnt
->sense
[0], SRpnt
->sense
[2],
3147 SRpnt
->sense
[12], SRpnt
->sense
[13]);
3149 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3150 (SRpnt
->sense
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3151 (SRpnt
->sense
[2] & 0x0f) == NO_SENSE
) {
3153 (STp
->buffer
)->buffer_bytes
= 0;
3157 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3158 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3162 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3165 STp
->first_frame_position
++;
3167 (STp
->buffer
)->buffer_bytes
= 0;
3171 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3177 /* Flush the tape buffer. The tape will be positioned correctly unless
3178 seek_next is true. */
3179 static int osst_flush_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int seek_next
)
3181 struct st_partstat
* STps
;
3182 int backspace
= 0, result
= 0;
3184 char * name
= tape_name(STp
);
3188 * If there was a bus reset, block further access
3191 if( STp
->pos_unknown
)
3194 if (STp
->ready
!= ST_READY
)
3197 STps
= &(STp
->ps
[STp
->partition
]);
3198 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3199 STp
->write_type
= OS_WRITE_DATA
;
3200 return osst_flush_write_buffer(STp
, aSRpnt
);
3202 if (STp
->block_size
== 0)
3206 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3209 if (!STp
->can_bsr
) {
3210 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3211 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3212 (STp
->buffer
)->buffer_bytes
= 0;
3213 (STp
->buffer
)->read_pointer
= 0;
3214 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3218 if (STps
->eof
== ST_FM_HIT
) {
3219 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3221 STps
->eof
= ST_NOEOF
;
3223 if (STps
->drv_file
>= 0)
3225 STps
->drv_block
= 0;
3228 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3229 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3231 else if (STps
->eof
== ST_FM_HIT
) {
3232 if (STps
->drv_file
>= 0)
3234 STps
->drv_block
= 0;
3235 STps
->eof
= ST_NOEOF
;
3241 static int osst_write_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int synchronous
)
3243 unsigned char cmd
[MAX_COMMAND_SIZE
];
3244 struct osst_request
* SRpnt
;
3247 char * name
= tape_name(STp
);
3250 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3252 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3254 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3257 /* error recovery may have bumped us past the header partition */
3258 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3260 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3262 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3267 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3268 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3271 // osst_build_stats(STp, &SRpnt);
3273 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3274 STp
->write_type
= OS_WRITE_DATA
;
3276 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3279 cmd
[4] = 1; /* one frame at a time... */
3280 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3283 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3284 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3286 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3287 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3291 STp
->write_pending
= 1;
3293 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3294 MAX_RETRIES
, synchronous
);
3300 if (STp
->buffer
->syscall_result
!= 0) {
3303 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3305 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3306 (SRpnt
->sense
[2] & 0x40)) {
3307 if ((SRpnt
->sense
[2] & 0x0f) == VOLUME_OVERFLOW
)
3311 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3316 STp
->first_frame_position
++;
3324 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3325 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3329 cmd
= do_lock
? SCSI_IOCTL_DOORLOCK
: SCSI_IOCTL_DOORUNLOCK
;
3331 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3333 retval
= scsi_ioctl(STp
->device
, cmd
, NULL
);
3335 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3338 STp
->door_locked
= ST_LOCK_FAILS
;
3343 /* Set the internal state after reset */
3344 static void reset_state(struct osst_tape
*STp
)
3347 struct st_partstat
*STps
;
3349 STp
->pos_unknown
= 0;
3350 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3351 STps
= &(STp
->ps
[i
]);
3353 STps
->eof
= ST_NOEOF
;
3355 STps
->last_block_valid
= 0;
3356 STps
->drv_block
= -1;
3357 STps
->drv_file
= -1;
3362 /* Entry points to osst */
3365 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3367 ssize_t total
, retval
= 0;
3368 ssize_t i
, do_count
, blks
, transfer
;
3369 int write_threshold
;
3370 int doing_write
= 0;
3371 const char __user
* b_point
;
3372 struct osst_request
* SRpnt
= NULL
;
3373 struct st_modedef
* STm
;
3374 struct st_partstat
* STps
;
3375 struct osst_tape
* STp
= filp
->private_data
;
3376 char * name
= tape_name(STp
);
3379 if (mutex_lock_interruptible(&STp
->lock
))
3380 return (-ERESTARTSYS
);
3383 * If we are in the middle of error recovery, don't let anyone
3384 * else try and use this device. Also, if error recovery fails, it
3385 * may try and take the device offline, in which case all further
3386 * access to the device is prohibited.
3388 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3393 if (STp
->ready
!= ST_READY
) {
3394 if (STp
->ready
== ST_NO_TAPE
)
3395 retval
= (-ENOMEDIUM
);
3400 STm
= &(STp
->modes
[STp
->current_mode
]);
3401 if (!STm
->defined
) {
3409 * If there was a bus reset, block further access
3412 if (STp
->pos_unknown
) {
3419 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3425 if (STp
->write_prot
) {
3430 /* Write must be integral number of blocks */
3431 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3432 printk(KERN_ERR
"%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3433 name
, count
, STp
->block_size
<1024?
3434 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3439 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3440 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3441 name
, STp
->first_frame_position
);
3446 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3447 STp
->door_locked
= ST_LOCKED_AUTO
;
3449 STps
= &(STp
->ps
[STp
->partition
]);
3451 if (STps
->rw
== ST_READING
) {
3453 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3454 STps
->drv_file
, STps
->drv_block
);
3456 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3461 if (STps
->rw
!= ST_WRITING
) {
3462 /* Are we totally rewriting this tape? */
3463 if (!STp
->header_ok
||
3464 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3465 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3466 STp
->wrt_pass_cntr
++;
3468 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3469 name
, STp
->wrt_pass_cntr
);
3471 osst_reset_header(STp
, &SRpnt
);
3472 STps
->drv_file
= STps
->drv_block
= 0;
3474 /* Do we know where we'll be writing on the tape? */
3476 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3477 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3478 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3479 STps
->drv_file
= STp
->filemark_cnt
;
3480 STps
->drv_block
= 0;
3483 /* We have no idea where the tape is positioned - give up */
3486 "%s:D: Cannot write at indeterminate position.\n", name
);
3492 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3493 STp
->filemark_cnt
= STps
->drv_file
;
3494 STp
->last_mark_ppos
=
3495 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3497 "%s:W: Overwriting file %d with old write pass counter %d\n",
3498 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3500 "%s:W: may lead to stale data being accepted on reading back!\n",
3504 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3505 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3511 if (!STp
->header_ok
) {
3513 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3519 if ((STp
->buffer
)->writing
) {
3520 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3521 osst_write_behind_check(STp
);
3522 if ((STp
->buffer
)->syscall_result
) {
3525 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3526 (STp
->buffer
)->midlevel_result
);
3528 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3529 STps
->eof
= ST_EOM_OK
;
3531 STps
->eof
= ST_EOM_ERROR
;
3534 if (STps
->eof
== ST_EOM_OK
) {
3538 else if (STps
->eof
== ST_EOM_ERROR
) {
3543 /* Check the buffer readability in cases where copy_user might catch
3544 the problems after some tape movement. */
3545 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3546 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3551 if (!STm
->do_buffer_writes
) {
3552 write_threshold
= 1;
3555 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3556 if (!STm
->do_async_writes
)
3562 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3563 name
, (int) count
, STps
->drv_file
, STps
->drv_block
,
3564 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3567 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3570 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3571 (STp
->buffer
)->buffer_bytes
;
3572 if (do_count
> count
)
3575 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3581 blks
= do_count
/ STp
->block_size
;
3582 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3584 i
= osst_write_frame(STp
, &SRpnt
, 1);
3586 if (i
== (-ENOSPC
)) {
3587 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3588 if (transfer
<= do_count
) {
3589 filp
->f_pos
+= do_count
- transfer
;
3590 count
-= do_count
- transfer
;
3591 if (STps
->drv_block
>= 0) {
3592 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3594 STps
->eof
= ST_EOM_OK
;
3595 retval
= (-ENOSPC
); /* EOM within current request */
3598 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3599 name
, (int) transfer
);
3603 STps
->eof
= ST_EOM_ERROR
;
3604 STps
->drv_block
= (-1); /* Too cautious? */
3605 retval
= (-EIO
); /* EOM for old data */
3608 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3616 if (SRpnt
!= NULL
) {
3617 osst_release_request(SRpnt
);
3620 STp
->buffer
->buffer_bytes
= 0;
3623 retval
= total
- count
;
3627 filp
->f_pos
+= do_count
;
3628 b_point
+= do_count
;
3630 if (STps
->drv_block
>= 0) {
3631 STps
->drv_block
+= blks
;
3633 STp
->buffer
->buffer_bytes
= 0;
3635 } /* end while write threshold exceeded */
3639 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3644 blks
= count
/ STp
->block_size
;
3645 STp
->logical_blk_num
+= blks
;
3646 if (STps
->drv_block
>= 0) {
3647 STps
->drv_block
+= blks
;
3649 filp
->f_pos
+= count
;
3653 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3654 retval
= (STp
->buffer
)->syscall_result
;
3658 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3659 /* Schedule an asynchronous write */
3660 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3661 STp
->block_size
) * STp
->block_size
;
3662 STp
->dirty
= !((STp
->buffer
)->writing
==
3663 (STp
->buffer
)->buffer_bytes
);
3665 i
= osst_write_frame(STp
, &SRpnt
, 0);
3670 SRpnt
= NULL
; /* Prevent releasing this request! */
3672 STps
->at_sm
&= (total
== 0);
3674 STps
->eof
= ST_NOEOF
;
3679 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3681 mutex_unlock(&STp
->lock
);
3688 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3690 ssize_t total
, retval
= 0;
3691 ssize_t i
, transfer
;
3693 struct st_modedef
* STm
;
3694 struct st_partstat
* STps
;
3695 struct osst_request
* SRpnt
= NULL
;
3696 struct osst_tape
* STp
= filp
->private_data
;
3697 char * name
= tape_name(STp
);
3700 if (mutex_lock_interruptible(&STp
->lock
))
3701 return (-ERESTARTSYS
);
3704 * If we are in the middle of error recovery, don't let anyone
3705 * else try and use this device. Also, if error recovery fails, it
3706 * may try and take the device offline, in which case all further
3707 * access to the device is prohibited.
3709 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3714 if (STp
->ready
!= ST_READY
) {
3715 if (STp
->ready
== ST_NO_TAPE
)
3716 retval
= (-ENOMEDIUM
);
3721 STm
= &(STp
->modes
[STp
->current_mode
]);
3722 if (!STm
->defined
) {
3728 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3733 /* Must have initialized medium */
3734 if (!STp
->header_ok
) {
3739 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3740 STp
->door_locked
= ST_LOCKED_AUTO
;
3742 STps
= &(STp
->ps
[STp
->partition
]);
3743 if (STps
->rw
== ST_WRITING
) {
3744 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3748 /* FIXME -- this may leave the tape without EOD and up2date headers */
3751 if ((count
% STp
->block_size
) != 0) {
3753 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3754 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3758 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3759 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3760 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3762 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3763 STps
->eof
>= ST_EOD_1
) {
3764 if (STps
->eof
< ST_EOD
) {
3769 retval
= (-EIO
); /* EOM or Blank Check */
3773 /* Check the buffer writability before any tape movement. Don't alter
3775 if (copy_from_user(&i
, buf
, 1) != 0 ||
3776 copy_to_user (buf
, &i
, 1) != 0 ||
3777 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3778 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3783 /* Loop until enough data in buffer or a special condition found */
3784 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3786 /* Get new data if the buffer is empty */
3787 if ((STp
->buffer
)->buffer_bytes
== 0) {
3788 if (STps
->eof
== ST_FM_HIT
)
3790 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3791 if (special
< 0) { /* No need to continue read */
3792 STp
->frame_in_buffer
= 0;
3798 /* Move the data from driver buffer to user buffer */
3799 if ((STp
->buffer
)->buffer_bytes
> 0) {
3801 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3802 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3803 STps
->eof
, (STp
->buffer
)->buffer_bytes
, (int) (count
- total
));
3805 /* force multiple of block size, note block_size may have been adjusted */
3806 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3807 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3808 STp
->block_size
) * STp
->block_size
;
3810 if (transfer
== 0) {
3812 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3813 name
, count
, STp
->block_size
< 1024?
3814 STp
->block_size
:STp
->block_size
/1024,
3815 STp
->block_size
<1024?'b':'k');
3818 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3823 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3824 STps
->drv_block
+= transfer
/ STp
->block_size
;
3825 filp
->f_pos
+= transfer
;
3830 if ((STp
->buffer
)->buffer_bytes
== 0) {
3833 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3834 name
, STp
->frame_seq_number
);
3836 STp
->frame_in_buffer
= 0;
3837 STp
->frame_seq_number
++; /* frame to look for next time */
3839 } /* for (total = 0, special = 0; total < count && !special; ) */
3841 /* Change the eof state if no data from tape or buffer */
3843 if (STps
->eof
== ST_FM_HIT
) {
3844 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3845 STps
->drv_block
= 0;
3846 if (STps
->drv_file
>= 0)
3849 else if (STps
->eof
== ST_EOD_1
) {
3850 STps
->eof
= ST_EOD_2
;
3851 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3853 STps
->drv_block
= 0;
3855 else if (STps
->eof
== ST_EOD_2
)
3858 else if (STps
->eof
== ST_FM
)
3859 STps
->eof
= ST_NOEOF
;
3864 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3866 mutex_unlock(&STp
->lock
);
3872 /* Set the driver options */
3873 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3876 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3877 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3878 STm
->do_read_ahead
);
3880 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3881 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3883 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3884 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3885 STp
->scsi2_logical
);
3887 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3890 "%s:D: debugging: %d\n",
3896 static int osst_set_options(struct osst_tape
*STp
, long options
)
3900 struct st_modedef
* STm
;
3901 char * name
= tape_name(STp
);
3903 STm
= &(STp
->modes
[STp
->current_mode
]);
3904 if (!STm
->defined
) {
3905 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3909 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3910 name
, STp
->current_mode
);
3914 code
= options
& MT_ST_OPTIONS
;
3915 if (code
== MT_ST_BOOLEANS
) {
3916 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3917 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3918 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3919 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3920 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3921 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3922 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3923 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3924 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3925 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3926 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3927 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3928 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3930 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3932 osst_log_options(STp
, STm
, name
);
3934 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3935 value
= (code
== MT_ST_SETBOOLEANS
);
3936 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3937 STm
->do_buffer_writes
= value
;
3938 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3939 STm
->do_async_writes
= value
;
3940 if ((options
& MT_ST_DEF_WRITES
) != 0)
3941 STm
->defaults_for_writes
= value
;
3942 if ((options
& MT_ST_READ_AHEAD
) != 0)
3943 STm
->do_read_ahead
= value
;
3944 if ((options
& MT_ST_TWO_FM
) != 0)
3945 STp
->two_fm
= value
;
3946 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3947 STp
->fast_mteom
= value
;
3948 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3949 STp
->do_auto_lock
= value
;
3950 if ((options
& MT_ST_CAN_BSR
) != 0)
3951 STp
->can_bsr
= value
;
3952 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3953 STp
->omit_blklims
= value
;
3954 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3955 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3956 STp
->can_partitions
= value
;
3957 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3958 STp
->scsi2_logical
= value
;
3959 if ((options
& MT_ST_SYSV
) != 0)
3962 if ((options
& MT_ST_DEBUGGING
) != 0)
3965 osst_log_options(STp
, STm
, name
);
3967 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3968 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3969 if (value
< 1 || value
> osst_buffer_size
) {
3970 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3974 STp
->write_threshold
= value
;
3975 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3978 else if (code
== MT_ST_DEF_BLKSIZE
) {
3979 value
= (options
& ~MT_ST_OPTIONS
);
3980 if (value
== ~MT_ST_OPTIONS
) {
3981 STm
->default_blksize
= (-1);
3982 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3985 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3986 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3990 STm
->default_blksize
= value
;
3991 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3992 name
, STm
->default_blksize
);
3995 else if (code
== MT_ST_TIMEOUTS
) {
3996 value
= (options
& ~MT_ST_OPTIONS
);
3997 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
3998 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
3999 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
4000 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
4003 STp
->timeout
= value
* HZ
;
4004 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
4007 else if (code
== MT_ST_DEF_OPTIONS
) {
4008 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
4009 value
= (options
& MT_ST_CLEAR_DEFAULT
);
4010 if (code
== MT_ST_DEF_DENSITY
) {
4011 if (value
== MT_ST_CLEAR_DEFAULT
) {
4012 STm
->default_density
= (-1);
4013 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
4016 STm
->default_density
= value
& 0xff;
4017 printk(KERN_INFO
"%s:I: Density default set to %x\n",
4018 name
, STm
->default_density
);
4021 else if (code
== MT_ST_DEF_DRVBUFFER
) {
4022 if (value
== MT_ST_CLEAR_DEFAULT
) {
4023 STp
->default_drvbuffer
= 0xff;
4024 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
4027 STp
->default_drvbuffer
= value
& 7;
4028 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
4029 name
, STp
->default_drvbuffer
);
4032 else if (code
== MT_ST_DEF_COMPRESSION
) {
4033 if (value
== MT_ST_CLEAR_DEFAULT
) {
4034 STm
->default_compression
= ST_DONT_TOUCH
;
4035 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
4038 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
4039 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
4051 /* Internal ioctl function */
4052 static int osst_int_ioctl(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
4053 unsigned int cmd_in
, unsigned long arg
)
4057 int i
, ioctl_result
;
4059 unsigned char cmd
[MAX_COMMAND_SIZE
];
4060 struct osst_request
* SRpnt
= * aSRpnt
;
4061 struct st_partstat
* STps
;
4062 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
4063 int datalen
= 0, direction
= DMA_NONE
;
4064 char * name
= tape_name(STp
);
4066 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
4067 if (STp
->ready
== ST_NO_TAPE
)
4068 return (-ENOMEDIUM
);
4072 timeout
= STp
->long_timeout
;
4073 STps
= &(STp
->ps
[STp
->partition
]);
4074 fileno
= STps
->drv_file
;
4075 blkno
= STps
->drv_block
;
4076 at_sm
= STps
->at_sm
;
4077 frame_seq_numbr
= STp
->frame_seq_number
;
4078 logical_blk_num
= STp
->logical_blk_num
;
4080 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4083 chg_eof
= 0; /* Changed from the FSF after this */
4087 if (STp
->linux_media
)
4088 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
4090 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
4094 at_sm
&= (arg
== 0);
4098 chg_eof
= 0; /* Changed from the FSF after this */
4102 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
4105 blkno
= (-1); /* We can't know the block number */
4106 at_sm
&= (arg
== 0);
4113 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
4114 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
4116 if (cmd_in
== MTFSR
) {
4117 logical_blk_num
+= arg
;
4118 if (blkno
>= 0) blkno
+= arg
;
4121 logical_blk_num
-= arg
;
4122 if (blkno
>= 0) blkno
-= arg
;
4124 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
4125 fileno
= STps
->drv_file
;
4126 blkno
= STps
->drv_block
;
4127 at_sm
&= (arg
== 0);
4132 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4133 cmd
[2] = (arg
>> 16);
4134 cmd
[3] = (arg
>> 8);
4138 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4139 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4142 blkno
= fileno
= (-1);
4148 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4150 cmd
[2] = (ltmp
>> 16);
4151 cmd
[3] = (ltmp
>> 8);
4157 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4158 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4163 blkno
= fileno
= (-1);
4168 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4169 STp
->write_type
= OS_WRITE_DATA
;
4170 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4175 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4177 for (i
=0; i
<arg
; i
++)
4178 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4179 if (fileno
>= 0) fileno
+= arg
;
4180 if (blkno
>= 0) blkno
= 0;
4184 if (STp
->write_prot
)
4188 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4189 if (cmd_in
== MTWSM
)
4191 cmd
[2] = (arg
>> 16);
4192 cmd
[3] = (arg
>> 8);
4194 timeout
= STp
->timeout
;
4197 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4198 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4203 at_sm
= (cmd_in
== MTWSM
);
4209 cmd
[0] = START_STOP
;
4210 cmd
[1] = 1; /* Don't wait for completion */
4211 if (cmd_in
== MTLOAD
) {
4212 if (STp
->ready
== ST_NO_TAPE
)
4213 cmd
[4] = 4; /* open tray */
4215 cmd
[4] = 1; /* load */
4217 if (cmd_in
== MTRETEN
)
4218 cmd
[4] = 3; /* retension then mount */
4219 if (cmd_in
== MTOFFL
)
4220 cmd
[4] = 4; /* rewind then eject */
4221 timeout
= STp
->timeout
;
4226 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4229 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4232 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4235 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4240 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4245 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4247 return 0; /* Should do something ? */
4252 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4254 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4255 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4256 ioctl_result
= -EIO
;
4259 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4261 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4263 ioctl_result
= -EIO
;
4266 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4267 fileno
= STp
->filemark_cnt
;
4272 if (STp
->write_prot
)
4274 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4275 i
= osst_write_eod(STp
, &SRpnt
);
4276 if (i
< ioctl_result
) ioctl_result
= i
;
4277 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4278 if (i
< ioctl_result
) ioctl_result
= i
;
4279 fileno
= blkno
= at_sm
= 0 ;
4283 cmd
[0] = REZERO_UNIT
; /* rewind */
4287 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4289 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4292 case MTSETBLK
: /* Set block length */
4293 if ((STps
->drv_block
== 0 ) &&
4295 ((STp
->buffer
)->buffer_bytes
== 0) &&
4296 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4297 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4298 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4300 * Only allowed to change the block size if you opened the
4301 * device at the beginning of a file before writing anything.
4302 * Note, that when reading, changing block_size is futile,
4303 * as the size used when writing overrides it.
4305 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4306 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4307 name
, STp
->block_size
);
4310 case MTSETDENSITY
: /* Set tape density */
4311 case MTSETDRVBUFFER
: /* Set drive buffering */
4312 case SET_DENS_AND_BLK
: /* Set density and block size */
4314 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4315 return (-EIO
); /* Not allowed if data in buffer */
4316 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4317 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4318 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4319 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4320 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4321 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4324 return 0; /* FIXME silently ignore if block size didn't change */
4330 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4332 ioctl_result
= (STp
->buffer
)->syscall_result
;
4336 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4338 return ioctl_result
;
4341 if (!ioctl_result
) { /* SCSI command successful */
4342 STp
->frame_seq_number
= frame_seq_numbr
;
4343 STp
->logical_blk_num
= logical_blk_num
;
4349 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4352 if (!ioctl_result
) { /* success */
4354 if (cmd_in
== MTFSFM
) {
4358 if (cmd_in
== MTBSFM
) {
4362 STps
->drv_block
= blkno
;
4363 STps
->drv_file
= fileno
;
4364 STps
->at_sm
= at_sm
;
4366 if (cmd_in
== MTEOM
)
4368 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4369 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4371 STp
->logical_blk_num
++;
4372 STp
->frame_seq_number
++;
4373 STp
->frame_in_buffer
= 0;
4374 STp
->buffer
->read_pointer
= 0;
4376 else if (cmd_in
== MTFSF
)
4377 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4379 STps
->eof
= ST_NOEOF
;
4381 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4382 STp
->rew_at_close
= 0;
4383 else if (cmd_in
== MTLOAD
) {
4384 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4385 STp
->ps
[i
].rw
= ST_IDLE
;
4386 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4391 if (cmd_in
== MTREW
) {
4392 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4393 if (ioctl_result
> 0)
4397 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4398 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4399 STps
->drv_file
= STps
->drv_block
= -1;
4401 STps
->drv_file
= STps
->drv_block
= 0;
4402 STps
->eof
= ST_NOEOF
;
4403 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4404 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4405 STps
->drv_file
= STps
->drv_block
= -1;
4407 STps
->drv_file
= STp
->filemark_cnt
;
4408 STps
->drv_block
= 0;
4411 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4412 STps
->drv_file
= STps
->drv_block
= (-1);
4413 STps
->eof
= ST_NOEOF
;
4415 } else if (cmd_in
== MTERASE
) {
4417 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4418 if (SRpnt
->sense
[2] & 0x40) {
4419 STps
->eof
= ST_EOM_OK
;
4420 STps
->drv_block
= 0;
4423 STps
->eof
= ST_NOEOF
;
4425 if ((SRpnt
->sense
[2] & 0x0f) == BLANK_CHECK
)
4428 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4429 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4433 return ioctl_result
;
4437 /* Open the device */
4438 static int __os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4440 unsigned short flags
;
4441 int i
, b_size
, new_session
= 0, retval
= 0;
4442 unsigned char cmd
[MAX_COMMAND_SIZE
];
4443 struct osst_request
* SRpnt
= NULL
;
4444 struct osst_tape
* STp
;
4445 struct st_modedef
* STm
;
4446 struct st_partstat
* STps
;
4448 int dev
= TAPE_NR(inode
);
4449 int mode
= TAPE_MODE(inode
);
4452 * We really want to do nonseekable_open(inode, filp); here, but some
4453 * versions of tar incorrectly call lseek on tapes and bail out if that
4454 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4456 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4458 write_lock(&os_scsi_tapes_lock
);
4459 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4460 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4461 write_unlock(&os_scsi_tapes_lock
);
4465 name
= tape_name(STp
);
4468 write_unlock(&os_scsi_tapes_lock
);
4470 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4474 if (scsi_device_get(STp
->device
)) {
4475 write_unlock(&os_scsi_tapes_lock
);
4477 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4481 filp
->private_data
= STp
;
4483 write_unlock(&os_scsi_tapes_lock
);
4484 STp
->rew_at_close
= TAPE_REWIND(inode
);
4486 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4490 if (mode
!= STp
->current_mode
) {
4493 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4494 name
, STp
->current_mode
, mode
);
4497 STp
->current_mode
= mode
;
4499 STm
= &(STp
->modes
[STp
->current_mode
]);
4501 flags
= filp
->f_flags
;
4502 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4504 STp
->raw
= TAPE_IS_RAW(inode
);
4508 /* Allocate data segments for this device's tape buffer */
4509 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4510 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4511 retval
= (-EOVERFLOW
);
4514 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4515 for (i
= 0, b_size
= 0;
4516 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4517 b_size
+= STp
->buffer
->sg
[i
++].length
);
4518 STp
->buffer
->aux
= (os_aux_t
*) (page_address(sg_page(&STp
->buffer
->sg
[i
])) + OS_DATA_SIZE
- b_size
);
4520 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4521 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4522 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4523 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4526 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4527 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4531 STp
->buffer
->writing
= 0;
4532 STp
->buffer
->syscall_result
= 0;
4534 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4535 STps
= &(STp
->ps
[i
]);
4538 STp
->ready
= ST_READY
;
4540 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4543 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4544 cmd
[0] = TEST_UNIT_READY
;
4546 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4548 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4551 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4552 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4553 SRpnt
->sense
[12] == 4 ) {
4555 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sense
[13]);
4557 if (filp
->f_flags
& O_NONBLOCK
) {
4561 if (SRpnt
->sense
[13] == 2) { /* initialize command required (LOAD) */
4562 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4563 cmd
[0] = START_STOP
;
4566 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4567 STp
->timeout
, MAX_RETRIES
, 1);
4569 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sense
[13]==1?15:3) * 60, 0);
4571 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4572 (SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4574 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4578 for (i
=0; i
< 10; i
++) {
4580 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4581 cmd
[0] = TEST_UNIT_READY
;
4583 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4584 STp
->timeout
, MAX_RETRIES
, 1);
4585 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4586 (SRpnt
->sense
[2] & 0x0f) != UNIT_ATTENTION
)
4590 STp
->pos_unknown
= 0;
4591 STp
->partition
= STp
->new_partition
= 0;
4592 if (STp
->can_partitions
)
4593 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4594 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4595 STps
= &(STp
->ps
[i
]);
4596 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4597 STps
->eof
= ST_NOEOF
;
4599 STps
->last_block_valid
= 0;
4600 STps
->drv_block
= 0;
4601 STps
->drv_file
= 0 ;
4604 STp
->recover_count
= 0;
4605 STp
->abort_count
= 0;
4608 * if we have valid headers from before, and the drive/tape seem untouched,
4609 * open without reconfiguring and re-reading the headers
4611 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4612 !SRpnt
->result
&& SRpnt
->sense
[0] == 0) {
4614 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4615 cmd
[0] = MODE_SENSE
;
4617 cmd
[2] = VENDOR_IDENT_PAGE
;
4618 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4620 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4622 if (STp
->buffer
->syscall_result
||
4623 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4624 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4625 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4626 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4628 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4629 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4630 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4631 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4632 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4636 i
= STp
->first_frame_position
;
4637 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4638 if (STp
->door_locked
== ST_UNLOCKED
) {
4639 if (do_door_lock(STp
, 1))
4640 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4642 STp
->door_locked
= ST_LOCKED_AUTO
;
4644 if (!STp
->frame_in_buffer
) {
4645 STp
->block_size
= (STm
->default_blksize
> 0) ?
4646 STm
->default_blksize
: OS_DATA_SIZE
;
4647 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4649 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4651 osst_release_request(SRpnt
);
4655 if (i
!= STp
->first_frame_position
)
4656 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4657 name
, i
, STp
->first_frame_position
);
4663 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4664 (SRpnt
->sense
[2] != 2 || SRpnt
->sense
[12] != 0x3A) ) {
4666 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4667 cmd
[0] = MODE_SELECT
;
4669 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4671 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4672 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4673 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4674 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4675 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4676 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4677 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4678 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4681 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4683 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4687 for (i
=0; i
< 10; i
++) {
4689 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4690 cmd
[0] = TEST_UNIT_READY
;
4692 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4693 STp
->timeout
, MAX_RETRIES
, 1);
4694 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4695 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
)
4698 if ((SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) {
4699 STp
->pos_unknown
= 0;
4700 STp
->partition
= STp
->new_partition
= 0;
4701 if (STp
->can_partitions
)
4702 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4703 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4704 STps
= &(STp
->ps
[i
]);
4706 STps
->eof
= ST_NOEOF
;
4708 STps
->last_block_valid
= 0;
4709 STps
->drv_block
= 0;
4710 STps
->drv_file
= 0 ;
4717 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4718 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4720 if ((STp
->buffer
)->syscall_result
!= 0) {
4721 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4722 (SRpnt
->sense
[0] & 0x70) == 0x70 &&
4723 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4724 SRpnt
->sense
[12] == 0x3a) { /* Check ASC */
4725 STp
->ready
= ST_NO_TAPE
;
4727 STp
->ready
= ST_NOT_READY
;
4728 osst_release_request(SRpnt
);
4730 STp
->density
= 0; /* Clear the erroneous "residue" */
4731 STp
->write_prot
= 0;
4732 STp
->block_size
= 0;
4733 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4734 STp
->partition
= STp
->new_partition
= 0;
4735 STp
->door_locked
= ST_UNLOCKED
;
4739 osst_configure_onstream(STp
, &SRpnt
);
4741 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4742 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4743 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4744 STp
->buffer
->buffer_bytes
=
4745 STp
->buffer
->read_pointer
=
4746 STp
->frame_in_buffer
= 0;
4750 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4751 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4752 (STp
->buffer
)->buffer_blocks
);
4755 if (STp
->drv_write_prot
) {
4756 STp
->write_prot
= 1;
4759 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4761 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4767 if (new_session
) { /* Change the drive parameters for the new mode */
4770 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4772 STp
->density_changed
= STp
->blksize_changed
= 0;
4773 STp
->compression_changed
= 0;
4777 * properly position the tape and check the ADR headers
4779 if (STp
->door_locked
== ST_UNLOCKED
) {
4780 if (do_door_lock(STp
, 1))
4781 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4783 STp
->door_locked
= ST_LOCKED_AUTO
;
4786 osst_analyze_headers(STp
, &SRpnt
);
4788 osst_release_request(SRpnt
);
4795 osst_release_request(SRpnt
);
4796 normalize_buffer(STp
->buffer
);
4799 scsi_device_put(STp
->device
);
4804 /* BKL pushdown: spaghetti avoidance wrapper */
4805 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4810 ret
= __os_scsi_tape_open(inode
, filp
);
4817 /* Flush the tape buffer before close */
4818 static int os_scsi_tape_flush(struct file
* filp
, fl_owner_t id
)
4820 int result
= 0, result2
;
4821 struct osst_tape
* STp
= filp
->private_data
;
4822 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4823 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4824 struct osst_request
* SRpnt
= NULL
;
4825 char * name
= tape_name(STp
);
4827 if (file_count(filp
) > 1)
4830 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4831 STp
->write_type
= OS_WRITE_DATA
;
4832 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4833 if (result
!= 0 && result
!= (-ENOSPC
))
4836 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4840 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4841 name
, (long)(filp
->f_pos
));
4842 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4843 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4846 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4849 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4850 name
, 1+STp
->two_fm
);
4853 else if (!STp
->rew_at_close
) {
4854 STps
= &(STp
->ps
[STp
->partition
]);
4855 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4857 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4858 else if (STps
->eof
== ST_FM_HIT
) {
4859 result
= cross_eof(STp
, &SRpnt
, 0);
4861 if (STps
->drv_file
>= 0)
4863 STps
->drv_block
= 0;
4867 STps
->eof
= ST_NOEOF
;
4870 else if ((STps
->eof
== ST_NOEOF
&&
4871 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4872 STps
->eof
== ST_FM_HIT
) {
4873 if (STps
->drv_file
>= 0)
4875 STps
->drv_block
= 0;
4881 if (STp
->rew_at_close
) {
4882 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4883 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4884 if (result
== 0 && result2
< 0)
4887 if (SRpnt
) osst_release_request(SRpnt
);
4889 if (STp
->abort_count
|| STp
->recover_count
) {
4890 printk(KERN_INFO
"%s:I:", name
);
4891 if (STp
->abort_count
)
4892 printk(" %d unrecovered errors", STp
->abort_count
);
4893 if (STp
->recover_count
)
4894 printk(" %d recovered errors", STp
->recover_count
);
4895 if (STp
->write_count
)
4896 printk(" in %d frames written", STp
->write_count
);
4897 if (STp
->read_count
)
4898 printk(" in %d frames read", STp
->read_count
);
4900 STp
->recover_count
= 0;
4901 STp
->abort_count
= 0;
4903 STp
->write_count
= 0;
4904 STp
->read_count
= 0;
4910 /* Close the device and release it */
4911 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4914 struct osst_tape
* STp
= filp
->private_data
;
4916 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4917 do_door_lock(STp
, 0);
4922 normalize_buffer(STp
->buffer
);
4923 write_lock(&os_scsi_tapes_lock
);
4925 write_unlock(&os_scsi_tapes_lock
);
4927 scsi_device_put(STp
->device
);
4933 /* The ioctl command */
4934 static int osst_ioctl(struct inode
* inode
,struct file
* file
,
4935 unsigned int cmd_in
, unsigned long arg
)
4937 int i
, cmd_nr
, cmd_type
, blk
, retval
= 0;
4938 struct st_modedef
* STm
;
4939 struct st_partstat
* STps
;
4940 struct osst_request
* SRpnt
= NULL
;
4941 struct osst_tape
* STp
= file
->private_data
;
4942 char * name
= tape_name(STp
);
4943 void __user
* p
= (void __user
*)arg
;
4945 if (mutex_lock_interruptible(&STp
->lock
))
4946 return -ERESTARTSYS
;
4949 if (debugging
&& !STp
->in_use
) {
4950 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4955 STm
= &(STp
->modes
[STp
->current_mode
]);
4956 STps
= &(STp
->ps
[STp
->partition
]);
4959 * If we are in the middle of error recovery, don't let anyone
4960 * else try and use this device. Also, if error recovery fails, it
4961 * may try and take the device offline, in which case all further
4962 * access to the device is prohibited.
4964 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4969 cmd_type
= _IOC_TYPE(cmd_in
);
4970 cmd_nr
= _IOC_NR(cmd_in
);
4972 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4973 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4975 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4979 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4984 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
4990 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
4991 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
4996 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
5001 if (!STp
->pos_unknown
) {
5003 if (STps
->eof
== ST_FM_HIT
) {
5004 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
5006 if (STps
->drv_file
>= 0)
5007 STps
->drv_file
+= 1;
5009 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
5011 if (STps
->drv_file
>= 0)
5012 STps
->drv_file
+= 1;
5016 if (mtc
.mt_op
== MTSEEK
) {
5017 /* Old position must be restored if partition will be changed */
5018 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
5021 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
5022 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
5023 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
5024 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
5025 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
5026 mtc
.mt_op
== MTCOMPRESSION
;
5028 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
5036 * If there was a bus reset, block further access
5037 * to this device. If the user wants to rewind the tape,
5038 * then reset the flag and allow access again.
5040 if(mtc
.mt_op
!= MTREW
&&
5041 mtc
.mt_op
!= MTOFFL
&&
5042 mtc
.mt_op
!= MTRETEN
&&
5043 mtc
.mt_op
!= MTERASE
&&
5044 mtc
.mt_op
!= MTSEEK
&&
5045 mtc
.mt_op
!= MTEOM
) {
5050 /* remove this when the midlevel properly clears was_reset */
5051 STp
->device
->was_reset
= 0;
5054 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
5055 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
5056 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
5057 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
5058 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
5061 * The user tells us to move to another position on the tape.
5062 * If we were appending to the tape content, that would leave
5063 * the tape without proper end, in that case write EOD and
5064 * update the header to reflect its position.
5067 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
5068 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
5069 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
5070 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5072 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
5073 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
5074 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5075 i
= osst_write_trailer(STp
, &SRpnt
,
5076 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5078 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5079 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
5080 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5090 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
5091 do_door_lock(STp
, 0); /* Ignore result! */
5093 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
5094 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
5095 retval
= osst_set_options(STp
, mtc
.mt_count
);
5099 if (mtc
.mt_op
== MTSETPART
) {
5100 if (mtc
.mt_count
>= STp
->nbr_partitions
)
5103 STp
->new_partition
= mtc
.mt_count
;
5109 if (mtc
.mt_op
== MTMKPART
) {
5110 if (!STp
->can_partitions
) {
5114 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
5115 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5119 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5120 STp
->ps
[i
].rw
= ST_IDLE
;
5121 STp
->ps
[i
].at_sm
= 0;
5122 STp
->ps
[i
].last_block_valid
= 0;
5124 STp
->partition
= STp
->new_partition
= 0;
5125 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
5126 STps
->drv_block
= STps
->drv_file
= 0;
5131 if (mtc
.mt_op
== MTSEEK
) {
5133 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
5135 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
5136 if (!STp
->can_partitions
)
5137 STp
->ps
[0].rw
= ST_IDLE
;
5142 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
5143 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5148 cross_eof(STp
, &SRpnt
, 0);
5150 if (mtc
.mt_op
== MTCOMPRESSION
)
5151 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5153 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5154 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5155 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5159 if (!STm
->defined
) {
5164 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5169 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5170 struct mtget mt_status
;
5172 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5177 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5178 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5179 mt_status
.mt_dsreg
=
5180 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5181 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5182 mt_status
.mt_blkno
= STps
->drv_block
;
5183 mt_status
.mt_fileno
= STps
->drv_file
;
5184 if (STp
->block_size
!= 0) {
5185 if (STps
->rw
== ST_WRITING
)
5186 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5187 else if (STps
->rw
== ST_READING
)
5188 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5189 STp
->block_size
- 1) / STp
->block_size
;
5192 mt_status
.mt_gstat
= 0;
5193 if (STp
->drv_write_prot
)
5194 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5195 if (mt_status
.mt_blkno
== 0) {
5196 if (mt_status
.mt_fileno
== 0)
5197 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5199 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5201 mt_status
.mt_resid
= STp
->partition
;
5202 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5203 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5204 else if (STps
->eof
>= ST_EOM_OK
)
5205 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5206 if (STp
->density
== 1)
5207 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5208 else if (STp
->density
== 2)
5209 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5210 else if (STp
->density
== 3)
5211 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5212 if (STp
->ready
== ST_READY
)
5213 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5214 if (STp
->ready
== ST_NO_TAPE
)
5215 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5217 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5218 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5219 STp
->drv_buffer
!= 0)
5220 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5222 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5228 STp
->recover_erreg
= 0; /* Clear after read */
5231 } /* End of MTIOCGET */
5233 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5234 struct mtpos mt_pos
;
5236 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5241 blk
= osst_get_frame_position(STp
, &SRpnt
);
5243 blk
= osst_get_sector(STp
, &SRpnt
);
5248 mt_pos
.mt_blkno
= blk
;
5249 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5254 if (SRpnt
) osst_release_request(SRpnt
);
5256 mutex_unlock(&STp
->lock
);
5258 return scsi_ioctl(STp
->device
, cmd_in
, p
);
5261 if (SRpnt
) osst_release_request(SRpnt
);
5263 mutex_unlock(&STp
->lock
);
5268 #ifdef CONFIG_COMPAT
5269 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5271 struct osst_tape
*STp
= file
->private_data
;
5272 struct scsi_device
*sdev
= STp
->device
;
5273 int ret
= -ENOIOCTLCMD
;
5274 if (sdev
->host
->hostt
->compat_ioctl
) {
5276 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5285 /* Memory handling routines */
5287 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5288 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5292 struct osst_buffer
*tb
;
5294 if (from_initialization
)
5295 priority
= GFP_ATOMIC
;
5297 priority
= GFP_KERNEL
;
5299 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5300 tb
= kzalloc(i
, priority
);
5302 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5306 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5307 tb
->use_sg
= max_sg
;
5310 tb
->buffer_size
= 0;
5314 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5315 i
, max_sg
, need_dma
);
5320 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5321 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5323 int segs
, nbr
, max_segs
, b_size
, order
, got
;
5326 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5329 if (STbuffer
->sg_segs
) {
5330 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5331 normalize_buffer(STbuffer
);
5333 /* See how many segments we can use -- need at least two */
5334 nbr
= max_segs
= STbuffer
->use_sg
;
5338 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5340 priority
|= GFP_DMA
;
5342 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5343 big enough to reach the goal (code assumes no segments in place) */
5344 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5345 struct page
*page
= alloc_pages(priority
, order
);
5347 STbuffer
->sg
[0].offset
= 0;
5349 sg_set_page(&STbuffer
->sg
[0], page
, b_size
, 0);
5350 STbuffer
->b_data
= page_address(page
);
5354 if (sg_page(&STbuffer
->sg
[0]) == NULL
) {
5355 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5358 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5359 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5360 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5361 struct page
*page
= alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5362 STbuffer
->sg
[segs
].offset
= 0;
5364 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5367 STbuffer
->buffer_size
= got
;
5369 normalize_buffer(STbuffer
);
5372 sg_set_page(&STbuffer
->sg
[segs
], page
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
, 0);
5373 got
+= STbuffer
->sg
[segs
].length
;
5374 STbuffer
->buffer_size
= got
;
5375 STbuffer
->sg_segs
= ++segs
;
5380 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5381 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5383 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5384 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5385 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5393 /* Release the segments */
5394 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5396 int i
, order
, b_size
;
5398 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5400 for (b_size
= PAGE_SIZE
, order
= 0;
5401 b_size
< STbuffer
->sg
[i
].length
;
5402 b_size
*= 2, order
++);
5404 __free_pages(sg_page(&STbuffer
->sg
[i
]), order
);
5405 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5408 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5409 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5410 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5412 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5416 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5417 negative error code. */
5418 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5420 int i
, cnt
, res
, offset
;
5422 for (i
=0, offset
=st_bp
->buffer_bytes
;
5423 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5424 offset
-= st_bp
->sg
[i
].length
;
5425 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5426 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5429 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5430 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5431 st_bp
->sg
[i
].length
- offset
: do_count
;
5432 res
= copy_from_user(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, ubp
, cnt
);
5436 st_bp
->buffer_bytes
+= cnt
;
5440 if (do_count
) { /* Should never happen */
5441 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5449 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5450 negative error code. */
5451 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5453 int i
, cnt
, res
, offset
;
5455 for (i
=0, offset
=st_bp
->read_pointer
;
5456 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5457 offset
-= st_bp
->sg
[i
].length
;
5458 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5459 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5462 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5463 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5464 st_bp
->sg
[i
].length
- offset
: do_count
;
5465 res
= copy_to_user(ubp
, page_address(sg_page(&st_bp
->sg
[i
])) + offset
, cnt
);
5469 st_bp
->buffer_bytes
-= cnt
;
5470 st_bp
->read_pointer
+= cnt
;
5474 if (do_count
) { /* Should never happen */
5475 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5481 /* Sets the tail of the buffer after fill point to zero.
5482 Returns zero (success) or negative error code. */
5483 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5485 int i
, offset
, do_count
, cnt
;
5487 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5488 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5489 offset
-= st_bp
->sg
[i
].length
;
5490 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5491 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5494 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5495 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5496 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5497 st_bp
->sg
[i
].length
- offset
: do_count
;
5498 memset(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, 0, cnt
);
5502 if (do_count
) { /* Should never happen */
5503 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5509 /* Copy a osst 32K chunk of memory into the buffer.
5510 Returns zero (success) or negative error code. */
5511 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5513 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5515 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5516 cnt
= st_bp
->sg
[i
].length
< do_count
?
5517 st_bp
->sg
[i
].length
: do_count
;
5518 memcpy(page_address(sg_page(&st_bp
->sg
[i
])), ptr
, cnt
);
5522 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5523 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5530 /* Copy a osst 32K chunk of memory from the buffer.
5531 Returns zero (success) or negative error code. */
5532 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5534 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5536 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5537 cnt
= st_bp
->sg
[i
].length
< do_count
?
5538 st_bp
->sg
[i
].length
: do_count
;
5539 memcpy(ptr
, page_address(sg_page(&st_bp
->sg
[i
])), cnt
);
5543 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5544 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5552 /* Module housekeeping */
5554 static void validate_options (void)
5557 osst_max_dev
= max_dev
;
5558 if (write_threshold_kbs
> 0)
5559 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5560 if (osst_write_threshold
> osst_buffer_size
)
5561 osst_write_threshold
= osst_buffer_size
;
5562 if (max_sg_segs
>= OSST_FIRST_SG
)
5563 osst_max_sg_segs
= max_sg_segs
;
5565 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5566 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5571 /* Set the boot options. Syntax: osst=xxx,yyy,...
5572 where xxx is write threshold in 1024 byte blocks,
5573 and yyy is number of s/g segments to use. */
5574 static int __init
osst_setup (char *str
)
5579 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5582 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5583 *parms
[i
].val
= ints
[i
+ 1];
5585 while (stp
!= NULL
) {
5586 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5587 int len
= strlen(parms
[i
].name
);
5588 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5589 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5591 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5595 if (i
>= ARRAY_SIZE(parms
))
5596 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5598 stp
= strchr(stp
, ',');
5607 __setup("osst=", osst_setup
);
5611 static const struct file_operations osst_fops
= {
5612 .owner
= THIS_MODULE
,
5614 .write
= osst_write
,
5615 .ioctl
= osst_ioctl
,
5616 #ifdef CONFIG_COMPAT
5617 .compat_ioctl
= osst_compat_ioctl
,
5619 .open
= os_scsi_tape_open
,
5620 .flush
= os_scsi_tape_flush
,
5621 .release
= os_scsi_tape_close
,
5624 static int osst_supports(struct scsi_device
* SDp
)
5626 struct osst_support_data
{
5630 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5633 static struct osst_support_data support_list
[] = {
5634 /* {"XXX", "Yy-", "", NULL}, example */
5638 struct osst_support_data
*rp
;
5640 /* We are willing to drive OnStream SC-x0 as well as the
5641 * * IDE, ParPort, FireWire, USB variants, if accessible by
5642 * * emulation layer (ide-scsi, usb-storage, ...) */
5644 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5645 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5646 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5647 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5653 * sysfs support for osst driver parameter information
5656 static ssize_t
osst_version_show(struct device_driver
*ddd
, char *buf
)
5658 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5661 static DRIVER_ATTR(version
, S_IRUGO
, osst_version_show
, NULL
);
5663 static int osst_create_sysfs_files(struct device_driver
*sysfs
)
5665 return driver_create_file(sysfs
, &driver_attr_version
);
5668 static void osst_remove_sysfs_files(struct device_driver
*sysfs
)
5670 driver_remove_file(sysfs
, &driver_attr_version
);
5674 * sysfs support for accessing ADR header information
5677 static ssize_t
osst_adr_rev_show(struct device
*dev
,
5678 struct device_attribute
*attr
, char *buf
)
5680 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5683 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5684 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5688 DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5690 static ssize_t
osst_linux_media_version_show(struct device
*dev
,
5691 struct device_attribute
*attr
,
5694 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5697 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5698 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5702 DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5704 static ssize_t
osst_capacity_show(struct device
*dev
,
5705 struct device_attribute
*attr
, char *buf
)
5707 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5710 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5711 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5715 DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5717 static ssize_t
osst_first_data_ppos_show(struct device
*dev
,
5718 struct device_attribute
*attr
,
5721 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5724 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5725 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5729 DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5731 static ssize_t
osst_eod_frame_ppos_show(struct device
*dev
,
5732 struct device_attribute
*attr
,
5735 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5738 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5739 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5743 DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5745 static ssize_t
osst_filemark_cnt_show(struct device
*dev
,
5746 struct device_attribute
*attr
, char *buf
)
5748 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5751 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5752 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5756 DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5758 static struct class *osst_sysfs_class
;
5760 static int osst_sysfs_init(void)
5762 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5763 if (IS_ERR(osst_sysfs_class
)) {
5764 printk(KERN_ERR
"osst :W: Unable to register sysfs class\n");
5765 return PTR_ERR(osst_sysfs_class
);
5771 static void osst_sysfs_destroy(dev_t dev
)
5773 device_destroy(osst_sysfs_class
, dev
);
5776 static int osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5778 struct device
*osst_member
;
5781 osst_member
= device_create(osst_sysfs_class
, device
, dev
, STp
,
5783 if (IS_ERR(osst_member
)) {
5784 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5785 return PTR_ERR(osst_member
);
5788 err
= device_create_file(osst_member
, &dev_attr_ADR_rev
);
5791 err
= device_create_file(osst_member
, &dev_attr_media_version
);
5794 err
= device_create_file(osst_member
, &dev_attr_capacity
);
5797 err
= device_create_file(osst_member
, &dev_attr_BOT_frame
);
5800 err
= device_create_file(osst_member
, &dev_attr_EOD_frame
);
5803 err
= device_create_file(osst_member
, &dev_attr_file_count
);
5810 osst_sysfs_destroy(dev
);
5814 static void osst_sysfs_cleanup(void)
5816 class_destroy(osst_sysfs_class
);
5820 * osst startup / cleanup code
5823 static int osst_probe(struct device
*dev
)
5825 struct scsi_device
* SDp
= to_scsi_device(dev
);
5826 struct osst_tape
* tpnt
;
5827 struct st_modedef
* STm
;
5828 struct st_partstat
* STps
;
5829 struct osst_buffer
* buffer
;
5830 struct gendisk
* drive
;
5831 int i
, dev_num
, err
= -ENODEV
;
5833 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5836 drive
= alloc_disk(1);
5838 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5842 /* if this is the first attach, build the infrastructure */
5843 write_lock(&os_scsi_tapes_lock
);
5844 if (os_scsi_tapes
== NULL
) {
5846 (struct osst_tape
**)kmalloc(osst_max_dev
* sizeof(struct osst_tape
*),
5848 if (os_scsi_tapes
== NULL
) {
5849 write_unlock(&os_scsi_tapes_lock
);
5850 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5853 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5856 if (osst_nr_dev
>= osst_max_dev
) {
5857 write_unlock(&os_scsi_tapes_lock
);
5858 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5862 /* find a free minor number */
5863 for (i
=0; os_scsi_tapes
[i
] && i
<osst_max_dev
; i
++);
5864 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5867 /* allocate a struct osst_tape for this device */
5868 tpnt
= kzalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5870 write_unlock(&os_scsi_tapes_lock
);
5871 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5875 /* allocate a buffer for this device */
5876 i
= SDp
->host
->sg_tablesize
;
5877 if (osst_max_sg_segs
< i
)
5878 i
= osst_max_sg_segs
;
5879 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5880 if (buffer
== NULL
) {
5881 write_unlock(&os_scsi_tapes_lock
);
5882 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5886 os_scsi_tapes
[dev_num
] = tpnt
;
5887 tpnt
->buffer
= buffer
;
5889 drive
->private_data
= &tpnt
->driver
;
5890 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5891 tpnt
->driver
= &osst_template
;
5892 tpnt
->drive
= drive
;
5894 tpnt
->capacity
= 0xfffff;
5896 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5897 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5899 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5900 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5901 tpnt
->can_partitions
= 0;
5902 tpnt
->two_fm
= OSST_TWO_FM
;
5903 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5904 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5905 tpnt
->write_threshold
= osst_write_threshold
;
5906 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5907 tpnt
->partition
= 0;
5908 tpnt
->new_partition
= 0;
5909 tpnt
->nbr_partitions
= 0;
5910 tpnt
->min_block
= 512;
5911 tpnt
->max_block
= OS_DATA_SIZE
;
5912 tpnt
->timeout
= OSST_TIMEOUT
;
5913 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5915 /* Recognize OnStream tapes */
5916 /* We don't need to test for OnStream, as this has been done in detect () */
5917 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5918 tpnt
->omit_blklims
= 1;
5920 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5921 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5922 tpnt
->frame_in_buffer
= 0;
5923 tpnt
->header_ok
= 0;
5924 tpnt
->linux_media
= 0;
5925 tpnt
->header_cache
= NULL
;
5927 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5928 STm
= &(tpnt
->modes
[i
]);
5930 STm
->sysv
= OSST_SYSV
;
5931 STm
->defaults_for_writes
= 0;
5932 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5933 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5934 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5935 STm
->default_compression
= ST_DONT_TOUCH
;
5936 STm
->default_blksize
= 512;
5937 STm
->default_density
= (-1); /* No forced density */
5940 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5941 STps
= &(tpnt
->ps
[i
]);
5943 STps
->eof
= ST_NOEOF
;
5945 STps
->last_block_valid
= 0;
5946 STps
->drv_block
= (-1);
5947 STps
->drv_file
= (-1);
5950 tpnt
->current_mode
= 0;
5951 tpnt
->modes
[0].defined
= 1;
5952 tpnt
->modes
[2].defined
= 1;
5953 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5955 mutex_init(&tpnt
->lock
);
5957 write_unlock(&os_scsi_tapes_lock
);
5963 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5965 goto out_free_buffer
;
5967 /* No-rewind entry */
5968 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5969 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5971 goto out_free_sysfs1
;
5974 sdev_printk(KERN_INFO
, SDp
,
5975 "osst :I: Attached OnStream %.5s tape as %s\n",
5976 SDp
->model
, tape_name(tpnt
));
5981 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, dev_num
));
5989 static int osst_remove(struct device
*dev
)
5991 struct scsi_device
* SDp
= to_scsi_device(dev
);
5992 struct osst_tape
* tpnt
;
5995 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
5998 write_lock(&os_scsi_tapes_lock
);
5999 for(i
=0; i
< osst_max_dev
; i
++) {
6000 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
6001 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
6002 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
6003 tpnt
->device
= NULL
;
6004 put_disk(tpnt
->drive
);
6005 os_scsi_tapes
[i
] = NULL
;
6007 write_unlock(&os_scsi_tapes_lock
);
6008 vfree(tpnt
->header_cache
);
6010 normalize_buffer(tpnt
->buffer
);
6011 kfree(tpnt
->buffer
);
6017 write_unlock(&os_scsi_tapes_lock
);
6021 static int __init
init_osst(void)
6025 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
6029 err
= osst_sysfs_init();
6033 err
= register_chrdev(OSST_MAJOR
, "osst", &osst_fops
);
6035 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
6039 err
= scsi_register_driver(&osst_template
.gendrv
);
6041 goto err_out_chrdev
;
6043 err
= osst_create_sysfs_files(&osst_template
.gendrv
);
6045 goto err_out_scsidrv
;
6050 scsi_unregister_driver(&osst_template
.gendrv
);
6052 unregister_chrdev(OSST_MAJOR
, "osst");
6054 osst_sysfs_cleanup();
6058 static void __exit
exit_osst (void)
6061 struct osst_tape
* STp
;
6063 osst_remove_sysfs_files(&osst_template
.gendrv
);
6064 scsi_unregister_driver(&osst_template
.gendrv
);
6065 unregister_chrdev(OSST_MAJOR
, "osst");
6066 osst_sysfs_cleanup();
6068 if (os_scsi_tapes
) {
6069 for (i
=0; i
< osst_max_dev
; ++i
) {
6070 if (!(STp
= os_scsi_tapes
[i
])) continue;
6071 /* This is defensive, supposed to happen during detach */
6072 vfree(STp
->header_cache
);
6074 normalize_buffer(STp
->buffer
);
6077 put_disk(STp
->drive
);
6080 kfree(os_scsi_tapes
);
6082 printk(KERN_INFO
"osst :I: Unloaded.\n");
6085 module_init(init_osst
);
6086 module_exit(exit_osst
);