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/signal.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 <linux/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)-1))
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
, blk_status_t status
)
325 struct scsi_request
*rq
= scsi_req(req
);
326 struct osst_request
*SRpnt
= req
->end_io_data
;
327 struct osst_tape
*STp
= SRpnt
->stp
;
328 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
330 STp
->buffer
->cmdstat
.midlevel_result
= SRpnt
->result
= rq
->result
;
332 STp
->write_pending
= 0;
335 memcpy(SRpnt
->sense
, rq
->sense
, SCSI_SENSE_BUFFERSIZE
);
337 complete(SRpnt
->waiting
);
341 blk_rq_unmap_user(SRpnt
->bio
);
344 blk_put_request(req
);
347 /* osst_request memory management */
348 static struct osst_request
*osst_allocate_request(void)
350 return kzalloc(sizeof(struct osst_request
), GFP_KERNEL
);
353 static void osst_release_request(struct osst_request
*streq
)
358 static int osst_execute(struct osst_request
*SRpnt
, const unsigned char *cmd
,
359 int cmd_len
, int data_direction
, void *buffer
, unsigned bufflen
,
360 int use_sg
, int timeout
, int retries
)
363 struct scsi_request
*rq
;
364 struct page
**pages
= NULL
;
365 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
368 int write
= (data_direction
== DMA_TO_DEVICE
);
370 req
= blk_get_request(SRpnt
->stp
->device
->request_queue
,
371 write
? REQ_OP_SCSI_OUT
: REQ_OP_SCSI_IN
, 0);
373 return DRIVER_ERROR
<< 24;
376 req
->rq_flags
|= RQF_QUIET
;
381 struct scatterlist
*sg
, *sgl
= (struct scatterlist
*)buffer
;
384 pages
= kcalloc(use_sg
, sizeof(struct page
*), GFP_KERNEL
);
388 for_each_sg(sgl
, sg
, use_sg
, i
)
389 pages
[i
] = sg_page(sg
);
391 mdata
->null_mapped
= 1;
393 mdata
->page_order
= get_order(sgl
[0].length
);
395 DIV_ROUND_UP(bufflen
, PAGE_SIZE
<< mdata
->page_order
);
398 err
= blk_rq_map_user(req
->q
, req
, mdata
, NULL
, bufflen
, GFP_KERNEL
);
403 SRpnt
->bio
= req
->bio
;
404 mdata
->pages
= pages
;
406 } else if (bufflen
) {
407 err
= blk_rq_map_kern(req
->q
, req
, buffer
, bufflen
, GFP_KERNEL
);
412 rq
->cmd_len
= cmd_len
;
413 memset(rq
->cmd
, 0, BLK_MAX_CDB
); /* ATAPI hates garbage after CDB */
414 memcpy(rq
->cmd
, cmd
, rq
->cmd_len
);
415 req
->timeout
= timeout
;
416 rq
->retries
= retries
;
417 req
->end_io_data
= SRpnt
;
419 blk_execute_rq_nowait(req
->q
, NULL
, req
, 1, osst_end_async
);
422 blk_put_request(req
);
423 return DRIVER_ERROR
<< 24;
426 /* Do the scsi command. Waits until command performed if do_wait is true.
427 Otherwise osst_write_behind_check() is used to check that the command
429 static struct osst_request
* osst_do_scsi(struct osst_request
*SRpnt
, struct osst_tape
*STp
,
430 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
433 unsigned short use_sg
;
434 #ifdef OSST_INJECT_ERRORS
435 static int inject
= 0;
436 static int repeat
= 0;
438 struct completion
*waiting
;
440 /* if async, make sure there's no command outstanding */
441 if (!do_wait
&& ((STp
->buffer
)->last_SRpnt
)) {
442 printk(KERN_ERR
"%s: Async command already active.\n",
444 if (signal_pending(current
))
445 (STp
->buffer
)->syscall_result
= (-EINTR
);
447 (STp
->buffer
)->syscall_result
= (-EBUSY
);
452 SRpnt
= osst_allocate_request();
454 printk(KERN_ERR
"%s: Can't allocate SCSI request.\n",
456 if (signal_pending(current
))
457 (STp
->buffer
)->syscall_result
= (-EINTR
);
459 (STp
->buffer
)->syscall_result
= (-EBUSY
);
465 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
466 which IO is outstanding. It's nulled out when the IO completes. */
468 (STp
->buffer
)->last_SRpnt
= SRpnt
;
470 waiting
= &STp
->wait
;
471 init_completion(waiting
);
472 SRpnt
->waiting
= waiting
;
474 use_sg
= (bytes
> STp
->buffer
->sg
[0].length
) ? STp
->buffer
->use_sg
: 0;
476 bp
= (char *)&(STp
->buffer
->sg
[0]);
477 if (STp
->buffer
->sg_segs
< use_sg
)
478 use_sg
= STp
->buffer
->sg_segs
;
481 bp
= (STp
->buffer
)->b_data
;
483 memcpy(SRpnt
->cmd
, cmd
, sizeof(SRpnt
->cmd
));
484 STp
->buffer
->cmdstat
.have_sense
= 0;
485 STp
->buffer
->syscall_result
= 0;
487 if (osst_execute(SRpnt
, cmd
, COMMAND_SIZE(cmd
[0]), direction
, bp
, bytes
,
488 use_sg
, timeout
, retries
))
489 /* could not allocate the buffer or request was too large */
490 (STp
->buffer
)->syscall_result
= (-EBUSY
);
492 wait_for_completion(waiting
);
493 SRpnt
->waiting
= NULL
;
494 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
495 #ifdef OSST_INJECT_ERRORS
496 if (STp
->buffer
->syscall_result
== 0 &&
499 ( (++ inject
% 83) == 29 ||
500 (STp
->first_frame_position
== 240
501 /* or STp->read_error_frame to fail again on the block calculated above */ &&
503 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
504 STp
->buffer
->last_result_fatal
= 1;
512 /* Handle the write-behind checking (downs the semaphore) */
513 static void osst_write_behind_check(struct osst_tape
*STp
)
515 struct osst_buffer
* STbuffer
;
517 STbuffer
= STp
->buffer
;
520 if (STp
->write_pending
)
525 wait_for_completion(&(STp
->wait
));
526 STp
->buffer
->last_SRpnt
->waiting
= NULL
;
528 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
530 if (STp
->buffer
->syscall_result
)
531 STp
->buffer
->syscall_result
=
532 osst_write_error_recovery(STp
, &(STp
->buffer
->last_SRpnt
), 1);
534 STp
->first_frame_position
++;
536 osst_release_request(STp
->buffer
->last_SRpnt
);
538 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
539 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
541 STbuffer
->last_SRpnt
= NULL
;
542 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
543 STbuffer
->writing
= 0;
550 /* Onstream specific Routines */
552 * Initialize the OnStream AUX
554 static void osst_init_aux(struct osst_tape
* STp
, int frame_type
, int frame_seq_number
,
555 int logical_blk_num
, int blk_sz
, int blk_cnt
)
557 os_aux_t
*aux
= STp
->buffer
->aux
;
558 os_partition_t
*par
= &aux
->partition
;
559 os_dat_t
*dat
= &aux
->dat
;
561 if (STp
->raw
) return;
563 memset(aux
, 0, sizeof(*aux
));
564 aux
->format_id
= htonl(0);
565 memcpy(aux
->application_sig
, "LIN4", 4);
566 aux
->hdwr
= htonl(0);
567 aux
->frame_type
= frame_type
;
569 switch (frame_type
) {
570 case OS_FRAME_TYPE_HEADER
:
571 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
572 par
->partition_num
= OS_CONFIG_PARTITION
;
573 par
->par_desc_ver
= OS_PARTITION_VERSION
;
574 par
->wrt_pass_cntr
= htons(0xffff);
575 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
576 par
->first_frame_ppos
= htonl(0);
577 par
->last_frame_ppos
= htonl(0xbb7);
578 aux
->frame_seq_num
= htonl(0);
579 aux
->logical_blk_num_high
= htonl(0);
580 aux
->logical_blk_num
= htonl(0);
581 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
583 case OS_FRAME_TYPE_DATA
:
584 case OS_FRAME_TYPE_MARKER
:
589 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
590 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
591 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
592 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
593 dat
->dat_list
[0].reserved
= 0;
594 case OS_FRAME_TYPE_EOD
:
595 aux
->update_frame_cntr
= htonl(0);
596 par
->partition_num
= OS_DATA_PARTITION
;
597 par
->par_desc_ver
= OS_PARTITION_VERSION
;
598 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
599 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
600 par
->last_frame_ppos
= htonl(STp
->capacity
);
601 aux
->frame_seq_num
= htonl(frame_seq_number
);
602 aux
->logical_blk_num_high
= htonl(0);
603 aux
->logical_blk_num
= htonl(logical_blk_num
);
605 default: ; /* probably FILL */
607 aux
->filemark_cnt
= htonl(STp
->filemark_cnt
);
608 aux
->phys_fm
= htonl(0xffffffff);
609 aux
->last_mark_ppos
= htonl(STp
->last_mark_ppos
);
610 aux
->last_mark_lbn
= htonl(STp
->last_mark_lbn
);
614 * Verify that we have the correct tape frame
616 static int osst_verify_frame(struct osst_tape
* STp
, int frame_seq_number
, int quiet
)
618 char * name
= tape_name(STp
);
619 os_aux_t
* aux
= STp
->buffer
->aux
;
620 os_partition_t
* par
= &(aux
->partition
);
621 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
622 unsigned int blk_cnt
, blk_sz
, i
;
625 if (STp
->buffer
->syscall_result
) {
626 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
627 memset(page_address(sg_page(&STp
->buffer
->sg
[i
])),
628 0, STp
->buffer
->sg
[i
].length
);
629 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
631 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
634 if (STp
->buffer
->syscall_result
) {
636 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
640 if (ntohl(aux
->format_id
) != 0) {
642 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
646 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
647 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
649 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
653 if (par
->partition_num
!= OS_DATA_PARTITION
) {
654 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
656 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
657 name
, par
->partition_num
);
662 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
664 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
668 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
670 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
671 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
675 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
676 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
677 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
680 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
685 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
686 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
687 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
688 STp
->first_frame_position
);
691 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
694 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
695 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
700 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
701 STps
->eof
= ST_FM_HIT
;
703 i
= ntohl(aux
->filemark_cnt
);
704 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
705 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
707 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
708 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
709 i
, STp
->first_frame_position
- 1);
711 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
712 if (i
>= STp
->filemark_cnt
)
713 STp
->filemark_cnt
= i
+1;
716 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
717 STps
->eof
= ST_EOD_1
;
718 STp
->frame_in_buffer
= 1;
720 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
721 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
722 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
723 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
724 STp
->buffer
->read_pointer
= 0;
725 STp
->frame_in_buffer
= 1;
727 /* See what block size was used to write file */
728 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
730 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
731 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
732 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
733 STp
->block_size
<1024?'b':'k');
734 STp
->block_size
= blk_sz
;
735 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
737 STps
->eof
= ST_NOEOF
;
739 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
740 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
744 if (STp
->read_error_frame
== 0)
745 STp
->read_error_frame
= STp
->first_frame_position
- 1;
750 * Wait for the unit to become Ready
752 static int osst_wait_ready(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
753 unsigned timeout
, int initial_delay
)
755 unsigned char cmd
[MAX_COMMAND_SIZE
];
756 struct osst_request
* SRpnt
;
757 unsigned long startwait
= jiffies
;
760 char * name
= tape_name(STp
);
762 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
765 if (initial_delay
> 0)
766 msleep(jiffies_to_msecs(initial_delay
));
768 memset(cmd
, 0, MAX_COMMAND_SIZE
);
769 cmd
[0] = TEST_UNIT_READY
;
771 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
773 if (!SRpnt
) return (-EBUSY
);
775 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
776 (( SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
777 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8) ) ||
778 ( SRpnt
->sense
[2] == 6 && SRpnt
->sense
[12] == 0x28 &&
779 SRpnt
->sense
[13] == 0 ) )) {
782 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
783 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
789 memset(cmd
, 0, MAX_COMMAND_SIZE
);
790 cmd
[0] = TEST_UNIT_READY
;
792 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
798 if ( STp
->buffer
->syscall_result
&&
799 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
801 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
802 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
803 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
804 SRpnt
->sense
[12], SRpnt
->sense
[13]);
809 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
815 * Wait for a tape to be inserted in the unit
817 static int osst_wait_for_medium(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, unsigned timeout
)
819 unsigned char cmd
[MAX_COMMAND_SIZE
];
820 struct osst_request
* SRpnt
;
821 unsigned long startwait
= jiffies
;
824 char * name
= tape_name(STp
);
826 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
829 memset(cmd
, 0, MAX_COMMAND_SIZE
);
830 cmd
[0] = TEST_UNIT_READY
;
832 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
834 if (!SRpnt
) return (-EBUSY
);
836 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
837 SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 0x3a && SRpnt
->sense
[13] == 0 ) {
840 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
841 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
847 memset(cmd
, 0, MAX_COMMAND_SIZE
);
848 cmd
[0] = TEST_UNIT_READY
;
850 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
856 if ( STp
->buffer
->syscall_result
&& SRpnt
->sense
[2] != 2 &&
857 SRpnt
->sense
[12] != 4 && SRpnt
->sense
[13] == 1) {
859 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
860 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
861 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
862 SRpnt
->sense
[12], SRpnt
->sense
[13]);
867 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
872 static int osst_position_tape_and_confirm(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int frame
)
876 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
877 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
878 if (retval
) return (retval
);
879 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
880 return (osst_get_frame_position(STp
, aSRpnt
));
884 * Wait for write(s) to complete
886 static int osst_flush_drive_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
888 unsigned char cmd
[MAX_COMMAND_SIZE
];
889 struct osst_request
* SRpnt
;
891 int delay
= OSST_WAIT_WRITE_COMPLETE
;
893 char * name
= tape_name(STp
);
895 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
898 memset(cmd
, 0, MAX_COMMAND_SIZE
);
899 cmd
[0] = WRITE_FILEMARKS
;
902 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
904 if (!SRpnt
) return (-EBUSY
);
905 if (STp
->buffer
->syscall_result
) {
906 if ((SRpnt
->sense
[2] & 0x0f) == 2 && SRpnt
->sense
[12] == 4) {
907 if (SRpnt
->sense
[13] == 8) {
908 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
911 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
913 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
914 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
919 #define OSST_POLL_PER_SEC 10
920 static int osst_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int curr
, int minlast
, int to
)
922 unsigned long startwait
= jiffies
;
923 char * name
= tape_name(STp
);
925 char notyetprinted
= 1;
927 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
928 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
930 while (time_before (jiffies
, startwait
+ to
*HZ
))
933 result
= osst_get_frame_position(STp
, aSRpnt
);
935 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
936 return 0; /* successful recovery leaves drive ready for frame */
937 if (result
< 0) break;
938 if (STp
->first_frame_position
== curr
&&
940 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
941 (minlast
>= 0 && STp
->cur_frames
> minlast
)
945 if (debugging
|| time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
))
947 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
948 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
949 STp
->last_frame_position
, STp
->cur_frames
,
950 result
, (jiffies
-startwait
)/HZ
,
951 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
956 if (time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
) && notyetprinted
)
958 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
959 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
960 STp
->last_frame_position
, STp
->cur_frames
, result
);
964 msleep(1000 / OSST_POLL_PER_SEC
);
967 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
968 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
969 STp
->last_frame_position
, STp
->cur_frames
,
970 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
975 static int osst_recover_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int writing
)
977 struct osst_request
* SRpnt
;
978 unsigned char cmd
[MAX_COMMAND_SIZE
];
979 unsigned long startwait
= jiffies
;
981 char * name
= tape_name(STp
);
985 char * olddata
= STp
->buffer
->b_data
;
986 int oldsize
= STp
->buffer
->buffer_size
;
988 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
990 memset(cmd
, 0, MAX_COMMAND_SIZE
);
991 cmd
[0] = WRITE_FILEMARKS
;
993 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
996 while (retval
&& time_before (jiffies
, startwait
+ 5*60*HZ
)) {
998 if (STp
->buffer
->syscall_result
&& (SRpnt
->sense
[2] & 0x0f) != 2) {
1000 /* some failure - not just not-ready */
1001 retval
= osst_write_error_recovery(STp
, aSRpnt
, 0);
1004 schedule_timeout_interruptible(HZ
/ OSST_POLL_PER_SEC
);
1006 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
1007 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1008 cmd
[0] = READ_POSITION
;
1010 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
1013 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
1014 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
1017 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
1019 /* TODO - figure out which error conditions can be handled */
1020 if (STp
->buffer
->syscall_result
)
1022 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
1023 (*aSRpnt
)->sense
[ 2] & 0x0f,
1024 (*aSRpnt
)->sense
[12],
1025 (*aSRpnt
)->sense
[13]);
1031 * Read the next OnStream tape frame at the current location
1033 static int osst_read_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int timeout
)
1035 unsigned char cmd
[MAX_COMMAND_SIZE
];
1036 struct osst_request
* SRpnt
;
1039 os_aux_t
* aux
= STp
->buffer
->aux
;
1040 char * name
= tape_name(STp
);
1044 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
1045 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
1047 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1054 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
1056 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1057 STp
->timeout
, MAX_RETRIES
, 1);
1062 if ((STp
->buffer
)->syscall_result
) {
1064 if (STp
->read_error_frame
== 0) {
1065 STp
->read_error_frame
= STp
->first_frame_position
;
1067 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
1072 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1074 SRpnt
->sense
[0], SRpnt
->sense
[1],
1075 SRpnt
->sense
[2], SRpnt
->sense
[3],
1076 SRpnt
->sense
[4], SRpnt
->sense
[5],
1077 SRpnt
->sense
[6], SRpnt
->sense
[7]);
1081 STp
->first_frame_position
++;
1086 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
1089 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
1090 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
1091 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
1092 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
1093 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
1094 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
1095 if (aux
->frame_type
==2)
1096 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
1097 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
1098 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
1104 static int osst_initiate_read(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1106 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1107 struct osst_request
* SRpnt
;
1108 unsigned char cmd
[MAX_COMMAND_SIZE
];
1110 char * name
= tape_name(STp
);
1112 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
1113 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
1114 STp
->write_type
= OS_WRITE_DATA
;
1115 osst_flush_write_buffer(STp
, aSRpnt
);
1116 osst_flush_drive_buffer(STp
, aSRpnt
);
1118 STps
->rw
= ST_READING
;
1119 STp
->frame_in_buffer
= 0;
1122 * Issue a read 0 command to get the OnStream drive
1123 * read frames into its buffer.
1125 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1130 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
1132 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
1134 if ((retval
= STp
->buffer
->syscall_result
))
1135 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1141 static int osst_get_logical_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1142 int frame_seq_number
, int quiet
)
1144 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1145 char * name
= tape_name(STp
);
1153 * If we want just any frame (-1) and there is a frame in the buffer, return it
1155 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1157 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1162 * Search and wait for the next logical tape frame
1166 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1167 name
, frame_seq_number
);
1168 if (STp
->read_error_frame
) {
1169 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1171 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1172 name
, STp
->read_error_frame
);
1174 STp
->read_error_frame
= 0;
1181 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1182 name
, frame_seq_number
, cnt
);
1184 if ( osst_initiate_read(STp
, aSRpnt
)
1185 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1188 position
= osst_get_frame_position(STp
, aSRpnt
);
1189 if (position
>= 0xbae && position
< 0xbb8)
1191 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1192 position
= STp
->read_error_frame
- 1;
1200 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1203 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1206 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1208 if (osst_verify_frame(STp
, -1, quiet
)) {
1209 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1210 if (STp
->fast_open
) {
1212 "%s:W: Found logical frame %d instead of %d after fast open\n",
1213 name
, x
, frame_seq_number
);
1215 STp
->read_error_frame
= 0;
1218 if (x
> frame_seq_number
) {
1220 /* positioning backwards did not bring us to the desired frame */
1221 position
= STp
->read_error_frame
- 1;
1224 position
= osst_get_frame_position(STp
, aSRpnt
)
1225 + frame_seq_number
- x
- 1;
1227 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1232 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1233 name
, x
, frame_seq_number
,
1234 STp
->first_frame_position
- position
);
1236 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1242 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1244 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1246 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1249 STp
->frame_in_buffer
= 0;
1252 STp
->recover_count
++;
1253 STp
->recover_erreg
++;
1254 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1255 name
, STp
->read_error_frame
);
1260 if (debugging
|| STps
->eof
)
1262 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1263 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1266 STp
->read_error_frame
= 0;
1270 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int logical_blk_num
)
1272 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1273 char * name
= tape_name(STp
);
1275 int frame_seq_estimate
, ppos_estimate
, move
;
1277 if (logical_blk_num
< 0) logical_blk_num
= 0;
1279 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1280 name
, logical_blk_num
, STp
->logical_blk_num
,
1281 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1282 STp
->block_size
<1024?'b':'k');
1284 /* Do we know where we are? */
1285 if (STps
->drv_block
>= 0) {
1286 move
= logical_blk_num
- STp
->logical_blk_num
;
1287 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1288 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1289 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1291 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1293 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1294 else ppos_estimate
= frame_seq_estimate
+ 20;
1295 while (++retries
< 10) {
1296 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1297 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1298 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1300 if (frame_seq_estimate
< 0) {
1301 frame_seq_estimate
= 0;
1304 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1305 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1306 /* we've located the estimated frame, now does it have our block? */
1307 if (logical_blk_num
< STp
->logical_blk_num
||
1308 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1309 if (STps
->eof
== ST_FM_HIT
)
1310 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1312 move
= logical_blk_num
- STp
->logical_blk_num
;
1313 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1314 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1316 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1319 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1320 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1321 STp
->logical_blk_num
, logical_blk_num
, move
);
1323 frame_seq_estimate
+= move
;
1324 ppos_estimate
+= move
;
1327 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1328 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1329 STp
->logical_blk_num
= logical_blk_num
;
1332 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1333 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1334 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1337 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1338 if (STps
->eof
== ST_FM_HIT
) {
1340 STps
->drv_block
= 0;
1342 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1343 STp
->logical_blk_num
-
1344 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1347 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1351 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1353 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1355 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1356 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1357 STp
->logical_blk_num
, logical_blk_num
);
1359 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1360 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1365 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1366 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1370 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1371 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1372 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1373 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1375 #define OSST_FRAME_SHIFT 6
1376 #define OSST_SECTOR_SHIFT 9
1377 #define OSST_SECTOR_MASK 0x03F
1379 static int osst_get_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1383 char * name
= tape_name(STp
);
1386 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1387 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1388 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1389 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1390 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1391 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1393 /* do we know where we are inside a file? */
1394 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1395 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1396 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1397 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1398 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1400 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1402 sector
= osst_get_frame_position(STp
, aSRpnt
);
1404 sector
<<= OSST_FRAME_SHIFT
;
1409 static int osst_seek_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int sector
)
1411 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1412 int frame
= sector
>> OSST_FRAME_SHIFT
,
1413 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1416 char * name
= tape_name(STp
);
1418 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1419 name
, sector
, frame
, offset
);
1421 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1423 if (frame
<= STp
->first_data_ppos
) {
1424 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1425 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1427 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1428 if (r
< 0) return r
;
1430 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1431 if (r
< 0) return r
;
1433 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1436 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1437 STp
->buffer
->read_pointer
= offset
;
1438 STp
->buffer
->buffer_bytes
-= offset
;
1440 STp
->frame_seq_number
++;
1441 STp
->frame_in_buffer
= 0;
1442 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1443 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1445 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1446 if (STps
->eof
== ST_FM_HIT
) {
1448 STps
->drv_block
= 0;
1450 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1451 STp
->logical_blk_num
-
1452 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1455 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1458 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1459 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1460 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1466 * Read back the drive's internal buffer contents, as a part
1467 * of the write error recovery mechanism for old OnStream
1468 * firmware revisions.
1469 * Precondition for this function to work: all frames in the
1470 * drive's buffer must be of one type (DATA, MARK or EOD)!
1472 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1473 unsigned int frame
, unsigned int skip
, int pending
)
1475 struct osst_request
* SRpnt
= * aSRpnt
;
1476 unsigned char * buffer
, * p
;
1477 unsigned char cmd
[MAX_COMMAND_SIZE
];
1478 int flag
, new_frame
, i
;
1479 int nframes
= STp
->cur_frames
;
1480 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1481 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1482 - (nframes
+ pending
- 1);
1483 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1484 - (nframes
+ pending
- 1) * blks_per_frame
;
1485 char * name
= tape_name(STp
);
1486 unsigned long startwait
= jiffies
;
1488 int dbg
= debugging
;
1491 if ((buffer
= vmalloc(array_size((nframes
+ 1), OS_DATA_SIZE
))) == NULL
)
1494 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1495 name
, nframes
, pending
?" and one that was pending":"");
1497 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1499 if (pending
&& debugging
)
1500 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1501 name
, frame_seq_number
+ nframes
,
1502 logical_blk_num
+ nframes
* blks_per_frame
,
1503 p
[0], p
[1], p
[2], p
[3]);
1505 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1507 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1508 cmd
[0] = 0x3C; /* Buffer Read */
1509 cmd
[1] = 6; /* Retrieve Faulty Block */
1510 cmd
[7] = 32768 >> 8;
1511 cmd
[8] = 32768 & 0xff;
1513 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1514 STp
->timeout
, MAX_RETRIES
, 1);
1516 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1517 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1522 osst_copy_from_buffer(STp
->buffer
, p
);
1525 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1526 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1530 osst_get_frame_position(STp
, aSRpnt
);
1533 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1535 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1536 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1538 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1541 if (STp
->write_type
== OS_WRITE_HEADER
) {
1543 p
+= skip
* OS_DATA_SIZE
;
1545 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1550 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1551 name
, new_frame
+i
, frame_seq_number
+i
);
1553 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1554 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1555 osst_get_frame_position(STp
, aSRpnt
);
1558 if (new_frame
> frame
+ 1000) {
1559 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1563 if ( i
>= nframes
+ pending
) break;
1566 osst_copy_to_buffer(STp
->buffer
, p
);
1568 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1570 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1571 logical_blk_num
+ i
*blks_per_frame
,
1572 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1573 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1581 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1582 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1583 p
[0], p
[1], p
[2], p
[3]);
1585 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1586 STp
->timeout
, MAX_RETRIES
, 1);
1588 if (STp
->buffer
->syscall_result
)
1591 p
+= OS_DATA_SIZE
; i
++;
1593 /* if we just sent the last frame, wait till all successfully written */
1594 if ( i
== nframes
+ pending
) {
1596 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1598 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1599 cmd
[0] = WRITE_FILEMARKS
;
1601 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1602 STp
->timeout
, MAX_RETRIES
, 1);
1605 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1606 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1610 flag
= STp
->buffer
->syscall_result
;
1611 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1613 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1614 cmd
[0] = TEST_UNIT_READY
;
1616 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1619 if (SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
1620 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8)) {
1621 /* in the process of becoming ready */
1625 if (STp
->buffer
->syscall_result
)
1631 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1637 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1638 SRpnt
->sense
[12] == 0 &&
1639 SRpnt
->sense
[13] == 2) {
1640 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1642 return (-EIO
); /* hit end of tape = fail */
1644 i
= ((SRpnt
->sense
[3] << 24) |
1645 (SRpnt
->sense
[4] << 16) |
1646 (SRpnt
->sense
[5] << 8) |
1647 SRpnt
->sense
[6] ) - new_frame
;
1648 p
= &buffer
[i
* OS_DATA_SIZE
];
1650 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1652 osst_get_frame_position(STp
, aSRpnt
);
1654 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1655 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1660 /* error recovery did not successfully complete */
1661 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1662 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1665 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1670 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1671 unsigned int frame
, unsigned int skip
, int pending
)
1673 unsigned char cmd
[MAX_COMMAND_SIZE
];
1674 struct osst_request
* SRpnt
;
1675 char * name
= tape_name(STp
);
1677 int attempts
= 1000 / skip
;
1679 unsigned long startwait
= jiffies
;
1681 int dbg
= debugging
;
1684 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1689 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1691 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1693 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1694 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1696 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1699 schedule_timeout_interruptible(msecs_to_jiffies(100));
1701 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1703 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1704 name
, STp
->first_frame_position
,
1705 STp
->last_frame_position
, STp
->cur_frames
);
1707 frame
= STp
->last_frame_position
;
1711 if (pending
&& STp
->cur_frames
< 50) {
1713 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1718 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1719 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1721 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1722 STp
->timeout
, MAX_RETRIES
, 1);
1725 if (STp
->buffer
->syscall_result
) { /* additional write error */
1726 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1727 SRpnt
->sense
[12] == 0 &&
1728 SRpnt
->sense
[13] == 2) {
1730 "%s:E: Volume overflow in write error recovery\n",
1732 break; /* hit end of tape = fail */
1741 if (STp
->cur_frames
== 0) {
1744 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1746 if (STp
->first_frame_position
!= expected
) {
1747 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1748 name
, STp
->first_frame_position
, expected
);
1755 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1756 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1760 schedule_timeout_interruptible(msecs_to_jiffies(100));
1762 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1770 * Error recovery algorithm for the OnStream tape.
1773 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
)
1775 struct osst_request
* SRpnt
= * aSRpnt
;
1776 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1777 char * name
= tape_name(STp
);
1780 unsigned int frame
, skip
;
1782 rw_state
= STps
->rw
;
1784 if ((SRpnt
->sense
[ 2] & 0x0f) != 3
1785 || SRpnt
->sense
[12] != 12
1786 || SRpnt
->sense
[13] != 0) {
1788 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1789 SRpnt
->sense
[2], SRpnt
->sense
[12], SRpnt
->sense
[13]);
1793 frame
= (SRpnt
->sense
[3] << 24) |
1794 (SRpnt
->sense
[4] << 16) |
1795 (SRpnt
->sense
[5] << 8) |
1797 skip
= SRpnt
->sense
[9];
1800 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1802 osst_get_frame_position(STp
, aSRpnt
);
1804 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1805 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1807 switch (STp
->write_type
) {
1810 case OS_WRITE_NEW_MARK
:
1812 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1813 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1814 if (STp
->os_fw_rev
>= 10600)
1815 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1817 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1818 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1820 retval
?"" :"Don't worry, ",
1821 retval
?" not ":" ");
1823 case OS_WRITE_LAST_MARK
:
1824 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1825 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1828 case OS_WRITE_HEADER
:
1829 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1830 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1833 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1834 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1836 osst_get_frame_position(STp
, aSRpnt
);
1838 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1839 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1840 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1843 STp
->recover_count
++;
1844 STp
->recover_erreg
++;
1848 STps
->rw
= rw_state
;
1852 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1853 int mt_op
, int mt_count
)
1855 char * name
= tape_name(STp
);
1857 int last_mark_ppos
= -1;
1860 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1862 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1864 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1868 if (STp
->linux_media_version
>= 4) {
1870 * direct lookup in header filemark list
1872 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1873 if (STp
->header_ok
&&
1874 STp
->header_cache
!= NULL
&&
1875 (cnt
- mt_count
) >= 0 &&
1876 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1877 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1878 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1880 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1882 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1883 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1884 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1886 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1888 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1889 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1890 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1891 mt_count
, last_mark_ppos
);
1893 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1894 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1895 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1898 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1902 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1903 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1904 name
, last_mark_ppos
);
1910 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1914 while (cnt
!= mt_count
) {
1915 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1916 if (last_mark_ppos
== -1)
1919 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1921 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1923 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1925 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1929 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1930 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1931 name
, last_mark_ppos
);
1936 if (mt_op
== MTBSFM
) {
1937 STp
->frame_seq_number
++;
1938 STp
->frame_in_buffer
= 0;
1939 STp
->buffer
->buffer_bytes
= 0;
1940 STp
->buffer
->read_pointer
= 0;
1941 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1947 * ADRL 1.1 compatible "slow" space filemarks fwd version
1949 * Just scans for the filemark sequentially.
1951 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1952 int mt_op
, int mt_count
)
1956 char * name
= tape_name(STp
);
1958 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1960 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1962 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1967 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1969 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1973 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1975 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1977 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1979 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1981 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1982 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1984 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1988 if (cnt
== mt_count
)
1990 STp
->frame_in_buffer
= 0;
1992 if (mt_op
== MTFSF
) {
1993 STp
->frame_seq_number
++;
1994 STp
->frame_in_buffer
= 0;
1995 STp
->buffer
->buffer_bytes
= 0;
1996 STp
->buffer
->read_pointer
= 0;
1997 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2003 * Fast linux specific version of OnStream FSF
2005 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
2006 int mt_op
, int mt_count
)
2008 char * name
= tape_name(STp
);
2010 next_mark_ppos
= -1;
2013 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
2015 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2017 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
2022 if (STp
->linux_media_version
>= 4) {
2024 * direct lookup in header filemark list
2026 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
2027 if (STp
->header_ok
&&
2028 STp
->header_cache
!= NULL
&&
2029 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
2030 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
2031 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2032 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
2034 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
2036 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
2037 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
2038 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
2040 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2042 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2043 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
2044 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
2045 mt_count
, next_mark_ppos
);
2047 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
2049 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2051 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2053 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2054 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2056 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2061 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2062 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2063 name
, next_mark_ppos
);
2066 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
2067 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
2068 name
, cnt
+mt_count
, next_mark_ppos
,
2069 ntohl(STp
->buffer
->aux
->filemark_cnt
));
2075 * Find nearest (usually previous) marker, then jump from marker to marker
2078 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
2080 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
2082 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
2086 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
2087 if (STp
->first_mark_ppos
== -1) {
2089 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2091 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2093 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
2094 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2097 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2102 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2103 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
2104 name
, STp
->first_mark_ppos
);
2108 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
2114 while (cnt
!= mt_count
) {
2115 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
2116 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
2118 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2120 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
2123 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
2125 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2127 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2129 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2134 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2135 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2136 name
, next_mark_ppos
);
2141 if (mt_op
== MTFSF
) {
2142 STp
->frame_seq_number
++;
2143 STp
->frame_in_buffer
= 0;
2144 STp
->buffer
->buffer_bytes
= 0;
2145 STp
->buffer
->read_pointer
= 0;
2146 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2152 * In debug mode, we want to see as many errors as possible
2153 * to test the error recovery mechanism.
2156 static void osst_set_retries(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int retries
)
2158 unsigned char cmd
[MAX_COMMAND_SIZE
];
2159 struct osst_request
* SRpnt
= * aSRpnt
;
2160 char * name
= tape_name(STp
);
2162 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2163 cmd
[0] = MODE_SELECT
;
2165 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2167 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2168 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2169 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2170 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2171 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2172 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2173 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2174 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2177 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2179 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2182 if ((STp
->buffer
)->syscall_result
)
2183 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2188 static int osst_write_filemark(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2191 int this_mark_ppos
= STp
->first_frame_position
;
2192 int this_mark_lbn
= STp
->logical_blk_num
;
2194 char * name
= tape_name(STp
);
2197 if (STp
->raw
) return 0;
2199 STp
->write_type
= OS_WRITE_NEW_MARK
;
2201 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2202 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2205 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2206 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2207 STp
->last_mark_ppos
= this_mark_ppos
;
2208 STp
->last_mark_lbn
= this_mark_lbn
;
2209 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2210 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2211 if (STp
->filemark_cnt
++ == 0)
2212 STp
->first_mark_ppos
= this_mark_ppos
;
2216 static int osst_write_eod(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2220 char * name
= tape_name(STp
);
2223 if (STp
->raw
) return 0;
2225 STp
->write_type
= OS_WRITE_EOD
;
2226 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2228 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2229 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2233 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2234 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2235 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2239 static int osst_write_filler(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2241 char * name
= tape_name(STp
);
2244 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2246 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2247 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2248 STp
->write_type
= OS_WRITE_FILLER
;
2250 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2251 STp
->buffer
->buffer_bytes
= 6;
2253 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2254 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2259 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2261 return osst_flush_drive_buffer(STp
, aSRpnt
);
2264 static int __osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2266 char * name
= tape_name(STp
);
2270 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2272 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2273 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2274 STp
->write_type
= OS_WRITE_HEADER
;
2276 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2277 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2279 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2280 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2284 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2286 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2291 static int osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int locate_eod
)
2293 os_header_t
* header
;
2295 char * name
= tape_name(STp
);
2298 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2300 if (STp
->raw
) return 0;
2302 if (STp
->header_cache
== NULL
) {
2303 if ((STp
->header_cache
= vmalloc(sizeof(os_header_t
))) == NULL
) {
2304 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2307 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2309 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2312 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2313 else STp
->update_frame_cntr
= 0;
2315 header
= STp
->header_cache
;
2316 strcpy(header
->ident_str
, "ADR_SEQ");
2317 header
->major_rev
= 1;
2318 header
->minor_rev
= 4;
2319 header
->ext_trk_tb_off
= htons(17192);
2320 header
->pt_par_num
= 1;
2321 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2322 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2323 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2324 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2325 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2326 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2327 header
->cfg_col_width
= htonl(20);
2328 header
->dat_col_width
= htonl(1500);
2329 header
->qfa_col_width
= htonl(0);
2330 header
->ext_track_tb
.nr_stream_part
= 1;
2331 header
->ext_track_tb
.et_ent_sz
= 32;
2332 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2333 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2334 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2335 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2336 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2337 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2338 header
->dat_fm_tab
.fm_part_num
= 0;
2339 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2340 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2341 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2343 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2344 if (STp
->update_frame_cntr
== 0)
2345 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2346 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2350 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2352 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2355 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2357 memcpy(STp
->application_sig
, "LIN4", 4);
2358 STp
->linux_media
= 1;
2359 STp
->linux_media_version
= 4;
2365 static int osst_reset_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2367 if (STp
->header_cache
!= NULL
)
2368 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2370 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2371 STp
->frame_in_buffer
= 0;
2372 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2373 STp
->filemark_cnt
= 0;
2374 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2375 return osst_write_header(STp
, aSRpnt
, 1);
2378 static int __osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int ppos
)
2380 char * name
= tape_name(STp
);
2381 os_header_t
* header
;
2384 int linux_media_version
,
2390 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2391 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2392 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2393 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2394 if (osst_initiate_read (STp
, aSRpnt
)) {
2395 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2399 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2401 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2405 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2406 aux
= STp
->buffer
->aux
;
2407 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2409 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2413 if (ntohl(aux
->frame_seq_num
) != 0 ||
2414 ntohl(aux
->logical_blk_num
) != 0 ||
2415 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2416 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2417 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2419 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2420 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2421 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2422 ntohl(aux
->partition
.last_frame_ppos
));
2426 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2427 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2428 strlcpy(id_string
, header
->ident_str
, 8);
2430 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2434 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2435 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2437 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2438 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2442 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2444 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2445 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2446 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2447 header
->major_rev
, header
->minor_rev
);
2449 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2453 if (header
->pt_par_num
!= 1)
2454 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2455 name
, header
->pt_par_num
);
2457 memcpy(id_string
, aux
->application_sig
, 4);
2459 if (memcmp(id_string
, "LIN", 3) == 0) {
2460 STp
->linux_media
= 1;
2461 linux_media_version
= id_string
[3] - '0';
2462 if (linux_media_version
!= 4)
2463 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2464 name
, linux_media_version
);
2466 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2469 if (linux_media_version
< STp
->linux_media_version
) {
2471 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2472 name
, ppos
, linux_media_version
);
2476 if (linux_media_version
> STp
->linux_media_version
) {
2478 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2479 name
, ppos
, linux_media_version
);
2481 memcpy(STp
->application_sig
, id_string
, 5);
2482 STp
->linux_media_version
= linux_media_version
;
2483 STp
->update_frame_cntr
= -1;
2485 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2487 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2488 name
, ppos
, update_frame_cntr
);
2490 if (STp
->header_cache
== NULL
) {
2491 if ((STp
->header_cache
= vmalloc(sizeof(os_header_t
))) == NULL
) {
2492 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2496 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2499 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2500 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2502 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2503 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2504 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2505 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2506 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2507 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2508 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2509 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2510 STp
->update_frame_cntr
= update_frame_cntr
;
2512 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2513 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2514 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2515 STp
->first_data_ppos
,
2516 ntohl(header
->partition
[0].last_frame_ppos
),
2517 ntohl(header
->partition
[0].eod_frame_ppos
));
2518 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2519 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2521 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2523 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2525 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2526 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2527 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2529 if (header
->minor_rev
== 4 &&
2530 (header
->ext_trk_tb_off
!= htons(17192) ||
2531 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2532 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2533 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2534 header
->cfg_col_width
!= htonl(20) ||
2535 header
->dat_col_width
!= htonl(1500) ||
2536 header
->qfa_col_width
!= htonl(0) ||
2537 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2538 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2539 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2540 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2541 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2542 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2543 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2544 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2545 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2546 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2547 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2548 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2555 static int osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2560 char * name
= tape_name(STp
);
2562 position
= osst_get_frame_position(STp
, aSRpnt
);
2565 STp
->header_ok
= STp
->linux_media
= 1;
2566 STp
->linux_media_version
= 0;
2569 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2570 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2571 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2572 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2574 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2577 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2578 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2580 first
= position
==10?0xbae: 5;
2581 last
= position
==10?0xbb3:10;
2583 for (ppos
= first
; ppos
< last
; ppos
++)
2584 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2587 first
= position
==10? 5:0xbae;
2588 last
= position
==10?10:0xbb3;
2590 for (ppos
= first
; ppos
< last
; ppos
++)
2591 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2595 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2596 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2597 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2600 if (position
<= STp
->first_data_ppos
) {
2601 position
= STp
->first_data_ppos
;
2602 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2604 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2610 static int osst_verify_position(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2612 int frame_position
= STp
->first_frame_position
;
2613 int frame_seq_numbr
= STp
->frame_seq_number
;
2614 int logical_blk_num
= STp
->logical_blk_num
;
2615 int halfway_frame
= STp
->frame_in_buffer
;
2616 int read_pointer
= STp
->buffer
->read_pointer
;
2617 int prev_mark_ppos
= -1;
2618 int actual_mark_ppos
, i
, n
;
2620 char * name
= tape_name(STp
);
2622 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2624 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2625 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2627 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2631 if (STp
->linux_media_version
>= 4) {
2632 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2633 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2636 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2637 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2638 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2639 if (frame_position
!= STp
->first_frame_position
||
2640 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2641 prev_mark_ppos
!= actual_mark_ppos
) {
2643 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2644 STp
->first_frame_position
, frame_position
,
2645 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2646 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2650 if (halfway_frame
) {
2651 /* prepare buffer for append and rewrite on top of original */
2652 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2653 STp
->buffer
->buffer_bytes
= read_pointer
;
2654 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2657 STp
->frame_in_buffer
= halfway_frame
;
2658 STp
->frame_seq_number
= frame_seq_numbr
;
2659 STp
->logical_blk_num
= logical_blk_num
;
2663 /* Acc. to OnStream, the vers. numbering is the following:
2664 * X.XX for released versions (X=digit),
2665 * XXXY for unreleased versions (Y=letter)
2666 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2667 * This fn makes monoton numbers out of this scheme ...
2669 static unsigned int osst_parse_firmware_rev (const char * str
)
2671 if (str
[1] == '.') {
2672 return (str
[0]-'0')*10000
2676 return (str
[0]-'0')*10000
2678 +(str
[2]-'0')*100 - 100
2684 * Configure the OnStream SCII tape drive for default operation
2686 static int osst_configure_onstream(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2688 unsigned char cmd
[MAX_COMMAND_SIZE
];
2689 char * name
= tape_name(STp
);
2690 struct osst_request
* SRpnt
= * aSRpnt
;
2691 osst_mode_parameter_header_t
* header
;
2692 osst_block_size_page_t
* bs
;
2693 osst_capabilities_page_t
* cp
;
2694 osst_tape_paramtr_page_t
* prm
;
2695 int drive_buffer_size
;
2697 if (STp
->ready
!= ST_READY
) {
2699 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2704 if (STp
->os_fw_rev
< 10600) {
2705 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2706 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2710 * Configure 32.5KB (data+aux) frame size.
2711 * Get the current frame size from the block size mode page
2713 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2714 cmd
[0] = MODE_SENSE
;
2716 cmd
[2] = BLOCK_SIZE_PAGE
;
2717 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2719 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2720 if (SRpnt
== NULL
) {
2722 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2727 if ((STp
->buffer
)->syscall_result
!= 0) {
2728 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2732 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2733 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2736 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2737 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2738 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2739 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2743 * Configure default auto columns mode, 32.5KB transfer mode
2751 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2752 cmd
[0] = MODE_SELECT
;
2754 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2756 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2758 if ((STp
->buffer
)->syscall_result
!= 0) {
2759 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2764 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2766 * In debug mode, we want to see as many errors as possible
2767 * to test the error recovery mechanism.
2769 osst_set_retries(STp
, aSRpnt
, 0);
2774 * Set vendor name to 'LIN4' for "Linux support version 4".
2777 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2778 cmd
[0] = MODE_SELECT
;
2780 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2782 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2783 header
->medium_type
= 0; /* Medium Type - ignoring */
2784 header
->dsp
= 0; /* Reserved */
2785 header
->bdl
= 0; /* Block Descriptor Length */
2787 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2788 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2789 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2790 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2791 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2792 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2793 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2794 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2796 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2799 if ((STp
->buffer
)->syscall_result
!= 0) {
2800 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2801 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2805 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2806 cmd
[0] = MODE_SENSE
;
2808 cmd
[2] = CAPABILITIES_PAGE
;
2809 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2811 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2814 if ((STp
->buffer
)->syscall_result
!= 0) {
2815 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2819 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2820 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2821 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2823 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2825 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2826 cmd
[0] = MODE_SENSE
;
2828 cmd
[2] = TAPE_PARAMTR_PAGE
;
2829 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2831 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2834 if ((STp
->buffer
)->syscall_result
!= 0) {
2835 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2839 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2840 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2841 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2843 STp
->density
= prm
->density
;
2844 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2846 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2847 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2855 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2856 it messes up the block number). */
2857 static int cross_eof(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int forward
)
2860 char * name
= tape_name(STp
);
2864 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2865 name
, forward
? "forward" : "backward");
2869 /* assumes that the filemark is already read by the drive, so this is low cost */
2870 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2873 /* assumes this is only called if we just read the filemark! */
2874 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2877 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2878 name
, forward
? "forward" : "backward");
2884 /* Get the tape position. */
2886 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2888 unsigned char scmd
[MAX_COMMAND_SIZE
];
2889 struct osst_request
* SRpnt
;
2891 char * name
= tape_name(STp
);
2893 /* KG: We want to be able to use it for checking Write Buffer availability
2894 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2896 char * olddata
= STp
->buffer
->b_data
;
2897 int oldsize
= STp
->buffer
->buffer_size
;
2899 if (STp
->ready
!= ST_READY
) return (-EIO
);
2901 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2902 scmd
[0] = READ_POSITION
;
2904 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2905 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2906 STp
->timeout
, MAX_RETRIES
, 1);
2908 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2913 if (STp
->buffer
->syscall_result
)
2914 result
= ((SRpnt
->sense
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2916 if (result
== -EINVAL
)
2917 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2919 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2920 unsigned char mysense
[16];
2921 memcpy (mysense
, SRpnt
->sense
, 16);
2922 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2923 scmd
[0] = READ_POSITION
;
2924 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2925 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2926 STp
->timeout
, MAX_RETRIES
, 1);
2928 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2929 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2930 SRpnt
->sense
[2],SRpnt
->sense
[12],SRpnt
->sense
[13]);
2932 if (!STp
->buffer
->syscall_result
)
2933 memcpy (SRpnt
->sense
, mysense
, 16);
2935 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2937 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2938 + ((STp
->buffer
)->b_data
[5] << 16)
2939 + ((STp
->buffer
)->b_data
[6] << 8)
2940 + (STp
->buffer
)->b_data
[7];
2941 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2942 + ((STp
->buffer
)->b_data
[ 9] << 16)
2943 + ((STp
->buffer
)->b_data
[10] << 8)
2944 + (STp
->buffer
)->b_data
[11];
2945 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2948 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2949 STp
->first_frame_position
, STp
->last_frame_position
,
2950 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2951 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2955 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2957 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2958 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2960 STp
->first_frame_position
= STp
->last_frame_position
;
2963 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2965 return (result
== 0 ? STp
->first_frame_position
: result
);
2969 /* Set the tape block */
2970 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int ppos
, int skip
)
2972 unsigned char scmd
[MAX_COMMAND_SIZE
];
2973 struct osst_request
* SRpnt
;
2974 struct st_partstat
* STps
;
2976 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2977 char * name
= tape_name(STp
);
2979 if (STp
->ready
!= ST_READY
) return (-EIO
);
2981 STps
= &(STp
->ps
[STp
->partition
]);
2983 if (ppos
< 0 || ppos
> STp
->capacity
) {
2984 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2985 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2992 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2994 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2997 scmd
[3] = (pp
>> 24);
2998 scmd
[4] = (pp
>> 16);
2999 scmd
[5] = (pp
>> 8);
3004 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
3010 if ((STp
->buffer
)->syscall_result
!= 0) {
3012 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
3013 name
, STp
->first_frame_position
, pp
);
3018 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
3019 } while ((pp
!= ppos
) && (pp
= ppos
));
3020 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
3021 STps
->eof
= ST_NOEOF
;
3024 STp
->frame_in_buffer
= 0;
3028 static int osst_write_trailer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int leave_at_EOT
)
3030 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
3033 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
3034 /* true unless the user wrote the filemark for us */
3035 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
3036 if (result
< 0) goto out
;
3037 result
= osst_write_filemark(STp
, aSRpnt
);
3038 if (result
< 0) goto out
;
3040 if (STps
->drv_file
>= 0)
3042 STps
->drv_block
= 0;
3044 result
= osst_write_eod(STp
, aSRpnt
);
3045 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
3052 /* osst versions of st functions - augmented and stripped to suit OnStream only */
3054 /* Flush the write buffer (never need to write if variable blocksize). */
3055 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
3057 int offset
, transfer
, blks
= 0;
3059 unsigned char cmd
[MAX_COMMAND_SIZE
];
3060 struct osst_request
* SRpnt
= *aSRpnt
;
3061 struct st_partstat
* STps
;
3062 char * name
= tape_name(STp
);
3064 if ((STp
->buffer
)->writing
) {
3065 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
3067 { printk(OSST_DEB_MSG
3068 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name
);
3070 *aSRpnt
= SRpnt
= NULL
;
3074 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name
);
3076 osst_write_behind_check(STp
);
3077 if ((STp
->buffer
)->syscall_result
) {
3080 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
3081 name
, (STp
->buffer
)->midlevel_result
);
3083 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3090 if (STp
->dirty
== 1) {
3093 STps
= &(STp
->ps
[STp
->partition
]);
3094 STps
->rw
= ST_WRITING
;
3095 offset
= STp
->buffer
->buffer_bytes
;
3096 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
3097 transfer
= OS_FRAME_SIZE
;
3099 if (offset
< OS_DATA_SIZE
)
3100 osst_zero_buffer_tail(STp
->buffer
);
3103 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
3104 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
3106 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3111 switch (STp
->write_type
) {
3115 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3116 name
, blks
, STp
->frame_seq_number
,
3117 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3119 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3120 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3123 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
3124 STp
->logical_blk_num
, 0, 0);
3126 case OS_WRITE_NEW_MARK
:
3127 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
3128 STp
->logical_blk_num
++, 0, blks
=1);
3130 case OS_WRITE_HEADER
:
3131 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
3133 default: /* probably FILLER */
3134 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
3138 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3139 name
, offset
, transfer
, blks
);
3142 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3143 STp
->timeout
, MAX_RETRIES
, 1);
3148 if ((STp
->buffer
)->syscall_result
!= 0) {
3151 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3152 name
, SRpnt
->sense
[0], SRpnt
->sense
[2],
3153 SRpnt
->sense
[12], SRpnt
->sense
[13]);
3155 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3156 (SRpnt
->sense
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3157 (SRpnt
->sense
[2] & 0x0f) == NO_SENSE
) {
3159 (STp
->buffer
)->buffer_bytes
= 0;
3163 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3164 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3168 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3171 STp
->first_frame_position
++;
3173 (STp
->buffer
)->buffer_bytes
= 0;
3177 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3183 /* Flush the tape buffer. The tape will be positioned correctly unless
3184 seek_next is true. */
3185 static int osst_flush_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int seek_next
)
3187 struct st_partstat
* STps
;
3188 int backspace
= 0, result
= 0;
3190 char * name
= tape_name(STp
);
3194 * If there was a bus reset, block further access
3197 if( STp
->pos_unknown
)
3200 if (STp
->ready
!= ST_READY
)
3203 STps
= &(STp
->ps
[STp
->partition
]);
3204 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3205 STp
->write_type
= OS_WRITE_DATA
;
3206 return osst_flush_write_buffer(STp
, aSRpnt
);
3208 if (STp
->block_size
== 0)
3212 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3215 if (!STp
->can_bsr
) {
3216 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3217 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3218 (STp
->buffer
)->buffer_bytes
= 0;
3219 (STp
->buffer
)->read_pointer
= 0;
3220 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3224 if (STps
->eof
== ST_FM_HIT
) {
3225 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3227 STps
->eof
= ST_NOEOF
;
3229 if (STps
->drv_file
>= 0)
3231 STps
->drv_block
= 0;
3234 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3235 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3237 else if (STps
->eof
== ST_FM_HIT
) {
3238 if (STps
->drv_file
>= 0)
3240 STps
->drv_block
= 0;
3241 STps
->eof
= ST_NOEOF
;
3247 static int osst_write_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int synchronous
)
3249 unsigned char cmd
[MAX_COMMAND_SIZE
];
3250 struct osst_request
* SRpnt
;
3253 char * name
= tape_name(STp
);
3256 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3258 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3260 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3263 /* error recovery may have bumped us past the header partition */
3264 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3266 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3268 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3273 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3274 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3277 // osst_build_stats(STp, &SRpnt);
3279 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3280 STp
->write_type
= OS_WRITE_DATA
;
3282 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3285 cmd
[4] = 1; /* one frame at a time... */
3286 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3289 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3290 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3292 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3293 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3297 STp
->write_pending
= 1;
3299 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3300 MAX_RETRIES
, synchronous
);
3306 if (STp
->buffer
->syscall_result
!= 0) {
3309 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3311 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3312 (SRpnt
->sense
[2] & 0x40)) {
3313 if ((SRpnt
->sense
[2] & 0x0f) == VOLUME_OVERFLOW
)
3317 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3322 STp
->first_frame_position
++;
3330 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3331 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3336 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3339 retval
= scsi_set_medium_removal(STp
->device
,
3340 do_lock
? SCSI_REMOVAL_PREVENT
: SCSI_REMOVAL_ALLOW
);
3342 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3344 STp
->door_locked
= ST_LOCK_FAILS
;
3348 /* Set the internal state after reset */
3349 static void reset_state(struct osst_tape
*STp
)
3352 struct st_partstat
*STps
;
3354 STp
->pos_unknown
= 0;
3355 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3356 STps
= &(STp
->ps
[i
]);
3358 STps
->eof
= ST_NOEOF
;
3360 STps
->last_block_valid
= 0;
3361 STps
->drv_block
= -1;
3362 STps
->drv_file
= -1;
3367 /* Entry points to osst */
3370 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3372 ssize_t total
, retval
= 0;
3373 ssize_t i
, do_count
, blks
, transfer
;
3374 int write_threshold
;
3375 int doing_write
= 0;
3376 const char __user
* b_point
;
3377 struct osst_request
* SRpnt
= NULL
;
3378 struct st_modedef
* STm
;
3379 struct st_partstat
* STps
;
3380 struct osst_tape
* STp
= filp
->private_data
;
3381 char * name
= tape_name(STp
);
3384 if (mutex_lock_interruptible(&STp
->lock
))
3385 return (-ERESTARTSYS
);
3388 * If we are in the middle of error recovery, don't let anyone
3389 * else try and use this device. Also, if error recovery fails, it
3390 * may try and take the device offline, in which case all further
3391 * access to the device is prohibited.
3393 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3398 if (STp
->ready
!= ST_READY
) {
3399 if (STp
->ready
== ST_NO_TAPE
)
3400 retval
= (-ENOMEDIUM
);
3405 STm
= &(STp
->modes
[STp
->current_mode
]);
3406 if (!STm
->defined
) {
3414 * If there was a bus reset, block further access
3417 if (STp
->pos_unknown
) {
3424 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3430 if (STp
->write_prot
) {
3435 /* Write must be integral number of blocks */
3436 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3437 printk(KERN_ERR
"%s:E: Write (%zd bytes) not multiple of tape block size (%d%c).\n",
3438 name
, count
, STp
->block_size
<1024?
3439 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3444 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3445 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3446 name
, STp
->first_frame_position
);
3451 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3452 STp
->door_locked
= ST_LOCKED_AUTO
;
3454 STps
= &(STp
->ps
[STp
->partition
]);
3456 if (STps
->rw
== ST_READING
) {
3458 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3459 STps
->drv_file
, STps
->drv_block
);
3461 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3466 if (STps
->rw
!= ST_WRITING
) {
3467 /* Are we totally rewriting this tape? */
3468 if (!STp
->header_ok
||
3469 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3470 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3471 STp
->wrt_pass_cntr
++;
3473 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3474 name
, STp
->wrt_pass_cntr
);
3476 osst_reset_header(STp
, &SRpnt
);
3477 STps
->drv_file
= STps
->drv_block
= 0;
3479 /* Do we know where we'll be writing on the tape? */
3481 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3482 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3483 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3484 STps
->drv_file
= STp
->filemark_cnt
;
3485 STps
->drv_block
= 0;
3488 /* We have no idea where the tape is positioned - give up */
3491 "%s:D: Cannot write at indeterminate position.\n", name
);
3497 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3498 STp
->filemark_cnt
= STps
->drv_file
;
3499 STp
->last_mark_ppos
=
3500 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3502 "%s:W: Overwriting file %d with old write pass counter %d\n",
3503 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3505 "%s:W: may lead to stale data being accepted on reading back!\n",
3509 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3510 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3516 if (!STp
->header_ok
) {
3518 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3524 if ((STp
->buffer
)->writing
) {
3525 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3526 osst_write_behind_check(STp
);
3527 if ((STp
->buffer
)->syscall_result
) {
3530 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3531 (STp
->buffer
)->midlevel_result
);
3533 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3534 STps
->eof
= ST_EOM_OK
;
3536 STps
->eof
= ST_EOM_ERROR
;
3539 if (STps
->eof
== ST_EOM_OK
) {
3543 else if (STps
->eof
== ST_EOM_ERROR
) {
3548 /* Check the buffer readability in cases where copy_user might catch
3549 the problems after some tape movement. */
3550 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3551 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3556 if (!STm
->do_buffer_writes
) {
3557 write_threshold
= 1;
3560 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3561 if (!STm
->do_async_writes
)
3567 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3568 name
, (int) count
, STps
->drv_file
, STps
->drv_block
,
3569 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3572 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3575 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3576 (STp
->buffer
)->buffer_bytes
;
3577 if (do_count
> count
)
3580 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3586 blks
= do_count
/ STp
->block_size
;
3587 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3589 i
= osst_write_frame(STp
, &SRpnt
, 1);
3591 if (i
== (-ENOSPC
)) {
3592 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3593 if (transfer
<= do_count
) {
3594 *ppos
+= do_count
- transfer
;
3595 count
-= do_count
- transfer
;
3596 if (STps
->drv_block
>= 0) {
3597 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3599 STps
->eof
= ST_EOM_OK
;
3600 retval
= (-ENOSPC
); /* EOM within current request */
3603 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3604 name
, (int) transfer
);
3608 STps
->eof
= ST_EOM_ERROR
;
3609 STps
->drv_block
= (-1); /* Too cautious? */
3610 retval
= (-EIO
); /* EOM for old data */
3613 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3621 if (SRpnt
!= NULL
) {
3622 osst_release_request(SRpnt
);
3625 STp
->buffer
->buffer_bytes
= 0;
3628 retval
= total
- count
;
3633 b_point
+= do_count
;
3635 if (STps
->drv_block
>= 0) {
3636 STps
->drv_block
+= blks
;
3638 STp
->buffer
->buffer_bytes
= 0;
3640 } /* end while write threshold exceeded */
3644 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3649 blks
= count
/ STp
->block_size
;
3650 STp
->logical_blk_num
+= blks
;
3651 if (STps
->drv_block
>= 0) {
3652 STps
->drv_block
+= blks
;
3658 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3659 retval
= (STp
->buffer
)->syscall_result
;
3663 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3664 /* Schedule an asynchronous write */
3665 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3666 STp
->block_size
) * STp
->block_size
;
3667 STp
->dirty
= !((STp
->buffer
)->writing
==
3668 (STp
->buffer
)->buffer_bytes
);
3670 i
= osst_write_frame(STp
, &SRpnt
, 0);
3675 SRpnt
= NULL
; /* Prevent releasing this request! */
3677 STps
->at_sm
&= (total
== 0);
3679 STps
->eof
= ST_NOEOF
;
3684 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3686 mutex_unlock(&STp
->lock
);
3693 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3695 ssize_t total
, retval
= 0;
3696 ssize_t i
, transfer
;
3698 struct st_modedef
* STm
;
3699 struct st_partstat
* STps
;
3700 struct osst_request
* SRpnt
= NULL
;
3701 struct osst_tape
* STp
= filp
->private_data
;
3702 char * name
= tape_name(STp
);
3705 if (mutex_lock_interruptible(&STp
->lock
))
3706 return (-ERESTARTSYS
);
3709 * If we are in the middle of error recovery, don't let anyone
3710 * else try and use this device. Also, if error recovery fails, it
3711 * may try and take the device offline, in which case all further
3712 * access to the device is prohibited.
3714 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3719 if (STp
->ready
!= ST_READY
) {
3720 if (STp
->ready
== ST_NO_TAPE
)
3721 retval
= (-ENOMEDIUM
);
3726 STm
= &(STp
->modes
[STp
->current_mode
]);
3727 if (!STm
->defined
) {
3733 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3738 /* Must have initialized medium */
3739 if (!STp
->header_ok
) {
3744 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3745 STp
->door_locked
= ST_LOCKED_AUTO
;
3747 STps
= &(STp
->ps
[STp
->partition
]);
3748 if (STps
->rw
== ST_WRITING
) {
3749 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3753 /* FIXME -- this may leave the tape without EOD and up2date headers */
3756 if ((count
% STp
->block_size
) != 0) {
3758 "%s:W: Read (%zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3759 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3763 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3764 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3765 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3767 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3768 STps
->eof
>= ST_EOD_1
) {
3769 if (STps
->eof
< ST_EOD
) {
3774 retval
= (-EIO
); /* EOM or Blank Check */
3778 /* Check the buffer writability before any tape movement. Don't alter
3780 if (copy_from_user(&i
, buf
, 1) != 0 ||
3781 copy_to_user (buf
, &i
, 1) != 0 ||
3782 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3783 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3788 /* Loop until enough data in buffer or a special condition found */
3789 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3791 /* Get new data if the buffer is empty */
3792 if ((STp
->buffer
)->buffer_bytes
== 0) {
3793 if (STps
->eof
== ST_FM_HIT
)
3795 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3796 if (special
< 0) { /* No need to continue read */
3797 STp
->frame_in_buffer
= 0;
3803 /* Move the data from driver buffer to user buffer */
3804 if ((STp
->buffer
)->buffer_bytes
> 0) {
3806 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3807 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3808 STps
->eof
, (STp
->buffer
)->buffer_bytes
, (int) (count
- total
));
3810 /* force multiple of block size, note block_size may have been adjusted */
3811 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3812 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3813 STp
->block_size
) * STp
->block_size
;
3815 if (transfer
== 0) {
3817 "%s:W: Nothing can be transferred, requested %zd, tape block size (%d%c).\n",
3818 name
, count
, STp
->block_size
< 1024?
3819 STp
->block_size
:STp
->block_size
/1024,
3820 STp
->block_size
<1024?'b':'k');
3823 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3828 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3829 STps
->drv_block
+= transfer
/ STp
->block_size
;
3835 if ((STp
->buffer
)->buffer_bytes
== 0) {
3838 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3839 name
, STp
->frame_seq_number
);
3841 STp
->frame_in_buffer
= 0;
3842 STp
->frame_seq_number
++; /* frame to look for next time */
3844 } /* for (total = 0, special = 0; total < count && !special; ) */
3846 /* Change the eof state if no data from tape or buffer */
3848 if (STps
->eof
== ST_FM_HIT
) {
3849 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3850 STps
->drv_block
= 0;
3851 if (STps
->drv_file
>= 0)
3854 else if (STps
->eof
== ST_EOD_1
) {
3855 STps
->eof
= ST_EOD_2
;
3856 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3858 STps
->drv_block
= 0;
3860 else if (STps
->eof
== ST_EOD_2
)
3863 else if (STps
->eof
== ST_FM
)
3864 STps
->eof
= ST_NOEOF
;
3869 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3871 mutex_unlock(&STp
->lock
);
3877 /* Set the driver options */
3878 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3881 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3882 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3883 STm
->do_read_ahead
);
3885 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3886 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3888 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3889 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3890 STp
->scsi2_logical
);
3892 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3895 "%s:D: debugging: %d\n",
3901 static int osst_set_options(struct osst_tape
*STp
, long options
)
3905 struct st_modedef
* STm
;
3906 char * name
= tape_name(STp
);
3908 STm
= &(STp
->modes
[STp
->current_mode
]);
3909 if (!STm
->defined
) {
3910 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3914 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3915 name
, STp
->current_mode
);
3919 code
= options
& MT_ST_OPTIONS
;
3920 if (code
== MT_ST_BOOLEANS
) {
3921 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3922 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3923 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3924 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3925 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3926 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3927 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3928 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3929 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3930 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3931 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3932 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3933 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3935 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3937 osst_log_options(STp
, STm
, name
);
3939 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3940 value
= (code
== MT_ST_SETBOOLEANS
);
3941 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3942 STm
->do_buffer_writes
= value
;
3943 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3944 STm
->do_async_writes
= value
;
3945 if ((options
& MT_ST_DEF_WRITES
) != 0)
3946 STm
->defaults_for_writes
= value
;
3947 if ((options
& MT_ST_READ_AHEAD
) != 0)
3948 STm
->do_read_ahead
= value
;
3949 if ((options
& MT_ST_TWO_FM
) != 0)
3950 STp
->two_fm
= value
;
3951 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3952 STp
->fast_mteom
= value
;
3953 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3954 STp
->do_auto_lock
= value
;
3955 if ((options
& MT_ST_CAN_BSR
) != 0)
3956 STp
->can_bsr
= value
;
3957 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3958 STp
->omit_blklims
= value
;
3959 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3960 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3961 STp
->can_partitions
= value
;
3962 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3963 STp
->scsi2_logical
= value
;
3964 if ((options
& MT_ST_SYSV
) != 0)
3967 if ((options
& MT_ST_DEBUGGING
) != 0)
3970 osst_log_options(STp
, STm
, name
);
3972 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3973 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3974 if (value
< 1 || value
> osst_buffer_size
) {
3975 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3979 STp
->write_threshold
= value
;
3980 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3983 else if (code
== MT_ST_DEF_BLKSIZE
) {
3984 value
= (options
& ~MT_ST_OPTIONS
);
3985 if (value
== ~MT_ST_OPTIONS
) {
3986 STm
->default_blksize
= (-1);
3987 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3990 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3991 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3995 STm
->default_blksize
= value
;
3996 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3997 name
, STm
->default_blksize
);
4000 else if (code
== MT_ST_TIMEOUTS
) {
4001 value
= (options
& ~MT_ST_OPTIONS
);
4002 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
4003 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
4004 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
4005 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
4008 STp
->timeout
= value
* HZ
;
4009 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
4012 else if (code
== MT_ST_DEF_OPTIONS
) {
4013 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
4014 value
= (options
& MT_ST_CLEAR_DEFAULT
);
4015 if (code
== MT_ST_DEF_DENSITY
) {
4016 if (value
== MT_ST_CLEAR_DEFAULT
) {
4017 STm
->default_density
= (-1);
4018 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
4021 STm
->default_density
= value
& 0xff;
4022 printk(KERN_INFO
"%s:I: Density default set to %x\n",
4023 name
, STm
->default_density
);
4026 else if (code
== MT_ST_DEF_DRVBUFFER
) {
4027 if (value
== MT_ST_CLEAR_DEFAULT
) {
4028 STp
->default_drvbuffer
= 0xff;
4029 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
4032 STp
->default_drvbuffer
= value
& 7;
4033 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
4034 name
, STp
->default_drvbuffer
);
4037 else if (code
== MT_ST_DEF_COMPRESSION
) {
4038 if (value
== MT_ST_CLEAR_DEFAULT
) {
4039 STm
->default_compression
= ST_DONT_TOUCH
;
4040 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
4043 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
4044 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
4056 /* Internal ioctl function */
4057 static int osst_int_ioctl(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
4058 unsigned int cmd_in
, unsigned long arg
)
4062 int i
, ioctl_result
;
4064 unsigned char cmd
[MAX_COMMAND_SIZE
];
4065 struct osst_request
* SRpnt
= * aSRpnt
;
4066 struct st_partstat
* STps
;
4067 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
4068 int datalen
= 0, direction
= DMA_NONE
;
4069 char * name
= tape_name(STp
);
4071 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
4072 if (STp
->ready
== ST_NO_TAPE
)
4073 return (-ENOMEDIUM
);
4077 timeout
= STp
->long_timeout
;
4078 STps
= &(STp
->ps
[STp
->partition
]);
4079 fileno
= STps
->drv_file
;
4080 blkno
= STps
->drv_block
;
4081 at_sm
= STps
->at_sm
;
4082 frame_seq_numbr
= STp
->frame_seq_number
;
4083 logical_blk_num
= STp
->logical_blk_num
;
4085 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4088 chg_eof
= 0; /* Changed from the FSF after this */
4092 if (STp
->linux_media
)
4093 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
4095 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
4099 at_sm
&= (arg
== 0);
4103 chg_eof
= 0; /* Changed from the FSF after this */
4107 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
4110 blkno
= (-1); /* We can't know the block number */
4111 at_sm
&= (arg
== 0);
4118 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
4119 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
4121 if (cmd_in
== MTFSR
) {
4122 logical_blk_num
+= arg
;
4123 if (blkno
>= 0) blkno
+= arg
;
4126 logical_blk_num
-= arg
;
4127 if (blkno
>= 0) blkno
-= arg
;
4129 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
4130 fileno
= STps
->drv_file
;
4131 blkno
= STps
->drv_block
;
4132 at_sm
&= (arg
== 0);
4137 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4138 cmd
[2] = (arg
>> 16);
4139 cmd
[3] = (arg
>> 8);
4143 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4144 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4147 blkno
= fileno
= (-1);
4153 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4155 cmd
[2] = (ltmp
>> 16);
4156 cmd
[3] = (ltmp
>> 8);
4162 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4163 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4168 blkno
= fileno
= (-1);
4173 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4174 STp
->write_type
= OS_WRITE_DATA
;
4175 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4180 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4182 for (i
=0; i
<arg
; i
++)
4183 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4184 if (fileno
>= 0) fileno
+= arg
;
4185 if (blkno
>= 0) blkno
= 0;
4189 if (STp
->write_prot
)
4193 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4194 if (cmd_in
== MTWSM
)
4196 cmd
[2] = (arg
>> 16);
4197 cmd
[3] = (arg
>> 8);
4199 timeout
= STp
->timeout
;
4202 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4203 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4208 at_sm
= (cmd_in
== MTWSM
);
4214 cmd
[0] = START_STOP
;
4215 cmd
[1] = 1; /* Don't wait for completion */
4216 if (cmd_in
== MTLOAD
) {
4217 if (STp
->ready
== ST_NO_TAPE
)
4218 cmd
[4] = 4; /* open tray */
4220 cmd
[4] = 1; /* load */
4222 if (cmd_in
== MTRETEN
)
4223 cmd
[4] = 3; /* retension then mount */
4224 if (cmd_in
== MTOFFL
)
4225 cmd
[4] = 4; /* rewind then eject */
4226 timeout
= STp
->timeout
;
4231 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4234 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4237 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4240 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4245 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4250 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4252 return 0; /* Should do something ? */
4257 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4259 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4260 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4261 ioctl_result
= -EIO
;
4264 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4266 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4268 ioctl_result
= -EIO
;
4271 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4272 fileno
= STp
->filemark_cnt
;
4277 if (STp
->write_prot
)
4279 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4280 i
= osst_write_eod(STp
, &SRpnt
);
4281 if (i
< ioctl_result
) ioctl_result
= i
;
4282 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4283 if (i
< ioctl_result
) ioctl_result
= i
;
4284 fileno
= blkno
= at_sm
= 0 ;
4288 cmd
[0] = REZERO_UNIT
; /* rewind */
4292 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4294 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4297 case MTSETBLK
: /* Set block length */
4298 if ((STps
->drv_block
== 0 ) &&
4300 ((STp
->buffer
)->buffer_bytes
== 0) &&
4301 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4302 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4303 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4305 * Only allowed to change the block size if you opened the
4306 * device at the beginning of a file before writing anything.
4307 * Note, that when reading, changing block_size is futile,
4308 * as the size used when writing overrides it.
4310 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4311 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4312 name
, STp
->block_size
);
4315 case MTSETDENSITY
: /* Set tape density */
4316 case MTSETDRVBUFFER
: /* Set drive buffering */
4317 case SET_DENS_AND_BLK
: /* Set density and block size */
4319 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4320 return (-EIO
); /* Not allowed if data in buffer */
4321 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4322 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4323 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4324 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4325 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4326 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4329 return 0; /* FIXME silently ignore if block size didn't change */
4335 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4337 ioctl_result
= (STp
->buffer
)->syscall_result
;
4341 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4343 return ioctl_result
;
4346 if (!ioctl_result
) { /* SCSI command successful */
4347 STp
->frame_seq_number
= frame_seq_numbr
;
4348 STp
->logical_blk_num
= logical_blk_num
;
4354 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4357 if (!ioctl_result
) { /* success */
4359 if (cmd_in
== MTFSFM
) {
4363 if (cmd_in
== MTBSFM
) {
4367 STps
->drv_block
= blkno
;
4368 STps
->drv_file
= fileno
;
4369 STps
->at_sm
= at_sm
;
4371 if (cmd_in
== MTEOM
)
4373 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4374 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4376 STp
->logical_blk_num
++;
4377 STp
->frame_seq_number
++;
4378 STp
->frame_in_buffer
= 0;
4379 STp
->buffer
->read_pointer
= 0;
4381 else if (cmd_in
== MTFSF
)
4382 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4384 STps
->eof
= ST_NOEOF
;
4386 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4387 STp
->rew_at_close
= 0;
4388 else if (cmd_in
== MTLOAD
) {
4389 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4390 STp
->ps
[i
].rw
= ST_IDLE
;
4391 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4396 if (cmd_in
== MTREW
) {
4397 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4398 if (ioctl_result
> 0)
4402 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4403 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4404 STps
->drv_file
= STps
->drv_block
= -1;
4406 STps
->drv_file
= STps
->drv_block
= 0;
4407 STps
->eof
= ST_NOEOF
;
4408 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4409 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4410 STps
->drv_file
= STps
->drv_block
= -1;
4412 STps
->drv_file
= STp
->filemark_cnt
;
4413 STps
->drv_block
= 0;
4416 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4417 STps
->drv_file
= STps
->drv_block
= (-1);
4418 STps
->eof
= ST_NOEOF
;
4420 } else if (cmd_in
== MTERASE
) {
4422 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4423 if (SRpnt
->sense
[2] & 0x40) {
4424 STps
->eof
= ST_EOM_OK
;
4425 STps
->drv_block
= 0;
4428 STps
->eof
= ST_NOEOF
;
4430 if ((SRpnt
->sense
[2] & 0x0f) == BLANK_CHECK
)
4433 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4434 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4438 return ioctl_result
;
4442 /* Open the device */
4443 static int __os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4445 unsigned short flags
;
4446 int i
, b_size
, new_session
= 0, retval
= 0;
4447 unsigned char cmd
[MAX_COMMAND_SIZE
];
4448 struct osst_request
* SRpnt
= NULL
;
4449 struct osst_tape
* STp
;
4450 struct st_modedef
* STm
;
4451 struct st_partstat
* STps
;
4453 int dev
= TAPE_NR(inode
);
4454 int mode
= TAPE_MODE(inode
);
4457 * We really want to do nonseekable_open(inode, filp); here, but some
4458 * versions of tar incorrectly call lseek on tapes and bail out if that
4459 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4461 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4463 write_lock(&os_scsi_tapes_lock
);
4464 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4465 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4466 write_unlock(&os_scsi_tapes_lock
);
4470 name
= tape_name(STp
);
4473 write_unlock(&os_scsi_tapes_lock
);
4475 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4479 if (scsi_device_get(STp
->device
)) {
4480 write_unlock(&os_scsi_tapes_lock
);
4482 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4486 filp
->private_data
= STp
;
4488 write_unlock(&os_scsi_tapes_lock
);
4489 STp
->rew_at_close
= TAPE_REWIND(inode
);
4491 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4495 if (mode
!= STp
->current_mode
) {
4498 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4499 name
, STp
->current_mode
, mode
);
4502 STp
->current_mode
= mode
;
4504 STm
= &(STp
->modes
[STp
->current_mode
]);
4506 flags
= filp
->f_flags
;
4507 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4509 STp
->raw
= TAPE_IS_RAW(inode
);
4513 /* Allocate data segments for this device's tape buffer */
4514 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4515 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4516 retval
= (-EOVERFLOW
);
4519 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4520 for (i
= 0, b_size
= 0;
4521 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4522 b_size
+= STp
->buffer
->sg
[i
++].length
);
4523 STp
->buffer
->aux
= (os_aux_t
*) (page_address(sg_page(&STp
->buffer
->sg
[i
])) + OS_DATA_SIZE
- b_size
);
4525 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4526 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4527 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4528 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4531 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4532 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4536 STp
->buffer
->writing
= 0;
4537 STp
->buffer
->syscall_result
= 0;
4539 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4540 STps
= &(STp
->ps
[i
]);
4543 STp
->ready
= ST_READY
;
4545 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4548 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4549 cmd
[0] = TEST_UNIT_READY
;
4551 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4553 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4556 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4557 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4558 SRpnt
->sense
[12] == 4 ) {
4560 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sense
[13]);
4562 if (filp
->f_flags
& O_NONBLOCK
) {
4566 if (SRpnt
->sense
[13] == 2) { /* initialize command required (LOAD) */
4567 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4568 cmd
[0] = START_STOP
;
4571 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4572 STp
->timeout
, MAX_RETRIES
, 1);
4574 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sense
[13]==1?15:3) * 60, 0);
4576 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4577 (SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4579 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4583 for (i
=0; i
< 10; i
++) {
4585 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4586 cmd
[0] = TEST_UNIT_READY
;
4588 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4589 STp
->timeout
, MAX_RETRIES
, 1);
4590 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4591 (SRpnt
->sense
[2] & 0x0f) != UNIT_ATTENTION
)
4595 STp
->pos_unknown
= 0;
4596 STp
->partition
= STp
->new_partition
= 0;
4597 if (STp
->can_partitions
)
4598 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4599 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4600 STps
= &(STp
->ps
[i
]);
4601 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4602 STps
->eof
= ST_NOEOF
;
4604 STps
->last_block_valid
= 0;
4605 STps
->drv_block
= 0;
4606 STps
->drv_file
= 0 ;
4609 STp
->recover_count
= 0;
4610 STp
->abort_count
= 0;
4613 * if we have valid headers from before, and the drive/tape seem untouched,
4614 * open without reconfiguring and re-reading the headers
4616 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4617 !SRpnt
->result
&& SRpnt
->sense
[0] == 0) {
4619 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4620 cmd
[0] = MODE_SENSE
;
4622 cmd
[2] = VENDOR_IDENT_PAGE
;
4623 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4625 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4627 if (STp
->buffer
->syscall_result
||
4628 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4629 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4630 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4631 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4633 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4634 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4635 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4636 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4637 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4641 i
= STp
->first_frame_position
;
4642 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4643 if (STp
->door_locked
== ST_UNLOCKED
) {
4644 if (do_door_lock(STp
, 1))
4645 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4647 STp
->door_locked
= ST_LOCKED_AUTO
;
4649 if (!STp
->frame_in_buffer
) {
4650 STp
->block_size
= (STm
->default_blksize
> 0) ?
4651 STm
->default_blksize
: OS_DATA_SIZE
;
4652 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4654 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4656 osst_release_request(SRpnt
);
4660 if (i
!= STp
->first_frame_position
)
4661 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4662 name
, i
, STp
->first_frame_position
);
4668 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4669 (SRpnt
->sense
[2] != 2 || SRpnt
->sense
[12] != 0x3A) ) {
4671 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4672 cmd
[0] = MODE_SELECT
;
4674 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4676 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4677 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4678 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4679 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4680 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4681 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4682 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4683 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4686 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4688 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4692 for (i
=0; i
< 10; i
++) {
4694 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4695 cmd
[0] = TEST_UNIT_READY
;
4697 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4698 STp
->timeout
, MAX_RETRIES
, 1);
4699 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4700 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
)
4703 if ((SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) {
4706 STp
->pos_unknown
= 0;
4707 STp
->partition
= STp
->new_partition
= 0;
4708 if (STp
->can_partitions
)
4709 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4710 for (j
= 0; j
< ST_NBR_PARTITIONS
; j
++) {
4711 STps
= &(STp
->ps
[j
]);
4713 STps
->eof
= ST_NOEOF
;
4715 STps
->last_block_valid
= 0;
4716 STps
->drv_block
= 0;
4717 STps
->drv_file
= 0 ;
4724 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4725 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4727 if ((STp
->buffer
)->syscall_result
!= 0) {
4728 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4729 (SRpnt
->sense
[0] & 0x70) == 0x70 &&
4730 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4731 SRpnt
->sense
[12] == 0x3a) { /* Check ASC */
4732 STp
->ready
= ST_NO_TAPE
;
4734 STp
->ready
= ST_NOT_READY
;
4735 osst_release_request(SRpnt
);
4737 STp
->density
= 0; /* Clear the erroneous "residue" */
4738 STp
->write_prot
= 0;
4739 STp
->block_size
= 0;
4740 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4741 STp
->partition
= STp
->new_partition
= 0;
4742 STp
->door_locked
= ST_UNLOCKED
;
4746 osst_configure_onstream(STp
, &SRpnt
);
4748 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4749 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4750 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4751 STp
->buffer
->buffer_bytes
=
4752 STp
->buffer
->read_pointer
=
4753 STp
->frame_in_buffer
= 0;
4757 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4758 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4759 (STp
->buffer
)->buffer_blocks
);
4762 if (STp
->drv_write_prot
) {
4763 STp
->write_prot
= 1;
4766 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4768 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4774 if (new_session
) { /* Change the drive parameters for the new mode */
4777 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4779 STp
->density_changed
= STp
->blksize_changed
= 0;
4780 STp
->compression_changed
= 0;
4784 * properly position the tape and check the ADR headers
4786 if (STp
->door_locked
== ST_UNLOCKED
) {
4787 if (do_door_lock(STp
, 1))
4788 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4790 STp
->door_locked
= ST_LOCKED_AUTO
;
4793 osst_analyze_headers(STp
, &SRpnt
);
4795 osst_release_request(SRpnt
);
4802 osst_release_request(SRpnt
);
4803 normalize_buffer(STp
->buffer
);
4806 scsi_device_put(STp
->device
);
4811 /* BKL pushdown: spaghetti avoidance wrapper */
4812 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4816 mutex_lock(&osst_int_mutex
);
4817 ret
= __os_scsi_tape_open(inode
, filp
);
4818 mutex_unlock(&osst_int_mutex
);
4824 /* Flush the tape buffer before close */
4825 static int os_scsi_tape_flush(struct file
* filp
, fl_owner_t id
)
4827 int result
= 0, result2
;
4828 struct osst_tape
* STp
= filp
->private_data
;
4829 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4830 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4831 struct osst_request
* SRpnt
= NULL
;
4832 char * name
= tape_name(STp
);
4834 if (file_count(filp
) > 1)
4837 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4838 STp
->write_type
= OS_WRITE_DATA
;
4839 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4840 if (result
!= 0 && result
!= (-ENOSPC
))
4843 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4847 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4848 name
, (long)(filp
->f_pos
));
4849 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4850 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4853 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4856 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4857 name
, 1+STp
->two_fm
);
4860 else if (!STp
->rew_at_close
) {
4861 STps
= &(STp
->ps
[STp
->partition
]);
4862 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4864 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4865 else if (STps
->eof
== ST_FM_HIT
) {
4866 result
= cross_eof(STp
, &SRpnt
, 0);
4868 if (STps
->drv_file
>= 0)
4870 STps
->drv_block
= 0;
4874 STps
->eof
= ST_NOEOF
;
4877 else if ((STps
->eof
== ST_NOEOF
&&
4878 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4879 STps
->eof
== ST_FM_HIT
) {
4880 if (STps
->drv_file
>= 0)
4882 STps
->drv_block
= 0;
4888 if (STp
->rew_at_close
) {
4889 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4890 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4891 if (result
== 0 && result2
< 0)
4894 if (SRpnt
) osst_release_request(SRpnt
);
4896 if (STp
->abort_count
|| STp
->recover_count
) {
4897 printk(KERN_INFO
"%s:I:", name
);
4898 if (STp
->abort_count
)
4899 printk(" %d unrecovered errors", STp
->abort_count
);
4900 if (STp
->recover_count
)
4901 printk(" %d recovered errors", STp
->recover_count
);
4902 if (STp
->write_count
)
4903 printk(" in %d frames written", STp
->write_count
);
4904 if (STp
->read_count
)
4905 printk(" in %d frames read", STp
->read_count
);
4907 STp
->recover_count
= 0;
4908 STp
->abort_count
= 0;
4910 STp
->write_count
= 0;
4911 STp
->read_count
= 0;
4917 /* Close the device and release it */
4918 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4921 struct osst_tape
* STp
= filp
->private_data
;
4923 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4924 do_door_lock(STp
, 0);
4929 normalize_buffer(STp
->buffer
);
4930 write_lock(&os_scsi_tapes_lock
);
4932 write_unlock(&os_scsi_tapes_lock
);
4934 scsi_device_put(STp
->device
);
4940 /* The ioctl command */
4941 static long osst_ioctl(struct file
* file
,
4942 unsigned int cmd_in
, unsigned long arg
)
4944 int i
, cmd_nr
, cmd_type
, blk
, retval
= 0;
4945 struct st_modedef
* STm
;
4946 struct st_partstat
* STps
;
4947 struct osst_request
* SRpnt
= NULL
;
4948 struct osst_tape
* STp
= file
->private_data
;
4949 char * name
= tape_name(STp
);
4950 void __user
* p
= (void __user
*)arg
;
4952 mutex_lock(&osst_int_mutex
);
4953 if (mutex_lock_interruptible(&STp
->lock
)) {
4954 mutex_unlock(&osst_int_mutex
);
4955 return -ERESTARTSYS
;
4959 if (debugging
&& !STp
->in_use
) {
4960 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4965 STm
= &(STp
->modes
[STp
->current_mode
]);
4966 STps
= &(STp
->ps
[STp
->partition
]);
4969 * If we are in the middle of error recovery, don't let anyone
4970 * else try and use this device. Also, if error recovery fails, it
4971 * may try and take the device offline, in which case all further
4972 * access to the device is prohibited.
4974 retval
= scsi_ioctl_block_when_processing_errors(STp
->device
, cmd_in
,
4975 file
->f_flags
& O_NDELAY
);
4979 cmd_type
= _IOC_TYPE(cmd_in
);
4980 cmd_nr
= _IOC_NR(cmd_in
);
4982 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4983 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4985 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4989 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4994 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
5000 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
5001 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
5006 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
5011 if (!STp
->pos_unknown
) {
5013 if (STps
->eof
== ST_FM_HIT
) {
5014 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
5016 if (STps
->drv_file
>= 0)
5017 STps
->drv_file
+= 1;
5019 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
5021 if (STps
->drv_file
>= 0)
5022 STps
->drv_file
+= 1;
5026 if (mtc
.mt_op
== MTSEEK
) {
5027 /* Old position must be restored if partition will be changed */
5028 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
5031 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
5032 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
5033 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
5034 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
5035 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
5036 mtc
.mt_op
== MTCOMPRESSION
;
5038 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
5046 * If there was a bus reset, block further access
5047 * to this device. If the user wants to rewind the tape,
5048 * then reset the flag and allow access again.
5050 if(mtc
.mt_op
!= MTREW
&&
5051 mtc
.mt_op
!= MTOFFL
&&
5052 mtc
.mt_op
!= MTRETEN
&&
5053 mtc
.mt_op
!= MTERASE
&&
5054 mtc
.mt_op
!= MTSEEK
&&
5055 mtc
.mt_op
!= MTEOM
) {
5060 /* remove this when the midlevel properly clears was_reset */
5061 STp
->device
->was_reset
= 0;
5064 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
5065 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
5066 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
5067 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
5068 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
5071 * The user tells us to move to another position on the tape.
5072 * If we were appending to the tape content, that would leave
5073 * the tape without proper end, in that case write EOD and
5074 * update the header to reflect its position.
5077 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
5078 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
5079 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
5080 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5082 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
5083 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
5084 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5085 i
= osst_write_trailer(STp
, &SRpnt
,
5086 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5088 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5089 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
5090 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5100 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
5101 do_door_lock(STp
, 0); /* Ignore result! */
5103 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
5104 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
5105 retval
= osst_set_options(STp
, mtc
.mt_count
);
5109 if (mtc
.mt_op
== MTSETPART
) {
5110 if (mtc
.mt_count
>= STp
->nbr_partitions
)
5113 STp
->new_partition
= mtc
.mt_count
;
5119 if (mtc
.mt_op
== MTMKPART
) {
5120 if (!STp
->can_partitions
) {
5124 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
5125 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5129 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5130 STp
->ps
[i
].rw
= ST_IDLE
;
5131 STp
->ps
[i
].at_sm
= 0;
5132 STp
->ps
[i
].last_block_valid
= 0;
5134 STp
->partition
= STp
->new_partition
= 0;
5135 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
5136 STps
->drv_block
= STps
->drv_file
= 0;
5141 if (mtc
.mt_op
== MTSEEK
) {
5143 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
5145 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
5146 if (!STp
->can_partitions
)
5147 STp
->ps
[0].rw
= ST_IDLE
;
5152 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
5153 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5158 cross_eof(STp
, &SRpnt
, 0);
5160 if (mtc
.mt_op
== MTCOMPRESSION
)
5161 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5163 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5164 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5165 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5169 if (!STm
->defined
) {
5174 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5179 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5180 struct mtget mt_status
;
5182 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5187 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5188 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5189 mt_status
.mt_dsreg
=
5190 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5191 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5192 mt_status
.mt_blkno
= STps
->drv_block
;
5193 mt_status
.mt_fileno
= STps
->drv_file
;
5194 if (STp
->block_size
!= 0) {
5195 if (STps
->rw
== ST_WRITING
)
5196 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5197 else if (STps
->rw
== ST_READING
)
5198 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5199 STp
->block_size
- 1) / STp
->block_size
;
5202 mt_status
.mt_gstat
= 0;
5203 if (STp
->drv_write_prot
)
5204 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5205 if (mt_status
.mt_blkno
== 0) {
5206 if (mt_status
.mt_fileno
== 0)
5207 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5209 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5211 mt_status
.mt_resid
= STp
->partition
;
5212 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5213 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5214 else if (STps
->eof
>= ST_EOM_OK
)
5215 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5216 if (STp
->density
== 1)
5217 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5218 else if (STp
->density
== 2)
5219 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5220 else if (STp
->density
== 3)
5221 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5222 if (STp
->ready
== ST_READY
)
5223 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5224 if (STp
->ready
== ST_NO_TAPE
)
5225 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5227 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5228 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5229 STp
->drv_buffer
!= 0)
5230 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5232 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5238 STp
->recover_erreg
= 0; /* Clear after read */
5241 } /* End of MTIOCGET */
5243 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5244 struct mtpos mt_pos
;
5246 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5251 blk
= osst_get_frame_position(STp
, &SRpnt
);
5253 blk
= osst_get_sector(STp
, &SRpnt
);
5258 mt_pos
.mt_blkno
= blk
;
5259 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5264 if (SRpnt
) osst_release_request(SRpnt
);
5266 mutex_unlock(&STp
->lock
);
5268 retval
= scsi_ioctl(STp
->device
, cmd_in
, p
);
5269 mutex_unlock(&osst_int_mutex
);
5273 if (SRpnt
) osst_release_request(SRpnt
);
5275 mutex_unlock(&STp
->lock
);
5276 mutex_unlock(&osst_int_mutex
);
5281 #ifdef CONFIG_COMPAT
5282 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5284 struct osst_tape
*STp
= file
->private_data
;
5285 struct scsi_device
*sdev
= STp
->device
;
5286 int ret
= -ENOIOCTLCMD
;
5287 if (sdev
->host
->hostt
->compat_ioctl
) {
5289 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5298 /* Memory handling routines */
5300 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5301 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5305 struct osst_buffer
*tb
;
5307 if (from_initialization
)
5308 priority
= GFP_ATOMIC
;
5310 priority
= GFP_KERNEL
;
5312 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5313 tb
= kzalloc(i
, priority
);
5315 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5319 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5320 tb
->use_sg
= max_sg
;
5323 tb
->buffer_size
= 0;
5327 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5328 i
, max_sg
, need_dma
);
5333 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5334 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5336 int segs
, nbr
, max_segs
, b_size
, order
, got
;
5339 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5342 if (STbuffer
->sg_segs
) {
5343 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5344 normalize_buffer(STbuffer
);
5346 /* See how many segments we can use -- need at least two */
5347 nbr
= max_segs
= STbuffer
->use_sg
;
5351 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5353 priority
|= GFP_DMA
;
5355 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5356 big enough to reach the goal (code assumes no segments in place) */
5357 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5358 struct page
*page
= alloc_pages(priority
, order
);
5360 STbuffer
->sg
[0].offset
= 0;
5362 sg_set_page(&STbuffer
->sg
[0], page
, b_size
, 0);
5363 STbuffer
->b_data
= page_address(page
);
5367 if (sg_page(&STbuffer
->sg
[0]) == NULL
) {
5368 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5371 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5372 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5373 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5374 struct page
*page
= alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5375 STbuffer
->sg
[segs
].offset
= 0;
5377 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5380 STbuffer
->buffer_size
= got
;
5382 normalize_buffer(STbuffer
);
5385 sg_set_page(&STbuffer
->sg
[segs
], page
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
, 0);
5386 got
+= STbuffer
->sg
[segs
].length
;
5387 STbuffer
->buffer_size
= got
;
5388 STbuffer
->sg_segs
= ++segs
;
5393 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5394 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5396 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5397 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5398 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5406 /* Release the segments */
5407 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5409 int i
, order
, b_size
;
5411 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5413 for (b_size
= PAGE_SIZE
, order
= 0;
5414 b_size
< STbuffer
->sg
[i
].length
;
5415 b_size
*= 2, order
++);
5417 __free_pages(sg_page(&STbuffer
->sg
[i
]), order
);
5418 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5421 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5422 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5423 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5425 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5429 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5430 negative error code. */
5431 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5433 int i
, cnt
, res
, offset
;
5435 for (i
=0, offset
=st_bp
->buffer_bytes
;
5436 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5437 offset
-= st_bp
->sg
[i
].length
;
5438 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5439 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5442 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5443 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5444 st_bp
->sg
[i
].length
- offset
: do_count
;
5445 res
= copy_from_user(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, ubp
, cnt
);
5449 st_bp
->buffer_bytes
+= cnt
;
5453 if (do_count
) { /* Should never happen */
5454 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5462 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5463 negative error code. */
5464 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5466 int i
, cnt
, res
, offset
;
5468 for (i
=0, offset
=st_bp
->read_pointer
;
5469 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5470 offset
-= st_bp
->sg
[i
].length
;
5471 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5472 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5475 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5476 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5477 st_bp
->sg
[i
].length
- offset
: do_count
;
5478 res
= copy_to_user(ubp
, page_address(sg_page(&st_bp
->sg
[i
])) + offset
, cnt
);
5482 st_bp
->buffer_bytes
-= cnt
;
5483 st_bp
->read_pointer
+= cnt
;
5487 if (do_count
) { /* Should never happen */
5488 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5494 /* Sets the tail of the buffer after fill point to zero.
5495 Returns zero (success) or negative error code. */
5496 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5498 int i
, offset
, do_count
, cnt
;
5500 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5501 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5502 offset
-= st_bp
->sg
[i
].length
;
5503 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5504 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5507 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5508 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5509 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5510 st_bp
->sg
[i
].length
- offset
: do_count
;
5511 memset(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, 0, cnt
);
5515 if (do_count
) { /* Should never happen */
5516 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5522 /* Copy a osst 32K chunk of memory into the buffer.
5523 Returns zero (success) or negative error code. */
5524 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5526 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5528 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5529 cnt
= st_bp
->sg
[i
].length
< do_count
?
5530 st_bp
->sg
[i
].length
: do_count
;
5531 memcpy(page_address(sg_page(&st_bp
->sg
[i
])), ptr
, cnt
);
5535 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5536 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5543 /* Copy a osst 32K chunk of memory from the buffer.
5544 Returns zero (success) or negative error code. */
5545 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5547 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5549 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5550 cnt
= st_bp
->sg
[i
].length
< do_count
?
5551 st_bp
->sg
[i
].length
: do_count
;
5552 memcpy(ptr
, page_address(sg_page(&st_bp
->sg
[i
])), cnt
);
5556 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5557 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5565 /* Module housekeeping */
5567 static void validate_options (void)
5570 osst_max_dev
= max_dev
;
5571 if (write_threshold_kbs
> 0)
5572 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5573 if (osst_write_threshold
> osst_buffer_size
)
5574 osst_write_threshold
= osst_buffer_size
;
5575 if (max_sg_segs
>= OSST_FIRST_SG
)
5576 osst_max_sg_segs
= max_sg_segs
;
5578 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5579 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5584 /* Set the boot options. Syntax: osst=xxx,yyy,...
5585 where xxx is write threshold in 1024 byte blocks,
5586 and yyy is number of s/g segments to use. */
5587 static int __init
osst_setup (char *str
)
5592 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5595 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5596 *parms
[i
].val
= ints
[i
+ 1];
5598 while (stp
!= NULL
) {
5599 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5600 int len
= strlen(parms
[i
].name
);
5601 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5602 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5604 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5608 if (i
>= ARRAY_SIZE(parms
))
5609 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5611 stp
= strchr(stp
, ',');
5620 __setup("osst=", osst_setup
);
5624 static const struct file_operations osst_fops
= {
5625 .owner
= THIS_MODULE
,
5627 .write
= osst_write
,
5628 .unlocked_ioctl
= osst_ioctl
,
5629 #ifdef CONFIG_COMPAT
5630 .compat_ioctl
= osst_compat_ioctl
,
5632 .open
= os_scsi_tape_open
,
5633 .flush
= os_scsi_tape_flush
,
5634 .release
= os_scsi_tape_close
,
5635 .llseek
= noop_llseek
,
5638 static int osst_supports(struct scsi_device
* SDp
)
5640 struct osst_support_data
{
5644 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5647 static struct osst_support_data support_list
[] = {
5648 /* {"XXX", "Yy-", "", NULL}, example */
5652 struct osst_support_data
*rp
;
5654 /* We are willing to drive OnStream SC-x0 as well as the
5655 * * IDE, ParPort, FireWire, USB variants, if accessible by
5656 * * emulation layer (ide-scsi, usb-storage, ...) */
5658 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5659 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5660 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5661 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5667 * sysfs support for osst driver parameter information
5670 static ssize_t
version_show(struct device_driver
*ddd
, char *buf
)
5672 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5675 static DRIVER_ATTR_RO(version
);
5677 static int osst_create_sysfs_files(struct device_driver
*sysfs
)
5679 return driver_create_file(sysfs
, &driver_attr_version
);
5682 static void osst_remove_sysfs_files(struct device_driver
*sysfs
)
5684 driver_remove_file(sysfs
, &driver_attr_version
);
5688 * sysfs support for accessing ADR header information
5691 static ssize_t
osst_adr_rev_show(struct device
*dev
,
5692 struct device_attribute
*attr
, char *buf
)
5694 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5697 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5698 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5702 DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5704 static ssize_t
osst_linux_media_version_show(struct device
*dev
,
5705 struct device_attribute
*attr
,
5708 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5711 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5712 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5716 DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5718 static ssize_t
osst_capacity_show(struct device
*dev
,
5719 struct device_attribute
*attr
, char *buf
)
5721 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5724 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5725 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5729 DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5731 static ssize_t
osst_first_data_ppos_show(struct device
*dev
,
5732 struct device_attribute
*attr
,
5735 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5738 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5739 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5743 DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5745 static ssize_t
osst_eod_frame_ppos_show(struct device
*dev
,
5746 struct device_attribute
*attr
,
5749 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5752 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5753 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5757 DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5759 static ssize_t
osst_filemark_cnt_show(struct device
*dev
,
5760 struct device_attribute
*attr
, char *buf
)
5762 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5765 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5766 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5770 DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5772 static struct class *osst_sysfs_class
;
5774 static int osst_sysfs_init(void)
5776 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5777 if (IS_ERR(osst_sysfs_class
)) {
5778 printk(KERN_ERR
"osst :W: Unable to register sysfs class\n");
5779 return PTR_ERR(osst_sysfs_class
);
5785 static void osst_sysfs_destroy(dev_t dev
)
5787 device_destroy(osst_sysfs_class
, dev
);
5790 static int osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5792 struct device
*osst_member
;
5795 osst_member
= device_create(osst_sysfs_class
, device
, dev
, STp
,
5797 if (IS_ERR(osst_member
)) {
5798 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5799 return PTR_ERR(osst_member
);
5802 err
= device_create_file(osst_member
, &dev_attr_ADR_rev
);
5805 err
= device_create_file(osst_member
, &dev_attr_media_version
);
5808 err
= device_create_file(osst_member
, &dev_attr_capacity
);
5811 err
= device_create_file(osst_member
, &dev_attr_BOT_frame
);
5814 err
= device_create_file(osst_member
, &dev_attr_EOD_frame
);
5817 err
= device_create_file(osst_member
, &dev_attr_file_count
);
5824 osst_sysfs_destroy(dev
);
5828 static void osst_sysfs_cleanup(void)
5830 class_destroy(osst_sysfs_class
);
5834 * osst startup / cleanup code
5837 static int osst_probe(struct device
*dev
)
5839 struct scsi_device
* SDp
= to_scsi_device(dev
);
5840 struct osst_tape
* tpnt
;
5841 struct st_modedef
* STm
;
5842 struct st_partstat
* STps
;
5843 struct osst_buffer
* buffer
;
5844 struct gendisk
* drive
;
5845 int i
, dev_num
, err
= -ENODEV
;
5847 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5850 drive
= alloc_disk(1);
5852 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5856 /* if this is the first attach, build the infrastructure */
5857 write_lock(&os_scsi_tapes_lock
);
5858 if (os_scsi_tapes
== NULL
) {
5859 os_scsi_tapes
= kmalloc_array(osst_max_dev
,
5860 sizeof(struct osst_tape
*),
5862 if (os_scsi_tapes
== NULL
) {
5863 write_unlock(&os_scsi_tapes_lock
);
5864 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5867 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5870 if (osst_nr_dev
>= osst_max_dev
) {
5871 write_unlock(&os_scsi_tapes_lock
);
5872 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5876 /* find a free minor number */
5877 for (i
= 0; i
< osst_max_dev
&& os_scsi_tapes
[i
]; i
++)
5879 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5882 /* allocate a struct osst_tape for this device */
5883 tpnt
= kzalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5885 write_unlock(&os_scsi_tapes_lock
);
5886 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5890 /* allocate a buffer for this device */
5891 i
= SDp
->host
->sg_tablesize
;
5892 if (osst_max_sg_segs
< i
)
5893 i
= osst_max_sg_segs
;
5894 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5895 if (buffer
== NULL
) {
5896 write_unlock(&os_scsi_tapes_lock
);
5897 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5901 os_scsi_tapes
[dev_num
] = tpnt
;
5902 tpnt
->buffer
= buffer
;
5904 drive
->private_data
= &tpnt
->driver
;
5905 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5906 tpnt
->driver
= &osst_template
;
5907 tpnt
->drive
= drive
;
5909 tpnt
->capacity
= 0xfffff;
5911 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5912 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5914 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5915 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5916 tpnt
->can_partitions
= 0;
5917 tpnt
->two_fm
= OSST_TWO_FM
;
5918 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5919 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5920 tpnt
->write_threshold
= osst_write_threshold
;
5921 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5922 tpnt
->partition
= 0;
5923 tpnt
->new_partition
= 0;
5924 tpnt
->nbr_partitions
= 0;
5925 tpnt
->min_block
= 512;
5926 tpnt
->max_block
= OS_DATA_SIZE
;
5927 tpnt
->timeout
= OSST_TIMEOUT
;
5928 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5930 /* Recognize OnStream tapes */
5931 /* We don't need to test for OnStream, as this has been done in detect () */
5932 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5933 tpnt
->omit_blklims
= 1;
5935 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5936 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5937 tpnt
->frame_in_buffer
= 0;
5938 tpnt
->header_ok
= 0;
5939 tpnt
->linux_media
= 0;
5940 tpnt
->header_cache
= NULL
;
5942 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5943 STm
= &(tpnt
->modes
[i
]);
5945 STm
->sysv
= OSST_SYSV
;
5946 STm
->defaults_for_writes
= 0;
5947 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5948 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5949 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5950 STm
->default_compression
= ST_DONT_TOUCH
;
5951 STm
->default_blksize
= 512;
5952 STm
->default_density
= (-1); /* No forced density */
5955 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5956 STps
= &(tpnt
->ps
[i
]);
5958 STps
->eof
= ST_NOEOF
;
5960 STps
->last_block_valid
= 0;
5961 STps
->drv_block
= (-1);
5962 STps
->drv_file
= (-1);
5965 tpnt
->current_mode
= 0;
5966 tpnt
->modes
[0].defined
= 1;
5967 tpnt
->modes
[2].defined
= 1;
5968 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5970 mutex_init(&tpnt
->lock
);
5972 write_unlock(&os_scsi_tapes_lock
);
5978 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5980 goto out_free_buffer
;
5982 /* No-rewind entry */
5983 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5984 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5986 goto out_free_sysfs1
;
5989 sdev_printk(KERN_INFO
, SDp
,
5990 "osst :I: Attached OnStream %.5s tape as %s\n",
5991 SDp
->model
, tape_name(tpnt
));
5996 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, dev_num
));
6004 static int osst_remove(struct device
*dev
)
6006 struct scsi_device
* SDp
= to_scsi_device(dev
);
6007 struct osst_tape
* tpnt
;
6010 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
6013 write_lock(&os_scsi_tapes_lock
);
6014 for(i
=0; i
< osst_max_dev
; i
++) {
6015 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
6016 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
6017 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
6018 tpnt
->device
= NULL
;
6019 put_disk(tpnt
->drive
);
6020 os_scsi_tapes
[i
] = NULL
;
6022 write_unlock(&os_scsi_tapes_lock
);
6023 vfree(tpnt
->header_cache
);
6025 normalize_buffer(tpnt
->buffer
);
6026 kfree(tpnt
->buffer
);
6032 write_unlock(&os_scsi_tapes_lock
);
6036 static int __init
init_osst(void)
6040 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
6044 err
= osst_sysfs_init();
6048 err
= register_chrdev(OSST_MAJOR
, "osst", &osst_fops
);
6050 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
6054 err
= scsi_register_driver(&osst_template
.gendrv
);
6056 goto err_out_chrdev
;
6058 err
= osst_create_sysfs_files(&osst_template
.gendrv
);
6060 goto err_out_scsidrv
;
6065 scsi_unregister_driver(&osst_template
.gendrv
);
6067 unregister_chrdev(OSST_MAJOR
, "osst");
6069 osst_sysfs_cleanup();
6073 static void __exit
exit_osst (void)
6076 struct osst_tape
* STp
;
6078 osst_remove_sysfs_files(&osst_template
.gendrv
);
6079 scsi_unregister_driver(&osst_template
.gendrv
);
6080 unregister_chrdev(OSST_MAJOR
, "osst");
6081 osst_sysfs_cleanup();
6083 if (os_scsi_tapes
) {
6084 for (i
=0; i
< osst_max_dev
; ++i
) {
6085 if (!(STp
= os_scsi_tapes
[i
])) continue;
6086 /* This is defensive, supposed to happen during detach */
6087 vfree(STp
->header_cache
);
6089 normalize_buffer(STp
->buffer
);
6092 put_disk(STp
->drive
);
6095 kfree(os_scsi_tapes
);
6097 printk(KERN_INFO
"osst :I: Unloaded.\n");
6100 module_init(init_osst
);
6101 module_exit(exit_osst
);