2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid
= "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27 static const char * osst_version
= "0.99.4";
29 /* The "failure to reconnect" firmware bug */
30 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31 #define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
34 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
41 #include <linux/slab.h>
42 #include <linux/init.h>
43 #include <linux/string.h>
44 #include <linux/errno.h>
45 #include <linux/mtio.h>
46 #include <linux/ioctl.h>
47 #include <linux/fcntl.h>
48 #include <linux/spinlock.h>
49 #include <linux/vmalloc.h>
50 #include <linux/blkdev.h>
51 #include <linux/moduleparam.h>
52 #include <linux/delay.h>
53 #include <linux/jiffies.h>
54 #include <linux/mutex.h>
55 #include <asm/uaccess.h>
57 #include <asm/system.h>
59 /* The driver prints some debugging information on the console if DEBUG
60 is defined and non-zero. */
63 /* The message level for the debug messages is currently set to KERN_NOTICE
64 so that people can easily see the messages. Later when the debugging messages
65 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
66 #define OSST_DEB_MSG KERN_NOTICE
68 #include <scsi/scsi.h>
69 #include <scsi/scsi_dbg.h>
70 #include <scsi/scsi_device.h>
71 #include <scsi/scsi_driver.h>
72 #include <scsi/scsi_eh.h>
73 #include <scsi/scsi_host.h>
74 #include <scsi/scsi_ioctl.h>
76 #define ST_KILOBYTE 1024
80 #include "osst_options.h"
81 #include "osst_detect.h"
83 static DEFINE_MUTEX(osst_int_mutex
);
84 static int max_dev
= 0;
85 static int write_threshold_kbs
= 0;
86 static int max_sg_segs
= 0;
89 MODULE_AUTHOR("Willem Riede");
90 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
91 MODULE_LICENSE("GPL");
92 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR
);
93 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE
);
95 module_param(max_dev
, int, 0444);
96 MODULE_PARM_DESC(max_dev
, "Maximum number of OnStream Tape Drives to attach (4)");
98 module_param(write_threshold_kbs
, int, 0644);
99 MODULE_PARM_DESC(write_threshold_kbs
, "Asynchronous write threshold (KB; 32)");
101 module_param(max_sg_segs
, int, 0644);
102 MODULE_PARM_DESC(max_sg_segs
, "Maximum number of scatter/gather segments to use (9)");
104 static struct osst_dev_parm
{
107 } parms
[] __initdata
= {
108 { "max_dev", &max_dev
},
109 { "write_threshold_kbs", &write_threshold_kbs
},
110 { "max_sg_segs", &max_sg_segs
}
114 /* Some default definitions have been moved to osst_options.h */
115 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
116 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
118 /* The buffer size should fit into the 24 bits for length in the
119 6-byte SCSI read and write commands. */
120 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
121 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
125 static int debugging
= 1;
126 /* uncomment define below to test error recovery */
127 // #define OSST_INJECT_ERRORS 1
130 /* Do not retry! The drive firmware already retries when appropriate,
131 and when it tries to tell us something, we had better listen... */
132 #define MAX_RETRIES 0
134 #define NO_TAPE NOT_READY
136 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
137 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
138 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
140 #define OSST_TIMEOUT (200 * HZ)
141 #define OSST_LONG_TIMEOUT (1800 * HZ)
143 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
144 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
145 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
146 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
148 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
150 #define SET_DENS_AND_BLK 0x10001
152 static int osst_buffer_size
= OSST_BUFFER_SIZE
;
153 static int osst_write_threshold
= OSST_WRITE_THRESHOLD
;
154 static int osst_max_sg_segs
= OSST_MAX_SG
;
155 static int osst_max_dev
= OSST_MAX_TAPES
;
156 static int osst_nr_dev
;
158 static struct osst_tape
**os_scsi_tapes
= NULL
;
159 static DEFINE_RWLOCK(os_scsi_tapes_lock
);
161 static int modes_defined
= 0;
163 static struct osst_buffer
*new_tape_buffer(int, int, int);
164 static int enlarge_buffer(struct osst_buffer
*, int);
165 static void normalize_buffer(struct osst_buffer
*);
166 static int append_to_buffer(const char __user
*, struct osst_buffer
*, int);
167 static int from_buffer(struct osst_buffer
*, char __user
*, int);
168 static int osst_zero_buffer_tail(struct osst_buffer
*);
169 static int osst_copy_to_buffer(struct osst_buffer
*, unsigned char *);
170 static int osst_copy_from_buffer(struct osst_buffer
*, unsigned char *);
172 static int osst_probe(struct device
*);
173 static int osst_remove(struct device
*);
175 static struct scsi_driver osst_template
= {
176 .owner
= THIS_MODULE
,
180 .remove
= osst_remove
,
184 static int osst_int_ioctl(struct osst_tape
*STp
, struct osst_request
** aSRpnt
,
185 unsigned int cmd_in
, unsigned long arg
);
187 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int frame
, int skip
);
189 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
191 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
193 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
);
195 static inline char *tape_name(struct osst_tape
*tape
)
197 return tape
->drive
->disk_name
;
200 /* Routines that handle the interaction with mid-layer SCSI routines */
203 /* Normalize Sense */
204 static void osst_analyze_sense(struct osst_request
*SRpnt
, struct st_cmdstatus
*s
)
207 const u8
*sense
= SRpnt
->sense
;
209 s
->have_sense
= scsi_normalize_sense(SRpnt
->sense
,
210 SCSI_SENSE_BUFFERSIZE
, &s
->sense_hdr
);
216 scsi_get_sense_info_fld(sense
, SCSI_SENSE_BUFFERSIZE
, &s
->uremainder64
);
217 switch (sense
[0] & 0x7f) {
222 s
->flags
= sense
[2] & 0xe0;
228 ucp
= scsi_sense_desc_find(sense
, SCSI_SENSE_BUFFERSIZE
, 4);
229 s
->flags
= ucp
? (ucp
[3] & 0xe0) : 0;
235 /* Convert the result to success code */
236 static int osst_chk_result(struct osst_tape
* STp
, struct osst_request
* SRpnt
)
238 char *name
= tape_name(STp
);
239 int result
= SRpnt
->result
;
240 u8
* sense
= SRpnt
->sense
, scode
;
244 struct st_cmdstatus
*cmdstatp
;
249 cmdstatp
= &STp
->buffer
->cmdstat
;
250 osst_analyze_sense(SRpnt
, cmdstatp
);
252 if (cmdstatp
->have_sense
)
253 scode
= STp
->buffer
->cmdstat
.sense_hdr
.sense_key
;
258 printk(OSST_DEB_MSG
"%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
260 SRpnt
->cmd
[0], SRpnt
->cmd
[1], SRpnt
->cmd
[2],
261 SRpnt
->cmd
[3], SRpnt
->cmd
[4], SRpnt
->cmd
[5]);
262 if (scode
) printk(OSST_DEB_MSG
"%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
263 name
, scode
, sense
[12], sense
[13]);
264 if (cmdstatp
->have_sense
)
265 __scsi_print_sense("osst ", 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("osst ", SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
282 static int notyetprinted
= 1;
285 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
286 name
, result
, driver_byte(result
),
291 "%s:I: This warning may be caused by your scsi controller,\n", name
);
293 "%s:I: it has been reported with some Buslogic cards.\n", name
);
297 STp
->pos_unknown
|= STp
->device
->was_reset
;
299 if (cmdstatp
->have_sense
&& scode
== RECOVERED_ERROR
) {
300 STp
->recover_count
++;
301 STp
->recover_erreg
++;
304 if (SRpnt
->cmd
[0] == READ_6
)
306 else if (SRpnt
->cmd
[0] == WRITE_6
)
310 printk(OSST_DEB_MSG
"%s:D: Recovered %s error (%d).\n", name
, stp
,
314 if ((sense
[2] & 0xe0) == 0)
321 /* Wakeup from interrupt */
322 static void osst_end_async(struct request
*req
, int update
)
324 struct osst_request
*SRpnt
= req
->end_io_data
;
325 struct osst_tape
*STp
= SRpnt
->stp
;
326 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
328 STp
->buffer
->cmdstat
.midlevel_result
= SRpnt
->result
= req
->errors
;
330 STp
->write_pending
= 0;
333 complete(SRpnt
->waiting
);
337 blk_rq_unmap_user(SRpnt
->bio
);
340 __blk_put_request(req
->q
, req
);
343 /* osst_request memory management */
344 static struct osst_request
*osst_allocate_request(void)
346 return kzalloc(sizeof(struct osst_request
), GFP_KERNEL
);
349 static void osst_release_request(struct osst_request
*streq
)
354 static int osst_execute(struct osst_request
*SRpnt
, const unsigned char *cmd
,
355 int cmd_len
, int data_direction
, void *buffer
, unsigned bufflen
,
356 int use_sg
, int timeout
, int retries
)
359 struct page
**pages
= NULL
;
360 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
363 int write
= (data_direction
== DMA_TO_DEVICE
);
365 req
= blk_get_request(SRpnt
->stp
->device
->request_queue
, write
, GFP_KERNEL
);
367 return DRIVER_ERROR
<< 24;
369 req
->cmd_type
= REQ_TYPE_BLOCK_PC
;
370 req
->cmd_flags
|= REQ_QUIET
;
375 struct scatterlist
*sg
, *sgl
= (struct scatterlist
*)buffer
;
378 pages
= kzalloc(use_sg
* sizeof(struct page
*), GFP_KERNEL
);
382 for_each_sg(sgl
, sg
, use_sg
, i
)
383 pages
[i
] = sg_page(sg
);
385 mdata
->null_mapped
= 1;
387 mdata
->page_order
= get_order(sgl
[0].length
);
389 DIV_ROUND_UP(bufflen
, PAGE_SIZE
<< mdata
->page_order
);
392 err
= blk_rq_map_user(req
->q
, req
, mdata
, NULL
, bufflen
, GFP_KERNEL
);
397 SRpnt
->bio
= req
->bio
;
398 mdata
->pages
= pages
;
400 } else if (bufflen
) {
401 err
= blk_rq_map_kern(req
->q
, req
, buffer
, bufflen
, GFP_KERNEL
);
406 req
->cmd_len
= cmd_len
;
407 memset(req
->cmd
, 0, BLK_MAX_CDB
); /* ATAPI hates garbage after CDB */
408 memcpy(req
->cmd
, cmd
, req
->cmd_len
);
409 req
->sense
= SRpnt
->sense
;
411 req
->timeout
= timeout
;
412 req
->retries
= retries
;
413 req
->end_io_data
= SRpnt
;
415 blk_execute_rq_nowait(req
->q
, NULL
, req
, 1, osst_end_async
);
418 blk_put_request(req
);
419 return DRIVER_ERROR
<< 24;
422 /* Do the scsi command. Waits until command performed if do_wait is true.
423 Otherwise osst_write_behind_check() is used to check that the command
425 static struct osst_request
* osst_do_scsi(struct osst_request
*SRpnt
, struct osst_tape
*STp
,
426 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
429 unsigned short use_sg
;
430 #ifdef OSST_INJECT_ERRORS
431 static int inject
= 0;
432 static int repeat
= 0;
434 struct completion
*waiting
;
436 /* if async, make sure there's no command outstanding */
437 if (!do_wait
&& ((STp
->buffer
)->last_SRpnt
)) {
438 printk(KERN_ERR
"%s: Async command already active.\n",
440 if (signal_pending(current
))
441 (STp
->buffer
)->syscall_result
= (-EINTR
);
443 (STp
->buffer
)->syscall_result
= (-EBUSY
);
448 SRpnt
= osst_allocate_request();
450 printk(KERN_ERR
"%s: Can't allocate SCSI request.\n",
452 if (signal_pending(current
))
453 (STp
->buffer
)->syscall_result
= (-EINTR
);
455 (STp
->buffer
)->syscall_result
= (-EBUSY
);
461 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
462 which IO is outstanding. It's nulled out when the IO completes. */
464 (STp
->buffer
)->last_SRpnt
= SRpnt
;
466 waiting
= &STp
->wait
;
467 init_completion(waiting
);
468 SRpnt
->waiting
= waiting
;
470 use_sg
= (bytes
> STp
->buffer
->sg
[0].length
) ? STp
->buffer
->use_sg
: 0;
472 bp
= (char *)&(STp
->buffer
->sg
[0]);
473 if (STp
->buffer
->sg_segs
< use_sg
)
474 use_sg
= STp
->buffer
->sg_segs
;
477 bp
= (STp
->buffer
)->b_data
;
479 memcpy(SRpnt
->cmd
, cmd
, sizeof(SRpnt
->cmd
));
480 STp
->buffer
->cmdstat
.have_sense
= 0;
481 STp
->buffer
->syscall_result
= 0;
483 if (osst_execute(SRpnt
, cmd
, COMMAND_SIZE(cmd
[0]), direction
, bp
, bytes
,
484 use_sg
, timeout
, retries
))
485 /* could not allocate the buffer or request was too large */
486 (STp
->buffer
)->syscall_result
= (-EBUSY
);
488 wait_for_completion(waiting
);
489 SRpnt
->waiting
= NULL
;
490 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
491 #ifdef OSST_INJECT_ERRORS
492 if (STp
->buffer
->syscall_result
== 0 &&
495 ( (++ inject
% 83) == 29 ||
496 (STp
->first_frame_position
== 240
497 /* or STp->read_error_frame to fail again on the block calculated above */ &&
499 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
500 STp
->buffer
->last_result_fatal
= 1;
508 /* Handle the write-behind checking (downs the semaphore) */
509 static void osst_write_behind_check(struct osst_tape
*STp
)
511 struct osst_buffer
* STbuffer
;
513 STbuffer
= STp
->buffer
;
516 if (STp
->write_pending
)
521 wait_for_completion(&(STp
->wait
));
522 STp
->buffer
->last_SRpnt
->waiting
= NULL
;
524 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
526 if (STp
->buffer
->syscall_result
)
527 STp
->buffer
->syscall_result
=
528 osst_write_error_recovery(STp
, &(STp
->buffer
->last_SRpnt
), 1);
530 STp
->first_frame_position
++;
532 osst_release_request(STp
->buffer
->last_SRpnt
);
534 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
535 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
537 STbuffer
->last_SRpnt
= NULL
;
538 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
539 STbuffer
->writing
= 0;
546 /* Onstream specific Routines */
548 * Initialize the OnStream AUX
550 static void osst_init_aux(struct osst_tape
* STp
, int frame_type
, int frame_seq_number
,
551 int logical_blk_num
, int blk_sz
, int blk_cnt
)
553 os_aux_t
*aux
= STp
->buffer
->aux
;
554 os_partition_t
*par
= &aux
->partition
;
555 os_dat_t
*dat
= &aux
->dat
;
557 if (STp
->raw
) return;
559 memset(aux
, 0, sizeof(*aux
));
560 aux
->format_id
= htonl(0);
561 memcpy(aux
->application_sig
, "LIN4", 4);
562 aux
->hdwr
= htonl(0);
563 aux
->frame_type
= frame_type
;
565 switch (frame_type
) {
566 case OS_FRAME_TYPE_HEADER
:
567 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
568 par
->partition_num
= OS_CONFIG_PARTITION
;
569 par
->par_desc_ver
= OS_PARTITION_VERSION
;
570 par
->wrt_pass_cntr
= htons(0xffff);
571 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
572 par
->first_frame_ppos
= htonl(0);
573 par
->last_frame_ppos
= htonl(0xbb7);
574 aux
->frame_seq_num
= htonl(0);
575 aux
->logical_blk_num_high
= htonl(0);
576 aux
->logical_blk_num
= htonl(0);
577 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
579 case OS_FRAME_TYPE_DATA
:
580 case OS_FRAME_TYPE_MARKER
:
585 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
586 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
587 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
588 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
589 dat
->dat_list
[0].reserved
= 0;
590 case OS_FRAME_TYPE_EOD
:
591 aux
->update_frame_cntr
= htonl(0);
592 par
->partition_num
= OS_DATA_PARTITION
;
593 par
->par_desc_ver
= OS_PARTITION_VERSION
;
594 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
595 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
596 par
->last_frame_ppos
= htonl(STp
->capacity
);
597 aux
->frame_seq_num
= htonl(frame_seq_number
);
598 aux
->logical_blk_num_high
= htonl(0);
599 aux
->logical_blk_num
= htonl(logical_blk_num
);
601 default: ; /* probably FILL */
603 aux
->filemark_cnt
= htonl(STp
->filemark_cnt
);
604 aux
->phys_fm
= htonl(0xffffffff);
605 aux
->last_mark_ppos
= htonl(STp
->last_mark_ppos
);
606 aux
->last_mark_lbn
= htonl(STp
->last_mark_lbn
);
610 * Verify that we have the correct tape frame
612 static int osst_verify_frame(struct osst_tape
* STp
, int frame_seq_number
, int quiet
)
614 char * name
= tape_name(STp
);
615 os_aux_t
* aux
= STp
->buffer
->aux
;
616 os_partition_t
* par
= &(aux
->partition
);
617 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
618 int blk_cnt
, blk_sz
, i
;
621 if (STp
->buffer
->syscall_result
) {
622 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
623 memset(page_address(sg_page(&STp
->buffer
->sg
[i
])),
624 0, STp
->buffer
->sg
[i
].length
);
625 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
627 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
630 if (STp
->buffer
->syscall_result
) {
632 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
636 if (ntohl(aux
->format_id
) != 0) {
638 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
642 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
643 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
645 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
649 if (par
->partition_num
!= OS_DATA_PARTITION
) {
650 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
652 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
653 name
, par
->partition_num
);
658 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
660 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
664 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
666 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
667 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
671 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
672 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
673 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
676 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
681 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
682 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
683 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
684 STp
->first_frame_position
);
687 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
690 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
691 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
696 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
697 STps
->eof
= ST_FM_HIT
;
699 i
= ntohl(aux
->filemark_cnt
);
700 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
701 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
703 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
704 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
705 i
, STp
->first_frame_position
- 1);
707 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
708 if (i
>= STp
->filemark_cnt
)
709 STp
->filemark_cnt
= i
+1;
712 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
713 STps
->eof
= ST_EOD_1
;
714 STp
->frame_in_buffer
= 1;
716 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
717 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
718 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
719 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
720 STp
->buffer
->read_pointer
= 0;
721 STp
->frame_in_buffer
= 1;
723 /* See what block size was used to write file */
724 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
726 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
727 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
728 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
729 STp
->block_size
<1024?'b':'k');
730 STp
->block_size
= blk_sz
;
731 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
733 STps
->eof
= ST_NOEOF
;
735 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
736 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
740 if (STp
->read_error_frame
== 0)
741 STp
->read_error_frame
= STp
->first_frame_position
- 1;
746 * Wait for the unit to become Ready
748 static int osst_wait_ready(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
749 unsigned timeout
, int initial_delay
)
751 unsigned char cmd
[MAX_COMMAND_SIZE
];
752 struct osst_request
* SRpnt
;
753 unsigned long startwait
= jiffies
;
756 char * name
= tape_name(STp
);
758 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
761 if (initial_delay
> 0)
762 msleep(jiffies_to_msecs(initial_delay
));
764 memset(cmd
, 0, MAX_COMMAND_SIZE
);
765 cmd
[0] = TEST_UNIT_READY
;
767 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
769 if (!SRpnt
) return (-EBUSY
);
771 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
772 (( SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
773 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8) ) ||
774 ( SRpnt
->sense
[2] == 6 && SRpnt
->sense
[12] == 0x28 &&
775 SRpnt
->sense
[13] == 0 ) )) {
778 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
779 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
785 memset(cmd
, 0, MAX_COMMAND_SIZE
);
786 cmd
[0] = TEST_UNIT_READY
;
788 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
794 if ( STp
->buffer
->syscall_result
&&
795 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
797 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
798 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
799 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
800 SRpnt
->sense
[12], SRpnt
->sense
[13]);
805 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
811 * Wait for a tape to be inserted in the unit
813 static int osst_wait_for_medium(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, unsigned timeout
)
815 unsigned char cmd
[MAX_COMMAND_SIZE
];
816 struct osst_request
* SRpnt
;
817 unsigned long startwait
= jiffies
;
820 char * name
= tape_name(STp
);
822 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
825 memset(cmd
, 0, MAX_COMMAND_SIZE
);
826 cmd
[0] = TEST_UNIT_READY
;
828 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
830 if (!SRpnt
) return (-EBUSY
);
832 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
833 SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 0x3a && SRpnt
->sense
[13] == 0 ) {
836 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
837 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
843 memset(cmd
, 0, MAX_COMMAND_SIZE
);
844 cmd
[0] = TEST_UNIT_READY
;
846 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
852 if ( STp
->buffer
->syscall_result
&& SRpnt
->sense
[2] != 2 &&
853 SRpnt
->sense
[12] != 4 && SRpnt
->sense
[13] == 1) {
855 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
856 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
857 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
858 SRpnt
->sense
[12], SRpnt
->sense
[13]);
863 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
868 static int osst_position_tape_and_confirm(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int frame
)
872 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
873 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
874 if (retval
) return (retval
);
875 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
876 return (osst_get_frame_position(STp
, aSRpnt
));
880 * Wait for write(s) to complete
882 static int osst_flush_drive_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
884 unsigned char cmd
[MAX_COMMAND_SIZE
];
885 struct osst_request
* SRpnt
;
887 int delay
= OSST_WAIT_WRITE_COMPLETE
;
889 char * name
= tape_name(STp
);
891 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
894 memset(cmd
, 0, MAX_COMMAND_SIZE
);
895 cmd
[0] = WRITE_FILEMARKS
;
898 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
900 if (!SRpnt
) return (-EBUSY
);
901 if (STp
->buffer
->syscall_result
) {
902 if ((SRpnt
->sense
[2] & 0x0f) == 2 && SRpnt
->sense
[12] == 4) {
903 if (SRpnt
->sense
[13] == 8) {
904 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
907 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
909 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
910 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
915 #define OSST_POLL_PER_SEC 10
916 static int osst_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int curr
, int minlast
, int to
)
918 unsigned long startwait
= jiffies
;
919 char * name
= tape_name(STp
);
921 char notyetprinted
= 1;
923 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
924 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
926 while (time_before (jiffies
, startwait
+ to
*HZ
))
929 result
= osst_get_frame_position(STp
, aSRpnt
);
931 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
932 return 0; /* successful recovery leaves drive ready for frame */
933 if (result
< 0) break;
934 if (STp
->first_frame_position
== curr
&&
936 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
937 (minlast
>= 0 && STp
->cur_frames
> minlast
)
941 if (debugging
|| time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
))
943 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
944 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
945 STp
->last_frame_position
, STp
->cur_frames
,
946 result
, (jiffies
-startwait
)/HZ
,
947 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
952 if (time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
) && notyetprinted
)
954 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
955 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
956 STp
->last_frame_position
, STp
->cur_frames
, result
);
960 msleep(1000 / OSST_POLL_PER_SEC
);
963 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
964 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
965 STp
->last_frame_position
, STp
->cur_frames
,
966 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
971 static int osst_recover_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int writing
)
973 struct osst_request
* SRpnt
;
974 unsigned char cmd
[MAX_COMMAND_SIZE
];
975 unsigned long startwait
= jiffies
;
977 char * name
= tape_name(STp
);
981 char * olddata
= STp
->buffer
->b_data
;
982 int oldsize
= STp
->buffer
->buffer_size
;
984 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
986 memset(cmd
, 0, MAX_COMMAND_SIZE
);
987 cmd
[0] = WRITE_FILEMARKS
;
989 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
992 while (retval
&& time_before (jiffies
, startwait
+ 5*60*HZ
)) {
994 if (STp
->buffer
->syscall_result
&& (SRpnt
->sense
[2] & 0x0f) != 2) {
996 /* some failure - not just not-ready */
997 retval
= osst_write_error_recovery(STp
, aSRpnt
, 0);
1000 schedule_timeout_interruptible(HZ
/ OSST_POLL_PER_SEC
);
1002 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
1003 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1004 cmd
[0] = READ_POSITION
;
1006 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
1009 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
1010 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
1013 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
1015 /* TODO - figure out which error conditions can be handled */
1016 if (STp
->buffer
->syscall_result
)
1018 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
1019 (*aSRpnt
)->sense
[ 2] & 0x0f,
1020 (*aSRpnt
)->sense
[12],
1021 (*aSRpnt
)->sense
[13]);
1027 * Read the next OnStream tape frame at the current location
1029 static int osst_read_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int timeout
)
1031 unsigned char cmd
[MAX_COMMAND_SIZE
];
1032 struct osst_request
* SRpnt
;
1035 os_aux_t
* aux
= STp
->buffer
->aux
;
1036 char * name
= tape_name(STp
);
1040 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
1041 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
1043 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1050 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
1052 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1053 STp
->timeout
, MAX_RETRIES
, 1);
1058 if ((STp
->buffer
)->syscall_result
) {
1060 if (STp
->read_error_frame
== 0) {
1061 STp
->read_error_frame
= STp
->first_frame_position
;
1063 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
1068 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1070 SRpnt
->sense
[0], SRpnt
->sense
[1],
1071 SRpnt
->sense
[2], SRpnt
->sense
[3],
1072 SRpnt
->sense
[4], SRpnt
->sense
[5],
1073 SRpnt
->sense
[6], SRpnt
->sense
[7]);
1077 STp
->first_frame_position
++;
1082 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
1085 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
1086 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
1087 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
1088 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
1089 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
1090 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
1091 if (aux
->frame_type
==2)
1092 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
1093 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
1094 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
1100 static int osst_initiate_read(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1102 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1103 struct osst_request
* SRpnt
;
1104 unsigned char cmd
[MAX_COMMAND_SIZE
];
1106 char * name
= tape_name(STp
);
1108 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
1109 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
1110 STp
->write_type
= OS_WRITE_DATA
;
1111 osst_flush_write_buffer(STp
, aSRpnt
);
1112 osst_flush_drive_buffer(STp
, aSRpnt
);
1114 STps
->rw
= ST_READING
;
1115 STp
->frame_in_buffer
= 0;
1118 * Issue a read 0 command to get the OnStream drive
1119 * read frames into its buffer.
1121 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1126 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
1128 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
1130 if ((retval
= STp
->buffer
->syscall_result
))
1131 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1137 static int osst_get_logical_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1138 int frame_seq_number
, int quiet
)
1140 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1141 char * name
= tape_name(STp
);
1149 * If we want just any frame (-1) and there is a frame in the buffer, return it
1151 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1153 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1158 * Search and wait for the next logical tape frame
1162 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1163 name
, frame_seq_number
);
1164 if (STp
->read_error_frame
) {
1165 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1167 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1168 name
, STp
->read_error_frame
);
1170 STp
->read_error_frame
= 0;
1177 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1178 name
, frame_seq_number
, cnt
);
1180 if ( osst_initiate_read(STp
, aSRpnt
)
1181 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1184 position
= osst_get_frame_position(STp
, aSRpnt
);
1185 if (position
>= 0xbae && position
< 0xbb8)
1187 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1188 position
= STp
->read_error_frame
- 1;
1196 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1199 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1202 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1204 if (osst_verify_frame(STp
, -1, quiet
)) {
1205 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1206 if (STp
->fast_open
) {
1208 "%s:W: Found logical frame %d instead of %d after fast open\n",
1209 name
, x
, frame_seq_number
);
1211 STp
->read_error_frame
= 0;
1214 if (x
> frame_seq_number
) {
1216 /* positioning backwards did not bring us to the desired frame */
1217 position
= STp
->read_error_frame
- 1;
1220 position
= osst_get_frame_position(STp
, aSRpnt
)
1221 + frame_seq_number
- x
- 1;
1223 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1228 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1229 name
, x
, frame_seq_number
,
1230 STp
->first_frame_position
- position
);
1232 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1238 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1240 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1242 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1245 STp
->frame_in_buffer
= 0;
1248 STp
->recover_count
++;
1249 STp
->recover_erreg
++;
1250 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1251 name
, STp
->read_error_frame
);
1256 if (debugging
|| STps
->eof
)
1258 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1259 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1262 STp
->read_error_frame
= 0;
1266 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int logical_blk_num
)
1268 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1269 char * name
= tape_name(STp
);
1271 int frame_seq_estimate
, ppos_estimate
, move
;
1273 if (logical_blk_num
< 0) logical_blk_num
= 0;
1275 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1276 name
, logical_blk_num
, STp
->logical_blk_num
,
1277 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1278 STp
->block_size
<1024?'b':'k');
1280 /* Do we know where we are? */
1281 if (STps
->drv_block
>= 0) {
1282 move
= logical_blk_num
- STp
->logical_blk_num
;
1283 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1284 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1285 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1287 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1289 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1290 else ppos_estimate
= frame_seq_estimate
+ 20;
1291 while (++retries
< 10) {
1292 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1293 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1294 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1296 if (frame_seq_estimate
< 0) {
1297 frame_seq_estimate
= 0;
1300 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1301 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1302 /* we've located the estimated frame, now does it have our block? */
1303 if (logical_blk_num
< STp
->logical_blk_num
||
1304 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1305 if (STps
->eof
== ST_FM_HIT
)
1306 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1308 move
= logical_blk_num
- STp
->logical_blk_num
;
1309 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1310 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1312 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1315 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1316 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1317 STp
->logical_blk_num
, logical_blk_num
, move
);
1319 frame_seq_estimate
+= move
;
1320 ppos_estimate
+= move
;
1323 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1324 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1325 STp
->logical_blk_num
= logical_blk_num
;
1328 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1329 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1330 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1333 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1334 if (STps
->eof
== ST_FM_HIT
) {
1336 STps
->drv_block
= 0;
1338 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1339 STp
->logical_blk_num
-
1340 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1343 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1347 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1349 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1351 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1352 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1353 STp
->logical_blk_num
, logical_blk_num
);
1355 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1356 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1361 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1362 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1366 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1367 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1368 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1369 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1371 #define OSST_FRAME_SHIFT 6
1372 #define OSST_SECTOR_SHIFT 9
1373 #define OSST_SECTOR_MASK 0x03F
1375 static int osst_get_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1379 char * name
= tape_name(STp
);
1382 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1383 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1384 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1385 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1386 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1387 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1389 /* do we know where we are inside a file? */
1390 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1391 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1392 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1393 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1394 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1396 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1398 sector
= osst_get_frame_position(STp
, aSRpnt
);
1400 sector
<<= OSST_FRAME_SHIFT
;
1405 static int osst_seek_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int sector
)
1407 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1408 int frame
= sector
>> OSST_FRAME_SHIFT
,
1409 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1412 char * name
= tape_name(STp
);
1414 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1415 name
, sector
, frame
, offset
);
1417 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1419 if (frame
<= STp
->first_data_ppos
) {
1420 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1421 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1423 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1424 if (r
< 0) return r
;
1426 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1427 if (r
< 0) return r
;
1429 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1432 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1433 STp
->buffer
->read_pointer
= offset
;
1434 STp
->buffer
->buffer_bytes
-= offset
;
1436 STp
->frame_seq_number
++;
1437 STp
->frame_in_buffer
= 0;
1438 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1439 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1441 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1442 if (STps
->eof
== ST_FM_HIT
) {
1444 STps
->drv_block
= 0;
1446 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1447 STp
->logical_blk_num
-
1448 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1451 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1454 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1455 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1456 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1462 * Read back the drive's internal buffer contents, as a part
1463 * of the write error recovery mechanism for old OnStream
1464 * firmware revisions.
1465 * Precondition for this function to work: all frames in the
1466 * drive's buffer must be of one type (DATA, MARK or EOD)!
1468 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1469 unsigned int frame
, unsigned int skip
, int pending
)
1471 struct osst_request
* SRpnt
= * aSRpnt
;
1472 unsigned char * buffer
, * p
;
1473 unsigned char cmd
[MAX_COMMAND_SIZE
];
1474 int flag
, new_frame
, i
;
1475 int nframes
= STp
->cur_frames
;
1476 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1477 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1478 - (nframes
+ pending
- 1);
1479 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1480 - (nframes
+ pending
- 1) * blks_per_frame
;
1481 char * name
= tape_name(STp
);
1482 unsigned long startwait
= jiffies
;
1484 int dbg
= debugging
;
1487 if ((buffer
= vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1490 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1491 name
, nframes
, pending
?" and one that was pending":"");
1493 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1495 if (pending
&& debugging
)
1496 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1497 name
, frame_seq_number
+ nframes
,
1498 logical_blk_num
+ nframes
* blks_per_frame
,
1499 p
[0], p
[1], p
[2], p
[3]);
1501 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1503 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1504 cmd
[0] = 0x3C; /* Buffer Read */
1505 cmd
[1] = 6; /* Retrieve Faulty Block */
1506 cmd
[7] = 32768 >> 8;
1507 cmd
[8] = 32768 & 0xff;
1509 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1510 STp
->timeout
, MAX_RETRIES
, 1);
1512 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1513 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1518 osst_copy_from_buffer(STp
->buffer
, p
);
1521 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1522 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1526 osst_get_frame_position(STp
, aSRpnt
);
1529 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1531 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1532 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1534 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1537 if (STp
->write_type
== OS_WRITE_HEADER
) {
1539 p
+= skip
* OS_DATA_SIZE
;
1541 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1546 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1547 name
, new_frame
+i
, frame_seq_number
+i
);
1549 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1550 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1551 osst_get_frame_position(STp
, aSRpnt
);
1554 if (new_frame
> frame
+ 1000) {
1555 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1559 if ( i
>= nframes
+ pending
) break;
1562 osst_copy_to_buffer(STp
->buffer
, p
);
1564 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1566 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1567 logical_blk_num
+ i
*blks_per_frame
,
1568 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1569 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1577 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1578 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1579 p
[0], p
[1], p
[2], p
[3]);
1581 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1582 STp
->timeout
, MAX_RETRIES
, 1);
1584 if (STp
->buffer
->syscall_result
)
1587 p
+= OS_DATA_SIZE
; i
++;
1589 /* if we just sent the last frame, wait till all successfully written */
1590 if ( i
== nframes
+ pending
) {
1592 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1594 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1595 cmd
[0] = WRITE_FILEMARKS
;
1597 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1598 STp
->timeout
, MAX_RETRIES
, 1);
1601 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1602 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1606 flag
= STp
->buffer
->syscall_result
;
1607 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1609 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1610 cmd
[0] = TEST_UNIT_READY
;
1612 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1615 if (SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
1616 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8)) {
1617 /* in the process of becoming ready */
1621 if (STp
->buffer
->syscall_result
)
1627 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1633 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1634 SRpnt
->sense
[12] == 0 &&
1635 SRpnt
->sense
[13] == 2) {
1636 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1638 return (-EIO
); /* hit end of tape = fail */
1640 i
= ((SRpnt
->sense
[3] << 24) |
1641 (SRpnt
->sense
[4] << 16) |
1642 (SRpnt
->sense
[5] << 8) |
1643 SRpnt
->sense
[6] ) - new_frame
;
1644 p
= &buffer
[i
* OS_DATA_SIZE
];
1646 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1648 osst_get_frame_position(STp
, aSRpnt
);
1650 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1651 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1656 /* error recovery did not successfully complete */
1657 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1658 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1661 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1666 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1667 unsigned int frame
, unsigned int skip
, int pending
)
1669 unsigned char cmd
[MAX_COMMAND_SIZE
];
1670 struct osst_request
* SRpnt
;
1671 char * name
= tape_name(STp
);
1673 int attempts
= 1000 / skip
;
1675 unsigned long startwait
= jiffies
;
1677 int dbg
= debugging
;
1680 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1685 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1687 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1689 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1690 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1692 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1695 schedule_timeout_interruptible(msecs_to_jiffies(100));
1697 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1699 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1700 name
, STp
->first_frame_position
,
1701 STp
->last_frame_position
, STp
->cur_frames
);
1703 frame
= STp
->last_frame_position
;
1707 if (pending
&& STp
->cur_frames
< 50) {
1709 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1714 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1715 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1717 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1718 STp
->timeout
, MAX_RETRIES
, 1);
1721 if (STp
->buffer
->syscall_result
) { /* additional write error */
1722 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1723 SRpnt
->sense
[12] == 0 &&
1724 SRpnt
->sense
[13] == 2) {
1726 "%s:E: Volume overflow in write error recovery\n",
1728 break; /* hit end of tape = fail */
1737 if (STp
->cur_frames
== 0) {
1740 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1742 if (STp
->first_frame_position
!= expected
) {
1743 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1744 name
, STp
->first_frame_position
, expected
);
1751 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1752 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1756 schedule_timeout_interruptible(msecs_to_jiffies(100));
1758 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1766 * Error recovery algorithm for the OnStream tape.
1769 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
)
1771 struct osst_request
* SRpnt
= * aSRpnt
;
1772 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1773 char * name
= tape_name(STp
);
1776 unsigned int frame
, skip
;
1778 rw_state
= STps
->rw
;
1780 if ((SRpnt
->sense
[ 2] & 0x0f) != 3
1781 || SRpnt
->sense
[12] != 12
1782 || SRpnt
->sense
[13] != 0) {
1784 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1785 SRpnt
->sense
[2], SRpnt
->sense
[12], SRpnt
->sense
[13]);
1789 frame
= (SRpnt
->sense
[3] << 24) |
1790 (SRpnt
->sense
[4] << 16) |
1791 (SRpnt
->sense
[5] << 8) |
1793 skip
= SRpnt
->sense
[9];
1796 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1798 osst_get_frame_position(STp
, aSRpnt
);
1800 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1801 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1803 switch (STp
->write_type
) {
1806 case OS_WRITE_NEW_MARK
:
1808 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1809 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1810 if (STp
->os_fw_rev
>= 10600)
1811 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1813 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1814 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1816 retval
?"" :"Don't worry, ",
1817 retval
?" not ":" ");
1819 case OS_WRITE_LAST_MARK
:
1820 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1821 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1824 case OS_WRITE_HEADER
:
1825 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1826 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1829 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1830 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1832 osst_get_frame_position(STp
, aSRpnt
);
1834 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1835 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1836 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1839 STp
->recover_count
++;
1840 STp
->recover_erreg
++;
1844 STps
->rw
= rw_state
;
1848 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1849 int mt_op
, int mt_count
)
1851 char * name
= tape_name(STp
);
1853 int last_mark_ppos
= -1;
1856 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1858 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1860 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1864 if (STp
->linux_media_version
>= 4) {
1866 * direct lookup in header filemark list
1868 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1869 if (STp
->header_ok
&&
1870 STp
->header_cache
!= NULL
&&
1871 (cnt
- mt_count
) >= 0 &&
1872 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1873 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1874 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1876 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1878 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1879 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1880 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1882 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1884 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1885 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1886 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1887 mt_count
, last_mark_ppos
);
1889 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1890 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1891 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1894 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1898 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1899 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1900 name
, last_mark_ppos
);
1906 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1910 while (cnt
!= mt_count
) {
1911 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1912 if (last_mark_ppos
== -1)
1915 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1917 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1919 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1921 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1925 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1926 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1927 name
, last_mark_ppos
);
1932 if (mt_op
== MTBSFM
) {
1933 STp
->frame_seq_number
++;
1934 STp
->frame_in_buffer
= 0;
1935 STp
->buffer
->buffer_bytes
= 0;
1936 STp
->buffer
->read_pointer
= 0;
1937 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1943 * ADRL 1.1 compatible "slow" space filemarks fwd version
1945 * Just scans for the filemark sequentially.
1947 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1948 int mt_op
, int mt_count
)
1952 char * name
= tape_name(STp
);
1954 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1956 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1958 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1963 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1965 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1969 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1971 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1973 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1975 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1977 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1978 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1980 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1984 if (cnt
== mt_count
)
1986 STp
->frame_in_buffer
= 0;
1988 if (mt_op
== MTFSF
) {
1989 STp
->frame_seq_number
++;
1990 STp
->frame_in_buffer
= 0;
1991 STp
->buffer
->buffer_bytes
= 0;
1992 STp
->buffer
->read_pointer
= 0;
1993 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1999 * Fast linux specific version of OnStream FSF
2001 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
2002 int mt_op
, int mt_count
)
2004 char * name
= tape_name(STp
);
2006 next_mark_ppos
= -1;
2009 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
2011 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2013 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
2018 if (STp
->linux_media_version
>= 4) {
2020 * direct lookup in header filemark list
2022 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
2023 if (STp
->header_ok
&&
2024 STp
->header_cache
!= NULL
&&
2025 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
2026 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
2027 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2028 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
2030 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
2032 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
2033 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
2034 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
2036 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2038 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2039 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
2040 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
2041 mt_count
, next_mark_ppos
);
2043 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
2045 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2047 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2049 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2050 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2052 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2057 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2058 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2059 name
, next_mark_ppos
);
2062 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
2063 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
2064 name
, cnt
+mt_count
, next_mark_ppos
,
2065 ntohl(STp
->buffer
->aux
->filemark_cnt
));
2071 * Find nearest (usually previous) marker, then jump from marker to marker
2074 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
2076 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
2078 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
2082 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
2083 if (STp
->first_mark_ppos
== -1) {
2085 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2087 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2089 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
2090 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2093 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2098 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2099 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
2100 name
, STp
->first_mark_ppos
);
2104 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
2110 while (cnt
!= mt_count
) {
2111 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
2112 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
2114 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2116 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
2119 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
2121 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2123 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2125 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2130 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2131 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2132 name
, next_mark_ppos
);
2137 if (mt_op
== MTFSF
) {
2138 STp
->frame_seq_number
++;
2139 STp
->frame_in_buffer
= 0;
2140 STp
->buffer
->buffer_bytes
= 0;
2141 STp
->buffer
->read_pointer
= 0;
2142 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2148 * In debug mode, we want to see as many errors as possible
2149 * to test the error recovery mechanism.
2152 static void osst_set_retries(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int retries
)
2154 unsigned char cmd
[MAX_COMMAND_SIZE
];
2155 struct osst_request
* SRpnt
= * aSRpnt
;
2156 char * name
= tape_name(STp
);
2158 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2159 cmd
[0] = MODE_SELECT
;
2161 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2163 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2164 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2165 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2166 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2167 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2168 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2169 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2170 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2173 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2175 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2178 if ((STp
->buffer
)->syscall_result
)
2179 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2184 static int osst_write_filemark(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2187 int this_mark_ppos
= STp
->first_frame_position
;
2188 int this_mark_lbn
= STp
->logical_blk_num
;
2190 char * name
= tape_name(STp
);
2193 if (STp
->raw
) return 0;
2195 STp
->write_type
= OS_WRITE_NEW_MARK
;
2197 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2198 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2201 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2202 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2203 STp
->last_mark_ppos
= this_mark_ppos
;
2204 STp
->last_mark_lbn
= this_mark_lbn
;
2205 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2206 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2207 if (STp
->filemark_cnt
++ == 0)
2208 STp
->first_mark_ppos
= this_mark_ppos
;
2212 static int osst_write_eod(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2216 char * name
= tape_name(STp
);
2219 if (STp
->raw
) return 0;
2221 STp
->write_type
= OS_WRITE_EOD
;
2222 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2224 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2225 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2229 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2230 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2231 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2235 static int osst_write_filler(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2237 char * name
= tape_name(STp
);
2240 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2242 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2243 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2244 STp
->write_type
= OS_WRITE_FILLER
;
2246 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2247 STp
->buffer
->buffer_bytes
= 6;
2249 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2250 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2255 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2257 return osst_flush_drive_buffer(STp
, aSRpnt
);
2260 static int __osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2262 char * name
= tape_name(STp
);
2266 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2268 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2269 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2270 STp
->write_type
= OS_WRITE_HEADER
;
2272 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2273 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2275 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2276 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2280 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2282 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2287 static int osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int locate_eod
)
2289 os_header_t
* header
;
2291 char * name
= tape_name(STp
);
2294 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2296 if (STp
->raw
) return 0;
2298 if (STp
->header_cache
== NULL
) {
2299 if ((STp
->header_cache
= vmalloc(sizeof(os_header_t
))) == NULL
) {
2300 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2303 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2305 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2308 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2309 else STp
->update_frame_cntr
= 0;
2311 header
= STp
->header_cache
;
2312 strcpy(header
->ident_str
, "ADR_SEQ");
2313 header
->major_rev
= 1;
2314 header
->minor_rev
= 4;
2315 header
->ext_trk_tb_off
= htons(17192);
2316 header
->pt_par_num
= 1;
2317 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2318 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2319 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2320 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2321 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2322 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2323 header
->cfg_col_width
= htonl(20);
2324 header
->dat_col_width
= htonl(1500);
2325 header
->qfa_col_width
= htonl(0);
2326 header
->ext_track_tb
.nr_stream_part
= 1;
2327 header
->ext_track_tb
.et_ent_sz
= 32;
2328 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2329 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2330 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2331 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2332 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2333 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2334 header
->dat_fm_tab
.fm_part_num
= 0;
2335 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2336 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2337 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2339 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2340 if (STp
->update_frame_cntr
== 0)
2341 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2342 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2346 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2348 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2351 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2353 memcpy(STp
->application_sig
, "LIN4", 4);
2354 STp
->linux_media
= 1;
2355 STp
->linux_media_version
= 4;
2361 static int osst_reset_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2363 if (STp
->header_cache
!= NULL
)
2364 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2366 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2367 STp
->frame_in_buffer
= 0;
2368 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2369 STp
->filemark_cnt
= 0;
2370 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2371 return osst_write_header(STp
, aSRpnt
, 1);
2374 static int __osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int ppos
)
2376 char * name
= tape_name(STp
);
2377 os_header_t
* header
;
2380 int linux_media_version
,
2386 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2387 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2388 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2389 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2390 if (osst_initiate_read (STp
, aSRpnt
)) {
2391 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2395 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2397 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2401 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2402 aux
= STp
->buffer
->aux
;
2403 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2405 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2409 if (ntohl(aux
->frame_seq_num
) != 0 ||
2410 ntohl(aux
->logical_blk_num
) != 0 ||
2411 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2412 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2413 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2415 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2416 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2417 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2418 ntohl(aux
->partition
.last_frame_ppos
));
2422 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2423 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2424 strlcpy(id_string
, header
->ident_str
, 8);
2426 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2430 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2431 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2433 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2434 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2438 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2440 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2441 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2442 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2443 header
->major_rev
, header
->minor_rev
);
2445 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2449 if (header
->pt_par_num
!= 1)
2450 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2451 name
, header
->pt_par_num
);
2453 memcpy(id_string
, aux
->application_sig
, 4);
2455 if (memcmp(id_string
, "LIN", 3) == 0) {
2456 STp
->linux_media
= 1;
2457 linux_media_version
= id_string
[3] - '0';
2458 if (linux_media_version
!= 4)
2459 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2460 name
, linux_media_version
);
2462 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2465 if (linux_media_version
< STp
->linux_media_version
) {
2467 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2468 name
, ppos
, linux_media_version
);
2472 if (linux_media_version
> STp
->linux_media_version
) {
2474 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2475 name
, ppos
, linux_media_version
);
2477 memcpy(STp
->application_sig
, id_string
, 5);
2478 STp
->linux_media_version
= linux_media_version
;
2479 STp
->update_frame_cntr
= -1;
2481 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2483 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2484 name
, ppos
, update_frame_cntr
);
2486 if (STp
->header_cache
== NULL
) {
2487 if ((STp
->header_cache
= vmalloc(sizeof(os_header_t
))) == NULL
) {
2488 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2492 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2495 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2496 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2498 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2499 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2500 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2501 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2502 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2503 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2504 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2505 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2506 STp
->update_frame_cntr
= update_frame_cntr
;
2508 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2509 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2510 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2511 STp
->first_data_ppos
,
2512 ntohl(header
->partition
[0].last_frame_ppos
),
2513 ntohl(header
->partition
[0].eod_frame_ppos
));
2514 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2515 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2517 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2519 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2521 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2522 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2523 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2525 if (header
->minor_rev
== 4 &&
2526 (header
->ext_trk_tb_off
!= htons(17192) ||
2527 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2528 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2529 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2530 header
->cfg_col_width
!= htonl(20) ||
2531 header
->dat_col_width
!= htonl(1500) ||
2532 header
->qfa_col_width
!= htonl(0) ||
2533 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2534 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2535 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2536 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2537 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2538 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2539 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2540 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2541 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2542 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2543 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2544 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2551 static int osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2556 char * name
= tape_name(STp
);
2558 position
= osst_get_frame_position(STp
, aSRpnt
);
2561 STp
->header_ok
= STp
->linux_media
= 1;
2562 STp
->linux_media_version
= 0;
2565 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2566 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2567 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2568 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2570 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2573 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2574 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2576 first
= position
==10?0xbae: 5;
2577 last
= position
==10?0xbb3:10;
2579 for (ppos
= first
; ppos
< last
; ppos
++)
2580 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2583 first
= position
==10? 5:0xbae;
2584 last
= position
==10?10:0xbb3;
2586 for (ppos
= first
; ppos
< last
; ppos
++)
2587 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2591 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2592 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2593 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2596 if (position
<= STp
->first_data_ppos
) {
2597 position
= STp
->first_data_ppos
;
2598 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2600 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2606 static int osst_verify_position(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2608 int frame_position
= STp
->first_frame_position
;
2609 int frame_seq_numbr
= STp
->frame_seq_number
;
2610 int logical_blk_num
= STp
->logical_blk_num
;
2611 int halfway_frame
= STp
->frame_in_buffer
;
2612 int read_pointer
= STp
->buffer
->read_pointer
;
2613 int prev_mark_ppos
= -1;
2614 int actual_mark_ppos
, i
, n
;
2616 char * name
= tape_name(STp
);
2618 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2620 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2621 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2623 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2627 if (STp
->linux_media_version
>= 4) {
2628 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2629 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2632 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2633 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2634 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2635 if (frame_position
!= STp
->first_frame_position
||
2636 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2637 prev_mark_ppos
!= actual_mark_ppos
) {
2639 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2640 STp
->first_frame_position
, frame_position
,
2641 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2642 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2646 if (halfway_frame
) {
2647 /* prepare buffer for append and rewrite on top of original */
2648 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2649 STp
->buffer
->buffer_bytes
= read_pointer
;
2650 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2653 STp
->frame_in_buffer
= halfway_frame
;
2654 STp
->frame_seq_number
= frame_seq_numbr
;
2655 STp
->logical_blk_num
= logical_blk_num
;
2659 /* Acc. to OnStream, the vers. numbering is the following:
2660 * X.XX for released versions (X=digit),
2661 * XXXY for unreleased versions (Y=letter)
2662 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2663 * This fn makes monoton numbers out of this scheme ...
2665 static unsigned int osst_parse_firmware_rev (const char * str
)
2667 if (str
[1] == '.') {
2668 return (str
[0]-'0')*10000
2672 return (str
[0]-'0')*10000
2674 +(str
[2]-'0')*100 - 100
2680 * Configure the OnStream SCII tape drive for default operation
2682 static int osst_configure_onstream(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2684 unsigned char cmd
[MAX_COMMAND_SIZE
];
2685 char * name
= tape_name(STp
);
2686 struct osst_request
* SRpnt
= * aSRpnt
;
2687 osst_mode_parameter_header_t
* header
;
2688 osst_block_size_page_t
* bs
;
2689 osst_capabilities_page_t
* cp
;
2690 osst_tape_paramtr_page_t
* prm
;
2691 int drive_buffer_size
;
2693 if (STp
->ready
!= ST_READY
) {
2695 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2700 if (STp
->os_fw_rev
< 10600) {
2701 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2702 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2706 * Configure 32.5KB (data+aux) frame size.
2707 * Get the current frame size from the block size mode page
2709 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2710 cmd
[0] = MODE_SENSE
;
2712 cmd
[2] = BLOCK_SIZE_PAGE
;
2713 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2715 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2716 if (SRpnt
== NULL
) {
2718 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2723 if ((STp
->buffer
)->syscall_result
!= 0) {
2724 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2728 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2729 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2732 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2733 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2734 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2735 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2739 * Configure default auto columns mode, 32.5KB transfer mode
2747 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2748 cmd
[0] = MODE_SELECT
;
2750 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2752 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2754 if ((STp
->buffer
)->syscall_result
!= 0) {
2755 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2760 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2762 * In debug mode, we want to see as many errors as possible
2763 * to test the error recovery mechanism.
2765 osst_set_retries(STp
, aSRpnt
, 0);
2770 * Set vendor name to 'LIN4' for "Linux support version 4".
2773 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2774 cmd
[0] = MODE_SELECT
;
2776 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2778 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2779 header
->medium_type
= 0; /* Medium Type - ignoring */
2780 header
->dsp
= 0; /* Reserved */
2781 header
->bdl
= 0; /* Block Descriptor Length */
2783 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2784 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2785 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2786 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2787 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2788 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2789 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2790 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2792 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2795 if ((STp
->buffer
)->syscall_result
!= 0) {
2796 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2797 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2801 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2802 cmd
[0] = MODE_SENSE
;
2804 cmd
[2] = CAPABILITIES_PAGE
;
2805 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2807 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2810 if ((STp
->buffer
)->syscall_result
!= 0) {
2811 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2815 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2816 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2817 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2819 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2821 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2822 cmd
[0] = MODE_SENSE
;
2824 cmd
[2] = TAPE_PARAMTR_PAGE
;
2825 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2827 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2830 if ((STp
->buffer
)->syscall_result
!= 0) {
2831 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2835 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2836 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2837 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2839 STp
->density
= prm
->density
;
2840 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2842 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2843 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2851 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2852 it messes up the block number). */
2853 static int cross_eof(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int forward
)
2856 char * name
= tape_name(STp
);
2860 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2861 name
, forward
? "forward" : "backward");
2865 /* assumes that the filemark is already read by the drive, so this is low cost */
2866 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2869 /* assumes this is only called if we just read the filemark! */
2870 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2873 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2874 name
, forward
? "forward" : "backward");
2880 /* Get the tape position. */
2882 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2884 unsigned char scmd
[MAX_COMMAND_SIZE
];
2885 struct osst_request
* SRpnt
;
2887 char * name
= tape_name(STp
);
2889 /* KG: We want to be able to use it for checking Write Buffer availability
2890 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2892 char * olddata
= STp
->buffer
->b_data
;
2893 int oldsize
= STp
->buffer
->buffer_size
;
2895 if (STp
->ready
!= ST_READY
) return (-EIO
);
2897 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2898 scmd
[0] = READ_POSITION
;
2900 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2901 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2902 STp
->timeout
, MAX_RETRIES
, 1);
2904 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2909 if (STp
->buffer
->syscall_result
)
2910 result
= ((SRpnt
->sense
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2912 if (result
== -EINVAL
)
2913 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2915 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2916 unsigned char mysense
[16];
2917 memcpy (mysense
, SRpnt
->sense
, 16);
2918 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2919 scmd
[0] = READ_POSITION
;
2920 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2921 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2922 STp
->timeout
, MAX_RETRIES
, 1);
2924 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2925 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2926 SRpnt
->sense
[2],SRpnt
->sense
[12],SRpnt
->sense
[13]);
2928 if (!STp
->buffer
->syscall_result
)
2929 memcpy (SRpnt
->sense
, mysense
, 16);
2931 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2933 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2934 + ((STp
->buffer
)->b_data
[5] << 16)
2935 + ((STp
->buffer
)->b_data
[6] << 8)
2936 + (STp
->buffer
)->b_data
[7];
2937 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2938 + ((STp
->buffer
)->b_data
[ 9] << 16)
2939 + ((STp
->buffer
)->b_data
[10] << 8)
2940 + (STp
->buffer
)->b_data
[11];
2941 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2944 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2945 STp
->first_frame_position
, STp
->last_frame_position
,
2946 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2947 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2951 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2953 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2954 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2956 STp
->first_frame_position
= STp
->last_frame_position
;
2959 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2961 return (result
== 0 ? STp
->first_frame_position
: result
);
2965 /* Set the tape block */
2966 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int ppos
, int skip
)
2968 unsigned char scmd
[MAX_COMMAND_SIZE
];
2969 struct osst_request
* SRpnt
;
2970 struct st_partstat
* STps
;
2972 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2973 char * name
= tape_name(STp
);
2975 if (STp
->ready
!= ST_READY
) return (-EIO
);
2977 STps
= &(STp
->ps
[STp
->partition
]);
2979 if (ppos
< 0 || ppos
> STp
->capacity
) {
2980 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2981 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2988 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2990 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2993 scmd
[3] = (pp
>> 24);
2994 scmd
[4] = (pp
>> 16);
2995 scmd
[5] = (pp
>> 8);
3000 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
3006 if ((STp
->buffer
)->syscall_result
!= 0) {
3008 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
3009 name
, STp
->first_frame_position
, pp
);
3014 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
3015 } while ((pp
!= ppos
) && (pp
= ppos
));
3016 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
3017 STps
->eof
= ST_NOEOF
;
3020 STp
->frame_in_buffer
= 0;
3024 static int osst_write_trailer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int leave_at_EOT
)
3026 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
3029 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
3030 /* true unless the user wrote the filemark for us */
3031 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
3032 if (result
< 0) goto out
;
3033 result
= osst_write_filemark(STp
, aSRpnt
);
3034 if (result
< 0) goto out
;
3036 if (STps
->drv_file
>= 0)
3038 STps
->drv_block
= 0;
3040 result
= osst_write_eod(STp
, aSRpnt
);
3041 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
3048 /* osst versions of st functions - augmented and stripped to suit OnStream only */
3050 /* Flush the write buffer (never need to write if variable blocksize). */
3051 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
3053 int offset
, transfer
, blks
= 0;
3055 unsigned char cmd
[MAX_COMMAND_SIZE
];
3056 struct osst_request
* SRpnt
= *aSRpnt
;
3057 struct st_partstat
* STps
;
3058 char * name
= tape_name(STp
);
3060 if ((STp
->buffer
)->writing
) {
3061 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
3063 { printk(OSST_DEB_MSG
3064 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name
);
3066 *aSRpnt
= SRpnt
= NULL
;
3070 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name
);
3072 osst_write_behind_check(STp
);
3073 if ((STp
->buffer
)->syscall_result
) {
3076 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
3077 name
, (STp
->buffer
)->midlevel_result
);
3079 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3086 if (STp
->dirty
== 1) {
3089 STps
= &(STp
->ps
[STp
->partition
]);
3090 STps
->rw
= ST_WRITING
;
3091 offset
= STp
->buffer
->buffer_bytes
;
3092 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
3093 transfer
= OS_FRAME_SIZE
;
3095 if (offset
< OS_DATA_SIZE
)
3096 osst_zero_buffer_tail(STp
->buffer
);
3099 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
3100 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
3102 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3107 switch (STp
->write_type
) {
3111 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3112 name
, blks
, STp
->frame_seq_number
,
3113 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3115 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3116 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3119 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
3120 STp
->logical_blk_num
, 0, 0);
3122 case OS_WRITE_NEW_MARK
:
3123 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
3124 STp
->logical_blk_num
++, 0, blks
=1);
3126 case OS_WRITE_HEADER
:
3127 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
3129 default: /* probably FILLER */
3130 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
3134 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3135 name
, offset
, transfer
, blks
);
3138 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3139 STp
->timeout
, MAX_RETRIES
, 1);
3144 if ((STp
->buffer
)->syscall_result
!= 0) {
3147 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3148 name
, SRpnt
->sense
[0], SRpnt
->sense
[2],
3149 SRpnt
->sense
[12], SRpnt
->sense
[13]);
3151 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3152 (SRpnt
->sense
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3153 (SRpnt
->sense
[2] & 0x0f) == NO_SENSE
) {
3155 (STp
->buffer
)->buffer_bytes
= 0;
3159 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3160 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3164 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3167 STp
->first_frame_position
++;
3169 (STp
->buffer
)->buffer_bytes
= 0;
3173 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3179 /* Flush the tape buffer. The tape will be positioned correctly unless
3180 seek_next is true. */
3181 static int osst_flush_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int seek_next
)
3183 struct st_partstat
* STps
;
3184 int backspace
= 0, result
= 0;
3186 char * name
= tape_name(STp
);
3190 * If there was a bus reset, block further access
3193 if( STp
->pos_unknown
)
3196 if (STp
->ready
!= ST_READY
)
3199 STps
= &(STp
->ps
[STp
->partition
]);
3200 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3201 STp
->write_type
= OS_WRITE_DATA
;
3202 return osst_flush_write_buffer(STp
, aSRpnt
);
3204 if (STp
->block_size
== 0)
3208 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3211 if (!STp
->can_bsr
) {
3212 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3213 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3214 (STp
->buffer
)->buffer_bytes
= 0;
3215 (STp
->buffer
)->read_pointer
= 0;
3216 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3220 if (STps
->eof
== ST_FM_HIT
) {
3221 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3223 STps
->eof
= ST_NOEOF
;
3225 if (STps
->drv_file
>= 0)
3227 STps
->drv_block
= 0;
3230 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3231 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3233 else if (STps
->eof
== ST_FM_HIT
) {
3234 if (STps
->drv_file
>= 0)
3236 STps
->drv_block
= 0;
3237 STps
->eof
= ST_NOEOF
;
3243 static int osst_write_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int synchronous
)
3245 unsigned char cmd
[MAX_COMMAND_SIZE
];
3246 struct osst_request
* SRpnt
;
3249 char * name
= tape_name(STp
);
3252 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3254 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3256 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3259 /* error recovery may have bumped us past the header partition */
3260 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3262 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3264 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3269 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3270 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3273 // osst_build_stats(STp, &SRpnt);
3275 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3276 STp
->write_type
= OS_WRITE_DATA
;
3278 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3281 cmd
[4] = 1; /* one frame at a time... */
3282 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3285 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3286 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3288 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3289 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3293 STp
->write_pending
= 1;
3295 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3296 MAX_RETRIES
, synchronous
);
3302 if (STp
->buffer
->syscall_result
!= 0) {
3305 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3307 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3308 (SRpnt
->sense
[2] & 0x40)) {
3309 if ((SRpnt
->sense
[2] & 0x0f) == VOLUME_OVERFLOW
)
3313 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3318 STp
->first_frame_position
++;
3326 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3327 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3331 cmd
= do_lock
? SCSI_IOCTL_DOORLOCK
: SCSI_IOCTL_DOORUNLOCK
;
3333 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3335 retval
= scsi_ioctl(STp
->device
, cmd
, NULL
);
3337 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3340 STp
->door_locked
= ST_LOCK_FAILS
;
3345 /* Set the internal state after reset */
3346 static void reset_state(struct osst_tape
*STp
)
3349 struct st_partstat
*STps
;
3351 STp
->pos_unknown
= 0;
3352 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3353 STps
= &(STp
->ps
[i
]);
3355 STps
->eof
= ST_NOEOF
;
3357 STps
->last_block_valid
= 0;
3358 STps
->drv_block
= -1;
3359 STps
->drv_file
= -1;
3364 /* Entry points to osst */
3367 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3369 ssize_t total
, retval
= 0;
3370 ssize_t i
, do_count
, blks
, transfer
;
3371 int write_threshold
;
3372 int doing_write
= 0;
3373 const char __user
* b_point
;
3374 struct osst_request
* SRpnt
= NULL
;
3375 struct st_modedef
* STm
;
3376 struct st_partstat
* STps
;
3377 struct osst_tape
* STp
= filp
->private_data
;
3378 char * name
= tape_name(STp
);
3381 if (mutex_lock_interruptible(&STp
->lock
))
3382 return (-ERESTARTSYS
);
3385 * If we are in the middle of error recovery, don't let anyone
3386 * else try and use this device. Also, if error recovery fails, it
3387 * may try and take the device offline, in which case all further
3388 * access to the device is prohibited.
3390 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3395 if (STp
->ready
!= ST_READY
) {
3396 if (STp
->ready
== ST_NO_TAPE
)
3397 retval
= (-ENOMEDIUM
);
3402 STm
= &(STp
->modes
[STp
->current_mode
]);
3403 if (!STm
->defined
) {
3411 * If there was a bus reset, block further access
3414 if (STp
->pos_unknown
) {
3421 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3427 if (STp
->write_prot
) {
3432 /* Write must be integral number of blocks */
3433 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3434 printk(KERN_ERR
"%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3435 name
, count
, STp
->block_size
<1024?
3436 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3441 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3442 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3443 name
, STp
->first_frame_position
);
3448 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3449 STp
->door_locked
= ST_LOCKED_AUTO
;
3451 STps
= &(STp
->ps
[STp
->partition
]);
3453 if (STps
->rw
== ST_READING
) {
3455 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3456 STps
->drv_file
, STps
->drv_block
);
3458 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3463 if (STps
->rw
!= ST_WRITING
) {
3464 /* Are we totally rewriting this tape? */
3465 if (!STp
->header_ok
||
3466 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3467 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3468 STp
->wrt_pass_cntr
++;
3470 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3471 name
, STp
->wrt_pass_cntr
);
3473 osst_reset_header(STp
, &SRpnt
);
3474 STps
->drv_file
= STps
->drv_block
= 0;
3476 /* Do we know where we'll be writing on the tape? */
3478 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3479 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3480 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3481 STps
->drv_file
= STp
->filemark_cnt
;
3482 STps
->drv_block
= 0;
3485 /* We have no idea where the tape is positioned - give up */
3488 "%s:D: Cannot write at indeterminate position.\n", name
);
3494 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3495 STp
->filemark_cnt
= STps
->drv_file
;
3496 STp
->last_mark_ppos
=
3497 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3499 "%s:W: Overwriting file %d with old write pass counter %d\n",
3500 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3502 "%s:W: may lead to stale data being accepted on reading back!\n",
3506 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3507 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3513 if (!STp
->header_ok
) {
3515 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3521 if ((STp
->buffer
)->writing
) {
3522 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3523 osst_write_behind_check(STp
);
3524 if ((STp
->buffer
)->syscall_result
) {
3527 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3528 (STp
->buffer
)->midlevel_result
);
3530 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3531 STps
->eof
= ST_EOM_OK
;
3533 STps
->eof
= ST_EOM_ERROR
;
3536 if (STps
->eof
== ST_EOM_OK
) {
3540 else if (STps
->eof
== ST_EOM_ERROR
) {
3545 /* Check the buffer readability in cases where copy_user might catch
3546 the problems after some tape movement. */
3547 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3548 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3553 if (!STm
->do_buffer_writes
) {
3554 write_threshold
= 1;
3557 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3558 if (!STm
->do_async_writes
)
3564 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3565 name
, (int) count
, STps
->drv_file
, STps
->drv_block
,
3566 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3569 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3572 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3573 (STp
->buffer
)->buffer_bytes
;
3574 if (do_count
> count
)
3577 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3583 blks
= do_count
/ STp
->block_size
;
3584 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3586 i
= osst_write_frame(STp
, &SRpnt
, 1);
3588 if (i
== (-ENOSPC
)) {
3589 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3590 if (transfer
<= do_count
) {
3591 *ppos
+= do_count
- transfer
;
3592 count
-= do_count
- transfer
;
3593 if (STps
->drv_block
>= 0) {
3594 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3596 STps
->eof
= ST_EOM_OK
;
3597 retval
= (-ENOSPC
); /* EOM within current request */
3600 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3601 name
, (int) transfer
);
3605 STps
->eof
= ST_EOM_ERROR
;
3606 STps
->drv_block
= (-1); /* Too cautious? */
3607 retval
= (-EIO
); /* EOM for old data */
3610 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3618 if (SRpnt
!= NULL
) {
3619 osst_release_request(SRpnt
);
3622 STp
->buffer
->buffer_bytes
= 0;
3625 retval
= total
- count
;
3630 b_point
+= do_count
;
3632 if (STps
->drv_block
>= 0) {
3633 STps
->drv_block
+= blks
;
3635 STp
->buffer
->buffer_bytes
= 0;
3637 } /* end while write threshold exceeded */
3641 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3646 blks
= count
/ STp
->block_size
;
3647 STp
->logical_blk_num
+= blks
;
3648 if (STps
->drv_block
>= 0) {
3649 STps
->drv_block
+= blks
;
3655 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3656 retval
= (STp
->buffer
)->syscall_result
;
3660 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3661 /* Schedule an asynchronous write */
3662 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3663 STp
->block_size
) * STp
->block_size
;
3664 STp
->dirty
= !((STp
->buffer
)->writing
==
3665 (STp
->buffer
)->buffer_bytes
);
3667 i
= osst_write_frame(STp
, &SRpnt
, 0);
3672 SRpnt
= NULL
; /* Prevent releasing this request! */
3674 STps
->at_sm
&= (total
== 0);
3676 STps
->eof
= ST_NOEOF
;
3681 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3683 mutex_unlock(&STp
->lock
);
3690 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3692 ssize_t total
, retval
= 0;
3693 ssize_t i
, transfer
;
3695 struct st_modedef
* STm
;
3696 struct st_partstat
* STps
;
3697 struct osst_request
* SRpnt
= NULL
;
3698 struct osst_tape
* STp
= filp
->private_data
;
3699 char * name
= tape_name(STp
);
3702 if (mutex_lock_interruptible(&STp
->lock
))
3703 return (-ERESTARTSYS
);
3706 * If we are in the middle of error recovery, don't let anyone
3707 * else try and use this device. Also, if error recovery fails, it
3708 * may try and take the device offline, in which case all further
3709 * access to the device is prohibited.
3711 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3716 if (STp
->ready
!= ST_READY
) {
3717 if (STp
->ready
== ST_NO_TAPE
)
3718 retval
= (-ENOMEDIUM
);
3723 STm
= &(STp
->modes
[STp
->current_mode
]);
3724 if (!STm
->defined
) {
3730 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3735 /* Must have initialized medium */
3736 if (!STp
->header_ok
) {
3741 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3742 STp
->door_locked
= ST_LOCKED_AUTO
;
3744 STps
= &(STp
->ps
[STp
->partition
]);
3745 if (STps
->rw
== ST_WRITING
) {
3746 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3750 /* FIXME -- this may leave the tape without EOD and up2date headers */
3753 if ((count
% STp
->block_size
) != 0) {
3755 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3756 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3760 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3761 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3762 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3764 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3765 STps
->eof
>= ST_EOD_1
) {
3766 if (STps
->eof
< ST_EOD
) {
3771 retval
= (-EIO
); /* EOM or Blank Check */
3775 /* Check the buffer writability before any tape movement. Don't alter
3777 if (copy_from_user(&i
, buf
, 1) != 0 ||
3778 copy_to_user (buf
, &i
, 1) != 0 ||
3779 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3780 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3785 /* Loop until enough data in buffer or a special condition found */
3786 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3788 /* Get new data if the buffer is empty */
3789 if ((STp
->buffer
)->buffer_bytes
== 0) {
3790 if (STps
->eof
== ST_FM_HIT
)
3792 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3793 if (special
< 0) { /* No need to continue read */
3794 STp
->frame_in_buffer
= 0;
3800 /* Move the data from driver buffer to user buffer */
3801 if ((STp
->buffer
)->buffer_bytes
> 0) {
3803 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3804 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3805 STps
->eof
, (STp
->buffer
)->buffer_bytes
, (int) (count
- total
));
3807 /* force multiple of block size, note block_size may have been adjusted */
3808 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3809 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3810 STp
->block_size
) * STp
->block_size
;
3812 if (transfer
== 0) {
3814 "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n",
3815 name
, count
, STp
->block_size
< 1024?
3816 STp
->block_size
:STp
->block_size
/1024,
3817 STp
->block_size
<1024?'b':'k');
3820 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3825 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3826 STps
->drv_block
+= transfer
/ STp
->block_size
;
3832 if ((STp
->buffer
)->buffer_bytes
== 0) {
3835 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3836 name
, STp
->frame_seq_number
);
3838 STp
->frame_in_buffer
= 0;
3839 STp
->frame_seq_number
++; /* frame to look for next time */
3841 } /* for (total = 0, special = 0; total < count && !special; ) */
3843 /* Change the eof state if no data from tape or buffer */
3845 if (STps
->eof
== ST_FM_HIT
) {
3846 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3847 STps
->drv_block
= 0;
3848 if (STps
->drv_file
>= 0)
3851 else if (STps
->eof
== ST_EOD_1
) {
3852 STps
->eof
= ST_EOD_2
;
3853 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3855 STps
->drv_block
= 0;
3857 else if (STps
->eof
== ST_EOD_2
)
3860 else if (STps
->eof
== ST_FM
)
3861 STps
->eof
= ST_NOEOF
;
3866 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3868 mutex_unlock(&STp
->lock
);
3874 /* Set the driver options */
3875 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3878 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3879 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3880 STm
->do_read_ahead
);
3882 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3883 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3885 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3886 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3887 STp
->scsi2_logical
);
3889 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3892 "%s:D: debugging: %d\n",
3898 static int osst_set_options(struct osst_tape
*STp
, long options
)
3902 struct st_modedef
* STm
;
3903 char * name
= tape_name(STp
);
3905 STm
= &(STp
->modes
[STp
->current_mode
]);
3906 if (!STm
->defined
) {
3907 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3911 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3912 name
, STp
->current_mode
);
3916 code
= options
& MT_ST_OPTIONS
;
3917 if (code
== MT_ST_BOOLEANS
) {
3918 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3919 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3920 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3921 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3922 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3923 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3924 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3925 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3926 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3927 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3928 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3929 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3930 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3932 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3934 osst_log_options(STp
, STm
, name
);
3936 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3937 value
= (code
== MT_ST_SETBOOLEANS
);
3938 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3939 STm
->do_buffer_writes
= value
;
3940 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3941 STm
->do_async_writes
= value
;
3942 if ((options
& MT_ST_DEF_WRITES
) != 0)
3943 STm
->defaults_for_writes
= value
;
3944 if ((options
& MT_ST_READ_AHEAD
) != 0)
3945 STm
->do_read_ahead
= value
;
3946 if ((options
& MT_ST_TWO_FM
) != 0)
3947 STp
->two_fm
= value
;
3948 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3949 STp
->fast_mteom
= value
;
3950 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3951 STp
->do_auto_lock
= value
;
3952 if ((options
& MT_ST_CAN_BSR
) != 0)
3953 STp
->can_bsr
= value
;
3954 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3955 STp
->omit_blklims
= value
;
3956 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3957 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3958 STp
->can_partitions
= value
;
3959 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3960 STp
->scsi2_logical
= value
;
3961 if ((options
& MT_ST_SYSV
) != 0)
3964 if ((options
& MT_ST_DEBUGGING
) != 0)
3967 osst_log_options(STp
, STm
, name
);
3969 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3970 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3971 if (value
< 1 || value
> osst_buffer_size
) {
3972 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3976 STp
->write_threshold
= value
;
3977 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3980 else if (code
== MT_ST_DEF_BLKSIZE
) {
3981 value
= (options
& ~MT_ST_OPTIONS
);
3982 if (value
== ~MT_ST_OPTIONS
) {
3983 STm
->default_blksize
= (-1);
3984 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3987 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3988 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3992 STm
->default_blksize
= value
;
3993 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3994 name
, STm
->default_blksize
);
3997 else if (code
== MT_ST_TIMEOUTS
) {
3998 value
= (options
& ~MT_ST_OPTIONS
);
3999 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
4000 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
4001 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
4002 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
4005 STp
->timeout
= value
* HZ
;
4006 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
4009 else if (code
== MT_ST_DEF_OPTIONS
) {
4010 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
4011 value
= (options
& MT_ST_CLEAR_DEFAULT
);
4012 if (code
== MT_ST_DEF_DENSITY
) {
4013 if (value
== MT_ST_CLEAR_DEFAULT
) {
4014 STm
->default_density
= (-1);
4015 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
4018 STm
->default_density
= value
& 0xff;
4019 printk(KERN_INFO
"%s:I: Density default set to %x\n",
4020 name
, STm
->default_density
);
4023 else if (code
== MT_ST_DEF_DRVBUFFER
) {
4024 if (value
== MT_ST_CLEAR_DEFAULT
) {
4025 STp
->default_drvbuffer
= 0xff;
4026 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
4029 STp
->default_drvbuffer
= value
& 7;
4030 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
4031 name
, STp
->default_drvbuffer
);
4034 else if (code
== MT_ST_DEF_COMPRESSION
) {
4035 if (value
== MT_ST_CLEAR_DEFAULT
) {
4036 STm
->default_compression
= ST_DONT_TOUCH
;
4037 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
4040 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
4041 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
4053 /* Internal ioctl function */
4054 static int osst_int_ioctl(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
4055 unsigned int cmd_in
, unsigned long arg
)
4059 int i
, ioctl_result
;
4061 unsigned char cmd
[MAX_COMMAND_SIZE
];
4062 struct osst_request
* SRpnt
= * aSRpnt
;
4063 struct st_partstat
* STps
;
4064 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
4065 int datalen
= 0, direction
= DMA_NONE
;
4066 char * name
= tape_name(STp
);
4068 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
4069 if (STp
->ready
== ST_NO_TAPE
)
4070 return (-ENOMEDIUM
);
4074 timeout
= STp
->long_timeout
;
4075 STps
= &(STp
->ps
[STp
->partition
]);
4076 fileno
= STps
->drv_file
;
4077 blkno
= STps
->drv_block
;
4078 at_sm
= STps
->at_sm
;
4079 frame_seq_numbr
= STp
->frame_seq_number
;
4080 logical_blk_num
= STp
->logical_blk_num
;
4082 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4085 chg_eof
= 0; /* Changed from the FSF after this */
4089 if (STp
->linux_media
)
4090 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
4092 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
4096 at_sm
&= (arg
== 0);
4100 chg_eof
= 0; /* Changed from the FSF after this */
4104 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
4107 blkno
= (-1); /* We can't know the block number */
4108 at_sm
&= (arg
== 0);
4115 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
4116 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
4118 if (cmd_in
== MTFSR
) {
4119 logical_blk_num
+= arg
;
4120 if (blkno
>= 0) blkno
+= arg
;
4123 logical_blk_num
-= arg
;
4124 if (blkno
>= 0) blkno
-= arg
;
4126 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
4127 fileno
= STps
->drv_file
;
4128 blkno
= STps
->drv_block
;
4129 at_sm
&= (arg
== 0);
4134 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4135 cmd
[2] = (arg
>> 16);
4136 cmd
[3] = (arg
>> 8);
4140 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4141 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4144 blkno
= fileno
= (-1);
4150 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4152 cmd
[2] = (ltmp
>> 16);
4153 cmd
[3] = (ltmp
>> 8);
4159 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4160 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4165 blkno
= fileno
= (-1);
4170 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4171 STp
->write_type
= OS_WRITE_DATA
;
4172 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4177 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4179 for (i
=0; i
<arg
; i
++)
4180 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4181 if (fileno
>= 0) fileno
+= arg
;
4182 if (blkno
>= 0) blkno
= 0;
4186 if (STp
->write_prot
)
4190 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4191 if (cmd_in
== MTWSM
)
4193 cmd
[2] = (arg
>> 16);
4194 cmd
[3] = (arg
>> 8);
4196 timeout
= STp
->timeout
;
4199 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4200 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4205 at_sm
= (cmd_in
== MTWSM
);
4211 cmd
[0] = START_STOP
;
4212 cmd
[1] = 1; /* Don't wait for completion */
4213 if (cmd_in
== MTLOAD
) {
4214 if (STp
->ready
== ST_NO_TAPE
)
4215 cmd
[4] = 4; /* open tray */
4217 cmd
[4] = 1; /* load */
4219 if (cmd_in
== MTRETEN
)
4220 cmd
[4] = 3; /* retension then mount */
4221 if (cmd_in
== MTOFFL
)
4222 cmd
[4] = 4; /* rewind then eject */
4223 timeout
= STp
->timeout
;
4228 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4231 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4234 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4237 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4242 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4247 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4249 return 0; /* Should do something ? */
4254 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4256 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4257 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4258 ioctl_result
= -EIO
;
4261 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4263 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4265 ioctl_result
= -EIO
;
4268 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4269 fileno
= STp
->filemark_cnt
;
4274 if (STp
->write_prot
)
4276 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4277 i
= osst_write_eod(STp
, &SRpnt
);
4278 if (i
< ioctl_result
) ioctl_result
= i
;
4279 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4280 if (i
< ioctl_result
) ioctl_result
= i
;
4281 fileno
= blkno
= at_sm
= 0 ;
4285 cmd
[0] = REZERO_UNIT
; /* rewind */
4289 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4291 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4294 case MTSETBLK
: /* Set block length */
4295 if ((STps
->drv_block
== 0 ) &&
4297 ((STp
->buffer
)->buffer_bytes
== 0) &&
4298 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4299 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4300 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4302 * Only allowed to change the block size if you opened the
4303 * device at the beginning of a file before writing anything.
4304 * Note, that when reading, changing block_size is futile,
4305 * as the size used when writing overrides it.
4307 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4308 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4309 name
, STp
->block_size
);
4312 case MTSETDENSITY
: /* Set tape density */
4313 case MTSETDRVBUFFER
: /* Set drive buffering */
4314 case SET_DENS_AND_BLK
: /* Set density and block size */
4316 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4317 return (-EIO
); /* Not allowed if data in buffer */
4318 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4319 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4320 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4321 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4322 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4323 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4326 return 0; /* FIXME silently ignore if block size didn't change */
4332 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4334 ioctl_result
= (STp
->buffer
)->syscall_result
;
4338 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4340 return ioctl_result
;
4343 if (!ioctl_result
) { /* SCSI command successful */
4344 STp
->frame_seq_number
= frame_seq_numbr
;
4345 STp
->logical_blk_num
= logical_blk_num
;
4351 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4354 if (!ioctl_result
) { /* success */
4356 if (cmd_in
== MTFSFM
) {
4360 if (cmd_in
== MTBSFM
) {
4364 STps
->drv_block
= blkno
;
4365 STps
->drv_file
= fileno
;
4366 STps
->at_sm
= at_sm
;
4368 if (cmd_in
== MTEOM
)
4370 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4371 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4373 STp
->logical_blk_num
++;
4374 STp
->frame_seq_number
++;
4375 STp
->frame_in_buffer
= 0;
4376 STp
->buffer
->read_pointer
= 0;
4378 else if (cmd_in
== MTFSF
)
4379 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4381 STps
->eof
= ST_NOEOF
;
4383 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4384 STp
->rew_at_close
= 0;
4385 else if (cmd_in
== MTLOAD
) {
4386 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4387 STp
->ps
[i
].rw
= ST_IDLE
;
4388 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4393 if (cmd_in
== MTREW
) {
4394 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4395 if (ioctl_result
> 0)
4399 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4400 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4401 STps
->drv_file
= STps
->drv_block
= -1;
4403 STps
->drv_file
= STps
->drv_block
= 0;
4404 STps
->eof
= ST_NOEOF
;
4405 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4406 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4407 STps
->drv_file
= STps
->drv_block
= -1;
4409 STps
->drv_file
= STp
->filemark_cnt
;
4410 STps
->drv_block
= 0;
4413 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4414 STps
->drv_file
= STps
->drv_block
= (-1);
4415 STps
->eof
= ST_NOEOF
;
4417 } else if (cmd_in
== MTERASE
) {
4419 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4420 if (SRpnt
->sense
[2] & 0x40) {
4421 STps
->eof
= ST_EOM_OK
;
4422 STps
->drv_block
= 0;
4425 STps
->eof
= ST_NOEOF
;
4427 if ((SRpnt
->sense
[2] & 0x0f) == BLANK_CHECK
)
4430 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4431 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4435 return ioctl_result
;
4439 /* Open the device */
4440 static int __os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4442 unsigned short flags
;
4443 int i
, b_size
, new_session
= 0, retval
= 0;
4444 unsigned char cmd
[MAX_COMMAND_SIZE
];
4445 struct osst_request
* SRpnt
= NULL
;
4446 struct osst_tape
* STp
;
4447 struct st_modedef
* STm
;
4448 struct st_partstat
* STps
;
4450 int dev
= TAPE_NR(inode
);
4451 int mode
= TAPE_MODE(inode
);
4454 * We really want to do nonseekable_open(inode, filp); here, but some
4455 * versions of tar incorrectly call lseek on tapes and bail out if that
4456 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4458 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4460 write_lock(&os_scsi_tapes_lock
);
4461 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4462 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4463 write_unlock(&os_scsi_tapes_lock
);
4467 name
= tape_name(STp
);
4470 write_unlock(&os_scsi_tapes_lock
);
4472 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4476 if (scsi_device_get(STp
->device
)) {
4477 write_unlock(&os_scsi_tapes_lock
);
4479 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4483 filp
->private_data
= STp
;
4485 write_unlock(&os_scsi_tapes_lock
);
4486 STp
->rew_at_close
= TAPE_REWIND(inode
);
4488 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4492 if (mode
!= STp
->current_mode
) {
4495 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4496 name
, STp
->current_mode
, mode
);
4499 STp
->current_mode
= mode
;
4501 STm
= &(STp
->modes
[STp
->current_mode
]);
4503 flags
= filp
->f_flags
;
4504 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4506 STp
->raw
= TAPE_IS_RAW(inode
);
4510 /* Allocate data segments for this device's tape buffer */
4511 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4512 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4513 retval
= (-EOVERFLOW
);
4516 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4517 for (i
= 0, b_size
= 0;
4518 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4519 b_size
+= STp
->buffer
->sg
[i
++].length
);
4520 STp
->buffer
->aux
= (os_aux_t
*) (page_address(sg_page(&STp
->buffer
->sg
[i
])) + OS_DATA_SIZE
- b_size
);
4522 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4523 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4524 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4525 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4528 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4529 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4533 STp
->buffer
->writing
= 0;
4534 STp
->buffer
->syscall_result
= 0;
4536 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4537 STps
= &(STp
->ps
[i
]);
4540 STp
->ready
= ST_READY
;
4542 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4545 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4546 cmd
[0] = TEST_UNIT_READY
;
4548 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4550 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4553 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4554 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4555 SRpnt
->sense
[12] == 4 ) {
4557 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sense
[13]);
4559 if (filp
->f_flags
& O_NONBLOCK
) {
4563 if (SRpnt
->sense
[13] == 2) { /* initialize command required (LOAD) */
4564 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4565 cmd
[0] = START_STOP
;
4568 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4569 STp
->timeout
, MAX_RETRIES
, 1);
4571 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sense
[13]==1?15:3) * 60, 0);
4573 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4574 (SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4576 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4580 for (i
=0; i
< 10; i
++) {
4582 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4583 cmd
[0] = TEST_UNIT_READY
;
4585 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4586 STp
->timeout
, MAX_RETRIES
, 1);
4587 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4588 (SRpnt
->sense
[2] & 0x0f) != UNIT_ATTENTION
)
4592 STp
->pos_unknown
= 0;
4593 STp
->partition
= STp
->new_partition
= 0;
4594 if (STp
->can_partitions
)
4595 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4596 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4597 STps
= &(STp
->ps
[i
]);
4598 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4599 STps
->eof
= ST_NOEOF
;
4601 STps
->last_block_valid
= 0;
4602 STps
->drv_block
= 0;
4603 STps
->drv_file
= 0 ;
4606 STp
->recover_count
= 0;
4607 STp
->abort_count
= 0;
4610 * if we have valid headers from before, and the drive/tape seem untouched,
4611 * open without reconfiguring and re-reading the headers
4613 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4614 !SRpnt
->result
&& SRpnt
->sense
[0] == 0) {
4616 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4617 cmd
[0] = MODE_SENSE
;
4619 cmd
[2] = VENDOR_IDENT_PAGE
;
4620 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4622 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4624 if (STp
->buffer
->syscall_result
||
4625 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4626 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4627 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4628 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4630 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4631 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4632 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4633 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4634 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4638 i
= STp
->first_frame_position
;
4639 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4640 if (STp
->door_locked
== ST_UNLOCKED
) {
4641 if (do_door_lock(STp
, 1))
4642 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4644 STp
->door_locked
= ST_LOCKED_AUTO
;
4646 if (!STp
->frame_in_buffer
) {
4647 STp
->block_size
= (STm
->default_blksize
> 0) ?
4648 STm
->default_blksize
: OS_DATA_SIZE
;
4649 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4651 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4653 osst_release_request(SRpnt
);
4657 if (i
!= STp
->first_frame_position
)
4658 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4659 name
, i
, STp
->first_frame_position
);
4665 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4666 (SRpnt
->sense
[2] != 2 || SRpnt
->sense
[12] != 0x3A) ) {
4668 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4669 cmd
[0] = MODE_SELECT
;
4671 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4673 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4674 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4675 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4676 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4677 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4678 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4679 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4680 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4683 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4685 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4689 for (i
=0; i
< 10; i
++) {
4691 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4692 cmd
[0] = TEST_UNIT_READY
;
4694 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4695 STp
->timeout
, MAX_RETRIES
, 1);
4696 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4697 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
)
4700 if ((SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) {
4701 STp
->pos_unknown
= 0;
4702 STp
->partition
= STp
->new_partition
= 0;
4703 if (STp
->can_partitions
)
4704 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4705 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4706 STps
= &(STp
->ps
[i
]);
4708 STps
->eof
= ST_NOEOF
;
4710 STps
->last_block_valid
= 0;
4711 STps
->drv_block
= 0;
4712 STps
->drv_file
= 0 ;
4719 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4720 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4722 if ((STp
->buffer
)->syscall_result
!= 0) {
4723 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4724 (SRpnt
->sense
[0] & 0x70) == 0x70 &&
4725 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4726 SRpnt
->sense
[12] == 0x3a) { /* Check ASC */
4727 STp
->ready
= ST_NO_TAPE
;
4729 STp
->ready
= ST_NOT_READY
;
4730 osst_release_request(SRpnt
);
4732 STp
->density
= 0; /* Clear the erroneous "residue" */
4733 STp
->write_prot
= 0;
4734 STp
->block_size
= 0;
4735 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4736 STp
->partition
= STp
->new_partition
= 0;
4737 STp
->door_locked
= ST_UNLOCKED
;
4741 osst_configure_onstream(STp
, &SRpnt
);
4743 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4744 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4745 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4746 STp
->buffer
->buffer_bytes
=
4747 STp
->buffer
->read_pointer
=
4748 STp
->frame_in_buffer
= 0;
4752 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4753 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4754 (STp
->buffer
)->buffer_blocks
);
4757 if (STp
->drv_write_prot
) {
4758 STp
->write_prot
= 1;
4761 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4763 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4769 if (new_session
) { /* Change the drive parameters for the new mode */
4772 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4774 STp
->density_changed
= STp
->blksize_changed
= 0;
4775 STp
->compression_changed
= 0;
4779 * properly position the tape and check the ADR headers
4781 if (STp
->door_locked
== ST_UNLOCKED
) {
4782 if (do_door_lock(STp
, 1))
4783 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4785 STp
->door_locked
= ST_LOCKED_AUTO
;
4788 osst_analyze_headers(STp
, &SRpnt
);
4790 osst_release_request(SRpnt
);
4797 osst_release_request(SRpnt
);
4798 normalize_buffer(STp
->buffer
);
4801 scsi_device_put(STp
->device
);
4806 /* BKL pushdown: spaghetti avoidance wrapper */
4807 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4811 mutex_lock(&osst_int_mutex
);
4812 ret
= __os_scsi_tape_open(inode
, filp
);
4813 mutex_unlock(&osst_int_mutex
);
4819 /* Flush the tape buffer before close */
4820 static int os_scsi_tape_flush(struct file
* filp
, fl_owner_t id
)
4822 int result
= 0, result2
;
4823 struct osst_tape
* STp
= filp
->private_data
;
4824 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4825 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4826 struct osst_request
* SRpnt
= NULL
;
4827 char * name
= tape_name(STp
);
4829 if (file_count(filp
) > 1)
4832 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4833 STp
->write_type
= OS_WRITE_DATA
;
4834 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4835 if (result
!= 0 && result
!= (-ENOSPC
))
4838 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4842 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4843 name
, (long)(filp
->f_pos
));
4844 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4845 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4848 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4851 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4852 name
, 1+STp
->two_fm
);
4855 else if (!STp
->rew_at_close
) {
4856 STps
= &(STp
->ps
[STp
->partition
]);
4857 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4859 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4860 else if (STps
->eof
== ST_FM_HIT
) {
4861 result
= cross_eof(STp
, &SRpnt
, 0);
4863 if (STps
->drv_file
>= 0)
4865 STps
->drv_block
= 0;
4869 STps
->eof
= ST_NOEOF
;
4872 else if ((STps
->eof
== ST_NOEOF
&&
4873 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4874 STps
->eof
== ST_FM_HIT
) {
4875 if (STps
->drv_file
>= 0)
4877 STps
->drv_block
= 0;
4883 if (STp
->rew_at_close
) {
4884 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4885 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4886 if (result
== 0 && result2
< 0)
4889 if (SRpnt
) osst_release_request(SRpnt
);
4891 if (STp
->abort_count
|| STp
->recover_count
) {
4892 printk(KERN_INFO
"%s:I:", name
);
4893 if (STp
->abort_count
)
4894 printk(" %d unrecovered errors", STp
->abort_count
);
4895 if (STp
->recover_count
)
4896 printk(" %d recovered errors", STp
->recover_count
);
4897 if (STp
->write_count
)
4898 printk(" in %d frames written", STp
->write_count
);
4899 if (STp
->read_count
)
4900 printk(" in %d frames read", STp
->read_count
);
4902 STp
->recover_count
= 0;
4903 STp
->abort_count
= 0;
4905 STp
->write_count
= 0;
4906 STp
->read_count
= 0;
4912 /* Close the device and release it */
4913 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4916 struct osst_tape
* STp
= filp
->private_data
;
4918 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4919 do_door_lock(STp
, 0);
4924 normalize_buffer(STp
->buffer
);
4925 write_lock(&os_scsi_tapes_lock
);
4927 write_unlock(&os_scsi_tapes_lock
);
4929 scsi_device_put(STp
->device
);
4935 /* The ioctl command */
4936 static long osst_ioctl(struct file
* file
,
4937 unsigned int cmd_in
, unsigned long arg
)
4939 int i
, cmd_nr
, cmd_type
, blk
, retval
= 0;
4940 struct st_modedef
* STm
;
4941 struct st_partstat
* STps
;
4942 struct osst_request
* SRpnt
= NULL
;
4943 struct osst_tape
* STp
= file
->private_data
;
4944 char * name
= tape_name(STp
);
4945 void __user
* p
= (void __user
*)arg
;
4947 mutex_lock(&osst_int_mutex
);
4948 if (mutex_lock_interruptible(&STp
->lock
)) {
4949 mutex_unlock(&osst_int_mutex
);
4950 return -ERESTARTSYS
;
4954 if (debugging
&& !STp
->in_use
) {
4955 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4960 STm
= &(STp
->modes
[STp
->current_mode
]);
4961 STps
= &(STp
->ps
[STp
->partition
]);
4964 * If we are in the middle of error recovery, don't let anyone
4965 * else try and use this device. Also, if error recovery fails, it
4966 * may try and take the device offline, in which case all further
4967 * access to the device is prohibited.
4969 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4974 cmd_type
= _IOC_TYPE(cmd_in
);
4975 cmd_nr
= _IOC_NR(cmd_in
);
4977 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4978 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4980 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4984 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4989 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
4995 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
4996 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
5001 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
5006 if (!STp
->pos_unknown
) {
5008 if (STps
->eof
== ST_FM_HIT
) {
5009 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
5011 if (STps
->drv_file
>= 0)
5012 STps
->drv_file
+= 1;
5014 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
5016 if (STps
->drv_file
>= 0)
5017 STps
->drv_file
+= 1;
5021 if (mtc
.mt_op
== MTSEEK
) {
5022 /* Old position must be restored if partition will be changed */
5023 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
5026 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
5027 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
5028 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
5029 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
5030 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
5031 mtc
.mt_op
== MTCOMPRESSION
;
5033 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
5041 * If there was a bus reset, block further access
5042 * to this device. If the user wants to rewind the tape,
5043 * then reset the flag and allow access again.
5045 if(mtc
.mt_op
!= MTREW
&&
5046 mtc
.mt_op
!= MTOFFL
&&
5047 mtc
.mt_op
!= MTRETEN
&&
5048 mtc
.mt_op
!= MTERASE
&&
5049 mtc
.mt_op
!= MTSEEK
&&
5050 mtc
.mt_op
!= MTEOM
) {
5055 /* remove this when the midlevel properly clears was_reset */
5056 STp
->device
->was_reset
= 0;
5059 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
5060 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
5061 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
5062 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
5063 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
5066 * The user tells us to move to another position on the tape.
5067 * If we were appending to the tape content, that would leave
5068 * the tape without proper end, in that case write EOD and
5069 * update the header to reflect its position.
5072 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
5073 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
5074 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
5075 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5077 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
5078 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
5079 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5080 i
= osst_write_trailer(STp
, &SRpnt
,
5081 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5083 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5084 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
5085 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5095 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
5096 do_door_lock(STp
, 0); /* Ignore result! */
5098 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
5099 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
5100 retval
= osst_set_options(STp
, mtc
.mt_count
);
5104 if (mtc
.mt_op
== MTSETPART
) {
5105 if (mtc
.mt_count
>= STp
->nbr_partitions
)
5108 STp
->new_partition
= mtc
.mt_count
;
5114 if (mtc
.mt_op
== MTMKPART
) {
5115 if (!STp
->can_partitions
) {
5119 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
5120 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5124 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5125 STp
->ps
[i
].rw
= ST_IDLE
;
5126 STp
->ps
[i
].at_sm
= 0;
5127 STp
->ps
[i
].last_block_valid
= 0;
5129 STp
->partition
= STp
->new_partition
= 0;
5130 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
5131 STps
->drv_block
= STps
->drv_file
= 0;
5136 if (mtc
.mt_op
== MTSEEK
) {
5138 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
5140 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
5141 if (!STp
->can_partitions
)
5142 STp
->ps
[0].rw
= ST_IDLE
;
5147 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
5148 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5153 cross_eof(STp
, &SRpnt
, 0);
5155 if (mtc
.mt_op
== MTCOMPRESSION
)
5156 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5158 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5159 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5160 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5164 if (!STm
->defined
) {
5169 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5174 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5175 struct mtget mt_status
;
5177 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5182 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5183 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5184 mt_status
.mt_dsreg
=
5185 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5186 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5187 mt_status
.mt_blkno
= STps
->drv_block
;
5188 mt_status
.mt_fileno
= STps
->drv_file
;
5189 if (STp
->block_size
!= 0) {
5190 if (STps
->rw
== ST_WRITING
)
5191 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5192 else if (STps
->rw
== ST_READING
)
5193 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5194 STp
->block_size
- 1) / STp
->block_size
;
5197 mt_status
.mt_gstat
= 0;
5198 if (STp
->drv_write_prot
)
5199 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5200 if (mt_status
.mt_blkno
== 0) {
5201 if (mt_status
.mt_fileno
== 0)
5202 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5204 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5206 mt_status
.mt_resid
= STp
->partition
;
5207 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5208 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5209 else if (STps
->eof
>= ST_EOM_OK
)
5210 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5211 if (STp
->density
== 1)
5212 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5213 else if (STp
->density
== 2)
5214 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5215 else if (STp
->density
== 3)
5216 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5217 if (STp
->ready
== ST_READY
)
5218 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5219 if (STp
->ready
== ST_NO_TAPE
)
5220 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5222 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5223 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5224 STp
->drv_buffer
!= 0)
5225 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5227 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5233 STp
->recover_erreg
= 0; /* Clear after read */
5236 } /* End of MTIOCGET */
5238 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5239 struct mtpos mt_pos
;
5241 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5246 blk
= osst_get_frame_position(STp
, &SRpnt
);
5248 blk
= osst_get_sector(STp
, &SRpnt
);
5253 mt_pos
.mt_blkno
= blk
;
5254 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5259 if (SRpnt
) osst_release_request(SRpnt
);
5261 mutex_unlock(&STp
->lock
);
5263 retval
= scsi_ioctl(STp
->device
, cmd_in
, p
);
5264 mutex_unlock(&osst_int_mutex
);
5268 if (SRpnt
) osst_release_request(SRpnt
);
5270 mutex_unlock(&STp
->lock
);
5271 mutex_unlock(&osst_int_mutex
);
5276 #ifdef CONFIG_COMPAT
5277 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5279 struct osst_tape
*STp
= file
->private_data
;
5280 struct scsi_device
*sdev
= STp
->device
;
5281 int ret
= -ENOIOCTLCMD
;
5282 if (sdev
->host
->hostt
->compat_ioctl
) {
5284 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5293 /* Memory handling routines */
5295 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5296 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5300 struct osst_buffer
*tb
;
5302 if (from_initialization
)
5303 priority
= GFP_ATOMIC
;
5305 priority
= GFP_KERNEL
;
5307 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5308 tb
= kzalloc(i
, priority
);
5310 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5314 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5315 tb
->use_sg
= max_sg
;
5318 tb
->buffer_size
= 0;
5322 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5323 i
, max_sg
, need_dma
);
5328 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5329 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5331 int segs
, nbr
, max_segs
, b_size
, order
, got
;
5334 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5337 if (STbuffer
->sg_segs
) {
5338 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5339 normalize_buffer(STbuffer
);
5341 /* See how many segments we can use -- need at least two */
5342 nbr
= max_segs
= STbuffer
->use_sg
;
5346 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5348 priority
|= GFP_DMA
;
5350 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5351 big enough to reach the goal (code assumes no segments in place) */
5352 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5353 struct page
*page
= alloc_pages(priority
, order
);
5355 STbuffer
->sg
[0].offset
= 0;
5357 sg_set_page(&STbuffer
->sg
[0], page
, b_size
, 0);
5358 STbuffer
->b_data
= page_address(page
);
5362 if (sg_page(&STbuffer
->sg
[0]) == NULL
) {
5363 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5366 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5367 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5368 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5369 struct page
*page
= alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5370 STbuffer
->sg
[segs
].offset
= 0;
5372 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5375 STbuffer
->buffer_size
= got
;
5377 normalize_buffer(STbuffer
);
5380 sg_set_page(&STbuffer
->sg
[segs
], page
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
, 0);
5381 got
+= STbuffer
->sg
[segs
].length
;
5382 STbuffer
->buffer_size
= got
;
5383 STbuffer
->sg_segs
= ++segs
;
5388 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5389 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5391 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5392 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5393 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5401 /* Release the segments */
5402 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5404 int i
, order
, b_size
;
5406 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5408 for (b_size
= PAGE_SIZE
, order
= 0;
5409 b_size
< STbuffer
->sg
[i
].length
;
5410 b_size
*= 2, order
++);
5412 __free_pages(sg_page(&STbuffer
->sg
[i
]), order
);
5413 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5416 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5417 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5418 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5420 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5424 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5425 negative error code. */
5426 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5428 int i
, cnt
, res
, offset
;
5430 for (i
=0, offset
=st_bp
->buffer_bytes
;
5431 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5432 offset
-= st_bp
->sg
[i
].length
;
5433 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5434 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5437 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5438 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5439 st_bp
->sg
[i
].length
- offset
: do_count
;
5440 res
= copy_from_user(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, ubp
, cnt
);
5444 st_bp
->buffer_bytes
+= cnt
;
5448 if (do_count
) { /* Should never happen */
5449 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5457 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5458 negative error code. */
5459 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5461 int i
, cnt
, res
, offset
;
5463 for (i
=0, offset
=st_bp
->read_pointer
;
5464 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5465 offset
-= st_bp
->sg
[i
].length
;
5466 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5467 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5470 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5471 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5472 st_bp
->sg
[i
].length
- offset
: do_count
;
5473 res
= copy_to_user(ubp
, page_address(sg_page(&st_bp
->sg
[i
])) + offset
, cnt
);
5477 st_bp
->buffer_bytes
-= cnt
;
5478 st_bp
->read_pointer
+= cnt
;
5482 if (do_count
) { /* Should never happen */
5483 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5489 /* Sets the tail of the buffer after fill point to zero.
5490 Returns zero (success) or negative error code. */
5491 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5493 int i
, offset
, do_count
, cnt
;
5495 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5496 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5497 offset
-= st_bp
->sg
[i
].length
;
5498 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5499 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5502 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5503 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5504 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5505 st_bp
->sg
[i
].length
- offset
: do_count
;
5506 memset(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, 0, cnt
);
5510 if (do_count
) { /* Should never happen */
5511 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5517 /* Copy a osst 32K chunk of memory into the buffer.
5518 Returns zero (success) or negative error code. */
5519 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5521 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5523 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5524 cnt
= st_bp
->sg
[i
].length
< do_count
?
5525 st_bp
->sg
[i
].length
: do_count
;
5526 memcpy(page_address(sg_page(&st_bp
->sg
[i
])), ptr
, cnt
);
5530 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5531 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5538 /* Copy a osst 32K chunk of memory from the buffer.
5539 Returns zero (success) or negative error code. */
5540 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5542 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5544 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5545 cnt
= st_bp
->sg
[i
].length
< do_count
?
5546 st_bp
->sg
[i
].length
: do_count
;
5547 memcpy(ptr
, page_address(sg_page(&st_bp
->sg
[i
])), cnt
);
5551 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5552 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5560 /* Module housekeeping */
5562 static void validate_options (void)
5565 osst_max_dev
= max_dev
;
5566 if (write_threshold_kbs
> 0)
5567 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5568 if (osst_write_threshold
> osst_buffer_size
)
5569 osst_write_threshold
= osst_buffer_size
;
5570 if (max_sg_segs
>= OSST_FIRST_SG
)
5571 osst_max_sg_segs
= max_sg_segs
;
5573 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5574 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5579 /* Set the boot options. Syntax: osst=xxx,yyy,...
5580 where xxx is write threshold in 1024 byte blocks,
5581 and yyy is number of s/g segments to use. */
5582 static int __init
osst_setup (char *str
)
5587 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5590 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5591 *parms
[i
].val
= ints
[i
+ 1];
5593 while (stp
!= NULL
) {
5594 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5595 int len
= strlen(parms
[i
].name
);
5596 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5597 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5599 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5603 if (i
>= ARRAY_SIZE(parms
))
5604 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5606 stp
= strchr(stp
, ',');
5615 __setup("osst=", osst_setup
);
5619 static const struct file_operations osst_fops
= {
5620 .owner
= THIS_MODULE
,
5622 .write
= osst_write
,
5623 .unlocked_ioctl
= osst_ioctl
,
5624 #ifdef CONFIG_COMPAT
5625 .compat_ioctl
= osst_compat_ioctl
,
5627 .open
= os_scsi_tape_open
,
5628 .flush
= os_scsi_tape_flush
,
5629 .release
= os_scsi_tape_close
,
5630 .llseek
= noop_llseek
,
5633 static int osst_supports(struct scsi_device
* SDp
)
5635 struct osst_support_data
{
5639 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5642 static struct osst_support_data support_list
[] = {
5643 /* {"XXX", "Yy-", "", NULL}, example */
5647 struct osst_support_data
*rp
;
5649 /* We are willing to drive OnStream SC-x0 as well as the
5650 * * IDE, ParPort, FireWire, USB variants, if accessible by
5651 * * emulation layer (ide-scsi, usb-storage, ...) */
5653 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5654 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5655 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5656 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5662 * sysfs support for osst driver parameter information
5665 static ssize_t
osst_version_show(struct device_driver
*ddd
, char *buf
)
5667 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5670 static DRIVER_ATTR(version
, S_IRUGO
, osst_version_show
, NULL
);
5672 static int osst_create_sysfs_files(struct device_driver
*sysfs
)
5674 return driver_create_file(sysfs
, &driver_attr_version
);
5677 static void osst_remove_sysfs_files(struct device_driver
*sysfs
)
5679 driver_remove_file(sysfs
, &driver_attr_version
);
5683 * sysfs support for accessing ADR header information
5686 static ssize_t
osst_adr_rev_show(struct device
*dev
,
5687 struct device_attribute
*attr
, char *buf
)
5689 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5692 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5693 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5697 DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5699 static ssize_t
osst_linux_media_version_show(struct device
*dev
,
5700 struct device_attribute
*attr
,
5703 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5706 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5707 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5711 DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5713 static ssize_t
osst_capacity_show(struct device
*dev
,
5714 struct device_attribute
*attr
, char *buf
)
5716 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5719 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5720 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5724 DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5726 static ssize_t
osst_first_data_ppos_show(struct device
*dev
,
5727 struct device_attribute
*attr
,
5730 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5733 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5734 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5738 DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5740 static ssize_t
osst_eod_frame_ppos_show(struct device
*dev
,
5741 struct device_attribute
*attr
,
5744 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5747 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5748 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5752 DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5754 static ssize_t
osst_filemark_cnt_show(struct device
*dev
,
5755 struct device_attribute
*attr
, char *buf
)
5757 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5760 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5761 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5765 DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5767 static struct class *osst_sysfs_class
;
5769 static int osst_sysfs_init(void)
5771 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5772 if (IS_ERR(osst_sysfs_class
)) {
5773 printk(KERN_ERR
"osst :W: Unable to register sysfs class\n");
5774 return PTR_ERR(osst_sysfs_class
);
5780 static void osst_sysfs_destroy(dev_t dev
)
5782 device_destroy(osst_sysfs_class
, dev
);
5785 static int osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5787 struct device
*osst_member
;
5790 osst_member
= device_create(osst_sysfs_class
, device
, dev
, STp
,
5792 if (IS_ERR(osst_member
)) {
5793 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5794 return PTR_ERR(osst_member
);
5797 err
= device_create_file(osst_member
, &dev_attr_ADR_rev
);
5800 err
= device_create_file(osst_member
, &dev_attr_media_version
);
5803 err
= device_create_file(osst_member
, &dev_attr_capacity
);
5806 err
= device_create_file(osst_member
, &dev_attr_BOT_frame
);
5809 err
= device_create_file(osst_member
, &dev_attr_EOD_frame
);
5812 err
= device_create_file(osst_member
, &dev_attr_file_count
);
5819 osst_sysfs_destroy(dev
);
5823 static void osst_sysfs_cleanup(void)
5825 class_destroy(osst_sysfs_class
);
5829 * osst startup / cleanup code
5832 static int osst_probe(struct device
*dev
)
5834 struct scsi_device
* SDp
= to_scsi_device(dev
);
5835 struct osst_tape
* tpnt
;
5836 struct st_modedef
* STm
;
5837 struct st_partstat
* STps
;
5838 struct osst_buffer
* buffer
;
5839 struct gendisk
* drive
;
5840 int i
, dev_num
, err
= -ENODEV
;
5842 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5845 drive
= alloc_disk(1);
5847 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5851 /* if this is the first attach, build the infrastructure */
5852 write_lock(&os_scsi_tapes_lock
);
5853 if (os_scsi_tapes
== NULL
) {
5854 os_scsi_tapes
= kmalloc(osst_max_dev
* sizeof(struct osst_tape
*), GFP_ATOMIC
);
5855 if (os_scsi_tapes
== NULL
) {
5856 write_unlock(&os_scsi_tapes_lock
);
5857 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5860 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5863 if (osst_nr_dev
>= osst_max_dev
) {
5864 write_unlock(&os_scsi_tapes_lock
);
5865 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5869 /* find a free minor number */
5870 for (i
= 0; i
< osst_max_dev
&& os_scsi_tapes
[i
]; i
++)
5872 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5875 /* allocate a struct osst_tape for this device */
5876 tpnt
= kzalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5878 write_unlock(&os_scsi_tapes_lock
);
5879 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5883 /* allocate a buffer for this device */
5884 i
= SDp
->host
->sg_tablesize
;
5885 if (osst_max_sg_segs
< i
)
5886 i
= osst_max_sg_segs
;
5887 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5888 if (buffer
== NULL
) {
5889 write_unlock(&os_scsi_tapes_lock
);
5890 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5894 os_scsi_tapes
[dev_num
] = tpnt
;
5895 tpnt
->buffer
= buffer
;
5897 drive
->private_data
= &tpnt
->driver
;
5898 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5899 tpnt
->driver
= &osst_template
;
5900 tpnt
->drive
= drive
;
5902 tpnt
->capacity
= 0xfffff;
5904 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5905 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5907 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5908 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5909 tpnt
->can_partitions
= 0;
5910 tpnt
->two_fm
= OSST_TWO_FM
;
5911 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5912 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5913 tpnt
->write_threshold
= osst_write_threshold
;
5914 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5915 tpnt
->partition
= 0;
5916 tpnt
->new_partition
= 0;
5917 tpnt
->nbr_partitions
= 0;
5918 tpnt
->min_block
= 512;
5919 tpnt
->max_block
= OS_DATA_SIZE
;
5920 tpnt
->timeout
= OSST_TIMEOUT
;
5921 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5923 /* Recognize OnStream tapes */
5924 /* We don't need to test for OnStream, as this has been done in detect () */
5925 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5926 tpnt
->omit_blklims
= 1;
5928 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5929 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5930 tpnt
->frame_in_buffer
= 0;
5931 tpnt
->header_ok
= 0;
5932 tpnt
->linux_media
= 0;
5933 tpnt
->header_cache
= NULL
;
5935 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5936 STm
= &(tpnt
->modes
[i
]);
5938 STm
->sysv
= OSST_SYSV
;
5939 STm
->defaults_for_writes
= 0;
5940 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5941 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5942 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5943 STm
->default_compression
= ST_DONT_TOUCH
;
5944 STm
->default_blksize
= 512;
5945 STm
->default_density
= (-1); /* No forced density */
5948 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5949 STps
= &(tpnt
->ps
[i
]);
5951 STps
->eof
= ST_NOEOF
;
5953 STps
->last_block_valid
= 0;
5954 STps
->drv_block
= (-1);
5955 STps
->drv_file
= (-1);
5958 tpnt
->current_mode
= 0;
5959 tpnt
->modes
[0].defined
= 1;
5960 tpnt
->modes
[2].defined
= 1;
5961 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5963 mutex_init(&tpnt
->lock
);
5965 write_unlock(&os_scsi_tapes_lock
);
5971 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5973 goto out_free_buffer
;
5975 /* No-rewind entry */
5976 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5977 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5979 goto out_free_sysfs1
;
5982 sdev_printk(KERN_INFO
, SDp
,
5983 "osst :I: Attached OnStream %.5s tape as %s\n",
5984 SDp
->model
, tape_name(tpnt
));
5989 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, dev_num
));
5997 static int osst_remove(struct device
*dev
)
5999 struct scsi_device
* SDp
= to_scsi_device(dev
);
6000 struct osst_tape
* tpnt
;
6003 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
6006 write_lock(&os_scsi_tapes_lock
);
6007 for(i
=0; i
< osst_max_dev
; i
++) {
6008 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
6009 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
6010 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
6011 tpnt
->device
= NULL
;
6012 put_disk(tpnt
->drive
);
6013 os_scsi_tapes
[i
] = NULL
;
6015 write_unlock(&os_scsi_tapes_lock
);
6016 vfree(tpnt
->header_cache
);
6018 normalize_buffer(tpnt
->buffer
);
6019 kfree(tpnt
->buffer
);
6025 write_unlock(&os_scsi_tapes_lock
);
6029 static int __init
init_osst(void)
6033 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
6037 err
= osst_sysfs_init();
6041 err
= register_chrdev(OSST_MAJOR
, "osst", &osst_fops
);
6043 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
6047 err
= scsi_register_driver(&osst_template
.gendrv
);
6049 goto err_out_chrdev
;
6051 err
= osst_create_sysfs_files(&osst_template
.gendrv
);
6053 goto err_out_scsidrv
;
6058 scsi_unregister_driver(&osst_template
.gendrv
);
6060 unregister_chrdev(OSST_MAJOR
, "osst");
6062 osst_sysfs_cleanup();
6066 static void __exit
exit_osst (void)
6069 struct osst_tape
* STp
;
6071 osst_remove_sysfs_files(&osst_template
.gendrv
);
6072 scsi_unregister_driver(&osst_template
.gendrv
);
6073 unregister_chrdev(OSST_MAJOR
, "osst");
6074 osst_sysfs_cleanup();
6076 if (os_scsi_tapes
) {
6077 for (i
=0; i
< osst_max_dev
; ++i
) {
6078 if (!(STp
= os_scsi_tapes
[i
])) continue;
6079 /* This is defensive, supposed to happen during detach */
6080 vfree(STp
->header_cache
);
6082 normalize_buffer(STp
->buffer
);
6085 put_disk(STp
->drive
);
6088 kfree(os_scsi_tapes
);
6090 printk(KERN_INFO
"osst :I: Unloaded.\n");
6093 module_init(init_osst
);
6094 module_exit(exit_osst
);