2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid
= "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27 static const char * osst_version
= "0.99.4";
29 /* The "failure to reconnect" firmware bug */
30 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31 #define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
34 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
41 #include <linux/slab.h>
42 #include <linux/init.h>
43 #include <linux/string.h>
44 #include <linux/errno.h>
45 #include <linux/mtio.h>
46 #include <linux/ioctl.h>
47 #include <linux/fcntl.h>
48 #include <linux/spinlock.h>
49 #include <linux/vmalloc.h>
50 #include <linux/blkdev.h>
51 #include <linux/moduleparam.h>
52 #include <linux/delay.h>
53 #include <linux/jiffies.h>
54 #include <linux/mutex.h>
55 #include <asm/uaccess.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 DEFINE_MUTEX(osst_int_mutex
);
83 static int max_dev
= 0;
84 static int write_threshold_kbs
= 0;
85 static int max_sg_segs
= 0;
88 MODULE_AUTHOR("Willem Riede");
89 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
90 MODULE_LICENSE("GPL");
91 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR
);
92 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE
);
94 module_param(max_dev
, int, 0444);
95 MODULE_PARM_DESC(max_dev
, "Maximum number of OnStream Tape Drives to attach (4)");
97 module_param(write_threshold_kbs
, int, 0644);
98 MODULE_PARM_DESC(write_threshold_kbs
, "Asynchronous write threshold (KB; 32)");
100 module_param(max_sg_segs
, int, 0644);
101 MODULE_PARM_DESC(max_sg_segs
, "Maximum number of scatter/gather segments to use (9)");
103 static struct osst_dev_parm
{
106 } parms
[] __initdata
= {
107 { "max_dev", &max_dev
},
108 { "write_threshold_kbs", &write_threshold_kbs
},
109 { "max_sg_segs", &max_sg_segs
}
113 /* Some default definitions have been moved to osst_options.h */
114 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
115 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
117 /* The buffer size should fit into the 24 bits for length in the
118 6-byte SCSI read and write commands. */
119 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
120 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
124 static int debugging
= 1;
125 /* uncomment define below to test error recovery */
126 // #define OSST_INJECT_ERRORS 1
129 /* Do not retry! The drive firmware already retries when appropriate,
130 and when it tries to tell us something, we had better listen... */
131 #define MAX_RETRIES 0
133 #define NO_TAPE NOT_READY
135 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
136 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
137 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
139 #define OSST_TIMEOUT (200 * HZ)
140 #define OSST_LONG_TIMEOUT (1800 * HZ)
142 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
143 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
144 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
145 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
147 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
149 #define SET_DENS_AND_BLK 0x10001
151 static int osst_buffer_size
= OSST_BUFFER_SIZE
;
152 static int osst_write_threshold
= OSST_WRITE_THRESHOLD
;
153 static int osst_max_sg_segs
= OSST_MAX_SG
;
154 static int osst_max_dev
= OSST_MAX_TAPES
;
155 static int osst_nr_dev
;
157 static struct osst_tape
**os_scsi_tapes
= NULL
;
158 static DEFINE_RWLOCK(os_scsi_tapes_lock
);
160 static int modes_defined
= 0;
162 static struct osst_buffer
*new_tape_buffer(int, int, int);
163 static int enlarge_buffer(struct osst_buffer
*, int);
164 static void normalize_buffer(struct osst_buffer
*);
165 static int append_to_buffer(const char __user
*, struct osst_buffer
*, int);
166 static int from_buffer(struct osst_buffer
*, char __user
*, int);
167 static int osst_zero_buffer_tail(struct osst_buffer
*);
168 static int osst_copy_to_buffer(struct osst_buffer
*, unsigned char *);
169 static int osst_copy_from_buffer(struct osst_buffer
*, unsigned char *);
171 static int osst_probe(struct device
*);
172 static int osst_remove(struct device
*);
174 static struct scsi_driver osst_template
= {
177 .owner
= THIS_MODULE
,
179 .remove
= osst_remove
,
183 static int osst_int_ioctl(struct osst_tape
*STp
, struct osst_request
** aSRpnt
,
184 unsigned int cmd_in
, unsigned long arg
);
186 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int frame
, int skip
);
188 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
190 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
192 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
);
194 static inline char *tape_name(struct osst_tape
*tape
)
196 return tape
->drive
->disk_name
;
199 /* Routines that handle the interaction with mid-layer SCSI routines */
202 /* Normalize Sense */
203 static void osst_analyze_sense(struct osst_request
*SRpnt
, struct st_cmdstatus
*s
)
206 const u8
*sense
= SRpnt
->sense
;
208 s
->have_sense
= scsi_normalize_sense(SRpnt
->sense
,
209 SCSI_SENSE_BUFFERSIZE
, &s
->sense_hdr
);
215 scsi_get_sense_info_fld(sense
, SCSI_SENSE_BUFFERSIZE
, &s
->uremainder64
);
216 switch (sense
[0] & 0x7f) {
221 s
->flags
= sense
[2] & 0xe0;
227 ucp
= scsi_sense_desc_find(sense
, SCSI_SENSE_BUFFERSIZE
, 4);
228 s
->flags
= ucp
? (ucp
[3] & 0xe0) : 0;
234 /* Convert the result to success code */
235 static int osst_chk_result(struct osst_tape
* STp
, struct osst_request
* SRpnt
)
237 char *name
= tape_name(STp
);
238 int result
= SRpnt
->result
;
239 u8
* sense
= SRpnt
->sense
, scode
;
243 struct st_cmdstatus
*cmdstatp
;
248 cmdstatp
= &STp
->buffer
->cmdstat
;
249 osst_analyze_sense(SRpnt
, cmdstatp
);
251 if (cmdstatp
->have_sense
)
252 scode
= STp
->buffer
->cmdstat
.sense_hdr
.sense_key
;
257 printk(OSST_DEB_MSG
"%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
259 SRpnt
->cmd
[0], SRpnt
->cmd
[1], SRpnt
->cmd
[2],
260 SRpnt
->cmd
[3], SRpnt
->cmd
[4], SRpnt
->cmd
[5]);
261 if (scode
) printk(OSST_DEB_MSG
"%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
262 name
, scode
, sense
[12], sense
[13]);
263 if (cmdstatp
->have_sense
)
264 __scsi_print_sense(STp
->device
, name
,
265 SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
269 if (cmdstatp
->have_sense
&& (
271 scode
!= RECOVERED_ERROR
&&
272 /* scode != UNIT_ATTENTION && */
273 scode
!= BLANK_CHECK
&&
274 scode
!= VOLUME_OVERFLOW
&&
275 SRpnt
->cmd
[0] != MODE_SENSE
&&
276 SRpnt
->cmd
[0] != TEST_UNIT_READY
)) { /* Abnormal conditions for tape */
277 if (cmdstatp
->have_sense
) {
278 printk(KERN_WARNING
"%s:W: Command with sense data:\n", name
);
279 __scsi_print_sense(STp
->device
, name
,
280 SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
283 static int notyetprinted
= 1;
286 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
287 name
, result
, driver_byte(result
),
292 "%s:I: This warning may be caused by your scsi controller,\n", name
);
294 "%s:I: it has been reported with some Buslogic cards.\n", name
);
298 STp
->pos_unknown
|= STp
->device
->was_reset
;
300 if (cmdstatp
->have_sense
&& scode
== RECOVERED_ERROR
) {
301 STp
->recover_count
++;
302 STp
->recover_erreg
++;
305 if (SRpnt
->cmd
[0] == READ_6
)
307 else if (SRpnt
->cmd
[0] == WRITE_6
)
311 printk(OSST_DEB_MSG
"%s:D: Recovered %s error (%d).\n", name
, stp
,
315 if ((sense
[2] & 0xe0) == 0)
322 /* Wakeup from interrupt */
323 static void osst_end_async(struct request
*req
, int update
)
325 struct osst_request
*SRpnt
= req
->end_io_data
;
326 struct osst_tape
*STp
= SRpnt
->stp
;
327 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
329 STp
->buffer
->cmdstat
.midlevel_result
= SRpnt
->result
= req
->errors
;
331 STp
->write_pending
= 0;
334 complete(SRpnt
->waiting
);
338 blk_rq_unmap_user(SRpnt
->bio
);
341 __blk_put_request(req
->q
, req
);
344 /* osst_request memory management */
345 static struct osst_request
*osst_allocate_request(void)
347 return kzalloc(sizeof(struct osst_request
), GFP_KERNEL
);
350 static void osst_release_request(struct osst_request
*streq
)
355 static int osst_execute(struct osst_request
*SRpnt
, const unsigned char *cmd
,
356 int cmd_len
, int data_direction
, void *buffer
, unsigned bufflen
,
357 int use_sg
, int timeout
, int retries
)
360 struct page
**pages
= NULL
;
361 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
364 int write
= (data_direction
== DMA_TO_DEVICE
);
366 req
= blk_get_request(SRpnt
->stp
->device
->request_queue
, write
, GFP_KERNEL
);
368 return DRIVER_ERROR
<< 24;
370 blk_rq_set_block_pc(req
);
371 req
->cmd_flags
|= REQ_QUIET
;
376 struct scatterlist
*sg
, *sgl
= (struct scatterlist
*)buffer
;
379 pages
= kzalloc(use_sg
* sizeof(struct page
*), GFP_KERNEL
);
383 for_each_sg(sgl
, sg
, use_sg
, i
)
384 pages
[i
] = sg_page(sg
);
386 mdata
->null_mapped
= 1;
388 mdata
->page_order
= get_order(sgl
[0].length
);
390 DIV_ROUND_UP(bufflen
, PAGE_SIZE
<< mdata
->page_order
);
393 err
= blk_rq_map_user(req
->q
, req
, mdata
, NULL
, bufflen
, GFP_KERNEL
);
398 SRpnt
->bio
= req
->bio
;
399 mdata
->pages
= pages
;
401 } else if (bufflen
) {
402 err
= blk_rq_map_kern(req
->q
, req
, buffer
, bufflen
, GFP_KERNEL
);
407 req
->cmd_len
= cmd_len
;
408 memset(req
->cmd
, 0, BLK_MAX_CDB
); /* ATAPI hates garbage after CDB */
409 memcpy(req
->cmd
, cmd
, req
->cmd_len
);
410 req
->sense
= SRpnt
->sense
;
412 req
->timeout
= timeout
;
413 req
->retries
= retries
;
414 req
->end_io_data
= SRpnt
;
416 blk_execute_rq_nowait(req
->q
, NULL
, req
, 1, osst_end_async
);
419 blk_put_request(req
);
420 return DRIVER_ERROR
<< 24;
423 /* Do the scsi command. Waits until command performed if do_wait is true.
424 Otherwise osst_write_behind_check() is used to check that the command
426 static struct osst_request
* osst_do_scsi(struct osst_request
*SRpnt
, struct osst_tape
*STp
,
427 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
430 unsigned short use_sg
;
431 #ifdef OSST_INJECT_ERRORS
432 static int inject
= 0;
433 static int repeat
= 0;
435 struct completion
*waiting
;
437 /* if async, make sure there's no command outstanding */
438 if (!do_wait
&& ((STp
->buffer
)->last_SRpnt
)) {
439 printk(KERN_ERR
"%s: Async command already active.\n",
441 if (signal_pending(current
))
442 (STp
->buffer
)->syscall_result
= (-EINTR
);
444 (STp
->buffer
)->syscall_result
= (-EBUSY
);
449 SRpnt
= osst_allocate_request();
451 printk(KERN_ERR
"%s: Can't allocate SCSI request.\n",
453 if (signal_pending(current
))
454 (STp
->buffer
)->syscall_result
= (-EINTR
);
456 (STp
->buffer
)->syscall_result
= (-EBUSY
);
462 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
463 which IO is outstanding. It's nulled out when the IO completes. */
465 (STp
->buffer
)->last_SRpnt
= SRpnt
;
467 waiting
= &STp
->wait
;
468 init_completion(waiting
);
469 SRpnt
->waiting
= waiting
;
471 use_sg
= (bytes
> STp
->buffer
->sg
[0].length
) ? STp
->buffer
->use_sg
: 0;
473 bp
= (char *)&(STp
->buffer
->sg
[0]);
474 if (STp
->buffer
->sg_segs
< use_sg
)
475 use_sg
= STp
->buffer
->sg_segs
;
478 bp
= (STp
->buffer
)->b_data
;
480 memcpy(SRpnt
->cmd
, cmd
, sizeof(SRpnt
->cmd
));
481 STp
->buffer
->cmdstat
.have_sense
= 0;
482 STp
->buffer
->syscall_result
= 0;
484 if (osst_execute(SRpnt
, cmd
, COMMAND_SIZE(cmd
[0]), direction
, bp
, bytes
,
485 use_sg
, timeout
, retries
))
486 /* could not allocate the buffer or request was too large */
487 (STp
->buffer
)->syscall_result
= (-EBUSY
);
489 wait_for_completion(waiting
);
490 SRpnt
->waiting
= NULL
;
491 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
492 #ifdef OSST_INJECT_ERRORS
493 if (STp
->buffer
->syscall_result
== 0 &&
496 ( (++ inject
% 83) == 29 ||
497 (STp
->first_frame_position
== 240
498 /* or STp->read_error_frame to fail again on the block calculated above */ &&
500 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
501 STp
->buffer
->last_result_fatal
= 1;
509 /* Handle the write-behind checking (downs the semaphore) */
510 static void osst_write_behind_check(struct osst_tape
*STp
)
512 struct osst_buffer
* STbuffer
;
514 STbuffer
= STp
->buffer
;
517 if (STp
->write_pending
)
522 wait_for_completion(&(STp
->wait
));
523 STp
->buffer
->last_SRpnt
->waiting
= NULL
;
525 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
527 if (STp
->buffer
->syscall_result
)
528 STp
->buffer
->syscall_result
=
529 osst_write_error_recovery(STp
, &(STp
->buffer
->last_SRpnt
), 1);
531 STp
->first_frame_position
++;
533 osst_release_request(STp
->buffer
->last_SRpnt
);
535 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
536 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
538 STbuffer
->last_SRpnt
= NULL
;
539 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
540 STbuffer
->writing
= 0;
547 /* Onstream specific Routines */
549 * Initialize the OnStream AUX
551 static void osst_init_aux(struct osst_tape
* STp
, int frame_type
, int frame_seq_number
,
552 int logical_blk_num
, int blk_sz
, int blk_cnt
)
554 os_aux_t
*aux
= STp
->buffer
->aux
;
555 os_partition_t
*par
= &aux
->partition
;
556 os_dat_t
*dat
= &aux
->dat
;
558 if (STp
->raw
) return;
560 memset(aux
, 0, sizeof(*aux
));
561 aux
->format_id
= htonl(0);
562 memcpy(aux
->application_sig
, "LIN4", 4);
563 aux
->hdwr
= htonl(0);
564 aux
->frame_type
= frame_type
;
566 switch (frame_type
) {
567 case OS_FRAME_TYPE_HEADER
:
568 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
569 par
->partition_num
= OS_CONFIG_PARTITION
;
570 par
->par_desc_ver
= OS_PARTITION_VERSION
;
571 par
->wrt_pass_cntr
= htons(0xffff);
572 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
573 par
->first_frame_ppos
= htonl(0);
574 par
->last_frame_ppos
= htonl(0xbb7);
575 aux
->frame_seq_num
= htonl(0);
576 aux
->logical_blk_num_high
= htonl(0);
577 aux
->logical_blk_num
= htonl(0);
578 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
580 case OS_FRAME_TYPE_DATA
:
581 case OS_FRAME_TYPE_MARKER
:
586 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
587 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
588 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
589 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
590 dat
->dat_list
[0].reserved
= 0;
591 case OS_FRAME_TYPE_EOD
:
592 aux
->update_frame_cntr
= htonl(0);
593 par
->partition_num
= OS_DATA_PARTITION
;
594 par
->par_desc_ver
= OS_PARTITION_VERSION
;
595 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
596 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
597 par
->last_frame_ppos
= htonl(STp
->capacity
);
598 aux
->frame_seq_num
= htonl(frame_seq_number
);
599 aux
->logical_blk_num_high
= htonl(0);
600 aux
->logical_blk_num
= htonl(logical_blk_num
);
602 default: ; /* probably FILL */
604 aux
->filemark_cnt
= htonl(STp
->filemark_cnt
);
605 aux
->phys_fm
= htonl(0xffffffff);
606 aux
->last_mark_ppos
= htonl(STp
->last_mark_ppos
);
607 aux
->last_mark_lbn
= htonl(STp
->last_mark_lbn
);
611 * Verify that we have the correct tape frame
613 static int osst_verify_frame(struct osst_tape
* STp
, int frame_seq_number
, int quiet
)
615 char * name
= tape_name(STp
);
616 os_aux_t
* aux
= STp
->buffer
->aux
;
617 os_partition_t
* par
= &(aux
->partition
);
618 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
619 int blk_cnt
, blk_sz
, i
;
622 if (STp
->buffer
->syscall_result
) {
623 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
624 memset(page_address(sg_page(&STp
->buffer
->sg
[i
])),
625 0, STp
->buffer
->sg
[i
].length
);
626 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
628 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
631 if (STp
->buffer
->syscall_result
) {
633 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
637 if (ntohl(aux
->format_id
) != 0) {
639 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
643 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
644 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
646 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
650 if (par
->partition_num
!= OS_DATA_PARTITION
) {
651 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
653 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
654 name
, par
->partition_num
);
659 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
661 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
665 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
667 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
668 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
672 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
673 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
674 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
677 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
682 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
683 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
684 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
685 STp
->first_frame_position
);
688 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
691 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
692 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
697 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
698 STps
->eof
= ST_FM_HIT
;
700 i
= ntohl(aux
->filemark_cnt
);
701 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
702 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
704 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
705 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
706 i
, STp
->first_frame_position
- 1);
708 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
709 if (i
>= STp
->filemark_cnt
)
710 STp
->filemark_cnt
= i
+1;
713 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
714 STps
->eof
= ST_EOD_1
;
715 STp
->frame_in_buffer
= 1;
717 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
718 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
719 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
720 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
721 STp
->buffer
->read_pointer
= 0;
722 STp
->frame_in_buffer
= 1;
724 /* See what block size was used to write file */
725 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
727 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
728 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
729 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
730 STp
->block_size
<1024?'b':'k');
731 STp
->block_size
= blk_sz
;
732 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
734 STps
->eof
= ST_NOEOF
;
736 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
737 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
741 if (STp
->read_error_frame
== 0)
742 STp
->read_error_frame
= STp
->first_frame_position
- 1;
747 * Wait for the unit to become Ready
749 static int osst_wait_ready(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
750 unsigned timeout
, int initial_delay
)
752 unsigned char cmd
[MAX_COMMAND_SIZE
];
753 struct osst_request
* SRpnt
;
754 unsigned long startwait
= jiffies
;
757 char * name
= tape_name(STp
);
759 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
762 if (initial_delay
> 0)
763 msleep(jiffies_to_msecs(initial_delay
));
765 memset(cmd
, 0, MAX_COMMAND_SIZE
);
766 cmd
[0] = TEST_UNIT_READY
;
768 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
770 if (!SRpnt
) return (-EBUSY
);
772 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
773 (( SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
774 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8) ) ||
775 ( SRpnt
->sense
[2] == 6 && SRpnt
->sense
[12] == 0x28 &&
776 SRpnt
->sense
[13] == 0 ) )) {
779 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
780 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
786 memset(cmd
, 0, MAX_COMMAND_SIZE
);
787 cmd
[0] = TEST_UNIT_READY
;
789 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
795 if ( STp
->buffer
->syscall_result
&&
796 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
798 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
799 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
800 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
801 SRpnt
->sense
[12], SRpnt
->sense
[13]);
806 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
812 * Wait for a tape to be inserted in the unit
814 static int osst_wait_for_medium(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, unsigned timeout
)
816 unsigned char cmd
[MAX_COMMAND_SIZE
];
817 struct osst_request
* SRpnt
;
818 unsigned long startwait
= jiffies
;
821 char * name
= tape_name(STp
);
823 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
826 memset(cmd
, 0, MAX_COMMAND_SIZE
);
827 cmd
[0] = TEST_UNIT_READY
;
829 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
831 if (!SRpnt
) return (-EBUSY
);
833 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
834 SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 0x3a && SRpnt
->sense
[13] == 0 ) {
837 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
838 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
844 memset(cmd
, 0, MAX_COMMAND_SIZE
);
845 cmd
[0] = TEST_UNIT_READY
;
847 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
853 if ( STp
->buffer
->syscall_result
&& SRpnt
->sense
[2] != 2 &&
854 SRpnt
->sense
[12] != 4 && SRpnt
->sense
[13] == 1) {
856 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
857 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
858 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
859 SRpnt
->sense
[12], SRpnt
->sense
[13]);
864 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
869 static int osst_position_tape_and_confirm(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int frame
)
873 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
874 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
875 if (retval
) return (retval
);
876 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
877 return (osst_get_frame_position(STp
, aSRpnt
));
881 * Wait for write(s) to complete
883 static int osst_flush_drive_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
885 unsigned char cmd
[MAX_COMMAND_SIZE
];
886 struct osst_request
* SRpnt
;
888 int delay
= OSST_WAIT_WRITE_COMPLETE
;
890 char * name
= tape_name(STp
);
892 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
895 memset(cmd
, 0, MAX_COMMAND_SIZE
);
896 cmd
[0] = WRITE_FILEMARKS
;
899 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
901 if (!SRpnt
) return (-EBUSY
);
902 if (STp
->buffer
->syscall_result
) {
903 if ((SRpnt
->sense
[2] & 0x0f) == 2 && SRpnt
->sense
[12] == 4) {
904 if (SRpnt
->sense
[13] == 8) {
905 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
908 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
910 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
911 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
916 #define OSST_POLL_PER_SEC 10
917 static int osst_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int curr
, int minlast
, int to
)
919 unsigned long startwait
= jiffies
;
920 char * name
= tape_name(STp
);
922 char notyetprinted
= 1;
924 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
925 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
927 while (time_before (jiffies
, startwait
+ to
*HZ
))
930 result
= osst_get_frame_position(STp
, aSRpnt
);
932 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
933 return 0; /* successful recovery leaves drive ready for frame */
934 if (result
< 0) break;
935 if (STp
->first_frame_position
== curr
&&
937 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
938 (minlast
>= 0 && STp
->cur_frames
> minlast
)
942 if (debugging
|| time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
))
944 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
945 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
946 STp
->last_frame_position
, STp
->cur_frames
,
947 result
, (jiffies
-startwait
)/HZ
,
948 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
953 if (time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
) && notyetprinted
)
955 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
956 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
957 STp
->last_frame_position
, STp
->cur_frames
, result
);
961 msleep(1000 / OSST_POLL_PER_SEC
);
964 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
965 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
966 STp
->last_frame_position
, STp
->cur_frames
,
967 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
972 static int osst_recover_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int writing
)
974 struct osst_request
* SRpnt
;
975 unsigned char cmd
[MAX_COMMAND_SIZE
];
976 unsigned long startwait
= jiffies
;
978 char * name
= tape_name(STp
);
982 char * olddata
= STp
->buffer
->b_data
;
983 int oldsize
= STp
->buffer
->buffer_size
;
985 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
987 memset(cmd
, 0, MAX_COMMAND_SIZE
);
988 cmd
[0] = WRITE_FILEMARKS
;
990 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
993 while (retval
&& time_before (jiffies
, startwait
+ 5*60*HZ
)) {
995 if (STp
->buffer
->syscall_result
&& (SRpnt
->sense
[2] & 0x0f) != 2) {
997 /* some failure - not just not-ready */
998 retval
= osst_write_error_recovery(STp
, aSRpnt
, 0);
1001 schedule_timeout_interruptible(HZ
/ OSST_POLL_PER_SEC
);
1003 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
1004 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1005 cmd
[0] = READ_POSITION
;
1007 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
1010 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
1011 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
1014 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
1016 /* TODO - figure out which error conditions can be handled */
1017 if (STp
->buffer
->syscall_result
)
1019 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
1020 (*aSRpnt
)->sense
[ 2] & 0x0f,
1021 (*aSRpnt
)->sense
[12],
1022 (*aSRpnt
)->sense
[13]);
1028 * Read the next OnStream tape frame at the current location
1030 static int osst_read_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int timeout
)
1032 unsigned char cmd
[MAX_COMMAND_SIZE
];
1033 struct osst_request
* SRpnt
;
1036 os_aux_t
* aux
= STp
->buffer
->aux
;
1037 char * name
= tape_name(STp
);
1041 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
1042 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
1044 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1051 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
1053 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1054 STp
->timeout
, MAX_RETRIES
, 1);
1059 if ((STp
->buffer
)->syscall_result
) {
1061 if (STp
->read_error_frame
== 0) {
1062 STp
->read_error_frame
= STp
->first_frame_position
;
1064 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
1069 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1071 SRpnt
->sense
[0], SRpnt
->sense
[1],
1072 SRpnt
->sense
[2], SRpnt
->sense
[3],
1073 SRpnt
->sense
[4], SRpnt
->sense
[5],
1074 SRpnt
->sense
[6], SRpnt
->sense
[7]);
1078 STp
->first_frame_position
++;
1083 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
1086 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
1087 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
1088 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
1089 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
1090 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
1091 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
1092 if (aux
->frame_type
==2)
1093 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
1094 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
1095 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
1101 static int osst_initiate_read(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1103 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1104 struct osst_request
* SRpnt
;
1105 unsigned char cmd
[MAX_COMMAND_SIZE
];
1107 char * name
= tape_name(STp
);
1109 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
1110 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
1111 STp
->write_type
= OS_WRITE_DATA
;
1112 osst_flush_write_buffer(STp
, aSRpnt
);
1113 osst_flush_drive_buffer(STp
, aSRpnt
);
1115 STps
->rw
= ST_READING
;
1116 STp
->frame_in_buffer
= 0;
1119 * Issue a read 0 command to get the OnStream drive
1120 * read frames into its buffer.
1122 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1127 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
1129 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
1131 if ((retval
= STp
->buffer
->syscall_result
))
1132 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1138 static int osst_get_logical_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1139 int frame_seq_number
, int quiet
)
1141 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1142 char * name
= tape_name(STp
);
1150 * If we want just any frame (-1) and there is a frame in the buffer, return it
1152 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1154 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1159 * Search and wait for the next logical tape frame
1163 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1164 name
, frame_seq_number
);
1165 if (STp
->read_error_frame
) {
1166 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1168 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1169 name
, STp
->read_error_frame
);
1171 STp
->read_error_frame
= 0;
1178 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1179 name
, frame_seq_number
, cnt
);
1181 if ( osst_initiate_read(STp
, aSRpnt
)
1182 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1185 position
= osst_get_frame_position(STp
, aSRpnt
);
1186 if (position
>= 0xbae && position
< 0xbb8)
1188 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1189 position
= STp
->read_error_frame
- 1;
1197 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1200 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1203 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1205 if (osst_verify_frame(STp
, -1, quiet
)) {
1206 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1207 if (STp
->fast_open
) {
1209 "%s:W: Found logical frame %d instead of %d after fast open\n",
1210 name
, x
, frame_seq_number
);
1212 STp
->read_error_frame
= 0;
1215 if (x
> frame_seq_number
) {
1217 /* positioning backwards did not bring us to the desired frame */
1218 position
= STp
->read_error_frame
- 1;
1221 position
= osst_get_frame_position(STp
, aSRpnt
)
1222 + frame_seq_number
- x
- 1;
1224 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1229 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1230 name
, x
, frame_seq_number
,
1231 STp
->first_frame_position
- position
);
1233 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1239 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1241 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1243 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1246 STp
->frame_in_buffer
= 0;
1249 STp
->recover_count
++;
1250 STp
->recover_erreg
++;
1251 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1252 name
, STp
->read_error_frame
);
1257 if (debugging
|| STps
->eof
)
1259 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1260 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1263 STp
->read_error_frame
= 0;
1267 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int logical_blk_num
)
1269 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1270 char * name
= tape_name(STp
);
1272 int frame_seq_estimate
, ppos_estimate
, move
;
1274 if (logical_blk_num
< 0) logical_blk_num
= 0;
1276 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1277 name
, logical_blk_num
, STp
->logical_blk_num
,
1278 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1279 STp
->block_size
<1024?'b':'k');
1281 /* Do we know where we are? */
1282 if (STps
->drv_block
>= 0) {
1283 move
= logical_blk_num
- STp
->logical_blk_num
;
1284 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1285 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1286 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1288 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1290 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1291 else ppos_estimate
= frame_seq_estimate
+ 20;
1292 while (++retries
< 10) {
1293 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1294 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1295 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1297 if (frame_seq_estimate
< 0) {
1298 frame_seq_estimate
= 0;
1301 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1302 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1303 /* we've located the estimated frame, now does it have our block? */
1304 if (logical_blk_num
< STp
->logical_blk_num
||
1305 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1306 if (STps
->eof
== ST_FM_HIT
)
1307 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1309 move
= logical_blk_num
- STp
->logical_blk_num
;
1310 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1311 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1313 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1316 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1317 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1318 STp
->logical_blk_num
, logical_blk_num
, move
);
1320 frame_seq_estimate
+= move
;
1321 ppos_estimate
+= move
;
1324 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1325 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1326 STp
->logical_blk_num
= logical_blk_num
;
1329 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1330 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1331 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1334 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1335 if (STps
->eof
== ST_FM_HIT
) {
1337 STps
->drv_block
= 0;
1339 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1340 STp
->logical_blk_num
-
1341 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1344 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1348 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1350 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1352 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1353 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1354 STp
->logical_blk_num
, logical_blk_num
);
1356 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1357 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1362 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1363 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1367 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1368 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1369 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1370 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1372 #define OSST_FRAME_SHIFT 6
1373 #define OSST_SECTOR_SHIFT 9
1374 #define OSST_SECTOR_MASK 0x03F
1376 static int osst_get_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1380 char * name
= tape_name(STp
);
1383 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1384 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1385 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1386 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1387 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1388 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1390 /* do we know where we are inside a file? */
1391 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1392 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1393 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1394 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1395 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1397 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1399 sector
= osst_get_frame_position(STp
, aSRpnt
);
1401 sector
<<= OSST_FRAME_SHIFT
;
1406 static int osst_seek_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int sector
)
1408 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1409 int frame
= sector
>> OSST_FRAME_SHIFT
,
1410 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1413 char * name
= tape_name(STp
);
1415 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1416 name
, sector
, frame
, offset
);
1418 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1420 if (frame
<= STp
->first_data_ppos
) {
1421 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1422 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1424 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1425 if (r
< 0) return r
;
1427 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1428 if (r
< 0) return r
;
1430 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1433 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1434 STp
->buffer
->read_pointer
= offset
;
1435 STp
->buffer
->buffer_bytes
-= offset
;
1437 STp
->frame_seq_number
++;
1438 STp
->frame_in_buffer
= 0;
1439 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1440 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1442 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1443 if (STps
->eof
== ST_FM_HIT
) {
1445 STps
->drv_block
= 0;
1447 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1448 STp
->logical_blk_num
-
1449 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1452 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1455 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1456 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1457 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1463 * Read back the drive's internal buffer contents, as a part
1464 * of the write error recovery mechanism for old OnStream
1465 * firmware revisions.
1466 * Precondition for this function to work: all frames in the
1467 * drive's buffer must be of one type (DATA, MARK or EOD)!
1469 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1470 unsigned int frame
, unsigned int skip
, int pending
)
1472 struct osst_request
* SRpnt
= * aSRpnt
;
1473 unsigned char * buffer
, * p
;
1474 unsigned char cmd
[MAX_COMMAND_SIZE
];
1475 int flag
, new_frame
, i
;
1476 int nframes
= STp
->cur_frames
;
1477 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1478 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1479 - (nframes
+ pending
- 1);
1480 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1481 - (nframes
+ pending
- 1) * blks_per_frame
;
1482 char * name
= tape_name(STp
);
1483 unsigned long startwait
= jiffies
;
1485 int dbg
= debugging
;
1488 if ((buffer
= vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1491 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1492 name
, nframes
, pending
?" and one that was pending":"");
1494 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1496 if (pending
&& debugging
)
1497 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1498 name
, frame_seq_number
+ nframes
,
1499 logical_blk_num
+ nframes
* blks_per_frame
,
1500 p
[0], p
[1], p
[2], p
[3]);
1502 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1504 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1505 cmd
[0] = 0x3C; /* Buffer Read */
1506 cmd
[1] = 6; /* Retrieve Faulty Block */
1507 cmd
[7] = 32768 >> 8;
1508 cmd
[8] = 32768 & 0xff;
1510 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1511 STp
->timeout
, MAX_RETRIES
, 1);
1513 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1514 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1519 osst_copy_from_buffer(STp
->buffer
, p
);
1522 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1523 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1527 osst_get_frame_position(STp
, aSRpnt
);
1530 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1532 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1533 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1535 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1538 if (STp
->write_type
== OS_WRITE_HEADER
) {
1540 p
+= skip
* OS_DATA_SIZE
;
1542 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1547 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1548 name
, new_frame
+i
, frame_seq_number
+i
);
1550 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1551 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1552 osst_get_frame_position(STp
, aSRpnt
);
1555 if (new_frame
> frame
+ 1000) {
1556 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1560 if ( i
>= nframes
+ pending
) break;
1563 osst_copy_to_buffer(STp
->buffer
, p
);
1565 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1567 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1568 logical_blk_num
+ i
*blks_per_frame
,
1569 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1570 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1578 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1579 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1580 p
[0], p
[1], p
[2], p
[3]);
1582 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1583 STp
->timeout
, MAX_RETRIES
, 1);
1585 if (STp
->buffer
->syscall_result
)
1588 p
+= OS_DATA_SIZE
; i
++;
1590 /* if we just sent the last frame, wait till all successfully written */
1591 if ( i
== nframes
+ pending
) {
1593 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1595 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1596 cmd
[0] = WRITE_FILEMARKS
;
1598 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1599 STp
->timeout
, MAX_RETRIES
, 1);
1602 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1603 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1607 flag
= STp
->buffer
->syscall_result
;
1608 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1610 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1611 cmd
[0] = TEST_UNIT_READY
;
1613 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1616 if (SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
1617 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8)) {
1618 /* in the process of becoming ready */
1622 if (STp
->buffer
->syscall_result
)
1628 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1634 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1635 SRpnt
->sense
[12] == 0 &&
1636 SRpnt
->sense
[13] == 2) {
1637 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1639 return (-EIO
); /* hit end of tape = fail */
1641 i
= ((SRpnt
->sense
[3] << 24) |
1642 (SRpnt
->sense
[4] << 16) |
1643 (SRpnt
->sense
[5] << 8) |
1644 SRpnt
->sense
[6] ) - new_frame
;
1645 p
= &buffer
[i
* OS_DATA_SIZE
];
1647 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1649 osst_get_frame_position(STp
, aSRpnt
);
1651 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1652 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1657 /* error recovery did not successfully complete */
1658 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1659 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1662 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1667 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1668 unsigned int frame
, unsigned int skip
, int pending
)
1670 unsigned char cmd
[MAX_COMMAND_SIZE
];
1671 struct osst_request
* SRpnt
;
1672 char * name
= tape_name(STp
);
1674 int attempts
= 1000 / skip
;
1676 unsigned long startwait
= jiffies
;
1678 int dbg
= debugging
;
1681 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1686 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1688 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1690 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1691 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1693 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1696 schedule_timeout_interruptible(msecs_to_jiffies(100));
1698 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1700 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1701 name
, STp
->first_frame_position
,
1702 STp
->last_frame_position
, STp
->cur_frames
);
1704 frame
= STp
->last_frame_position
;
1708 if (pending
&& STp
->cur_frames
< 50) {
1710 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1715 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1716 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1718 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1719 STp
->timeout
, MAX_RETRIES
, 1);
1722 if (STp
->buffer
->syscall_result
) { /* additional write error */
1723 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1724 SRpnt
->sense
[12] == 0 &&
1725 SRpnt
->sense
[13] == 2) {
1727 "%s:E: Volume overflow in write error recovery\n",
1729 break; /* hit end of tape = fail */
1738 if (STp
->cur_frames
== 0) {
1741 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1743 if (STp
->first_frame_position
!= expected
) {
1744 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1745 name
, STp
->first_frame_position
, expected
);
1752 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1753 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1757 schedule_timeout_interruptible(msecs_to_jiffies(100));
1759 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1767 * Error recovery algorithm for the OnStream tape.
1770 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
)
1772 struct osst_request
* SRpnt
= * aSRpnt
;
1773 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1774 char * name
= tape_name(STp
);
1777 unsigned int frame
, skip
;
1779 rw_state
= STps
->rw
;
1781 if ((SRpnt
->sense
[ 2] & 0x0f) != 3
1782 || SRpnt
->sense
[12] != 12
1783 || SRpnt
->sense
[13] != 0) {
1785 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1786 SRpnt
->sense
[2], SRpnt
->sense
[12], SRpnt
->sense
[13]);
1790 frame
= (SRpnt
->sense
[3] << 24) |
1791 (SRpnt
->sense
[4] << 16) |
1792 (SRpnt
->sense
[5] << 8) |
1794 skip
= SRpnt
->sense
[9];
1797 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1799 osst_get_frame_position(STp
, aSRpnt
);
1801 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1802 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1804 switch (STp
->write_type
) {
1807 case OS_WRITE_NEW_MARK
:
1809 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1810 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1811 if (STp
->os_fw_rev
>= 10600)
1812 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1814 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1815 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1817 retval
?"" :"Don't worry, ",
1818 retval
?" not ":" ");
1820 case OS_WRITE_LAST_MARK
:
1821 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1822 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1825 case OS_WRITE_HEADER
:
1826 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1827 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1830 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1831 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1833 osst_get_frame_position(STp
, aSRpnt
);
1835 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1836 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1837 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1840 STp
->recover_count
++;
1841 STp
->recover_erreg
++;
1845 STps
->rw
= rw_state
;
1849 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1850 int mt_op
, int mt_count
)
1852 char * name
= tape_name(STp
);
1854 int last_mark_ppos
= -1;
1857 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1859 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1861 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1865 if (STp
->linux_media_version
>= 4) {
1867 * direct lookup in header filemark list
1869 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1870 if (STp
->header_ok
&&
1871 STp
->header_cache
!= NULL
&&
1872 (cnt
- mt_count
) >= 0 &&
1873 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1874 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1875 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1877 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1879 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1880 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1881 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1883 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1885 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1886 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1887 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1888 mt_count
, last_mark_ppos
);
1890 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1891 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1892 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1895 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1899 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1900 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1901 name
, last_mark_ppos
);
1907 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1911 while (cnt
!= mt_count
) {
1912 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1913 if (last_mark_ppos
== -1)
1916 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1918 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1920 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1922 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1926 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1927 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1928 name
, last_mark_ppos
);
1933 if (mt_op
== MTBSFM
) {
1934 STp
->frame_seq_number
++;
1935 STp
->frame_in_buffer
= 0;
1936 STp
->buffer
->buffer_bytes
= 0;
1937 STp
->buffer
->read_pointer
= 0;
1938 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1944 * ADRL 1.1 compatible "slow" space filemarks fwd version
1946 * Just scans for the filemark sequentially.
1948 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1949 int mt_op
, int mt_count
)
1953 char * name
= tape_name(STp
);
1955 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1957 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1959 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1964 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1966 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1970 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1972 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1974 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1976 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1978 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1979 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1981 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1985 if (cnt
== mt_count
)
1987 STp
->frame_in_buffer
= 0;
1989 if (mt_op
== MTFSF
) {
1990 STp
->frame_seq_number
++;
1991 STp
->frame_in_buffer
= 0;
1992 STp
->buffer
->buffer_bytes
= 0;
1993 STp
->buffer
->read_pointer
= 0;
1994 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2000 * Fast linux specific version of OnStream FSF
2002 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
2003 int mt_op
, int mt_count
)
2005 char * name
= tape_name(STp
);
2007 next_mark_ppos
= -1;
2010 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
2012 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2014 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
2019 if (STp
->linux_media_version
>= 4) {
2021 * direct lookup in header filemark list
2023 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
2024 if (STp
->header_ok
&&
2025 STp
->header_cache
!= NULL
&&
2026 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
2027 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
2028 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2029 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
2031 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
2033 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
2034 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
2035 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
2037 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2039 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2040 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
2041 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
2042 mt_count
, next_mark_ppos
);
2044 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
2046 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2048 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2050 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2051 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2053 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2058 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2059 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2060 name
, next_mark_ppos
);
2063 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
2064 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
2065 name
, cnt
+mt_count
, next_mark_ppos
,
2066 ntohl(STp
->buffer
->aux
->filemark_cnt
));
2072 * Find nearest (usually previous) marker, then jump from marker to marker
2075 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
2077 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
2079 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
2083 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
2084 if (STp
->first_mark_ppos
== -1) {
2086 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2088 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2090 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
2091 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2094 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2099 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2100 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
2101 name
, STp
->first_mark_ppos
);
2105 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
2111 while (cnt
!= mt_count
) {
2112 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
2113 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
2115 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2117 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
2120 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
2122 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2124 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2126 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2131 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2132 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2133 name
, next_mark_ppos
);
2138 if (mt_op
== MTFSF
) {
2139 STp
->frame_seq_number
++;
2140 STp
->frame_in_buffer
= 0;
2141 STp
->buffer
->buffer_bytes
= 0;
2142 STp
->buffer
->read_pointer
= 0;
2143 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2149 * In debug mode, we want to see as many errors as possible
2150 * to test the error recovery mechanism.
2153 static void osst_set_retries(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int retries
)
2155 unsigned char cmd
[MAX_COMMAND_SIZE
];
2156 struct osst_request
* SRpnt
= * aSRpnt
;
2157 char * name
= tape_name(STp
);
2159 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2160 cmd
[0] = MODE_SELECT
;
2162 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2164 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2165 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2166 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2167 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2168 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2169 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2170 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2171 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2174 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2176 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2179 if ((STp
->buffer
)->syscall_result
)
2180 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2185 static int osst_write_filemark(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2188 int this_mark_ppos
= STp
->first_frame_position
;
2189 int this_mark_lbn
= STp
->logical_blk_num
;
2191 char * name
= tape_name(STp
);
2194 if (STp
->raw
) return 0;
2196 STp
->write_type
= OS_WRITE_NEW_MARK
;
2198 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2199 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2202 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2203 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2204 STp
->last_mark_ppos
= this_mark_ppos
;
2205 STp
->last_mark_lbn
= this_mark_lbn
;
2206 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2207 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2208 if (STp
->filemark_cnt
++ == 0)
2209 STp
->first_mark_ppos
= this_mark_ppos
;
2213 static int osst_write_eod(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2217 char * name
= tape_name(STp
);
2220 if (STp
->raw
) return 0;
2222 STp
->write_type
= OS_WRITE_EOD
;
2223 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2225 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2226 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2230 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2231 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2232 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2236 static int osst_write_filler(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2238 char * name
= tape_name(STp
);
2241 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2243 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2244 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2245 STp
->write_type
= OS_WRITE_FILLER
;
2247 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2248 STp
->buffer
->buffer_bytes
= 6;
2250 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2251 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2256 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2258 return osst_flush_drive_buffer(STp
, aSRpnt
);
2261 static int __osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2263 char * name
= tape_name(STp
);
2267 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2269 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2270 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2271 STp
->write_type
= OS_WRITE_HEADER
;
2273 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2274 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2276 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2277 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2281 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2283 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2288 static int osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int locate_eod
)
2290 os_header_t
* header
;
2292 char * name
= tape_name(STp
);
2295 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2297 if (STp
->raw
) return 0;
2299 if (STp
->header_cache
== NULL
) {
2300 if ((STp
->header_cache
= vmalloc(sizeof(os_header_t
))) == NULL
) {
2301 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2304 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2306 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2309 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2310 else STp
->update_frame_cntr
= 0;
2312 header
= STp
->header_cache
;
2313 strcpy(header
->ident_str
, "ADR_SEQ");
2314 header
->major_rev
= 1;
2315 header
->minor_rev
= 4;
2316 header
->ext_trk_tb_off
= htons(17192);
2317 header
->pt_par_num
= 1;
2318 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2319 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2320 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2321 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2322 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2323 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2324 header
->cfg_col_width
= htonl(20);
2325 header
->dat_col_width
= htonl(1500);
2326 header
->qfa_col_width
= htonl(0);
2327 header
->ext_track_tb
.nr_stream_part
= 1;
2328 header
->ext_track_tb
.et_ent_sz
= 32;
2329 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2330 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2331 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2332 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2333 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2334 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2335 header
->dat_fm_tab
.fm_part_num
= 0;
2336 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2337 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2338 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2340 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2341 if (STp
->update_frame_cntr
== 0)
2342 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2343 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2347 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2349 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2352 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2354 memcpy(STp
->application_sig
, "LIN4", 4);
2355 STp
->linux_media
= 1;
2356 STp
->linux_media_version
= 4;
2362 static int osst_reset_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2364 if (STp
->header_cache
!= NULL
)
2365 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2367 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2368 STp
->frame_in_buffer
= 0;
2369 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2370 STp
->filemark_cnt
= 0;
2371 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2372 return osst_write_header(STp
, aSRpnt
, 1);
2375 static int __osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int ppos
)
2377 char * name
= tape_name(STp
);
2378 os_header_t
* header
;
2381 int linux_media_version
,
2387 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2388 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2389 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2390 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2391 if (osst_initiate_read (STp
, aSRpnt
)) {
2392 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2396 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2398 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2402 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2403 aux
= STp
->buffer
->aux
;
2404 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2406 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2410 if (ntohl(aux
->frame_seq_num
) != 0 ||
2411 ntohl(aux
->logical_blk_num
) != 0 ||
2412 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2413 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2414 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2416 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2417 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2418 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2419 ntohl(aux
->partition
.last_frame_ppos
));
2423 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2424 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2425 strlcpy(id_string
, header
->ident_str
, 8);
2427 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2431 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2432 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2434 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2435 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2439 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2441 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2442 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2443 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2444 header
->major_rev
, header
->minor_rev
);
2446 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2450 if (header
->pt_par_num
!= 1)
2451 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2452 name
, header
->pt_par_num
);
2454 memcpy(id_string
, aux
->application_sig
, 4);
2456 if (memcmp(id_string
, "LIN", 3) == 0) {
2457 STp
->linux_media
= 1;
2458 linux_media_version
= id_string
[3] - '0';
2459 if (linux_media_version
!= 4)
2460 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2461 name
, linux_media_version
);
2463 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2466 if (linux_media_version
< STp
->linux_media_version
) {
2468 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2469 name
, ppos
, linux_media_version
);
2473 if (linux_media_version
> STp
->linux_media_version
) {
2475 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2476 name
, ppos
, linux_media_version
);
2478 memcpy(STp
->application_sig
, id_string
, 5);
2479 STp
->linux_media_version
= linux_media_version
;
2480 STp
->update_frame_cntr
= -1;
2482 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2484 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2485 name
, ppos
, update_frame_cntr
);
2487 if (STp
->header_cache
== NULL
) {
2488 if ((STp
->header_cache
= vmalloc(sizeof(os_header_t
))) == NULL
) {
2489 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2493 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2496 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2497 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2499 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2500 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2501 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2502 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2503 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2504 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2505 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2506 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2507 STp
->update_frame_cntr
= update_frame_cntr
;
2509 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2510 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2511 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2512 STp
->first_data_ppos
,
2513 ntohl(header
->partition
[0].last_frame_ppos
),
2514 ntohl(header
->partition
[0].eod_frame_ppos
));
2515 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2516 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2518 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2520 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2522 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2523 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2524 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2526 if (header
->minor_rev
== 4 &&
2527 (header
->ext_trk_tb_off
!= htons(17192) ||
2528 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2529 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2530 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2531 header
->cfg_col_width
!= htonl(20) ||
2532 header
->dat_col_width
!= htonl(1500) ||
2533 header
->qfa_col_width
!= htonl(0) ||
2534 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2535 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2536 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2537 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2538 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2539 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2540 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2541 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2542 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2543 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2544 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2545 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2552 static int osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2557 char * name
= tape_name(STp
);
2559 position
= osst_get_frame_position(STp
, aSRpnt
);
2562 STp
->header_ok
= STp
->linux_media
= 1;
2563 STp
->linux_media_version
= 0;
2566 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2567 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2568 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2569 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2571 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2574 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2575 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2577 first
= position
==10?0xbae: 5;
2578 last
= position
==10?0xbb3:10;
2580 for (ppos
= first
; ppos
< last
; ppos
++)
2581 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2584 first
= position
==10? 5:0xbae;
2585 last
= position
==10?10:0xbb3;
2587 for (ppos
= first
; ppos
< last
; ppos
++)
2588 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2592 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2593 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2594 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2597 if (position
<= STp
->first_data_ppos
) {
2598 position
= STp
->first_data_ppos
;
2599 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2601 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2607 static int osst_verify_position(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2609 int frame_position
= STp
->first_frame_position
;
2610 int frame_seq_numbr
= STp
->frame_seq_number
;
2611 int logical_blk_num
= STp
->logical_blk_num
;
2612 int halfway_frame
= STp
->frame_in_buffer
;
2613 int read_pointer
= STp
->buffer
->read_pointer
;
2614 int prev_mark_ppos
= -1;
2615 int actual_mark_ppos
, i
, n
;
2617 char * name
= tape_name(STp
);
2619 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2621 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2622 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2624 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2628 if (STp
->linux_media_version
>= 4) {
2629 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2630 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2633 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2634 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2635 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2636 if (frame_position
!= STp
->first_frame_position
||
2637 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2638 prev_mark_ppos
!= actual_mark_ppos
) {
2640 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2641 STp
->first_frame_position
, frame_position
,
2642 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2643 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2647 if (halfway_frame
) {
2648 /* prepare buffer for append and rewrite on top of original */
2649 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2650 STp
->buffer
->buffer_bytes
= read_pointer
;
2651 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2654 STp
->frame_in_buffer
= halfway_frame
;
2655 STp
->frame_seq_number
= frame_seq_numbr
;
2656 STp
->logical_blk_num
= logical_blk_num
;
2660 /* Acc. to OnStream, the vers. numbering is the following:
2661 * X.XX for released versions (X=digit),
2662 * XXXY for unreleased versions (Y=letter)
2663 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2664 * This fn makes monoton numbers out of this scheme ...
2666 static unsigned int osst_parse_firmware_rev (const char * str
)
2668 if (str
[1] == '.') {
2669 return (str
[0]-'0')*10000
2673 return (str
[0]-'0')*10000
2675 +(str
[2]-'0')*100 - 100
2681 * Configure the OnStream SCII tape drive for default operation
2683 static int osst_configure_onstream(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2685 unsigned char cmd
[MAX_COMMAND_SIZE
];
2686 char * name
= tape_name(STp
);
2687 struct osst_request
* SRpnt
= * aSRpnt
;
2688 osst_mode_parameter_header_t
* header
;
2689 osst_block_size_page_t
* bs
;
2690 osst_capabilities_page_t
* cp
;
2691 osst_tape_paramtr_page_t
* prm
;
2692 int drive_buffer_size
;
2694 if (STp
->ready
!= ST_READY
) {
2696 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2701 if (STp
->os_fw_rev
< 10600) {
2702 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2703 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2707 * Configure 32.5KB (data+aux) frame size.
2708 * Get the current frame size from the block size mode page
2710 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2711 cmd
[0] = MODE_SENSE
;
2713 cmd
[2] = BLOCK_SIZE_PAGE
;
2714 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2716 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2717 if (SRpnt
== NULL
) {
2719 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2724 if ((STp
->buffer
)->syscall_result
!= 0) {
2725 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2729 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2730 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2733 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2734 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2735 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2736 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2740 * Configure default auto columns mode, 32.5KB transfer mode
2748 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2749 cmd
[0] = MODE_SELECT
;
2751 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2753 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2755 if ((STp
->buffer
)->syscall_result
!= 0) {
2756 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2761 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2763 * In debug mode, we want to see as many errors as possible
2764 * to test the error recovery mechanism.
2766 osst_set_retries(STp
, aSRpnt
, 0);
2771 * Set vendor name to 'LIN4' for "Linux support version 4".
2774 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2775 cmd
[0] = MODE_SELECT
;
2777 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2779 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2780 header
->medium_type
= 0; /* Medium Type - ignoring */
2781 header
->dsp
= 0; /* Reserved */
2782 header
->bdl
= 0; /* Block Descriptor Length */
2784 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2785 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2786 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2787 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2788 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2789 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2790 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2791 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2793 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2796 if ((STp
->buffer
)->syscall_result
!= 0) {
2797 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2798 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2802 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2803 cmd
[0] = MODE_SENSE
;
2805 cmd
[2] = CAPABILITIES_PAGE
;
2806 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2808 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2811 if ((STp
->buffer
)->syscall_result
!= 0) {
2812 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2816 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2817 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2818 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2820 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2822 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2823 cmd
[0] = MODE_SENSE
;
2825 cmd
[2] = TAPE_PARAMTR_PAGE
;
2826 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2828 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2831 if ((STp
->buffer
)->syscall_result
!= 0) {
2832 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2836 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2837 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2838 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2840 STp
->density
= prm
->density
;
2841 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2843 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2844 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2852 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2853 it messes up the block number). */
2854 static int cross_eof(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int forward
)
2857 char * name
= tape_name(STp
);
2861 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2862 name
, forward
? "forward" : "backward");
2866 /* assumes that the filemark is already read by the drive, so this is low cost */
2867 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2870 /* assumes this is only called if we just read the filemark! */
2871 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2874 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2875 name
, forward
? "forward" : "backward");
2881 /* Get the tape position. */
2883 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2885 unsigned char scmd
[MAX_COMMAND_SIZE
];
2886 struct osst_request
* SRpnt
;
2888 char * name
= tape_name(STp
);
2890 /* KG: We want to be able to use it for checking Write Buffer availability
2891 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2893 char * olddata
= STp
->buffer
->b_data
;
2894 int oldsize
= STp
->buffer
->buffer_size
;
2896 if (STp
->ready
!= ST_READY
) return (-EIO
);
2898 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2899 scmd
[0] = READ_POSITION
;
2901 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2902 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2903 STp
->timeout
, MAX_RETRIES
, 1);
2905 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2910 if (STp
->buffer
->syscall_result
)
2911 result
= ((SRpnt
->sense
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2913 if (result
== -EINVAL
)
2914 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2916 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2917 unsigned char mysense
[16];
2918 memcpy (mysense
, SRpnt
->sense
, 16);
2919 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2920 scmd
[0] = READ_POSITION
;
2921 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2922 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2923 STp
->timeout
, MAX_RETRIES
, 1);
2925 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2926 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2927 SRpnt
->sense
[2],SRpnt
->sense
[12],SRpnt
->sense
[13]);
2929 if (!STp
->buffer
->syscall_result
)
2930 memcpy (SRpnt
->sense
, mysense
, 16);
2932 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2934 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2935 + ((STp
->buffer
)->b_data
[5] << 16)
2936 + ((STp
->buffer
)->b_data
[6] << 8)
2937 + (STp
->buffer
)->b_data
[7];
2938 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2939 + ((STp
->buffer
)->b_data
[ 9] << 16)
2940 + ((STp
->buffer
)->b_data
[10] << 8)
2941 + (STp
->buffer
)->b_data
[11];
2942 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2945 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2946 STp
->first_frame_position
, STp
->last_frame_position
,
2947 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2948 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2952 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2954 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2955 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2957 STp
->first_frame_position
= STp
->last_frame_position
;
2960 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2962 return (result
== 0 ? STp
->first_frame_position
: result
);
2966 /* Set the tape block */
2967 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int ppos
, int skip
)
2969 unsigned char scmd
[MAX_COMMAND_SIZE
];
2970 struct osst_request
* SRpnt
;
2971 struct st_partstat
* STps
;
2973 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2974 char * name
= tape_name(STp
);
2976 if (STp
->ready
!= ST_READY
) return (-EIO
);
2978 STps
= &(STp
->ps
[STp
->partition
]);
2980 if (ppos
< 0 || ppos
> STp
->capacity
) {
2981 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2982 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2989 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2991 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2994 scmd
[3] = (pp
>> 24);
2995 scmd
[4] = (pp
>> 16);
2996 scmd
[5] = (pp
>> 8);
3001 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
3007 if ((STp
->buffer
)->syscall_result
!= 0) {
3009 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
3010 name
, STp
->first_frame_position
, pp
);
3015 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
3016 } while ((pp
!= ppos
) && (pp
= ppos
));
3017 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
3018 STps
->eof
= ST_NOEOF
;
3021 STp
->frame_in_buffer
= 0;
3025 static int osst_write_trailer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int leave_at_EOT
)
3027 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
3030 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
3031 /* true unless the user wrote the filemark for us */
3032 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
3033 if (result
< 0) goto out
;
3034 result
= osst_write_filemark(STp
, aSRpnt
);
3035 if (result
< 0) goto out
;
3037 if (STps
->drv_file
>= 0)
3039 STps
->drv_block
= 0;
3041 result
= osst_write_eod(STp
, aSRpnt
);
3042 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
3049 /* osst versions of st functions - augmented and stripped to suit OnStream only */
3051 /* Flush the write buffer (never need to write if variable blocksize). */
3052 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
3054 int offset
, transfer
, blks
= 0;
3056 unsigned char cmd
[MAX_COMMAND_SIZE
];
3057 struct osst_request
* SRpnt
= *aSRpnt
;
3058 struct st_partstat
* STps
;
3059 char * name
= tape_name(STp
);
3061 if ((STp
->buffer
)->writing
) {
3062 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
3064 { printk(OSST_DEB_MSG
3065 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name
);
3067 *aSRpnt
= SRpnt
= NULL
;
3071 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name
);
3073 osst_write_behind_check(STp
);
3074 if ((STp
->buffer
)->syscall_result
) {
3077 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
3078 name
, (STp
->buffer
)->midlevel_result
);
3080 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3087 if (STp
->dirty
== 1) {
3090 STps
= &(STp
->ps
[STp
->partition
]);
3091 STps
->rw
= ST_WRITING
;
3092 offset
= STp
->buffer
->buffer_bytes
;
3093 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
3094 transfer
= OS_FRAME_SIZE
;
3096 if (offset
< OS_DATA_SIZE
)
3097 osst_zero_buffer_tail(STp
->buffer
);
3100 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
3101 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
3103 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3108 switch (STp
->write_type
) {
3112 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3113 name
, blks
, STp
->frame_seq_number
,
3114 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3116 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3117 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3120 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
3121 STp
->logical_blk_num
, 0, 0);
3123 case OS_WRITE_NEW_MARK
:
3124 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
3125 STp
->logical_blk_num
++, 0, blks
=1);
3127 case OS_WRITE_HEADER
:
3128 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
3130 default: /* probably FILLER */
3131 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
3135 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3136 name
, offset
, transfer
, blks
);
3139 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3140 STp
->timeout
, MAX_RETRIES
, 1);
3145 if ((STp
->buffer
)->syscall_result
!= 0) {
3148 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3149 name
, SRpnt
->sense
[0], SRpnt
->sense
[2],
3150 SRpnt
->sense
[12], SRpnt
->sense
[13]);
3152 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3153 (SRpnt
->sense
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3154 (SRpnt
->sense
[2] & 0x0f) == NO_SENSE
) {
3156 (STp
->buffer
)->buffer_bytes
= 0;
3160 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3161 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3165 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3168 STp
->first_frame_position
++;
3170 (STp
->buffer
)->buffer_bytes
= 0;
3174 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3180 /* Flush the tape buffer. The tape will be positioned correctly unless
3181 seek_next is true. */
3182 static int osst_flush_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int seek_next
)
3184 struct st_partstat
* STps
;
3185 int backspace
= 0, result
= 0;
3187 char * name
= tape_name(STp
);
3191 * If there was a bus reset, block further access
3194 if( STp
->pos_unknown
)
3197 if (STp
->ready
!= ST_READY
)
3200 STps
= &(STp
->ps
[STp
->partition
]);
3201 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3202 STp
->write_type
= OS_WRITE_DATA
;
3203 return osst_flush_write_buffer(STp
, aSRpnt
);
3205 if (STp
->block_size
== 0)
3209 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3212 if (!STp
->can_bsr
) {
3213 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3214 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3215 (STp
->buffer
)->buffer_bytes
= 0;
3216 (STp
->buffer
)->read_pointer
= 0;
3217 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3221 if (STps
->eof
== ST_FM_HIT
) {
3222 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3224 STps
->eof
= ST_NOEOF
;
3226 if (STps
->drv_file
>= 0)
3228 STps
->drv_block
= 0;
3231 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3232 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3234 else if (STps
->eof
== ST_FM_HIT
) {
3235 if (STps
->drv_file
>= 0)
3237 STps
->drv_block
= 0;
3238 STps
->eof
= ST_NOEOF
;
3244 static int osst_write_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int synchronous
)
3246 unsigned char cmd
[MAX_COMMAND_SIZE
];
3247 struct osst_request
* SRpnt
;
3250 char * name
= tape_name(STp
);
3253 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3255 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3257 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3260 /* error recovery may have bumped us past the header partition */
3261 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3263 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3265 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3270 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3271 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3274 // osst_build_stats(STp, &SRpnt);
3276 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3277 STp
->write_type
= OS_WRITE_DATA
;
3279 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3282 cmd
[4] = 1; /* one frame at a time... */
3283 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3286 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3287 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3289 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3290 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3294 STp
->write_pending
= 1;
3296 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3297 MAX_RETRIES
, synchronous
);
3303 if (STp
->buffer
->syscall_result
!= 0) {
3306 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3308 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3309 (SRpnt
->sense
[2] & 0x40)) {
3310 if ((SRpnt
->sense
[2] & 0x0f) == VOLUME_OVERFLOW
)
3314 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3319 STp
->first_frame_position
++;
3327 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3328 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3333 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3336 retval
= scsi_set_medium_removal(STp
->device
,
3337 do_lock
? SCSI_REMOVAL_PREVENT
: SCSI_REMOVAL_ALLOW
);
3339 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3341 STp
->door_locked
= ST_LOCK_FAILS
;
3345 /* Set the internal state after reset */
3346 static void reset_state(struct osst_tape
*STp
)
3349 struct st_partstat
*STps
;
3351 STp
->pos_unknown
= 0;
3352 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3353 STps
= &(STp
->ps
[i
]);
3355 STps
->eof
= ST_NOEOF
;
3357 STps
->last_block_valid
= 0;
3358 STps
->drv_block
= -1;
3359 STps
->drv_file
= -1;
3364 /* Entry points to osst */
3367 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3369 ssize_t total
, retval
= 0;
3370 ssize_t i
, do_count
, blks
, transfer
;
3371 int write_threshold
;
3372 int doing_write
= 0;
3373 const char __user
* b_point
;
3374 struct osst_request
* SRpnt
= NULL
;
3375 struct st_modedef
* STm
;
3376 struct st_partstat
* STps
;
3377 struct osst_tape
* STp
= filp
->private_data
;
3378 char * name
= tape_name(STp
);
3381 if (mutex_lock_interruptible(&STp
->lock
))
3382 return (-ERESTARTSYS
);
3385 * If we are in the middle of error recovery, don't let anyone
3386 * else try and use this device. Also, if error recovery fails, it
3387 * may try and take the device offline, in which case all further
3388 * access to the device is prohibited.
3390 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3395 if (STp
->ready
!= ST_READY
) {
3396 if (STp
->ready
== ST_NO_TAPE
)
3397 retval
= (-ENOMEDIUM
);
3402 STm
= &(STp
->modes
[STp
->current_mode
]);
3403 if (!STm
->defined
) {
3411 * If there was a bus reset, block further access
3414 if (STp
->pos_unknown
) {
3421 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3427 if (STp
->write_prot
) {
3432 /* Write must be integral number of blocks */
3433 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3434 printk(KERN_ERR
"%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3435 name
, count
, STp
->block_size
<1024?
3436 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3441 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3442 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3443 name
, STp
->first_frame_position
);
3448 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3449 STp
->door_locked
= ST_LOCKED_AUTO
;
3451 STps
= &(STp
->ps
[STp
->partition
]);
3453 if (STps
->rw
== ST_READING
) {
3455 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3456 STps
->drv_file
, STps
->drv_block
);
3458 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3463 if (STps
->rw
!= ST_WRITING
) {
3464 /* Are we totally rewriting this tape? */
3465 if (!STp
->header_ok
||
3466 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3467 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3468 STp
->wrt_pass_cntr
++;
3470 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3471 name
, STp
->wrt_pass_cntr
);
3473 osst_reset_header(STp
, &SRpnt
);
3474 STps
->drv_file
= STps
->drv_block
= 0;
3476 /* Do we know where we'll be writing on the tape? */
3478 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3479 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3480 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3481 STps
->drv_file
= STp
->filemark_cnt
;
3482 STps
->drv_block
= 0;
3485 /* We have no idea where the tape is positioned - give up */
3488 "%s:D: Cannot write at indeterminate position.\n", name
);
3494 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3495 STp
->filemark_cnt
= STps
->drv_file
;
3496 STp
->last_mark_ppos
=
3497 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3499 "%s:W: Overwriting file %d with old write pass counter %d\n",
3500 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3502 "%s:W: may lead to stale data being accepted on reading back!\n",
3506 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3507 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3513 if (!STp
->header_ok
) {
3515 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3521 if ((STp
->buffer
)->writing
) {
3522 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3523 osst_write_behind_check(STp
);
3524 if ((STp
->buffer
)->syscall_result
) {
3527 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3528 (STp
->buffer
)->midlevel_result
);
3530 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3531 STps
->eof
= ST_EOM_OK
;
3533 STps
->eof
= ST_EOM_ERROR
;
3536 if (STps
->eof
== ST_EOM_OK
) {
3540 else if (STps
->eof
== ST_EOM_ERROR
) {
3545 /* Check the buffer readability in cases where copy_user might catch
3546 the problems after some tape movement. */
3547 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3548 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3553 if (!STm
->do_buffer_writes
) {
3554 write_threshold
= 1;
3557 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3558 if (!STm
->do_async_writes
)
3564 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3565 name
, (int) count
, STps
->drv_file
, STps
->drv_block
,
3566 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3569 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3572 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3573 (STp
->buffer
)->buffer_bytes
;
3574 if (do_count
> count
)
3577 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3583 blks
= do_count
/ STp
->block_size
;
3584 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3586 i
= osst_write_frame(STp
, &SRpnt
, 1);
3588 if (i
== (-ENOSPC
)) {
3589 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3590 if (transfer
<= do_count
) {
3591 *ppos
+= do_count
- transfer
;
3592 count
-= do_count
- transfer
;
3593 if (STps
->drv_block
>= 0) {
3594 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3596 STps
->eof
= ST_EOM_OK
;
3597 retval
= (-ENOSPC
); /* EOM within current request */
3600 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3601 name
, (int) transfer
);
3605 STps
->eof
= ST_EOM_ERROR
;
3606 STps
->drv_block
= (-1); /* Too cautious? */
3607 retval
= (-EIO
); /* EOM for old data */
3610 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3618 if (SRpnt
!= NULL
) {
3619 osst_release_request(SRpnt
);
3622 STp
->buffer
->buffer_bytes
= 0;
3625 retval
= total
- count
;
3630 b_point
+= do_count
;
3632 if (STps
->drv_block
>= 0) {
3633 STps
->drv_block
+= blks
;
3635 STp
->buffer
->buffer_bytes
= 0;
3637 } /* end while write threshold exceeded */
3641 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3646 blks
= count
/ STp
->block_size
;
3647 STp
->logical_blk_num
+= blks
;
3648 if (STps
->drv_block
>= 0) {
3649 STps
->drv_block
+= blks
;
3655 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3656 retval
= (STp
->buffer
)->syscall_result
;
3660 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3661 /* Schedule an asynchronous write */
3662 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3663 STp
->block_size
) * STp
->block_size
;
3664 STp
->dirty
= !((STp
->buffer
)->writing
==
3665 (STp
->buffer
)->buffer_bytes
);
3667 i
= osst_write_frame(STp
, &SRpnt
, 0);
3672 SRpnt
= NULL
; /* Prevent releasing this request! */
3674 STps
->at_sm
&= (total
== 0);
3676 STps
->eof
= ST_NOEOF
;
3681 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3683 mutex_unlock(&STp
->lock
);
3690 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3692 ssize_t total
, retval
= 0;
3693 ssize_t i
, transfer
;
3695 struct st_modedef
* STm
;
3696 struct st_partstat
* STps
;
3697 struct osst_request
* SRpnt
= NULL
;
3698 struct osst_tape
* STp
= filp
->private_data
;
3699 char * name
= tape_name(STp
);
3702 if (mutex_lock_interruptible(&STp
->lock
))
3703 return (-ERESTARTSYS
);
3706 * If we are in the middle of error recovery, don't let anyone
3707 * else try and use this device. Also, if error recovery fails, it
3708 * may try and take the device offline, in which case all further
3709 * access to the device is prohibited.
3711 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3716 if (STp
->ready
!= ST_READY
) {
3717 if (STp
->ready
== ST_NO_TAPE
)
3718 retval
= (-ENOMEDIUM
);
3723 STm
= &(STp
->modes
[STp
->current_mode
]);
3724 if (!STm
->defined
) {
3730 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3735 /* Must have initialized medium */
3736 if (!STp
->header_ok
) {
3741 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3742 STp
->door_locked
= ST_LOCKED_AUTO
;
3744 STps
= &(STp
->ps
[STp
->partition
]);
3745 if (STps
->rw
== ST_WRITING
) {
3746 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3750 /* FIXME -- this may leave the tape without EOD and up2date headers */
3753 if ((count
% STp
->block_size
) != 0) {
3755 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3756 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3760 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3761 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3762 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3764 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3765 STps
->eof
>= ST_EOD_1
) {
3766 if (STps
->eof
< ST_EOD
) {
3771 retval
= (-EIO
); /* EOM or Blank Check */
3775 /* Check the buffer writability before any tape movement. Don't alter
3777 if (copy_from_user(&i
, buf
, 1) != 0 ||
3778 copy_to_user (buf
, &i
, 1) != 0 ||
3779 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3780 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3785 /* Loop until enough data in buffer or a special condition found */
3786 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3788 /* Get new data if the buffer is empty */
3789 if ((STp
->buffer
)->buffer_bytes
== 0) {
3790 if (STps
->eof
== ST_FM_HIT
)
3792 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3793 if (special
< 0) { /* No need to continue read */
3794 STp
->frame_in_buffer
= 0;
3800 /* Move the data from driver buffer to user buffer */
3801 if ((STp
->buffer
)->buffer_bytes
> 0) {
3803 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3804 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3805 STps
->eof
, (STp
->buffer
)->buffer_bytes
, (int) (count
- total
));
3807 /* force multiple of block size, note block_size may have been adjusted */
3808 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3809 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3810 STp
->block_size
) * STp
->block_size
;
3812 if (transfer
== 0) {
3814 "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n",
3815 name
, count
, STp
->block_size
< 1024?
3816 STp
->block_size
:STp
->block_size
/1024,
3817 STp
->block_size
<1024?'b':'k');
3820 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3825 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3826 STps
->drv_block
+= transfer
/ STp
->block_size
;
3832 if ((STp
->buffer
)->buffer_bytes
== 0) {
3835 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3836 name
, STp
->frame_seq_number
);
3838 STp
->frame_in_buffer
= 0;
3839 STp
->frame_seq_number
++; /* frame to look for next time */
3841 } /* for (total = 0, special = 0; total < count && !special; ) */
3843 /* Change the eof state if no data from tape or buffer */
3845 if (STps
->eof
== ST_FM_HIT
) {
3846 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3847 STps
->drv_block
= 0;
3848 if (STps
->drv_file
>= 0)
3851 else if (STps
->eof
== ST_EOD_1
) {
3852 STps
->eof
= ST_EOD_2
;
3853 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3855 STps
->drv_block
= 0;
3857 else if (STps
->eof
== ST_EOD_2
)
3860 else if (STps
->eof
== ST_FM
)
3861 STps
->eof
= ST_NOEOF
;
3866 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3868 mutex_unlock(&STp
->lock
);
3874 /* Set the driver options */
3875 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3878 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3879 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3880 STm
->do_read_ahead
);
3882 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3883 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3885 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3886 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3887 STp
->scsi2_logical
);
3889 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3892 "%s:D: debugging: %d\n",
3898 static int osst_set_options(struct osst_tape
*STp
, long options
)
3902 struct st_modedef
* STm
;
3903 char * name
= tape_name(STp
);
3905 STm
= &(STp
->modes
[STp
->current_mode
]);
3906 if (!STm
->defined
) {
3907 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3911 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3912 name
, STp
->current_mode
);
3916 code
= options
& MT_ST_OPTIONS
;
3917 if (code
== MT_ST_BOOLEANS
) {
3918 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3919 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3920 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3921 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3922 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3923 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3924 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3925 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3926 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3927 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3928 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3929 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3930 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3932 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3934 osst_log_options(STp
, STm
, name
);
3936 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3937 value
= (code
== MT_ST_SETBOOLEANS
);
3938 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3939 STm
->do_buffer_writes
= value
;
3940 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3941 STm
->do_async_writes
= value
;
3942 if ((options
& MT_ST_DEF_WRITES
) != 0)
3943 STm
->defaults_for_writes
= value
;
3944 if ((options
& MT_ST_READ_AHEAD
) != 0)
3945 STm
->do_read_ahead
= value
;
3946 if ((options
& MT_ST_TWO_FM
) != 0)
3947 STp
->two_fm
= value
;
3948 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3949 STp
->fast_mteom
= value
;
3950 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3951 STp
->do_auto_lock
= value
;
3952 if ((options
& MT_ST_CAN_BSR
) != 0)
3953 STp
->can_bsr
= value
;
3954 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3955 STp
->omit_blklims
= value
;
3956 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3957 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3958 STp
->can_partitions
= value
;
3959 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3960 STp
->scsi2_logical
= value
;
3961 if ((options
& MT_ST_SYSV
) != 0)
3964 if ((options
& MT_ST_DEBUGGING
) != 0)
3967 osst_log_options(STp
, STm
, name
);
3969 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3970 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3971 if (value
< 1 || value
> osst_buffer_size
) {
3972 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3976 STp
->write_threshold
= value
;
3977 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3980 else if (code
== MT_ST_DEF_BLKSIZE
) {
3981 value
= (options
& ~MT_ST_OPTIONS
);
3982 if (value
== ~MT_ST_OPTIONS
) {
3983 STm
->default_blksize
= (-1);
3984 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3987 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3988 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3992 STm
->default_blksize
= value
;
3993 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3994 name
, STm
->default_blksize
);
3997 else if (code
== MT_ST_TIMEOUTS
) {
3998 value
= (options
& ~MT_ST_OPTIONS
);
3999 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
4000 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
4001 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
4002 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
4005 STp
->timeout
= value
* HZ
;
4006 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
4009 else if (code
== MT_ST_DEF_OPTIONS
) {
4010 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
4011 value
= (options
& MT_ST_CLEAR_DEFAULT
);
4012 if (code
== MT_ST_DEF_DENSITY
) {
4013 if (value
== MT_ST_CLEAR_DEFAULT
) {
4014 STm
->default_density
= (-1);
4015 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
4018 STm
->default_density
= value
& 0xff;
4019 printk(KERN_INFO
"%s:I: Density default set to %x\n",
4020 name
, STm
->default_density
);
4023 else if (code
== MT_ST_DEF_DRVBUFFER
) {
4024 if (value
== MT_ST_CLEAR_DEFAULT
) {
4025 STp
->default_drvbuffer
= 0xff;
4026 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
4029 STp
->default_drvbuffer
= value
& 7;
4030 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
4031 name
, STp
->default_drvbuffer
);
4034 else if (code
== MT_ST_DEF_COMPRESSION
) {
4035 if (value
== MT_ST_CLEAR_DEFAULT
) {
4036 STm
->default_compression
= ST_DONT_TOUCH
;
4037 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
4040 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
4041 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
4053 /* Internal ioctl function */
4054 static int osst_int_ioctl(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
4055 unsigned int cmd_in
, unsigned long arg
)
4059 int i
, ioctl_result
;
4061 unsigned char cmd
[MAX_COMMAND_SIZE
];
4062 struct osst_request
* SRpnt
= * aSRpnt
;
4063 struct st_partstat
* STps
;
4064 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
4065 int datalen
= 0, direction
= DMA_NONE
;
4066 char * name
= tape_name(STp
);
4068 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
4069 if (STp
->ready
== ST_NO_TAPE
)
4070 return (-ENOMEDIUM
);
4074 timeout
= STp
->long_timeout
;
4075 STps
= &(STp
->ps
[STp
->partition
]);
4076 fileno
= STps
->drv_file
;
4077 blkno
= STps
->drv_block
;
4078 at_sm
= STps
->at_sm
;
4079 frame_seq_numbr
= STp
->frame_seq_number
;
4080 logical_blk_num
= STp
->logical_blk_num
;
4082 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4085 chg_eof
= 0; /* Changed from the FSF after this */
4089 if (STp
->linux_media
)
4090 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
4092 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
4096 at_sm
&= (arg
== 0);
4100 chg_eof
= 0; /* Changed from the FSF after this */
4104 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
4107 blkno
= (-1); /* We can't know the block number */
4108 at_sm
&= (arg
== 0);
4115 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
4116 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
4118 if (cmd_in
== MTFSR
) {
4119 logical_blk_num
+= arg
;
4120 if (blkno
>= 0) blkno
+= arg
;
4123 logical_blk_num
-= arg
;
4124 if (blkno
>= 0) blkno
-= arg
;
4126 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
4127 fileno
= STps
->drv_file
;
4128 blkno
= STps
->drv_block
;
4129 at_sm
&= (arg
== 0);
4134 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4135 cmd
[2] = (arg
>> 16);
4136 cmd
[3] = (arg
>> 8);
4140 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4141 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4144 blkno
= fileno
= (-1);
4150 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4152 cmd
[2] = (ltmp
>> 16);
4153 cmd
[3] = (ltmp
>> 8);
4159 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4160 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4165 blkno
= fileno
= (-1);
4170 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4171 STp
->write_type
= OS_WRITE_DATA
;
4172 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4177 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4179 for (i
=0; i
<arg
; i
++)
4180 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4181 if (fileno
>= 0) fileno
+= arg
;
4182 if (blkno
>= 0) blkno
= 0;
4186 if (STp
->write_prot
)
4190 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4191 if (cmd_in
== MTWSM
)
4193 cmd
[2] = (arg
>> 16);
4194 cmd
[3] = (arg
>> 8);
4196 timeout
= STp
->timeout
;
4199 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4200 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4205 at_sm
= (cmd_in
== MTWSM
);
4211 cmd
[0] = START_STOP
;
4212 cmd
[1] = 1; /* Don't wait for completion */
4213 if (cmd_in
== MTLOAD
) {
4214 if (STp
->ready
== ST_NO_TAPE
)
4215 cmd
[4] = 4; /* open tray */
4217 cmd
[4] = 1; /* load */
4219 if (cmd_in
== MTRETEN
)
4220 cmd
[4] = 3; /* retension then mount */
4221 if (cmd_in
== MTOFFL
)
4222 cmd
[4] = 4; /* rewind then eject */
4223 timeout
= STp
->timeout
;
4228 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4231 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4234 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4237 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4242 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4247 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4249 return 0; /* Should do something ? */
4254 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4256 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4257 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4258 ioctl_result
= -EIO
;
4261 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4263 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4265 ioctl_result
= -EIO
;
4268 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4269 fileno
= STp
->filemark_cnt
;
4274 if (STp
->write_prot
)
4276 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4277 i
= osst_write_eod(STp
, &SRpnt
);
4278 if (i
< ioctl_result
) ioctl_result
= i
;
4279 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4280 if (i
< ioctl_result
) ioctl_result
= i
;
4281 fileno
= blkno
= at_sm
= 0 ;
4285 cmd
[0] = REZERO_UNIT
; /* rewind */
4289 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4291 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4294 case MTSETBLK
: /* Set block length */
4295 if ((STps
->drv_block
== 0 ) &&
4297 ((STp
->buffer
)->buffer_bytes
== 0) &&
4298 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4299 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4300 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4302 * Only allowed to change the block size if you opened the
4303 * device at the beginning of a file before writing anything.
4304 * Note, that when reading, changing block_size is futile,
4305 * as the size used when writing overrides it.
4307 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4308 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4309 name
, STp
->block_size
);
4312 case MTSETDENSITY
: /* Set tape density */
4313 case MTSETDRVBUFFER
: /* Set drive buffering */
4314 case SET_DENS_AND_BLK
: /* Set density and block size */
4316 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4317 return (-EIO
); /* Not allowed if data in buffer */
4318 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4319 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4320 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4321 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4322 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4323 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4326 return 0; /* FIXME silently ignore if block size didn't change */
4332 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4334 ioctl_result
= (STp
->buffer
)->syscall_result
;
4338 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4340 return ioctl_result
;
4343 if (!ioctl_result
) { /* SCSI command successful */
4344 STp
->frame_seq_number
= frame_seq_numbr
;
4345 STp
->logical_blk_num
= logical_blk_num
;
4351 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4354 if (!ioctl_result
) { /* success */
4356 if (cmd_in
== MTFSFM
) {
4360 if (cmd_in
== MTBSFM
) {
4364 STps
->drv_block
= blkno
;
4365 STps
->drv_file
= fileno
;
4366 STps
->at_sm
= at_sm
;
4368 if (cmd_in
== MTEOM
)
4370 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4371 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4373 STp
->logical_blk_num
++;
4374 STp
->frame_seq_number
++;
4375 STp
->frame_in_buffer
= 0;
4376 STp
->buffer
->read_pointer
= 0;
4378 else if (cmd_in
== MTFSF
)
4379 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4381 STps
->eof
= ST_NOEOF
;
4383 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4384 STp
->rew_at_close
= 0;
4385 else if (cmd_in
== MTLOAD
) {
4386 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4387 STp
->ps
[i
].rw
= ST_IDLE
;
4388 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4393 if (cmd_in
== MTREW
) {
4394 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4395 if (ioctl_result
> 0)
4399 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4400 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4401 STps
->drv_file
= STps
->drv_block
= -1;
4403 STps
->drv_file
= STps
->drv_block
= 0;
4404 STps
->eof
= ST_NOEOF
;
4405 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4406 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4407 STps
->drv_file
= STps
->drv_block
= -1;
4409 STps
->drv_file
= STp
->filemark_cnt
;
4410 STps
->drv_block
= 0;
4413 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4414 STps
->drv_file
= STps
->drv_block
= (-1);
4415 STps
->eof
= ST_NOEOF
;
4417 } else if (cmd_in
== MTERASE
) {
4419 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4420 if (SRpnt
->sense
[2] & 0x40) {
4421 STps
->eof
= ST_EOM_OK
;
4422 STps
->drv_block
= 0;
4425 STps
->eof
= ST_NOEOF
;
4427 if ((SRpnt
->sense
[2] & 0x0f) == BLANK_CHECK
)
4430 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4431 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4435 return ioctl_result
;
4439 /* Open the device */
4440 static int __os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4442 unsigned short flags
;
4443 int i
, b_size
, new_session
= 0, retval
= 0;
4444 unsigned char cmd
[MAX_COMMAND_SIZE
];
4445 struct osst_request
* SRpnt
= NULL
;
4446 struct osst_tape
* STp
;
4447 struct st_modedef
* STm
;
4448 struct st_partstat
* STps
;
4450 int dev
= TAPE_NR(inode
);
4451 int mode
= TAPE_MODE(inode
);
4454 * We really want to do nonseekable_open(inode, filp); here, but some
4455 * versions of tar incorrectly call lseek on tapes and bail out if that
4456 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4458 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4460 write_lock(&os_scsi_tapes_lock
);
4461 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4462 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4463 write_unlock(&os_scsi_tapes_lock
);
4467 name
= tape_name(STp
);
4470 write_unlock(&os_scsi_tapes_lock
);
4472 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4476 if (scsi_device_get(STp
->device
)) {
4477 write_unlock(&os_scsi_tapes_lock
);
4479 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4483 filp
->private_data
= STp
;
4485 write_unlock(&os_scsi_tapes_lock
);
4486 STp
->rew_at_close
= TAPE_REWIND(inode
);
4488 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4492 if (mode
!= STp
->current_mode
) {
4495 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4496 name
, STp
->current_mode
, mode
);
4499 STp
->current_mode
= mode
;
4501 STm
= &(STp
->modes
[STp
->current_mode
]);
4503 flags
= filp
->f_flags
;
4504 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4506 STp
->raw
= TAPE_IS_RAW(inode
);
4510 /* Allocate data segments for this device's tape buffer */
4511 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4512 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4513 retval
= (-EOVERFLOW
);
4516 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4517 for (i
= 0, b_size
= 0;
4518 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4519 b_size
+= STp
->buffer
->sg
[i
++].length
);
4520 STp
->buffer
->aux
= (os_aux_t
*) (page_address(sg_page(&STp
->buffer
->sg
[i
])) + OS_DATA_SIZE
- b_size
);
4522 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4523 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4524 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4525 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4528 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4529 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4533 STp
->buffer
->writing
= 0;
4534 STp
->buffer
->syscall_result
= 0;
4536 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4537 STps
= &(STp
->ps
[i
]);
4540 STp
->ready
= ST_READY
;
4542 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4545 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4546 cmd
[0] = TEST_UNIT_READY
;
4548 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4550 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4553 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4554 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4555 SRpnt
->sense
[12] == 4 ) {
4557 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sense
[13]);
4559 if (filp
->f_flags
& O_NONBLOCK
) {
4563 if (SRpnt
->sense
[13] == 2) { /* initialize command required (LOAD) */
4564 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4565 cmd
[0] = START_STOP
;
4568 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4569 STp
->timeout
, MAX_RETRIES
, 1);
4571 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sense
[13]==1?15:3) * 60, 0);
4573 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4574 (SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4576 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4580 for (i
=0; i
< 10; i
++) {
4582 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4583 cmd
[0] = TEST_UNIT_READY
;
4585 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4586 STp
->timeout
, MAX_RETRIES
, 1);
4587 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4588 (SRpnt
->sense
[2] & 0x0f) != UNIT_ATTENTION
)
4592 STp
->pos_unknown
= 0;
4593 STp
->partition
= STp
->new_partition
= 0;
4594 if (STp
->can_partitions
)
4595 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4596 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4597 STps
= &(STp
->ps
[i
]);
4598 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4599 STps
->eof
= ST_NOEOF
;
4601 STps
->last_block_valid
= 0;
4602 STps
->drv_block
= 0;
4603 STps
->drv_file
= 0 ;
4606 STp
->recover_count
= 0;
4607 STp
->abort_count
= 0;
4610 * if we have valid headers from before, and the drive/tape seem untouched,
4611 * open without reconfiguring and re-reading the headers
4613 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4614 !SRpnt
->result
&& SRpnt
->sense
[0] == 0) {
4616 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4617 cmd
[0] = MODE_SENSE
;
4619 cmd
[2] = VENDOR_IDENT_PAGE
;
4620 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4622 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4624 if (STp
->buffer
->syscall_result
||
4625 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4626 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4627 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4628 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4630 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4631 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4632 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4633 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4634 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4638 i
= STp
->first_frame_position
;
4639 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4640 if (STp
->door_locked
== ST_UNLOCKED
) {
4641 if (do_door_lock(STp
, 1))
4642 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4644 STp
->door_locked
= ST_LOCKED_AUTO
;
4646 if (!STp
->frame_in_buffer
) {
4647 STp
->block_size
= (STm
->default_blksize
> 0) ?
4648 STm
->default_blksize
: OS_DATA_SIZE
;
4649 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4651 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4653 osst_release_request(SRpnt
);
4657 if (i
!= STp
->first_frame_position
)
4658 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4659 name
, i
, STp
->first_frame_position
);
4665 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4666 (SRpnt
->sense
[2] != 2 || SRpnt
->sense
[12] != 0x3A) ) {
4668 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4669 cmd
[0] = MODE_SELECT
;
4671 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4673 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4674 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4675 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4676 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4677 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4678 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4679 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4680 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4683 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4685 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4689 for (i
=0; i
< 10; i
++) {
4691 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4692 cmd
[0] = TEST_UNIT_READY
;
4694 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4695 STp
->timeout
, MAX_RETRIES
, 1);
4696 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4697 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
)
4700 if ((SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) {
4703 STp
->pos_unknown
= 0;
4704 STp
->partition
= STp
->new_partition
= 0;
4705 if (STp
->can_partitions
)
4706 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4707 for (j
= 0; j
< ST_NBR_PARTITIONS
; j
++) {
4708 STps
= &(STp
->ps
[j
]);
4710 STps
->eof
= ST_NOEOF
;
4712 STps
->last_block_valid
= 0;
4713 STps
->drv_block
= 0;
4714 STps
->drv_file
= 0 ;
4721 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4722 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4724 if ((STp
->buffer
)->syscall_result
!= 0) {
4725 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4726 (SRpnt
->sense
[0] & 0x70) == 0x70 &&
4727 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4728 SRpnt
->sense
[12] == 0x3a) { /* Check ASC */
4729 STp
->ready
= ST_NO_TAPE
;
4731 STp
->ready
= ST_NOT_READY
;
4732 osst_release_request(SRpnt
);
4734 STp
->density
= 0; /* Clear the erroneous "residue" */
4735 STp
->write_prot
= 0;
4736 STp
->block_size
= 0;
4737 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4738 STp
->partition
= STp
->new_partition
= 0;
4739 STp
->door_locked
= ST_UNLOCKED
;
4743 osst_configure_onstream(STp
, &SRpnt
);
4745 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4746 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4747 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4748 STp
->buffer
->buffer_bytes
=
4749 STp
->buffer
->read_pointer
=
4750 STp
->frame_in_buffer
= 0;
4754 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4755 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4756 (STp
->buffer
)->buffer_blocks
);
4759 if (STp
->drv_write_prot
) {
4760 STp
->write_prot
= 1;
4763 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4765 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4771 if (new_session
) { /* Change the drive parameters for the new mode */
4774 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4776 STp
->density_changed
= STp
->blksize_changed
= 0;
4777 STp
->compression_changed
= 0;
4781 * properly position the tape and check the ADR headers
4783 if (STp
->door_locked
== ST_UNLOCKED
) {
4784 if (do_door_lock(STp
, 1))
4785 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4787 STp
->door_locked
= ST_LOCKED_AUTO
;
4790 osst_analyze_headers(STp
, &SRpnt
);
4792 osst_release_request(SRpnt
);
4799 osst_release_request(SRpnt
);
4800 normalize_buffer(STp
->buffer
);
4803 scsi_device_put(STp
->device
);
4808 /* BKL pushdown: spaghetti avoidance wrapper */
4809 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4813 mutex_lock(&osst_int_mutex
);
4814 ret
= __os_scsi_tape_open(inode
, filp
);
4815 mutex_unlock(&osst_int_mutex
);
4821 /* Flush the tape buffer before close */
4822 static int os_scsi_tape_flush(struct file
* filp
, fl_owner_t id
)
4824 int result
= 0, result2
;
4825 struct osst_tape
* STp
= filp
->private_data
;
4826 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4827 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4828 struct osst_request
* SRpnt
= NULL
;
4829 char * name
= tape_name(STp
);
4831 if (file_count(filp
) > 1)
4834 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4835 STp
->write_type
= OS_WRITE_DATA
;
4836 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4837 if (result
!= 0 && result
!= (-ENOSPC
))
4840 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4844 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4845 name
, (long)(filp
->f_pos
));
4846 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4847 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4850 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4853 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4854 name
, 1+STp
->two_fm
);
4857 else if (!STp
->rew_at_close
) {
4858 STps
= &(STp
->ps
[STp
->partition
]);
4859 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4861 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4862 else if (STps
->eof
== ST_FM_HIT
) {
4863 result
= cross_eof(STp
, &SRpnt
, 0);
4865 if (STps
->drv_file
>= 0)
4867 STps
->drv_block
= 0;
4871 STps
->eof
= ST_NOEOF
;
4874 else if ((STps
->eof
== ST_NOEOF
&&
4875 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4876 STps
->eof
== ST_FM_HIT
) {
4877 if (STps
->drv_file
>= 0)
4879 STps
->drv_block
= 0;
4885 if (STp
->rew_at_close
) {
4886 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4887 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4888 if (result
== 0 && result2
< 0)
4891 if (SRpnt
) osst_release_request(SRpnt
);
4893 if (STp
->abort_count
|| STp
->recover_count
) {
4894 printk(KERN_INFO
"%s:I:", name
);
4895 if (STp
->abort_count
)
4896 printk(" %d unrecovered errors", STp
->abort_count
);
4897 if (STp
->recover_count
)
4898 printk(" %d recovered errors", STp
->recover_count
);
4899 if (STp
->write_count
)
4900 printk(" in %d frames written", STp
->write_count
);
4901 if (STp
->read_count
)
4902 printk(" in %d frames read", STp
->read_count
);
4904 STp
->recover_count
= 0;
4905 STp
->abort_count
= 0;
4907 STp
->write_count
= 0;
4908 STp
->read_count
= 0;
4914 /* Close the device and release it */
4915 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4918 struct osst_tape
* STp
= filp
->private_data
;
4920 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4921 do_door_lock(STp
, 0);
4926 normalize_buffer(STp
->buffer
);
4927 write_lock(&os_scsi_tapes_lock
);
4929 write_unlock(&os_scsi_tapes_lock
);
4931 scsi_device_put(STp
->device
);
4937 /* The ioctl command */
4938 static long osst_ioctl(struct file
* file
,
4939 unsigned int cmd_in
, unsigned long arg
)
4941 int i
, cmd_nr
, cmd_type
, blk
, retval
= 0;
4942 struct st_modedef
* STm
;
4943 struct st_partstat
* STps
;
4944 struct osst_request
* SRpnt
= NULL
;
4945 struct osst_tape
* STp
= file
->private_data
;
4946 char * name
= tape_name(STp
);
4947 void __user
* p
= (void __user
*)arg
;
4949 mutex_lock(&osst_int_mutex
);
4950 if (mutex_lock_interruptible(&STp
->lock
)) {
4951 mutex_unlock(&osst_int_mutex
);
4952 return -ERESTARTSYS
;
4956 if (debugging
&& !STp
->in_use
) {
4957 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4962 STm
= &(STp
->modes
[STp
->current_mode
]);
4963 STps
= &(STp
->ps
[STp
->partition
]);
4966 * If we are in the middle of error recovery, don't let anyone
4967 * else try and use this device. Also, if error recovery fails, it
4968 * may try and take the device offline, in which case all further
4969 * access to the device is prohibited.
4971 retval
= scsi_ioctl_block_when_processing_errors(STp
->device
, cmd_in
,
4972 file
->f_flags
& O_NDELAY
);
4976 cmd_type
= _IOC_TYPE(cmd_in
);
4977 cmd_nr
= _IOC_NR(cmd_in
);
4979 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4980 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4982 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4986 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4991 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
4997 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
4998 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
5003 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
5008 if (!STp
->pos_unknown
) {
5010 if (STps
->eof
== ST_FM_HIT
) {
5011 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
5013 if (STps
->drv_file
>= 0)
5014 STps
->drv_file
+= 1;
5016 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
5018 if (STps
->drv_file
>= 0)
5019 STps
->drv_file
+= 1;
5023 if (mtc
.mt_op
== MTSEEK
) {
5024 /* Old position must be restored if partition will be changed */
5025 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
5028 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
5029 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
5030 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
5031 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
5032 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
5033 mtc
.mt_op
== MTCOMPRESSION
;
5035 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
5043 * If there was a bus reset, block further access
5044 * to this device. If the user wants to rewind the tape,
5045 * then reset the flag and allow access again.
5047 if(mtc
.mt_op
!= MTREW
&&
5048 mtc
.mt_op
!= MTOFFL
&&
5049 mtc
.mt_op
!= MTRETEN
&&
5050 mtc
.mt_op
!= MTERASE
&&
5051 mtc
.mt_op
!= MTSEEK
&&
5052 mtc
.mt_op
!= MTEOM
) {
5057 /* remove this when the midlevel properly clears was_reset */
5058 STp
->device
->was_reset
= 0;
5061 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
5062 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
5063 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
5064 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
5065 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
5068 * The user tells us to move to another position on the tape.
5069 * If we were appending to the tape content, that would leave
5070 * the tape without proper end, in that case write EOD and
5071 * update the header to reflect its position.
5074 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
5075 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
5076 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
5077 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5079 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
5080 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
5081 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5082 i
= osst_write_trailer(STp
, &SRpnt
,
5083 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5085 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5086 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
5087 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5097 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
5098 do_door_lock(STp
, 0); /* Ignore result! */
5100 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
5101 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
5102 retval
= osst_set_options(STp
, mtc
.mt_count
);
5106 if (mtc
.mt_op
== MTSETPART
) {
5107 if (mtc
.mt_count
>= STp
->nbr_partitions
)
5110 STp
->new_partition
= mtc
.mt_count
;
5116 if (mtc
.mt_op
== MTMKPART
) {
5117 if (!STp
->can_partitions
) {
5121 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
5122 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5126 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5127 STp
->ps
[i
].rw
= ST_IDLE
;
5128 STp
->ps
[i
].at_sm
= 0;
5129 STp
->ps
[i
].last_block_valid
= 0;
5131 STp
->partition
= STp
->new_partition
= 0;
5132 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
5133 STps
->drv_block
= STps
->drv_file
= 0;
5138 if (mtc
.mt_op
== MTSEEK
) {
5140 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
5142 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
5143 if (!STp
->can_partitions
)
5144 STp
->ps
[0].rw
= ST_IDLE
;
5149 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
5150 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5155 cross_eof(STp
, &SRpnt
, 0);
5157 if (mtc
.mt_op
== MTCOMPRESSION
)
5158 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5160 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5161 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5162 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5166 if (!STm
->defined
) {
5171 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5176 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5177 struct mtget mt_status
;
5179 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5184 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5185 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5186 mt_status
.mt_dsreg
=
5187 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5188 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5189 mt_status
.mt_blkno
= STps
->drv_block
;
5190 mt_status
.mt_fileno
= STps
->drv_file
;
5191 if (STp
->block_size
!= 0) {
5192 if (STps
->rw
== ST_WRITING
)
5193 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5194 else if (STps
->rw
== ST_READING
)
5195 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5196 STp
->block_size
- 1) / STp
->block_size
;
5199 mt_status
.mt_gstat
= 0;
5200 if (STp
->drv_write_prot
)
5201 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5202 if (mt_status
.mt_blkno
== 0) {
5203 if (mt_status
.mt_fileno
== 0)
5204 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5206 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5208 mt_status
.mt_resid
= STp
->partition
;
5209 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5210 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5211 else if (STps
->eof
>= ST_EOM_OK
)
5212 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5213 if (STp
->density
== 1)
5214 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5215 else if (STp
->density
== 2)
5216 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5217 else if (STp
->density
== 3)
5218 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5219 if (STp
->ready
== ST_READY
)
5220 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5221 if (STp
->ready
== ST_NO_TAPE
)
5222 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5224 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5225 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5226 STp
->drv_buffer
!= 0)
5227 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5229 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5235 STp
->recover_erreg
= 0; /* Clear after read */
5238 } /* End of MTIOCGET */
5240 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5241 struct mtpos mt_pos
;
5243 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5248 blk
= osst_get_frame_position(STp
, &SRpnt
);
5250 blk
= osst_get_sector(STp
, &SRpnt
);
5255 mt_pos
.mt_blkno
= blk
;
5256 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5261 if (SRpnt
) osst_release_request(SRpnt
);
5263 mutex_unlock(&STp
->lock
);
5265 retval
= scsi_ioctl(STp
->device
, cmd_in
, p
);
5266 mutex_unlock(&osst_int_mutex
);
5270 if (SRpnt
) osst_release_request(SRpnt
);
5272 mutex_unlock(&STp
->lock
);
5273 mutex_unlock(&osst_int_mutex
);
5278 #ifdef CONFIG_COMPAT
5279 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5281 struct osst_tape
*STp
= file
->private_data
;
5282 struct scsi_device
*sdev
= STp
->device
;
5283 int ret
= -ENOIOCTLCMD
;
5284 if (sdev
->host
->hostt
->compat_ioctl
) {
5286 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5295 /* Memory handling routines */
5297 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5298 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5302 struct osst_buffer
*tb
;
5304 if (from_initialization
)
5305 priority
= GFP_ATOMIC
;
5307 priority
= GFP_KERNEL
;
5309 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5310 tb
= kzalloc(i
, priority
);
5312 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5316 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5317 tb
->use_sg
= max_sg
;
5320 tb
->buffer_size
= 0;
5324 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5325 i
, max_sg
, need_dma
);
5330 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5331 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5333 int segs
, nbr
, max_segs
, b_size
, order
, got
;
5336 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5339 if (STbuffer
->sg_segs
) {
5340 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5341 normalize_buffer(STbuffer
);
5343 /* See how many segments we can use -- need at least two */
5344 nbr
= max_segs
= STbuffer
->use_sg
;
5348 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5350 priority
|= GFP_DMA
;
5352 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5353 big enough to reach the goal (code assumes no segments in place) */
5354 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5355 struct page
*page
= alloc_pages(priority
, order
);
5357 STbuffer
->sg
[0].offset
= 0;
5359 sg_set_page(&STbuffer
->sg
[0], page
, b_size
, 0);
5360 STbuffer
->b_data
= page_address(page
);
5364 if (sg_page(&STbuffer
->sg
[0]) == NULL
) {
5365 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5368 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5369 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5370 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5371 struct page
*page
= alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5372 STbuffer
->sg
[segs
].offset
= 0;
5374 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5377 STbuffer
->buffer_size
= got
;
5379 normalize_buffer(STbuffer
);
5382 sg_set_page(&STbuffer
->sg
[segs
], page
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
, 0);
5383 got
+= STbuffer
->sg
[segs
].length
;
5384 STbuffer
->buffer_size
= got
;
5385 STbuffer
->sg_segs
= ++segs
;
5390 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5391 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5393 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5394 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5395 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5403 /* Release the segments */
5404 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5406 int i
, order
, b_size
;
5408 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5410 for (b_size
= PAGE_SIZE
, order
= 0;
5411 b_size
< STbuffer
->sg
[i
].length
;
5412 b_size
*= 2, order
++);
5414 __free_pages(sg_page(&STbuffer
->sg
[i
]), order
);
5415 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5418 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5419 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5420 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5422 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5426 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5427 negative error code. */
5428 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5430 int i
, cnt
, res
, offset
;
5432 for (i
=0, offset
=st_bp
->buffer_bytes
;
5433 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5434 offset
-= st_bp
->sg
[i
].length
;
5435 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5436 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5439 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5440 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5441 st_bp
->sg
[i
].length
- offset
: do_count
;
5442 res
= copy_from_user(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, ubp
, cnt
);
5446 st_bp
->buffer_bytes
+= cnt
;
5450 if (do_count
) { /* Should never happen */
5451 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5459 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5460 negative error code. */
5461 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5463 int i
, cnt
, res
, offset
;
5465 for (i
=0, offset
=st_bp
->read_pointer
;
5466 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5467 offset
-= st_bp
->sg
[i
].length
;
5468 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5469 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5472 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5473 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5474 st_bp
->sg
[i
].length
- offset
: do_count
;
5475 res
= copy_to_user(ubp
, page_address(sg_page(&st_bp
->sg
[i
])) + offset
, cnt
);
5479 st_bp
->buffer_bytes
-= cnt
;
5480 st_bp
->read_pointer
+= cnt
;
5484 if (do_count
) { /* Should never happen */
5485 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5491 /* Sets the tail of the buffer after fill point to zero.
5492 Returns zero (success) or negative error code. */
5493 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5495 int i
, offset
, do_count
, cnt
;
5497 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5498 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5499 offset
-= st_bp
->sg
[i
].length
;
5500 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5501 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5504 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5505 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5506 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5507 st_bp
->sg
[i
].length
- offset
: do_count
;
5508 memset(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, 0, cnt
);
5512 if (do_count
) { /* Should never happen */
5513 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5519 /* Copy a osst 32K chunk of memory into the buffer.
5520 Returns zero (success) or negative error code. */
5521 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5523 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5525 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5526 cnt
= st_bp
->sg
[i
].length
< do_count
?
5527 st_bp
->sg
[i
].length
: do_count
;
5528 memcpy(page_address(sg_page(&st_bp
->sg
[i
])), ptr
, cnt
);
5532 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5533 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5540 /* Copy a osst 32K chunk of memory from the buffer.
5541 Returns zero (success) or negative error code. */
5542 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5544 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5546 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5547 cnt
= st_bp
->sg
[i
].length
< do_count
?
5548 st_bp
->sg
[i
].length
: do_count
;
5549 memcpy(ptr
, page_address(sg_page(&st_bp
->sg
[i
])), cnt
);
5553 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5554 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5562 /* Module housekeeping */
5564 static void validate_options (void)
5567 osst_max_dev
= max_dev
;
5568 if (write_threshold_kbs
> 0)
5569 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5570 if (osst_write_threshold
> osst_buffer_size
)
5571 osst_write_threshold
= osst_buffer_size
;
5572 if (max_sg_segs
>= OSST_FIRST_SG
)
5573 osst_max_sg_segs
= max_sg_segs
;
5575 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5576 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5581 /* Set the boot options. Syntax: osst=xxx,yyy,...
5582 where xxx is write threshold in 1024 byte blocks,
5583 and yyy is number of s/g segments to use. */
5584 static int __init
osst_setup (char *str
)
5589 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5592 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5593 *parms
[i
].val
= ints
[i
+ 1];
5595 while (stp
!= NULL
) {
5596 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5597 int len
= strlen(parms
[i
].name
);
5598 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5599 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5601 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5605 if (i
>= ARRAY_SIZE(parms
))
5606 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5608 stp
= strchr(stp
, ',');
5617 __setup("osst=", osst_setup
);
5621 static const struct file_operations osst_fops
= {
5622 .owner
= THIS_MODULE
,
5624 .write
= osst_write
,
5625 .unlocked_ioctl
= osst_ioctl
,
5626 #ifdef CONFIG_COMPAT
5627 .compat_ioctl
= osst_compat_ioctl
,
5629 .open
= os_scsi_tape_open
,
5630 .flush
= os_scsi_tape_flush
,
5631 .release
= os_scsi_tape_close
,
5632 .llseek
= noop_llseek
,
5635 static int osst_supports(struct scsi_device
* SDp
)
5637 struct osst_support_data
{
5641 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5644 static struct osst_support_data support_list
[] = {
5645 /* {"XXX", "Yy-", "", NULL}, example */
5649 struct osst_support_data
*rp
;
5651 /* We are willing to drive OnStream SC-x0 as well as the
5652 * * IDE, ParPort, FireWire, USB variants, if accessible by
5653 * * emulation layer (ide-scsi, usb-storage, ...) */
5655 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5656 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5657 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5658 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5664 * sysfs support for osst driver parameter information
5667 static ssize_t
osst_version_show(struct device_driver
*ddd
, char *buf
)
5669 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5672 static DRIVER_ATTR(version
, S_IRUGO
, osst_version_show
, NULL
);
5674 static int osst_create_sysfs_files(struct device_driver
*sysfs
)
5676 return driver_create_file(sysfs
, &driver_attr_version
);
5679 static void osst_remove_sysfs_files(struct device_driver
*sysfs
)
5681 driver_remove_file(sysfs
, &driver_attr_version
);
5685 * sysfs support for accessing ADR header information
5688 static ssize_t
osst_adr_rev_show(struct device
*dev
,
5689 struct device_attribute
*attr
, char *buf
)
5691 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5694 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5695 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5699 DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5701 static ssize_t
osst_linux_media_version_show(struct device
*dev
,
5702 struct device_attribute
*attr
,
5705 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5708 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5709 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5713 DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5715 static ssize_t
osst_capacity_show(struct device
*dev
,
5716 struct device_attribute
*attr
, char *buf
)
5718 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5721 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5722 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5726 DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5728 static ssize_t
osst_first_data_ppos_show(struct device
*dev
,
5729 struct device_attribute
*attr
,
5732 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5735 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5736 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5740 DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5742 static ssize_t
osst_eod_frame_ppos_show(struct device
*dev
,
5743 struct device_attribute
*attr
,
5746 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5749 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5750 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5754 DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5756 static ssize_t
osst_filemark_cnt_show(struct device
*dev
,
5757 struct device_attribute
*attr
, char *buf
)
5759 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5762 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5763 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5767 DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5769 static struct class *osst_sysfs_class
;
5771 static int osst_sysfs_init(void)
5773 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5774 if (IS_ERR(osst_sysfs_class
)) {
5775 printk(KERN_ERR
"osst :W: Unable to register sysfs class\n");
5776 return PTR_ERR(osst_sysfs_class
);
5782 static void osst_sysfs_destroy(dev_t dev
)
5784 device_destroy(osst_sysfs_class
, dev
);
5787 static int osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5789 struct device
*osst_member
;
5792 osst_member
= device_create(osst_sysfs_class
, device
, dev
, STp
,
5794 if (IS_ERR(osst_member
)) {
5795 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5796 return PTR_ERR(osst_member
);
5799 err
= device_create_file(osst_member
, &dev_attr_ADR_rev
);
5802 err
= device_create_file(osst_member
, &dev_attr_media_version
);
5805 err
= device_create_file(osst_member
, &dev_attr_capacity
);
5808 err
= device_create_file(osst_member
, &dev_attr_BOT_frame
);
5811 err
= device_create_file(osst_member
, &dev_attr_EOD_frame
);
5814 err
= device_create_file(osst_member
, &dev_attr_file_count
);
5821 osst_sysfs_destroy(dev
);
5825 static void osst_sysfs_cleanup(void)
5827 class_destroy(osst_sysfs_class
);
5831 * osst startup / cleanup code
5834 static int osst_probe(struct device
*dev
)
5836 struct scsi_device
* SDp
= to_scsi_device(dev
);
5837 struct osst_tape
* tpnt
;
5838 struct st_modedef
* STm
;
5839 struct st_partstat
* STps
;
5840 struct osst_buffer
* buffer
;
5841 struct gendisk
* drive
;
5842 int i
, dev_num
, err
= -ENODEV
;
5844 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5847 drive
= alloc_disk(1);
5849 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5853 /* if this is the first attach, build the infrastructure */
5854 write_lock(&os_scsi_tapes_lock
);
5855 if (os_scsi_tapes
== NULL
) {
5856 os_scsi_tapes
= kmalloc(osst_max_dev
* sizeof(struct osst_tape
*), GFP_ATOMIC
);
5857 if (os_scsi_tapes
== NULL
) {
5858 write_unlock(&os_scsi_tapes_lock
);
5859 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5862 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5865 if (osst_nr_dev
>= osst_max_dev
) {
5866 write_unlock(&os_scsi_tapes_lock
);
5867 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5871 /* find a free minor number */
5872 for (i
= 0; i
< osst_max_dev
&& os_scsi_tapes
[i
]; i
++)
5874 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5877 /* allocate a struct osst_tape for this device */
5878 tpnt
= kzalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5880 write_unlock(&os_scsi_tapes_lock
);
5881 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5885 /* allocate a buffer for this device */
5886 i
= SDp
->host
->sg_tablesize
;
5887 if (osst_max_sg_segs
< i
)
5888 i
= osst_max_sg_segs
;
5889 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5890 if (buffer
== NULL
) {
5891 write_unlock(&os_scsi_tapes_lock
);
5892 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5896 os_scsi_tapes
[dev_num
] = tpnt
;
5897 tpnt
->buffer
= buffer
;
5899 drive
->private_data
= &tpnt
->driver
;
5900 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5901 tpnt
->driver
= &osst_template
;
5902 tpnt
->drive
= drive
;
5904 tpnt
->capacity
= 0xfffff;
5906 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5907 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5909 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5910 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5911 tpnt
->can_partitions
= 0;
5912 tpnt
->two_fm
= OSST_TWO_FM
;
5913 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5914 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5915 tpnt
->write_threshold
= osst_write_threshold
;
5916 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5917 tpnt
->partition
= 0;
5918 tpnt
->new_partition
= 0;
5919 tpnt
->nbr_partitions
= 0;
5920 tpnt
->min_block
= 512;
5921 tpnt
->max_block
= OS_DATA_SIZE
;
5922 tpnt
->timeout
= OSST_TIMEOUT
;
5923 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5925 /* Recognize OnStream tapes */
5926 /* We don't need to test for OnStream, as this has been done in detect () */
5927 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5928 tpnt
->omit_blklims
= 1;
5930 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5931 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5932 tpnt
->frame_in_buffer
= 0;
5933 tpnt
->header_ok
= 0;
5934 tpnt
->linux_media
= 0;
5935 tpnt
->header_cache
= NULL
;
5937 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5938 STm
= &(tpnt
->modes
[i
]);
5940 STm
->sysv
= OSST_SYSV
;
5941 STm
->defaults_for_writes
= 0;
5942 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5943 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5944 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5945 STm
->default_compression
= ST_DONT_TOUCH
;
5946 STm
->default_blksize
= 512;
5947 STm
->default_density
= (-1); /* No forced density */
5950 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5951 STps
= &(tpnt
->ps
[i
]);
5953 STps
->eof
= ST_NOEOF
;
5955 STps
->last_block_valid
= 0;
5956 STps
->drv_block
= (-1);
5957 STps
->drv_file
= (-1);
5960 tpnt
->current_mode
= 0;
5961 tpnt
->modes
[0].defined
= 1;
5962 tpnt
->modes
[2].defined
= 1;
5963 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5965 mutex_init(&tpnt
->lock
);
5967 write_unlock(&os_scsi_tapes_lock
);
5973 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5975 goto out_free_buffer
;
5977 /* No-rewind entry */
5978 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5979 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5981 goto out_free_sysfs1
;
5984 sdev_printk(KERN_INFO
, SDp
,
5985 "osst :I: Attached OnStream %.5s tape as %s\n",
5986 SDp
->model
, tape_name(tpnt
));
5991 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, dev_num
));
5999 static int osst_remove(struct device
*dev
)
6001 struct scsi_device
* SDp
= to_scsi_device(dev
);
6002 struct osst_tape
* tpnt
;
6005 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
6008 write_lock(&os_scsi_tapes_lock
);
6009 for(i
=0; i
< osst_max_dev
; i
++) {
6010 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
6011 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
6012 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
6013 tpnt
->device
= NULL
;
6014 put_disk(tpnt
->drive
);
6015 os_scsi_tapes
[i
] = NULL
;
6017 write_unlock(&os_scsi_tapes_lock
);
6018 vfree(tpnt
->header_cache
);
6020 normalize_buffer(tpnt
->buffer
);
6021 kfree(tpnt
->buffer
);
6027 write_unlock(&os_scsi_tapes_lock
);
6031 static int __init
init_osst(void)
6035 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
6039 err
= osst_sysfs_init();
6043 err
= register_chrdev(OSST_MAJOR
, "osst", &osst_fops
);
6045 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
6049 err
= scsi_register_driver(&osst_template
.gendrv
);
6051 goto err_out_chrdev
;
6053 err
= osst_create_sysfs_files(&osst_template
.gendrv
);
6055 goto err_out_scsidrv
;
6060 scsi_unregister_driver(&osst_template
.gendrv
);
6062 unregister_chrdev(OSST_MAJOR
, "osst");
6064 osst_sysfs_cleanup();
6068 static void __exit
exit_osst (void)
6071 struct osst_tape
* STp
;
6073 osst_remove_sysfs_files(&osst_template
.gendrv
);
6074 scsi_unregister_driver(&osst_template
.gendrv
);
6075 unregister_chrdev(OSST_MAJOR
, "osst");
6076 osst_sysfs_cleanup();
6078 if (os_scsi_tapes
) {
6079 for (i
=0; i
< osst_max_dev
; ++i
) {
6080 if (!(STp
= os_scsi_tapes
[i
])) continue;
6081 /* This is defensive, supposed to happen during detach */
6082 vfree(STp
->header_cache
);
6084 normalize_buffer(STp
->buffer
);
6087 put_disk(STp
->drive
);
6090 kfree(os_scsi_tapes
);
6092 printk(KERN_INFO
"osst :I: Unloaded.\n");
6095 module_init(init_osst
);
6096 module_exit(exit_osst
);