2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid
= "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27 static const char * osst_version
= "0.99.4";
29 /* The "failure to reconnect" firmware bug */
30 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31 #define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
34 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/sched/signal.h>
39 #include <linux/proc_fs.h>
41 #include <linux/slab.h>
42 #include <linux/init.h>
43 #include <linux/string.h>
44 #include <linux/errno.h>
45 #include <linux/mtio.h>
46 #include <linux/ioctl.h>
47 #include <linux/fcntl.h>
48 #include <linux/spinlock.h>
49 #include <linux/vmalloc.h>
50 #include <linux/blkdev.h>
51 #include <linux/moduleparam.h>
52 #include <linux/delay.h>
53 #include <linux/jiffies.h>
54 #include <linux/mutex.h>
55 #include <linux/uaccess.h>
58 /* The driver prints some debugging information on the console if DEBUG
59 is defined and non-zero. */
62 /* The message level for the debug messages is currently set to KERN_NOTICE
63 so that people can easily see the messages. Later when the debugging messages
64 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
65 #define OSST_DEB_MSG KERN_NOTICE
67 #include <scsi/scsi.h>
68 #include <scsi/scsi_dbg.h>
69 #include <scsi/scsi_device.h>
70 #include <scsi/scsi_driver.h>
71 #include <scsi/scsi_eh.h>
72 #include <scsi/scsi_host.h>
73 #include <scsi/scsi_ioctl.h>
75 #define ST_KILOBYTE 1024
79 #include "osst_options.h"
80 #include "osst_detect.h"
82 static DEFINE_MUTEX(osst_int_mutex
);
83 static int max_dev
= 0;
84 static int write_threshold_kbs
= 0;
85 static int max_sg_segs
= 0;
88 MODULE_AUTHOR("Willem Riede");
89 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
90 MODULE_LICENSE("GPL");
91 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR
);
92 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE
);
94 module_param(max_dev
, int, 0444);
95 MODULE_PARM_DESC(max_dev
, "Maximum number of OnStream Tape Drives to attach (4)");
97 module_param(write_threshold_kbs
, int, 0644);
98 MODULE_PARM_DESC(write_threshold_kbs
, "Asynchronous write threshold (KB; 32)");
100 module_param(max_sg_segs
, int, 0644);
101 MODULE_PARM_DESC(max_sg_segs
, "Maximum number of scatter/gather segments to use (9)");
103 static struct osst_dev_parm
{
106 } parms
[] __initdata
= {
107 { "max_dev", &max_dev
},
108 { "write_threshold_kbs", &write_threshold_kbs
},
109 { "max_sg_segs", &max_sg_segs
}
113 /* Some default definitions have been moved to osst_options.h */
114 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
115 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
117 /* The buffer size should fit into the 24 bits for length in the
118 6-byte SCSI read and write commands. */
119 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
120 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
124 static int debugging
= 1;
125 /* uncomment define below to test error recovery */
126 // #define OSST_INJECT_ERRORS 1
129 /* Do not retry! The drive firmware already retries when appropriate,
130 and when it tries to tell us something, we had better listen... */
131 #define MAX_RETRIES 0
133 #define NO_TAPE NOT_READY
135 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
136 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
137 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
139 #define OSST_TIMEOUT (200 * HZ)
140 #define OSST_LONG_TIMEOUT (1800 * HZ)
142 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
143 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
144 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
145 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
147 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
149 #define SET_DENS_AND_BLK 0x10001
151 static int osst_buffer_size
= OSST_BUFFER_SIZE
;
152 static int osst_write_threshold
= OSST_WRITE_THRESHOLD
;
153 static int osst_max_sg_segs
= OSST_MAX_SG
;
154 static int osst_max_dev
= OSST_MAX_TAPES
;
155 static int osst_nr_dev
;
157 static struct osst_tape
**os_scsi_tapes
= NULL
;
158 static DEFINE_RWLOCK(os_scsi_tapes_lock
);
160 static int modes_defined
= 0;
162 static struct osst_buffer
*new_tape_buffer(int, int, int);
163 static int enlarge_buffer(struct osst_buffer
*, int);
164 static void normalize_buffer(struct osst_buffer
*);
165 static int append_to_buffer(const char __user
*, struct osst_buffer
*, int);
166 static int from_buffer(struct osst_buffer
*, char __user
*, int);
167 static int osst_zero_buffer_tail(struct osst_buffer
*);
168 static int osst_copy_to_buffer(struct osst_buffer
*, unsigned char *);
169 static int osst_copy_from_buffer(struct osst_buffer
*, unsigned char *);
171 static int osst_probe(struct device
*);
172 static int osst_remove(struct device
*);
174 static struct scsi_driver osst_template
= {
177 .owner
= THIS_MODULE
,
179 .remove
= osst_remove
,
183 static int osst_int_ioctl(struct osst_tape
*STp
, struct osst_request
** aSRpnt
,
184 unsigned int cmd_in
, unsigned long arg
);
186 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int frame
, int skip
);
188 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
190 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
);
192 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
);
194 static inline char *tape_name(struct osst_tape
*tape
)
196 return tape
->drive
->disk_name
;
199 /* Routines that handle the interaction with mid-layer SCSI routines */
202 /* Normalize Sense */
203 static void osst_analyze_sense(struct osst_request
*SRpnt
, struct st_cmdstatus
*s
)
206 const u8
*sense
= SRpnt
->sense
;
208 s
->have_sense
= scsi_normalize_sense(SRpnt
->sense
,
209 SCSI_SENSE_BUFFERSIZE
, &s
->sense_hdr
);
215 scsi_get_sense_info_fld(sense
, SCSI_SENSE_BUFFERSIZE
, &s
->uremainder64
);
216 switch (sense
[0] & 0x7f) {
221 s
->flags
= sense
[2] & 0xe0;
227 ucp
= scsi_sense_desc_find(sense
, SCSI_SENSE_BUFFERSIZE
, 4);
228 s
->flags
= ucp
? (ucp
[3] & 0xe0) : 0;
234 /* Convert the result to success code */
235 static int osst_chk_result(struct osst_tape
* STp
, struct osst_request
* SRpnt
)
237 char *name
= tape_name(STp
);
238 int result
= SRpnt
->result
;
239 u8
* sense
= SRpnt
->sense
, scode
;
243 struct st_cmdstatus
*cmdstatp
;
248 cmdstatp
= &STp
->buffer
->cmdstat
;
249 osst_analyze_sense(SRpnt
, cmdstatp
);
251 if (cmdstatp
->have_sense
)
252 scode
= STp
->buffer
->cmdstat
.sense_hdr
.sense_key
;
257 printk(OSST_DEB_MSG
"%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
259 SRpnt
->cmd
[0], SRpnt
->cmd
[1], SRpnt
->cmd
[2],
260 SRpnt
->cmd
[3], SRpnt
->cmd
[4], SRpnt
->cmd
[5]);
261 if (scode
) printk(OSST_DEB_MSG
"%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
262 name
, scode
, sense
[12], sense
[13]);
263 if (cmdstatp
->have_sense
)
264 __scsi_print_sense(STp
->device
, name
,
265 SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
269 if (cmdstatp
->have_sense
&& (
271 scode
!= RECOVERED_ERROR
&&
272 /* scode != UNIT_ATTENTION && */
273 scode
!= BLANK_CHECK
&&
274 scode
!= VOLUME_OVERFLOW
&&
275 SRpnt
->cmd
[0] != MODE_SENSE
&&
276 SRpnt
->cmd
[0] != TEST_UNIT_READY
)) { /* Abnormal conditions for tape */
277 if (cmdstatp
->have_sense
) {
278 printk(KERN_WARNING
"%s:W: Command with sense data:\n", name
);
279 __scsi_print_sense(STp
->device
, name
,
280 SRpnt
->sense
, SCSI_SENSE_BUFFERSIZE
);
283 static int notyetprinted
= 1;
286 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
287 name
, result
, driver_byte(result
),
292 "%s:I: This warning may be caused by your scsi controller,\n", name
);
294 "%s:I: it has been reported with some Buslogic cards.\n", name
);
298 STp
->pos_unknown
|= STp
->device
->was_reset
;
300 if (cmdstatp
->have_sense
&& scode
== RECOVERED_ERROR
) {
301 STp
->recover_count
++;
302 STp
->recover_erreg
++;
305 if (SRpnt
->cmd
[0] == READ_6
)
307 else if (SRpnt
->cmd
[0] == WRITE_6
)
311 printk(OSST_DEB_MSG
"%s:D: Recovered %s error (%d).\n", name
, stp
,
315 if ((sense
[2] & 0xe0) == 0)
322 /* Wakeup from interrupt */
323 static void osst_end_async(struct request
*req
, int update
)
325 struct scsi_request
*rq
= scsi_req(req
);
326 struct osst_request
*SRpnt
= req
->end_io_data
;
327 struct osst_tape
*STp
= SRpnt
->stp
;
328 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
330 STp
->buffer
->cmdstat
.midlevel_result
= SRpnt
->result
= req
->errors
;
332 STp
->write_pending
= 0;
335 memcpy(SRpnt
->sense
, rq
->sense
, SCSI_SENSE_BUFFERSIZE
);
337 complete(SRpnt
->waiting
);
341 blk_rq_unmap_user(SRpnt
->bio
);
344 __blk_put_request(req
->q
, req
);
347 /* osst_request memory management */
348 static struct osst_request
*osst_allocate_request(void)
350 return kzalloc(sizeof(struct osst_request
), GFP_KERNEL
);
353 static void osst_release_request(struct osst_request
*streq
)
358 static int osst_execute(struct osst_request
*SRpnt
, const unsigned char *cmd
,
359 int cmd_len
, int data_direction
, void *buffer
, unsigned bufflen
,
360 int use_sg
, int timeout
, int retries
)
363 struct scsi_request
*rq
;
364 struct page
**pages
= NULL
;
365 struct rq_map_data
*mdata
= &SRpnt
->stp
->buffer
->map_data
;
368 int write
= (data_direction
== DMA_TO_DEVICE
);
370 req
= blk_get_request(SRpnt
->stp
->device
->request_queue
,
371 write
? REQ_OP_SCSI_OUT
: REQ_OP_SCSI_IN
, GFP_KERNEL
);
373 return DRIVER_ERROR
<< 24;
377 req
->rq_flags
|= RQF_QUIET
;
382 struct scatterlist
*sg
, *sgl
= (struct scatterlist
*)buffer
;
385 pages
= kzalloc(use_sg
* sizeof(struct page
*), GFP_KERNEL
);
389 for_each_sg(sgl
, sg
, use_sg
, i
)
390 pages
[i
] = sg_page(sg
);
392 mdata
->null_mapped
= 1;
394 mdata
->page_order
= get_order(sgl
[0].length
);
396 DIV_ROUND_UP(bufflen
, PAGE_SIZE
<< mdata
->page_order
);
399 err
= blk_rq_map_user(req
->q
, req
, mdata
, NULL
, bufflen
, GFP_KERNEL
);
404 SRpnt
->bio
= req
->bio
;
405 mdata
->pages
= pages
;
407 } else if (bufflen
) {
408 err
= blk_rq_map_kern(req
->q
, req
, buffer
, bufflen
, GFP_KERNEL
);
413 rq
->cmd_len
= cmd_len
;
414 memset(rq
->cmd
, 0, BLK_MAX_CDB
); /* ATAPI hates garbage after CDB */
415 memcpy(rq
->cmd
, cmd
, rq
->cmd_len
);
416 req
->timeout
= timeout
;
417 req
->retries
= retries
;
418 req
->end_io_data
= SRpnt
;
420 blk_execute_rq_nowait(req
->q
, NULL
, req
, 1, osst_end_async
);
423 blk_put_request(req
);
424 return DRIVER_ERROR
<< 24;
427 /* Do the scsi command. Waits until command performed if do_wait is true.
428 Otherwise osst_write_behind_check() is used to check that the command
430 static struct osst_request
* osst_do_scsi(struct osst_request
*SRpnt
, struct osst_tape
*STp
,
431 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
434 unsigned short use_sg
;
435 #ifdef OSST_INJECT_ERRORS
436 static int inject
= 0;
437 static int repeat
= 0;
439 struct completion
*waiting
;
441 /* if async, make sure there's no command outstanding */
442 if (!do_wait
&& ((STp
->buffer
)->last_SRpnt
)) {
443 printk(KERN_ERR
"%s: Async command already active.\n",
445 if (signal_pending(current
))
446 (STp
->buffer
)->syscall_result
= (-EINTR
);
448 (STp
->buffer
)->syscall_result
= (-EBUSY
);
453 SRpnt
= osst_allocate_request();
455 printk(KERN_ERR
"%s: Can't allocate SCSI request.\n",
457 if (signal_pending(current
))
458 (STp
->buffer
)->syscall_result
= (-EINTR
);
460 (STp
->buffer
)->syscall_result
= (-EBUSY
);
466 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
467 which IO is outstanding. It's nulled out when the IO completes. */
469 (STp
->buffer
)->last_SRpnt
= SRpnt
;
471 waiting
= &STp
->wait
;
472 init_completion(waiting
);
473 SRpnt
->waiting
= waiting
;
475 use_sg
= (bytes
> STp
->buffer
->sg
[0].length
) ? STp
->buffer
->use_sg
: 0;
477 bp
= (char *)&(STp
->buffer
->sg
[0]);
478 if (STp
->buffer
->sg_segs
< use_sg
)
479 use_sg
= STp
->buffer
->sg_segs
;
482 bp
= (STp
->buffer
)->b_data
;
484 memcpy(SRpnt
->cmd
, cmd
, sizeof(SRpnt
->cmd
));
485 STp
->buffer
->cmdstat
.have_sense
= 0;
486 STp
->buffer
->syscall_result
= 0;
488 if (osst_execute(SRpnt
, cmd
, COMMAND_SIZE(cmd
[0]), direction
, bp
, bytes
,
489 use_sg
, timeout
, retries
))
490 /* could not allocate the buffer or request was too large */
491 (STp
->buffer
)->syscall_result
= (-EBUSY
);
493 wait_for_completion(waiting
);
494 SRpnt
->waiting
= NULL
;
495 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
496 #ifdef OSST_INJECT_ERRORS
497 if (STp
->buffer
->syscall_result
== 0 &&
500 ( (++ inject
% 83) == 29 ||
501 (STp
->first_frame_position
== 240
502 /* or STp->read_error_frame to fail again on the block calculated above */ &&
504 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
505 STp
->buffer
->last_result_fatal
= 1;
513 /* Handle the write-behind checking (downs the semaphore) */
514 static void osst_write_behind_check(struct osst_tape
*STp
)
516 struct osst_buffer
* STbuffer
;
518 STbuffer
= STp
->buffer
;
521 if (STp
->write_pending
)
526 wait_for_completion(&(STp
->wait
));
527 STp
->buffer
->last_SRpnt
->waiting
= NULL
;
529 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
531 if (STp
->buffer
->syscall_result
)
532 STp
->buffer
->syscall_result
=
533 osst_write_error_recovery(STp
, &(STp
->buffer
->last_SRpnt
), 1);
535 STp
->first_frame_position
++;
537 osst_release_request(STp
->buffer
->last_SRpnt
);
539 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
540 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
542 STbuffer
->last_SRpnt
= NULL
;
543 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
544 STbuffer
->writing
= 0;
551 /* Onstream specific Routines */
553 * Initialize the OnStream AUX
555 static void osst_init_aux(struct osst_tape
* STp
, int frame_type
, int frame_seq_number
,
556 int logical_blk_num
, int blk_sz
, int blk_cnt
)
558 os_aux_t
*aux
= STp
->buffer
->aux
;
559 os_partition_t
*par
= &aux
->partition
;
560 os_dat_t
*dat
= &aux
->dat
;
562 if (STp
->raw
) return;
564 memset(aux
, 0, sizeof(*aux
));
565 aux
->format_id
= htonl(0);
566 memcpy(aux
->application_sig
, "LIN4", 4);
567 aux
->hdwr
= htonl(0);
568 aux
->frame_type
= frame_type
;
570 switch (frame_type
) {
571 case OS_FRAME_TYPE_HEADER
:
572 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
573 par
->partition_num
= OS_CONFIG_PARTITION
;
574 par
->par_desc_ver
= OS_PARTITION_VERSION
;
575 par
->wrt_pass_cntr
= htons(0xffff);
576 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
577 par
->first_frame_ppos
= htonl(0);
578 par
->last_frame_ppos
= htonl(0xbb7);
579 aux
->frame_seq_num
= htonl(0);
580 aux
->logical_blk_num_high
= htonl(0);
581 aux
->logical_blk_num
= htonl(0);
582 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
584 case OS_FRAME_TYPE_DATA
:
585 case OS_FRAME_TYPE_MARKER
:
590 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
591 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
592 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
593 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
594 dat
->dat_list
[0].reserved
= 0;
595 case OS_FRAME_TYPE_EOD
:
596 aux
->update_frame_cntr
= htonl(0);
597 par
->partition_num
= OS_DATA_PARTITION
;
598 par
->par_desc_ver
= OS_PARTITION_VERSION
;
599 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
600 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
601 par
->last_frame_ppos
= htonl(STp
->capacity
);
602 aux
->frame_seq_num
= htonl(frame_seq_number
);
603 aux
->logical_blk_num_high
= htonl(0);
604 aux
->logical_blk_num
= htonl(logical_blk_num
);
606 default: ; /* probably FILL */
608 aux
->filemark_cnt
= htonl(STp
->filemark_cnt
);
609 aux
->phys_fm
= htonl(0xffffffff);
610 aux
->last_mark_ppos
= htonl(STp
->last_mark_ppos
);
611 aux
->last_mark_lbn
= htonl(STp
->last_mark_lbn
);
615 * Verify that we have the correct tape frame
617 static int osst_verify_frame(struct osst_tape
* STp
, int frame_seq_number
, int quiet
)
619 char * name
= tape_name(STp
);
620 os_aux_t
* aux
= STp
->buffer
->aux
;
621 os_partition_t
* par
= &(aux
->partition
);
622 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
623 int blk_cnt
, blk_sz
, i
;
626 if (STp
->buffer
->syscall_result
) {
627 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
628 memset(page_address(sg_page(&STp
->buffer
->sg
[i
])),
629 0, STp
->buffer
->sg
[i
].length
);
630 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
632 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
635 if (STp
->buffer
->syscall_result
) {
637 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
641 if (ntohl(aux
->format_id
) != 0) {
643 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
647 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
648 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
650 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
654 if (par
->partition_num
!= OS_DATA_PARTITION
) {
655 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
657 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
658 name
, par
->partition_num
);
663 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
665 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
669 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
671 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
672 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
676 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
677 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
678 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
681 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
686 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
687 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
688 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
689 STp
->first_frame_position
);
692 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
695 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
696 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
701 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
702 STps
->eof
= ST_FM_HIT
;
704 i
= ntohl(aux
->filemark_cnt
);
705 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
706 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
708 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
709 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
710 i
, STp
->first_frame_position
- 1);
712 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
713 if (i
>= STp
->filemark_cnt
)
714 STp
->filemark_cnt
= i
+1;
717 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
718 STps
->eof
= ST_EOD_1
;
719 STp
->frame_in_buffer
= 1;
721 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
722 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
723 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
724 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
725 STp
->buffer
->read_pointer
= 0;
726 STp
->frame_in_buffer
= 1;
728 /* See what block size was used to write file */
729 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
731 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
732 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
733 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
734 STp
->block_size
<1024?'b':'k');
735 STp
->block_size
= blk_sz
;
736 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
738 STps
->eof
= ST_NOEOF
;
740 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
741 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
745 if (STp
->read_error_frame
== 0)
746 STp
->read_error_frame
= STp
->first_frame_position
- 1;
751 * Wait for the unit to become Ready
753 static int osst_wait_ready(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
754 unsigned timeout
, int initial_delay
)
756 unsigned char cmd
[MAX_COMMAND_SIZE
];
757 struct osst_request
* SRpnt
;
758 unsigned long startwait
= jiffies
;
761 char * name
= tape_name(STp
);
763 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
766 if (initial_delay
> 0)
767 msleep(jiffies_to_msecs(initial_delay
));
769 memset(cmd
, 0, MAX_COMMAND_SIZE
);
770 cmd
[0] = TEST_UNIT_READY
;
772 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
774 if (!SRpnt
) return (-EBUSY
);
776 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
777 (( SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
778 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8) ) ||
779 ( SRpnt
->sense
[2] == 6 && SRpnt
->sense
[12] == 0x28 &&
780 SRpnt
->sense
[13] == 0 ) )) {
783 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
784 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
790 memset(cmd
, 0, MAX_COMMAND_SIZE
);
791 cmd
[0] = TEST_UNIT_READY
;
793 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
799 if ( STp
->buffer
->syscall_result
&&
800 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
802 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
803 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
804 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
805 SRpnt
->sense
[12], SRpnt
->sense
[13]);
810 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
816 * Wait for a tape to be inserted in the unit
818 static int osst_wait_for_medium(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, unsigned timeout
)
820 unsigned char cmd
[MAX_COMMAND_SIZE
];
821 struct osst_request
* SRpnt
;
822 unsigned long startwait
= jiffies
;
825 char * name
= tape_name(STp
);
827 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
830 memset(cmd
, 0, MAX_COMMAND_SIZE
);
831 cmd
[0] = TEST_UNIT_READY
;
833 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
835 if (!SRpnt
) return (-EBUSY
);
837 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
838 SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 0x3a && SRpnt
->sense
[13] == 0 ) {
841 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
842 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
848 memset(cmd
, 0, MAX_COMMAND_SIZE
);
849 cmd
[0] = TEST_UNIT_READY
;
851 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
857 if ( STp
->buffer
->syscall_result
&& SRpnt
->sense
[2] != 2 &&
858 SRpnt
->sense
[12] != 4 && SRpnt
->sense
[13] == 1) {
860 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
861 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
862 STp
->buffer
->syscall_result
, SRpnt
->sense
[0], SRpnt
->sense
[2],
863 SRpnt
->sense
[12], SRpnt
->sense
[13]);
868 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
873 static int osst_position_tape_and_confirm(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int frame
)
877 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
878 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
879 if (retval
) return (retval
);
880 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
881 return (osst_get_frame_position(STp
, aSRpnt
));
885 * Wait for write(s) to complete
887 static int osst_flush_drive_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
889 unsigned char cmd
[MAX_COMMAND_SIZE
];
890 struct osst_request
* SRpnt
;
892 int delay
= OSST_WAIT_WRITE_COMPLETE
;
894 char * name
= tape_name(STp
);
896 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
899 memset(cmd
, 0, MAX_COMMAND_SIZE
);
900 cmd
[0] = WRITE_FILEMARKS
;
903 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
905 if (!SRpnt
) return (-EBUSY
);
906 if (STp
->buffer
->syscall_result
) {
907 if ((SRpnt
->sense
[2] & 0x0f) == 2 && SRpnt
->sense
[12] == 4) {
908 if (SRpnt
->sense
[13] == 8) {
909 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
912 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
914 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
915 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
920 #define OSST_POLL_PER_SEC 10
921 static int osst_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int curr
, int minlast
, int to
)
923 unsigned long startwait
= jiffies
;
924 char * name
= tape_name(STp
);
926 char notyetprinted
= 1;
928 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
929 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
931 while (time_before (jiffies
, startwait
+ to
*HZ
))
934 result
= osst_get_frame_position(STp
, aSRpnt
);
936 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
937 return 0; /* successful recovery leaves drive ready for frame */
938 if (result
< 0) break;
939 if (STp
->first_frame_position
== curr
&&
941 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
942 (minlast
>= 0 && STp
->cur_frames
> minlast
)
946 if (debugging
|| time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
))
948 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
949 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
950 STp
->last_frame_position
, STp
->cur_frames
,
951 result
, (jiffies
-startwait
)/HZ
,
952 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
957 if (time_after_eq(jiffies
, startwait
+ 2*HZ
/OSST_POLL_PER_SEC
) && notyetprinted
)
959 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
960 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
961 STp
->last_frame_position
, STp
->cur_frames
, result
);
965 msleep(1000 / OSST_POLL_PER_SEC
);
968 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
969 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
970 STp
->last_frame_position
, STp
->cur_frames
,
971 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
976 static int osst_recover_wait_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int writing
)
978 struct osst_request
* SRpnt
;
979 unsigned char cmd
[MAX_COMMAND_SIZE
];
980 unsigned long startwait
= jiffies
;
982 char * name
= tape_name(STp
);
986 char * olddata
= STp
->buffer
->b_data
;
987 int oldsize
= STp
->buffer
->buffer_size
;
989 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
991 memset(cmd
, 0, MAX_COMMAND_SIZE
);
992 cmd
[0] = WRITE_FILEMARKS
;
994 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
997 while (retval
&& time_before (jiffies
, startwait
+ 5*60*HZ
)) {
999 if (STp
->buffer
->syscall_result
&& (SRpnt
->sense
[2] & 0x0f) != 2) {
1001 /* some failure - not just not-ready */
1002 retval
= osst_write_error_recovery(STp
, aSRpnt
, 0);
1005 schedule_timeout_interruptible(HZ
/ OSST_POLL_PER_SEC
);
1007 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
1008 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1009 cmd
[0] = READ_POSITION
;
1011 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
1014 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
1015 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
1018 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
1020 /* TODO - figure out which error conditions can be handled */
1021 if (STp
->buffer
->syscall_result
)
1023 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
1024 (*aSRpnt
)->sense
[ 2] & 0x0f,
1025 (*aSRpnt
)->sense
[12],
1026 (*aSRpnt
)->sense
[13]);
1032 * Read the next OnStream tape frame at the current location
1034 static int osst_read_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int timeout
)
1036 unsigned char cmd
[MAX_COMMAND_SIZE
];
1037 struct osst_request
* SRpnt
;
1040 os_aux_t
* aux
= STp
->buffer
->aux
;
1041 char * name
= tape_name(STp
);
1045 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
1046 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
1048 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1055 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
1057 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1058 STp
->timeout
, MAX_RETRIES
, 1);
1063 if ((STp
->buffer
)->syscall_result
) {
1065 if (STp
->read_error_frame
== 0) {
1066 STp
->read_error_frame
= STp
->first_frame_position
;
1068 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
1073 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1075 SRpnt
->sense
[0], SRpnt
->sense
[1],
1076 SRpnt
->sense
[2], SRpnt
->sense
[3],
1077 SRpnt
->sense
[4], SRpnt
->sense
[5],
1078 SRpnt
->sense
[6], SRpnt
->sense
[7]);
1082 STp
->first_frame_position
++;
1087 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
1090 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
1091 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
1092 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
1093 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
1094 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
1095 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
1096 if (aux
->frame_type
==2)
1097 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
1098 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
1099 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
1105 static int osst_initiate_read(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1107 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1108 struct osst_request
* SRpnt
;
1109 unsigned char cmd
[MAX_COMMAND_SIZE
];
1111 char * name
= tape_name(STp
);
1113 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
1114 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
1115 STp
->write_type
= OS_WRITE_DATA
;
1116 osst_flush_write_buffer(STp
, aSRpnt
);
1117 osst_flush_drive_buffer(STp
, aSRpnt
);
1119 STps
->rw
= ST_READING
;
1120 STp
->frame_in_buffer
= 0;
1123 * Issue a read 0 command to get the OnStream drive
1124 * read frames into its buffer.
1126 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1131 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
1133 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
1135 if ((retval
= STp
->buffer
->syscall_result
))
1136 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1142 static int osst_get_logical_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1143 int frame_seq_number
, int quiet
)
1145 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1146 char * name
= tape_name(STp
);
1154 * If we want just any frame (-1) and there is a frame in the buffer, return it
1156 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1158 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1163 * Search and wait for the next logical tape frame
1167 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1168 name
, frame_seq_number
);
1169 if (STp
->read_error_frame
) {
1170 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1172 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1173 name
, STp
->read_error_frame
);
1175 STp
->read_error_frame
= 0;
1182 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1183 name
, frame_seq_number
, cnt
);
1185 if ( osst_initiate_read(STp
, aSRpnt
)
1186 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1189 position
= osst_get_frame_position(STp
, aSRpnt
);
1190 if (position
>= 0xbae && position
< 0xbb8)
1192 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1193 position
= STp
->read_error_frame
- 1;
1201 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1204 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1207 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1209 if (osst_verify_frame(STp
, -1, quiet
)) {
1210 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1211 if (STp
->fast_open
) {
1213 "%s:W: Found logical frame %d instead of %d after fast open\n",
1214 name
, x
, frame_seq_number
);
1216 STp
->read_error_frame
= 0;
1219 if (x
> frame_seq_number
) {
1221 /* positioning backwards did not bring us to the desired frame */
1222 position
= STp
->read_error_frame
- 1;
1225 position
= osst_get_frame_position(STp
, aSRpnt
)
1226 + frame_seq_number
- x
- 1;
1228 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1233 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1234 name
, x
, frame_seq_number
,
1235 STp
->first_frame_position
- position
);
1237 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1243 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1245 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1247 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1250 STp
->frame_in_buffer
= 0;
1253 STp
->recover_count
++;
1254 STp
->recover_erreg
++;
1255 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1256 name
, STp
->read_error_frame
);
1261 if (debugging
|| STps
->eof
)
1263 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1264 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1267 STp
->read_error_frame
= 0;
1271 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int logical_blk_num
)
1273 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1274 char * name
= tape_name(STp
);
1276 int frame_seq_estimate
, ppos_estimate
, move
;
1278 if (logical_blk_num
< 0) logical_blk_num
= 0;
1280 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1281 name
, logical_blk_num
, STp
->logical_blk_num
,
1282 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1283 STp
->block_size
<1024?'b':'k');
1285 /* Do we know where we are? */
1286 if (STps
->drv_block
>= 0) {
1287 move
= logical_blk_num
- STp
->logical_blk_num
;
1288 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1289 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1290 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1292 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1294 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1295 else ppos_estimate
= frame_seq_estimate
+ 20;
1296 while (++retries
< 10) {
1297 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1298 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1299 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1301 if (frame_seq_estimate
< 0) {
1302 frame_seq_estimate
= 0;
1305 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1306 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1307 /* we've located the estimated frame, now does it have our block? */
1308 if (logical_blk_num
< STp
->logical_blk_num
||
1309 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1310 if (STps
->eof
== ST_FM_HIT
)
1311 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1313 move
= logical_blk_num
- STp
->logical_blk_num
;
1314 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1315 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1317 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1320 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1321 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1322 STp
->logical_blk_num
, logical_blk_num
, move
);
1324 frame_seq_estimate
+= move
;
1325 ppos_estimate
+= move
;
1328 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1329 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1330 STp
->logical_blk_num
= logical_blk_num
;
1333 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1334 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1335 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1338 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1339 if (STps
->eof
== ST_FM_HIT
) {
1341 STps
->drv_block
= 0;
1343 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1344 STp
->logical_blk_num
-
1345 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1348 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1352 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1354 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1356 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1357 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1358 STp
->logical_blk_num
, logical_blk_num
);
1360 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1361 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1366 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1367 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1371 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1372 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1373 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1374 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1376 #define OSST_FRAME_SHIFT 6
1377 #define OSST_SECTOR_SHIFT 9
1378 #define OSST_SECTOR_MASK 0x03F
1380 static int osst_get_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
1384 char * name
= tape_name(STp
);
1387 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1388 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1389 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1390 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1391 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1392 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1394 /* do we know where we are inside a file? */
1395 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1396 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1397 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1398 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1399 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1401 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1403 sector
= osst_get_frame_position(STp
, aSRpnt
);
1405 sector
<<= OSST_FRAME_SHIFT
;
1410 static int osst_seek_sector(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int sector
)
1412 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1413 int frame
= sector
>> OSST_FRAME_SHIFT
,
1414 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1417 char * name
= tape_name(STp
);
1419 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1420 name
, sector
, frame
, offset
);
1422 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1424 if (frame
<= STp
->first_data_ppos
) {
1425 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1426 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1428 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1429 if (r
< 0) return r
;
1431 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1432 if (r
< 0) return r
;
1434 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1437 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1438 STp
->buffer
->read_pointer
= offset
;
1439 STp
->buffer
->buffer_bytes
-= offset
;
1441 STp
->frame_seq_number
++;
1442 STp
->frame_in_buffer
= 0;
1443 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1444 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1446 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1447 if (STps
->eof
== ST_FM_HIT
) {
1449 STps
->drv_block
= 0;
1451 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1452 STp
->logical_blk_num
-
1453 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1456 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1459 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1460 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1461 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1467 * Read back the drive's internal buffer contents, as a part
1468 * of the write error recovery mechanism for old OnStream
1469 * firmware revisions.
1470 * Precondition for this function to work: all frames in the
1471 * drive's buffer must be of one type (DATA, MARK or EOD)!
1473 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1474 unsigned int frame
, unsigned int skip
, int pending
)
1476 struct osst_request
* SRpnt
= * aSRpnt
;
1477 unsigned char * buffer
, * p
;
1478 unsigned char cmd
[MAX_COMMAND_SIZE
];
1479 int flag
, new_frame
, i
;
1480 int nframes
= STp
->cur_frames
;
1481 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1482 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1483 - (nframes
+ pending
- 1);
1484 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1485 - (nframes
+ pending
- 1) * blks_per_frame
;
1486 char * name
= tape_name(STp
);
1487 unsigned long startwait
= jiffies
;
1489 int dbg
= debugging
;
1492 if ((buffer
= vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1495 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1496 name
, nframes
, pending
?" and one that was pending":"");
1498 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1500 if (pending
&& debugging
)
1501 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1502 name
, frame_seq_number
+ nframes
,
1503 logical_blk_num
+ nframes
* blks_per_frame
,
1504 p
[0], p
[1], p
[2], p
[3]);
1506 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1508 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1509 cmd
[0] = 0x3C; /* Buffer Read */
1510 cmd
[1] = 6; /* Retrieve Faulty Block */
1511 cmd
[7] = 32768 >> 8;
1512 cmd
[8] = 32768 & 0xff;
1514 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1515 STp
->timeout
, MAX_RETRIES
, 1);
1517 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1518 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1523 osst_copy_from_buffer(STp
->buffer
, p
);
1526 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1527 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1531 osst_get_frame_position(STp
, aSRpnt
);
1534 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1536 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1537 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1539 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1542 if (STp
->write_type
== OS_WRITE_HEADER
) {
1544 p
+= skip
* OS_DATA_SIZE
;
1546 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1551 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1552 name
, new_frame
+i
, frame_seq_number
+i
);
1554 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1555 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1556 osst_get_frame_position(STp
, aSRpnt
);
1559 if (new_frame
> frame
+ 1000) {
1560 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1564 if ( i
>= nframes
+ pending
) break;
1567 osst_copy_to_buffer(STp
->buffer
, p
);
1569 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1571 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1572 logical_blk_num
+ i
*blks_per_frame
,
1573 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1574 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1582 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1583 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1584 p
[0], p
[1], p
[2], p
[3]);
1586 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1587 STp
->timeout
, MAX_RETRIES
, 1);
1589 if (STp
->buffer
->syscall_result
)
1592 p
+= OS_DATA_SIZE
; i
++;
1594 /* if we just sent the last frame, wait till all successfully written */
1595 if ( i
== nframes
+ pending
) {
1597 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1599 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1600 cmd
[0] = WRITE_FILEMARKS
;
1602 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1603 STp
->timeout
, MAX_RETRIES
, 1);
1606 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1607 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1611 flag
= STp
->buffer
->syscall_result
;
1612 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1614 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1615 cmd
[0] = TEST_UNIT_READY
;
1617 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1620 if (SRpnt
->sense
[2] == 2 && SRpnt
->sense
[12] == 4 &&
1621 (SRpnt
->sense
[13] == 1 || SRpnt
->sense
[13] == 8)) {
1622 /* in the process of becoming ready */
1626 if (STp
->buffer
->syscall_result
)
1632 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1638 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1639 SRpnt
->sense
[12] == 0 &&
1640 SRpnt
->sense
[13] == 2) {
1641 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1643 return (-EIO
); /* hit end of tape = fail */
1645 i
= ((SRpnt
->sense
[3] << 24) |
1646 (SRpnt
->sense
[4] << 16) |
1647 (SRpnt
->sense
[5] << 8) |
1648 SRpnt
->sense
[6] ) - new_frame
;
1649 p
= &buffer
[i
* OS_DATA_SIZE
];
1651 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1653 osst_get_frame_position(STp
, aSRpnt
);
1655 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1656 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1661 /* error recovery did not successfully complete */
1662 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1663 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1666 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1671 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1672 unsigned int frame
, unsigned int skip
, int pending
)
1674 unsigned char cmd
[MAX_COMMAND_SIZE
];
1675 struct osst_request
* SRpnt
;
1676 char * name
= tape_name(STp
);
1678 int attempts
= 1000 / skip
;
1680 unsigned long startwait
= jiffies
;
1682 int dbg
= debugging
;
1685 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1690 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1692 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1694 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1695 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1697 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1700 schedule_timeout_interruptible(msecs_to_jiffies(100));
1702 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1704 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1705 name
, STp
->first_frame_position
,
1706 STp
->last_frame_position
, STp
->cur_frames
);
1708 frame
= STp
->last_frame_position
;
1712 if (pending
&& STp
->cur_frames
< 50) {
1714 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1719 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1720 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1722 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1723 STp
->timeout
, MAX_RETRIES
, 1);
1726 if (STp
->buffer
->syscall_result
) { /* additional write error */
1727 if ((SRpnt
->sense
[ 2] & 0x0f) == 13 &&
1728 SRpnt
->sense
[12] == 0 &&
1729 SRpnt
->sense
[13] == 2) {
1731 "%s:E: Volume overflow in write error recovery\n",
1733 break; /* hit end of tape = fail */
1742 if (STp
->cur_frames
== 0) {
1745 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1747 if (STp
->first_frame_position
!= expected
) {
1748 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1749 name
, STp
->first_frame_position
, expected
);
1756 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1757 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1761 schedule_timeout_interruptible(msecs_to_jiffies(100));
1763 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1771 * Error recovery algorithm for the OnStream tape.
1774 static int osst_write_error_recovery(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int pending
)
1776 struct osst_request
* SRpnt
= * aSRpnt
;
1777 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1778 char * name
= tape_name(STp
);
1781 unsigned int frame
, skip
;
1783 rw_state
= STps
->rw
;
1785 if ((SRpnt
->sense
[ 2] & 0x0f) != 3
1786 || SRpnt
->sense
[12] != 12
1787 || SRpnt
->sense
[13] != 0) {
1789 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1790 SRpnt
->sense
[2], SRpnt
->sense
[12], SRpnt
->sense
[13]);
1794 frame
= (SRpnt
->sense
[3] << 24) |
1795 (SRpnt
->sense
[4] << 16) |
1796 (SRpnt
->sense
[5] << 8) |
1798 skip
= SRpnt
->sense
[9];
1801 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1803 osst_get_frame_position(STp
, aSRpnt
);
1805 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1806 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1808 switch (STp
->write_type
) {
1811 case OS_WRITE_NEW_MARK
:
1813 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1814 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1815 if (STp
->os_fw_rev
>= 10600)
1816 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1818 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1819 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1821 retval
?"" :"Don't worry, ",
1822 retval
?" not ":" ");
1824 case OS_WRITE_LAST_MARK
:
1825 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1826 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1829 case OS_WRITE_HEADER
:
1830 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1831 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1834 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1835 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1837 osst_get_frame_position(STp
, aSRpnt
);
1839 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1840 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1841 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1844 STp
->recover_count
++;
1845 STp
->recover_erreg
++;
1849 STps
->rw
= rw_state
;
1853 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1854 int mt_op
, int mt_count
)
1856 char * name
= tape_name(STp
);
1858 int last_mark_ppos
= -1;
1861 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1863 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1865 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1869 if (STp
->linux_media_version
>= 4) {
1871 * direct lookup in header filemark list
1873 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1874 if (STp
->header_ok
&&
1875 STp
->header_cache
!= NULL
&&
1876 (cnt
- mt_count
) >= 0 &&
1877 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1878 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1879 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1881 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1883 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1884 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1885 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1887 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1889 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1890 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1891 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1892 mt_count
, last_mark_ppos
);
1894 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1895 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1896 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1899 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1903 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1904 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1905 name
, last_mark_ppos
);
1911 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1915 while (cnt
!= mt_count
) {
1916 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1917 if (last_mark_ppos
== -1)
1920 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1922 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1924 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1926 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1930 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1931 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1932 name
, last_mark_ppos
);
1937 if (mt_op
== MTBSFM
) {
1938 STp
->frame_seq_number
++;
1939 STp
->frame_in_buffer
= 0;
1940 STp
->buffer
->buffer_bytes
= 0;
1941 STp
->buffer
->read_pointer
= 0;
1942 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1948 * ADRL 1.1 compatible "slow" space filemarks fwd version
1950 * Just scans for the filemark sequentially.
1952 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
1953 int mt_op
, int mt_count
)
1957 char * name
= tape_name(STp
);
1959 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1961 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1963 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1968 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1970 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1974 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1976 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1978 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1980 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1982 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1983 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1985 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1989 if (cnt
== mt_count
)
1991 STp
->frame_in_buffer
= 0;
1993 if (mt_op
== MTFSF
) {
1994 STp
->frame_seq_number
++;
1995 STp
->frame_in_buffer
= 0;
1996 STp
->buffer
->buffer_bytes
= 0;
1997 STp
->buffer
->read_pointer
= 0;
1998 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2004 * Fast linux specific version of OnStream FSF
2006 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
2007 int mt_op
, int mt_count
)
2009 char * name
= tape_name(STp
);
2011 next_mark_ppos
= -1;
2014 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
2016 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2018 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
2023 if (STp
->linux_media_version
>= 4) {
2025 * direct lookup in header filemark list
2027 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
2028 if (STp
->header_ok
&&
2029 STp
->header_cache
!= NULL
&&
2030 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
2031 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
2032 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2033 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
2035 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
2037 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
2038 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
2039 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
2041 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2043 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
2044 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
2045 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
2046 mt_count
, next_mark_ppos
);
2048 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
2050 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2052 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2054 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2055 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2057 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2062 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2063 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2064 name
, next_mark_ppos
);
2067 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
2068 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
2069 name
, cnt
+mt_count
, next_mark_ppos
,
2070 ntohl(STp
->buffer
->aux
->filemark_cnt
));
2076 * Find nearest (usually previous) marker, then jump from marker to marker
2079 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
2081 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
2083 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
2087 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
2088 if (STp
->first_mark_ppos
== -1) {
2090 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2092 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
2094 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
2095 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2098 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2103 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2104 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
2105 name
, STp
->first_mark_ppos
);
2109 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
2115 while (cnt
!= mt_count
) {
2116 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
2117 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
2119 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
2121 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
2124 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
2126 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
2128 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2130 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
2135 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
2136 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2137 name
, next_mark_ppos
);
2142 if (mt_op
== MTFSF
) {
2143 STp
->frame_seq_number
++;
2144 STp
->frame_in_buffer
= 0;
2145 STp
->buffer
->buffer_bytes
= 0;
2146 STp
->buffer
->read_pointer
= 0;
2147 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2153 * In debug mode, we want to see as many errors as possible
2154 * to test the error recovery mechanism.
2157 static void osst_set_retries(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int retries
)
2159 unsigned char cmd
[MAX_COMMAND_SIZE
];
2160 struct osst_request
* SRpnt
= * aSRpnt
;
2161 char * name
= tape_name(STp
);
2163 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2164 cmd
[0] = MODE_SELECT
;
2166 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2168 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2169 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2170 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2171 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2172 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2173 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2174 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2175 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2178 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2180 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2183 if ((STp
->buffer
)->syscall_result
)
2184 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2189 static int osst_write_filemark(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2192 int this_mark_ppos
= STp
->first_frame_position
;
2193 int this_mark_lbn
= STp
->logical_blk_num
;
2195 char * name
= tape_name(STp
);
2198 if (STp
->raw
) return 0;
2200 STp
->write_type
= OS_WRITE_NEW_MARK
;
2202 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2203 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2206 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2207 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2208 STp
->last_mark_ppos
= this_mark_ppos
;
2209 STp
->last_mark_lbn
= this_mark_lbn
;
2210 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2211 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2212 if (STp
->filemark_cnt
++ == 0)
2213 STp
->first_mark_ppos
= this_mark_ppos
;
2217 static int osst_write_eod(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2221 char * name
= tape_name(STp
);
2224 if (STp
->raw
) return 0;
2226 STp
->write_type
= OS_WRITE_EOD
;
2227 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2229 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2230 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2234 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2235 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2236 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2240 static int osst_write_filler(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2242 char * name
= tape_name(STp
);
2245 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2247 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2248 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2249 STp
->write_type
= OS_WRITE_FILLER
;
2251 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2252 STp
->buffer
->buffer_bytes
= 6;
2254 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2255 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2260 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2262 return osst_flush_drive_buffer(STp
, aSRpnt
);
2265 static int __osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int where
, int count
)
2267 char * name
= tape_name(STp
);
2271 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2273 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2274 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2275 STp
->write_type
= OS_WRITE_HEADER
;
2277 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2278 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2280 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2281 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2285 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2287 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2292 static int osst_write_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int locate_eod
)
2294 os_header_t
* header
;
2296 char * name
= tape_name(STp
);
2299 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2301 if (STp
->raw
) return 0;
2303 if (STp
->header_cache
== NULL
) {
2304 if ((STp
->header_cache
= vmalloc(sizeof(os_header_t
))) == NULL
) {
2305 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2308 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2310 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2313 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2314 else STp
->update_frame_cntr
= 0;
2316 header
= STp
->header_cache
;
2317 strcpy(header
->ident_str
, "ADR_SEQ");
2318 header
->major_rev
= 1;
2319 header
->minor_rev
= 4;
2320 header
->ext_trk_tb_off
= htons(17192);
2321 header
->pt_par_num
= 1;
2322 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2323 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2324 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2325 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2326 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2327 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2328 header
->cfg_col_width
= htonl(20);
2329 header
->dat_col_width
= htonl(1500);
2330 header
->qfa_col_width
= htonl(0);
2331 header
->ext_track_tb
.nr_stream_part
= 1;
2332 header
->ext_track_tb
.et_ent_sz
= 32;
2333 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2334 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2335 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2336 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2337 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2338 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2339 header
->dat_fm_tab
.fm_part_num
= 0;
2340 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2341 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2342 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2344 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2345 if (STp
->update_frame_cntr
== 0)
2346 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2347 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2351 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2353 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2356 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2358 memcpy(STp
->application_sig
, "LIN4", 4);
2359 STp
->linux_media
= 1;
2360 STp
->linux_media_version
= 4;
2366 static int osst_reset_header(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2368 if (STp
->header_cache
!= NULL
)
2369 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2371 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2372 STp
->frame_in_buffer
= 0;
2373 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2374 STp
->filemark_cnt
= 0;
2375 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2376 return osst_write_header(STp
, aSRpnt
, 1);
2379 static int __osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int ppos
)
2381 char * name
= tape_name(STp
);
2382 os_header_t
* header
;
2385 int linux_media_version
,
2391 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2392 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2393 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2394 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2395 if (osst_initiate_read (STp
, aSRpnt
)) {
2396 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2400 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2402 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2406 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2407 aux
= STp
->buffer
->aux
;
2408 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2410 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2414 if (ntohl(aux
->frame_seq_num
) != 0 ||
2415 ntohl(aux
->logical_blk_num
) != 0 ||
2416 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2417 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2418 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2420 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2421 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2422 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2423 ntohl(aux
->partition
.last_frame_ppos
));
2427 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2428 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2429 strlcpy(id_string
, header
->ident_str
, 8);
2431 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2435 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2436 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2438 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2439 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2443 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2445 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2446 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2447 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2448 header
->major_rev
, header
->minor_rev
);
2450 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2454 if (header
->pt_par_num
!= 1)
2455 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2456 name
, header
->pt_par_num
);
2458 memcpy(id_string
, aux
->application_sig
, 4);
2460 if (memcmp(id_string
, "LIN", 3) == 0) {
2461 STp
->linux_media
= 1;
2462 linux_media_version
= id_string
[3] - '0';
2463 if (linux_media_version
!= 4)
2464 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2465 name
, linux_media_version
);
2467 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2470 if (linux_media_version
< STp
->linux_media_version
) {
2472 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2473 name
, ppos
, linux_media_version
);
2477 if (linux_media_version
> STp
->linux_media_version
) {
2479 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2480 name
, ppos
, linux_media_version
);
2482 memcpy(STp
->application_sig
, id_string
, 5);
2483 STp
->linux_media_version
= linux_media_version
;
2484 STp
->update_frame_cntr
= -1;
2486 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2488 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2489 name
, ppos
, update_frame_cntr
);
2491 if (STp
->header_cache
== NULL
) {
2492 if ((STp
->header_cache
= vmalloc(sizeof(os_header_t
))) == NULL
) {
2493 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2497 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2500 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2501 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2503 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2504 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2505 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2506 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2507 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2508 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2509 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2510 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2511 STp
->update_frame_cntr
= update_frame_cntr
;
2513 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2514 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2515 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2516 STp
->first_data_ppos
,
2517 ntohl(header
->partition
[0].last_frame_ppos
),
2518 ntohl(header
->partition
[0].eod_frame_ppos
));
2519 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2520 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2522 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2524 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2526 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2527 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2528 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2530 if (header
->minor_rev
== 4 &&
2531 (header
->ext_trk_tb_off
!= htons(17192) ||
2532 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2533 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2534 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2535 header
->cfg_col_width
!= htonl(20) ||
2536 header
->dat_col_width
!= htonl(1500) ||
2537 header
->qfa_col_width
!= htonl(0) ||
2538 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2539 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2540 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2541 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2542 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2543 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2544 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2545 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2546 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2547 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2548 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2549 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2556 static int osst_analyze_headers(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2561 char * name
= tape_name(STp
);
2563 position
= osst_get_frame_position(STp
, aSRpnt
);
2566 STp
->header_ok
= STp
->linux_media
= 1;
2567 STp
->linux_media_version
= 0;
2570 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2571 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2572 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2573 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2575 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2578 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2579 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2581 first
= position
==10?0xbae: 5;
2582 last
= position
==10?0xbb3:10;
2584 for (ppos
= first
; ppos
< last
; ppos
++)
2585 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2588 first
= position
==10? 5:0xbae;
2589 last
= position
==10?10:0xbb3;
2591 for (ppos
= first
; ppos
< last
; ppos
++)
2592 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2596 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2597 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2598 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2601 if (position
<= STp
->first_data_ppos
) {
2602 position
= STp
->first_data_ppos
;
2603 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2605 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2611 static int osst_verify_position(struct osst_tape
* STp
, struct osst_request
** aSRpnt
)
2613 int frame_position
= STp
->first_frame_position
;
2614 int frame_seq_numbr
= STp
->frame_seq_number
;
2615 int logical_blk_num
= STp
->logical_blk_num
;
2616 int halfway_frame
= STp
->frame_in_buffer
;
2617 int read_pointer
= STp
->buffer
->read_pointer
;
2618 int prev_mark_ppos
= -1;
2619 int actual_mark_ppos
, i
, n
;
2621 char * name
= tape_name(STp
);
2623 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2625 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2626 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2628 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2632 if (STp
->linux_media_version
>= 4) {
2633 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2634 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2637 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2638 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2639 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2640 if (frame_position
!= STp
->first_frame_position
||
2641 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2642 prev_mark_ppos
!= actual_mark_ppos
) {
2644 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2645 STp
->first_frame_position
, frame_position
,
2646 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2647 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2651 if (halfway_frame
) {
2652 /* prepare buffer for append and rewrite on top of original */
2653 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2654 STp
->buffer
->buffer_bytes
= read_pointer
;
2655 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2658 STp
->frame_in_buffer
= halfway_frame
;
2659 STp
->frame_seq_number
= frame_seq_numbr
;
2660 STp
->logical_blk_num
= logical_blk_num
;
2664 /* Acc. to OnStream, the vers. numbering is the following:
2665 * X.XX for released versions (X=digit),
2666 * XXXY for unreleased versions (Y=letter)
2667 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2668 * This fn makes monoton numbers out of this scheme ...
2670 static unsigned int osst_parse_firmware_rev (const char * str
)
2672 if (str
[1] == '.') {
2673 return (str
[0]-'0')*10000
2677 return (str
[0]-'0')*10000
2679 +(str
[2]-'0')*100 - 100
2685 * Configure the OnStream SCII tape drive for default operation
2687 static int osst_configure_onstream(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2689 unsigned char cmd
[MAX_COMMAND_SIZE
];
2690 char * name
= tape_name(STp
);
2691 struct osst_request
* SRpnt
= * aSRpnt
;
2692 osst_mode_parameter_header_t
* header
;
2693 osst_block_size_page_t
* bs
;
2694 osst_capabilities_page_t
* cp
;
2695 osst_tape_paramtr_page_t
* prm
;
2696 int drive_buffer_size
;
2698 if (STp
->ready
!= ST_READY
) {
2700 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2705 if (STp
->os_fw_rev
< 10600) {
2706 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2707 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2711 * Configure 32.5KB (data+aux) frame size.
2712 * Get the current frame size from the block size mode page
2714 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2715 cmd
[0] = MODE_SENSE
;
2717 cmd
[2] = BLOCK_SIZE_PAGE
;
2718 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2720 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2721 if (SRpnt
== NULL
) {
2723 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2728 if ((STp
->buffer
)->syscall_result
!= 0) {
2729 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2733 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2734 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2737 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2738 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2739 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2740 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2744 * Configure default auto columns mode, 32.5KB transfer mode
2752 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2753 cmd
[0] = MODE_SELECT
;
2755 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2757 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2759 if ((STp
->buffer
)->syscall_result
!= 0) {
2760 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2765 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2767 * In debug mode, we want to see as many errors as possible
2768 * to test the error recovery mechanism.
2770 osst_set_retries(STp
, aSRpnt
, 0);
2775 * Set vendor name to 'LIN4' for "Linux support version 4".
2778 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2779 cmd
[0] = MODE_SELECT
;
2781 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2783 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2784 header
->medium_type
= 0; /* Medium Type - ignoring */
2785 header
->dsp
= 0; /* Reserved */
2786 header
->bdl
= 0; /* Block Descriptor Length */
2788 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2789 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2790 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2791 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2792 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2793 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2794 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2795 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2797 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2800 if ((STp
->buffer
)->syscall_result
!= 0) {
2801 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2802 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2806 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2807 cmd
[0] = MODE_SENSE
;
2809 cmd
[2] = CAPABILITIES_PAGE
;
2810 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2812 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2815 if ((STp
->buffer
)->syscall_result
!= 0) {
2816 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2820 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2821 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2822 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2824 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2826 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2827 cmd
[0] = MODE_SENSE
;
2829 cmd
[2] = TAPE_PARAMTR_PAGE
;
2830 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2832 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2835 if ((STp
->buffer
)->syscall_result
!= 0) {
2836 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2840 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2841 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2842 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2844 STp
->density
= prm
->density
;
2845 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2847 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2848 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2856 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2857 it messes up the block number). */
2858 static int cross_eof(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int forward
)
2861 char * name
= tape_name(STp
);
2865 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2866 name
, forward
? "forward" : "backward");
2870 /* assumes that the filemark is already read by the drive, so this is low cost */
2871 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2874 /* assumes this is only called if we just read the filemark! */
2875 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2878 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2879 name
, forward
? "forward" : "backward");
2885 /* Get the tape position. */
2887 static int osst_get_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
2889 unsigned char scmd
[MAX_COMMAND_SIZE
];
2890 struct osst_request
* SRpnt
;
2892 char * name
= tape_name(STp
);
2894 /* KG: We want to be able to use it for checking Write Buffer availability
2895 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2897 char * olddata
= STp
->buffer
->b_data
;
2898 int oldsize
= STp
->buffer
->buffer_size
;
2900 if (STp
->ready
!= ST_READY
) return (-EIO
);
2902 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2903 scmd
[0] = READ_POSITION
;
2905 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2906 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2907 STp
->timeout
, MAX_RETRIES
, 1);
2909 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2914 if (STp
->buffer
->syscall_result
)
2915 result
= ((SRpnt
->sense
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2917 if (result
== -EINVAL
)
2918 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2920 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2921 unsigned char mysense
[16];
2922 memcpy (mysense
, SRpnt
->sense
, 16);
2923 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2924 scmd
[0] = READ_POSITION
;
2925 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2926 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2927 STp
->timeout
, MAX_RETRIES
, 1);
2929 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2930 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2931 SRpnt
->sense
[2],SRpnt
->sense
[12],SRpnt
->sense
[13]);
2933 if (!STp
->buffer
->syscall_result
)
2934 memcpy (SRpnt
->sense
, mysense
, 16);
2936 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2938 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2939 + ((STp
->buffer
)->b_data
[5] << 16)
2940 + ((STp
->buffer
)->b_data
[6] << 8)
2941 + (STp
->buffer
)->b_data
[7];
2942 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2943 + ((STp
->buffer
)->b_data
[ 9] << 16)
2944 + ((STp
->buffer
)->b_data
[10] << 8)
2945 + (STp
->buffer
)->b_data
[11];
2946 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2949 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2950 STp
->first_frame_position
, STp
->last_frame_position
,
2951 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2952 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2956 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2958 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2959 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2961 STp
->first_frame_position
= STp
->last_frame_position
;
2964 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2966 return (result
== 0 ? STp
->first_frame_position
: result
);
2970 /* Set the tape block */
2971 static int osst_set_frame_position(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int ppos
, int skip
)
2973 unsigned char scmd
[MAX_COMMAND_SIZE
];
2974 struct osst_request
* SRpnt
;
2975 struct st_partstat
* STps
;
2977 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2978 char * name
= tape_name(STp
);
2980 if (STp
->ready
!= ST_READY
) return (-EIO
);
2982 STps
= &(STp
->ps
[STp
->partition
]);
2984 if (ppos
< 0 || ppos
> STp
->capacity
) {
2985 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2986 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2993 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2995 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2998 scmd
[3] = (pp
>> 24);
2999 scmd
[4] = (pp
>> 16);
3000 scmd
[5] = (pp
>> 8);
3005 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
3011 if ((STp
->buffer
)->syscall_result
!= 0) {
3013 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
3014 name
, STp
->first_frame_position
, pp
);
3019 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
3020 } while ((pp
!= ppos
) && (pp
= ppos
));
3021 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
3022 STps
->eof
= ST_NOEOF
;
3025 STp
->frame_in_buffer
= 0;
3029 static int osst_write_trailer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
, int leave_at_EOT
)
3031 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
3034 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
3035 /* true unless the user wrote the filemark for us */
3036 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
3037 if (result
< 0) goto out
;
3038 result
= osst_write_filemark(STp
, aSRpnt
);
3039 if (result
< 0) goto out
;
3041 if (STps
->drv_file
>= 0)
3043 STps
->drv_block
= 0;
3045 result
= osst_write_eod(STp
, aSRpnt
);
3046 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
3053 /* osst versions of st functions - augmented and stripped to suit OnStream only */
3055 /* Flush the write buffer (never need to write if variable blocksize). */
3056 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct osst_request
** aSRpnt
)
3058 int offset
, transfer
, blks
= 0;
3060 unsigned char cmd
[MAX_COMMAND_SIZE
];
3061 struct osst_request
* SRpnt
= *aSRpnt
;
3062 struct st_partstat
* STps
;
3063 char * name
= tape_name(STp
);
3065 if ((STp
->buffer
)->writing
) {
3066 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
3068 { printk(OSST_DEB_MSG
3069 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name
);
3071 *aSRpnt
= SRpnt
= NULL
;
3075 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name
);
3077 osst_write_behind_check(STp
);
3078 if ((STp
->buffer
)->syscall_result
) {
3081 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
3082 name
, (STp
->buffer
)->midlevel_result
);
3084 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3091 if (STp
->dirty
== 1) {
3094 STps
= &(STp
->ps
[STp
->partition
]);
3095 STps
->rw
= ST_WRITING
;
3096 offset
= STp
->buffer
->buffer_bytes
;
3097 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
3098 transfer
= OS_FRAME_SIZE
;
3100 if (offset
< OS_DATA_SIZE
)
3101 osst_zero_buffer_tail(STp
->buffer
);
3104 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
3105 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
3107 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3112 switch (STp
->write_type
) {
3116 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3117 name
, blks
, STp
->frame_seq_number
,
3118 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3120 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3121 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3124 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
3125 STp
->logical_blk_num
, 0, 0);
3127 case OS_WRITE_NEW_MARK
:
3128 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
3129 STp
->logical_blk_num
++, 0, blks
=1);
3131 case OS_WRITE_HEADER
:
3132 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
3134 default: /* probably FILLER */
3135 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
3139 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3140 name
, offset
, transfer
, blks
);
3143 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3144 STp
->timeout
, MAX_RETRIES
, 1);
3149 if ((STp
->buffer
)->syscall_result
!= 0) {
3152 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3153 name
, SRpnt
->sense
[0], SRpnt
->sense
[2],
3154 SRpnt
->sense
[12], SRpnt
->sense
[13]);
3156 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3157 (SRpnt
->sense
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3158 (SRpnt
->sense
[2] & 0x0f) == NO_SENSE
) {
3160 (STp
->buffer
)->buffer_bytes
= 0;
3164 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3165 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3169 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3172 STp
->first_frame_position
++;
3174 (STp
->buffer
)->buffer_bytes
= 0;
3178 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3184 /* Flush the tape buffer. The tape will be positioned correctly unless
3185 seek_next is true. */
3186 static int osst_flush_buffer(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int seek_next
)
3188 struct st_partstat
* STps
;
3189 int backspace
= 0, result
= 0;
3191 char * name
= tape_name(STp
);
3195 * If there was a bus reset, block further access
3198 if( STp
->pos_unknown
)
3201 if (STp
->ready
!= ST_READY
)
3204 STps
= &(STp
->ps
[STp
->partition
]);
3205 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3206 STp
->write_type
= OS_WRITE_DATA
;
3207 return osst_flush_write_buffer(STp
, aSRpnt
);
3209 if (STp
->block_size
== 0)
3213 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3216 if (!STp
->can_bsr
) {
3217 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3218 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3219 (STp
->buffer
)->buffer_bytes
= 0;
3220 (STp
->buffer
)->read_pointer
= 0;
3221 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3225 if (STps
->eof
== ST_FM_HIT
) {
3226 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3228 STps
->eof
= ST_NOEOF
;
3230 if (STps
->drv_file
>= 0)
3232 STps
->drv_block
= 0;
3235 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3236 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3238 else if (STps
->eof
== ST_FM_HIT
) {
3239 if (STps
->drv_file
>= 0)
3241 STps
->drv_block
= 0;
3242 STps
->eof
= ST_NOEOF
;
3248 static int osst_write_frame(struct osst_tape
* STp
, struct osst_request
** aSRpnt
, int synchronous
)
3250 unsigned char cmd
[MAX_COMMAND_SIZE
];
3251 struct osst_request
* SRpnt
;
3254 char * name
= tape_name(STp
);
3257 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3259 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3261 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3264 /* error recovery may have bumped us past the header partition */
3265 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3267 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3269 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3274 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3275 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3278 // osst_build_stats(STp, &SRpnt);
3280 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3281 STp
->write_type
= OS_WRITE_DATA
;
3283 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3286 cmd
[4] = 1; /* one frame at a time... */
3287 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3290 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3291 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3293 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3294 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3298 STp
->write_pending
= 1;
3300 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3301 MAX_RETRIES
, synchronous
);
3307 if (STp
->buffer
->syscall_result
!= 0) {
3310 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3312 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
3313 (SRpnt
->sense
[2] & 0x40)) {
3314 if ((SRpnt
->sense
[2] & 0x0f) == VOLUME_OVERFLOW
)
3318 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3323 STp
->first_frame_position
++;
3331 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3332 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3337 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3340 retval
= scsi_set_medium_removal(STp
->device
,
3341 do_lock
? SCSI_REMOVAL_PREVENT
: SCSI_REMOVAL_ALLOW
);
3343 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3345 STp
->door_locked
= ST_LOCK_FAILS
;
3349 /* Set the internal state after reset */
3350 static void reset_state(struct osst_tape
*STp
)
3353 struct st_partstat
*STps
;
3355 STp
->pos_unknown
= 0;
3356 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3357 STps
= &(STp
->ps
[i
]);
3359 STps
->eof
= ST_NOEOF
;
3361 STps
->last_block_valid
= 0;
3362 STps
->drv_block
= -1;
3363 STps
->drv_file
= -1;
3368 /* Entry points to osst */
3371 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3373 ssize_t total
, retval
= 0;
3374 ssize_t i
, do_count
, blks
, transfer
;
3375 int write_threshold
;
3376 int doing_write
= 0;
3377 const char __user
* b_point
;
3378 struct osst_request
* SRpnt
= NULL
;
3379 struct st_modedef
* STm
;
3380 struct st_partstat
* STps
;
3381 struct osst_tape
* STp
= filp
->private_data
;
3382 char * name
= tape_name(STp
);
3385 if (mutex_lock_interruptible(&STp
->lock
))
3386 return (-ERESTARTSYS
);
3389 * If we are in the middle of error recovery, don't let anyone
3390 * else try and use this device. Also, if error recovery fails, it
3391 * may try and take the device offline, in which case all further
3392 * access to the device is prohibited.
3394 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3399 if (STp
->ready
!= ST_READY
) {
3400 if (STp
->ready
== ST_NO_TAPE
)
3401 retval
= (-ENOMEDIUM
);
3406 STm
= &(STp
->modes
[STp
->current_mode
]);
3407 if (!STm
->defined
) {
3415 * If there was a bus reset, block further access
3418 if (STp
->pos_unknown
) {
3425 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3431 if (STp
->write_prot
) {
3436 /* Write must be integral number of blocks */
3437 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3438 printk(KERN_ERR
"%s:E: Write (%zd bytes) not multiple of tape block size (%d%c).\n",
3439 name
, count
, STp
->block_size
<1024?
3440 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3445 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3446 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3447 name
, STp
->first_frame_position
);
3452 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3453 STp
->door_locked
= ST_LOCKED_AUTO
;
3455 STps
= &(STp
->ps
[STp
->partition
]);
3457 if (STps
->rw
== ST_READING
) {
3459 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3460 STps
->drv_file
, STps
->drv_block
);
3462 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3467 if (STps
->rw
!= ST_WRITING
) {
3468 /* Are we totally rewriting this tape? */
3469 if (!STp
->header_ok
||
3470 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3471 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3472 STp
->wrt_pass_cntr
++;
3474 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3475 name
, STp
->wrt_pass_cntr
);
3477 osst_reset_header(STp
, &SRpnt
);
3478 STps
->drv_file
= STps
->drv_block
= 0;
3480 /* Do we know where we'll be writing on the tape? */
3482 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3483 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3484 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3485 STps
->drv_file
= STp
->filemark_cnt
;
3486 STps
->drv_block
= 0;
3489 /* We have no idea where the tape is positioned - give up */
3492 "%s:D: Cannot write at indeterminate position.\n", name
);
3498 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3499 STp
->filemark_cnt
= STps
->drv_file
;
3500 STp
->last_mark_ppos
=
3501 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3503 "%s:W: Overwriting file %d with old write pass counter %d\n",
3504 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3506 "%s:W: may lead to stale data being accepted on reading back!\n",
3510 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3511 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3517 if (!STp
->header_ok
) {
3519 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3525 if ((STp
->buffer
)->writing
) {
3526 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3527 osst_write_behind_check(STp
);
3528 if ((STp
->buffer
)->syscall_result
) {
3531 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3532 (STp
->buffer
)->midlevel_result
);
3534 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3535 STps
->eof
= ST_EOM_OK
;
3537 STps
->eof
= ST_EOM_ERROR
;
3540 if (STps
->eof
== ST_EOM_OK
) {
3544 else if (STps
->eof
== ST_EOM_ERROR
) {
3549 /* Check the buffer readability in cases where copy_user might catch
3550 the problems after some tape movement. */
3551 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3552 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3557 if (!STm
->do_buffer_writes
) {
3558 write_threshold
= 1;
3561 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3562 if (!STm
->do_async_writes
)
3568 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3569 name
, (int) count
, STps
->drv_file
, STps
->drv_block
,
3570 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3573 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3576 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3577 (STp
->buffer
)->buffer_bytes
;
3578 if (do_count
> count
)
3581 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3587 blks
= do_count
/ STp
->block_size
;
3588 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3590 i
= osst_write_frame(STp
, &SRpnt
, 1);
3592 if (i
== (-ENOSPC
)) {
3593 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3594 if (transfer
<= do_count
) {
3595 *ppos
+= do_count
- transfer
;
3596 count
-= do_count
- transfer
;
3597 if (STps
->drv_block
>= 0) {
3598 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3600 STps
->eof
= ST_EOM_OK
;
3601 retval
= (-ENOSPC
); /* EOM within current request */
3604 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3605 name
, (int) transfer
);
3609 STps
->eof
= ST_EOM_ERROR
;
3610 STps
->drv_block
= (-1); /* Too cautious? */
3611 retval
= (-EIO
); /* EOM for old data */
3614 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3622 if (SRpnt
!= NULL
) {
3623 osst_release_request(SRpnt
);
3626 STp
->buffer
->buffer_bytes
= 0;
3629 retval
= total
- count
;
3634 b_point
+= do_count
;
3636 if (STps
->drv_block
>= 0) {
3637 STps
->drv_block
+= blks
;
3639 STp
->buffer
->buffer_bytes
= 0;
3641 } /* end while write threshold exceeded */
3645 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3650 blks
= count
/ STp
->block_size
;
3651 STp
->logical_blk_num
+= blks
;
3652 if (STps
->drv_block
>= 0) {
3653 STps
->drv_block
+= blks
;
3659 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3660 retval
= (STp
->buffer
)->syscall_result
;
3664 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3665 /* Schedule an asynchronous write */
3666 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3667 STp
->block_size
) * STp
->block_size
;
3668 STp
->dirty
= !((STp
->buffer
)->writing
==
3669 (STp
->buffer
)->buffer_bytes
);
3671 i
= osst_write_frame(STp
, &SRpnt
, 0);
3676 SRpnt
= NULL
; /* Prevent releasing this request! */
3678 STps
->at_sm
&= (total
== 0);
3680 STps
->eof
= ST_NOEOF
;
3685 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3687 mutex_unlock(&STp
->lock
);
3694 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3696 ssize_t total
, retval
= 0;
3697 ssize_t i
, transfer
;
3699 struct st_modedef
* STm
;
3700 struct st_partstat
* STps
;
3701 struct osst_request
* SRpnt
= NULL
;
3702 struct osst_tape
* STp
= filp
->private_data
;
3703 char * name
= tape_name(STp
);
3706 if (mutex_lock_interruptible(&STp
->lock
))
3707 return (-ERESTARTSYS
);
3710 * If we are in the middle of error recovery, don't let anyone
3711 * else try and use this device. Also, if error recovery fails, it
3712 * may try and take the device offline, in which case all further
3713 * access to the device is prohibited.
3715 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3720 if (STp
->ready
!= ST_READY
) {
3721 if (STp
->ready
== ST_NO_TAPE
)
3722 retval
= (-ENOMEDIUM
);
3727 STm
= &(STp
->modes
[STp
->current_mode
]);
3728 if (!STm
->defined
) {
3734 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3739 /* Must have initialized medium */
3740 if (!STp
->header_ok
) {
3745 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3746 STp
->door_locked
= ST_LOCKED_AUTO
;
3748 STps
= &(STp
->ps
[STp
->partition
]);
3749 if (STps
->rw
== ST_WRITING
) {
3750 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3754 /* FIXME -- this may leave the tape without EOD and up2date headers */
3757 if ((count
% STp
->block_size
) != 0) {
3759 "%s:W: Read (%zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3760 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3764 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3765 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3766 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3768 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3769 STps
->eof
>= ST_EOD_1
) {
3770 if (STps
->eof
< ST_EOD
) {
3775 retval
= (-EIO
); /* EOM or Blank Check */
3779 /* Check the buffer writability before any tape movement. Don't alter
3781 if (copy_from_user(&i
, buf
, 1) != 0 ||
3782 copy_to_user (buf
, &i
, 1) != 0 ||
3783 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3784 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3789 /* Loop until enough data in buffer or a special condition found */
3790 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3792 /* Get new data if the buffer is empty */
3793 if ((STp
->buffer
)->buffer_bytes
== 0) {
3794 if (STps
->eof
== ST_FM_HIT
)
3796 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3797 if (special
< 0) { /* No need to continue read */
3798 STp
->frame_in_buffer
= 0;
3804 /* Move the data from driver buffer to user buffer */
3805 if ((STp
->buffer
)->buffer_bytes
> 0) {
3807 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3808 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3809 STps
->eof
, (STp
->buffer
)->buffer_bytes
, (int) (count
- total
));
3811 /* force multiple of block size, note block_size may have been adjusted */
3812 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3813 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3814 STp
->block_size
) * STp
->block_size
;
3816 if (transfer
== 0) {
3818 "%s:W: Nothing can be transferred, requested %zd, tape block size (%d%c).\n",
3819 name
, count
, STp
->block_size
< 1024?
3820 STp
->block_size
:STp
->block_size
/1024,
3821 STp
->block_size
<1024?'b':'k');
3824 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3829 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3830 STps
->drv_block
+= transfer
/ STp
->block_size
;
3836 if ((STp
->buffer
)->buffer_bytes
== 0) {
3839 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3840 name
, STp
->frame_seq_number
);
3842 STp
->frame_in_buffer
= 0;
3843 STp
->frame_seq_number
++; /* frame to look for next time */
3845 } /* for (total = 0, special = 0; total < count && !special; ) */
3847 /* Change the eof state if no data from tape or buffer */
3849 if (STps
->eof
== ST_FM_HIT
) {
3850 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3851 STps
->drv_block
= 0;
3852 if (STps
->drv_file
>= 0)
3855 else if (STps
->eof
== ST_EOD_1
) {
3856 STps
->eof
= ST_EOD_2
;
3857 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3859 STps
->drv_block
= 0;
3861 else if (STps
->eof
== ST_EOD_2
)
3864 else if (STps
->eof
== ST_FM
)
3865 STps
->eof
= ST_NOEOF
;
3870 if (SRpnt
!= NULL
) osst_release_request(SRpnt
);
3872 mutex_unlock(&STp
->lock
);
3878 /* Set the driver options */
3879 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3882 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3883 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3884 STm
->do_read_ahead
);
3886 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3887 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3889 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3890 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3891 STp
->scsi2_logical
);
3893 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3896 "%s:D: debugging: %d\n",
3902 static int osst_set_options(struct osst_tape
*STp
, long options
)
3906 struct st_modedef
* STm
;
3907 char * name
= tape_name(STp
);
3909 STm
= &(STp
->modes
[STp
->current_mode
]);
3910 if (!STm
->defined
) {
3911 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3915 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3916 name
, STp
->current_mode
);
3920 code
= options
& MT_ST_OPTIONS
;
3921 if (code
== MT_ST_BOOLEANS
) {
3922 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3923 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3924 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3925 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3926 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3927 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3928 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3929 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3930 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3931 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3932 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3933 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3934 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3936 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3938 osst_log_options(STp
, STm
, name
);
3940 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3941 value
= (code
== MT_ST_SETBOOLEANS
);
3942 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3943 STm
->do_buffer_writes
= value
;
3944 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3945 STm
->do_async_writes
= value
;
3946 if ((options
& MT_ST_DEF_WRITES
) != 0)
3947 STm
->defaults_for_writes
= value
;
3948 if ((options
& MT_ST_READ_AHEAD
) != 0)
3949 STm
->do_read_ahead
= value
;
3950 if ((options
& MT_ST_TWO_FM
) != 0)
3951 STp
->two_fm
= value
;
3952 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3953 STp
->fast_mteom
= value
;
3954 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3955 STp
->do_auto_lock
= value
;
3956 if ((options
& MT_ST_CAN_BSR
) != 0)
3957 STp
->can_bsr
= value
;
3958 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3959 STp
->omit_blklims
= value
;
3960 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3961 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3962 STp
->can_partitions
= value
;
3963 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3964 STp
->scsi2_logical
= value
;
3965 if ((options
& MT_ST_SYSV
) != 0)
3968 if ((options
& MT_ST_DEBUGGING
) != 0)
3971 osst_log_options(STp
, STm
, name
);
3973 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3974 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3975 if (value
< 1 || value
> osst_buffer_size
) {
3976 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3980 STp
->write_threshold
= value
;
3981 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3984 else if (code
== MT_ST_DEF_BLKSIZE
) {
3985 value
= (options
& ~MT_ST_OPTIONS
);
3986 if (value
== ~MT_ST_OPTIONS
) {
3987 STm
->default_blksize
= (-1);
3988 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3991 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3992 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3996 STm
->default_blksize
= value
;
3997 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3998 name
, STm
->default_blksize
);
4001 else if (code
== MT_ST_TIMEOUTS
) {
4002 value
= (options
& ~MT_ST_OPTIONS
);
4003 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
4004 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
4005 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
4006 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
4009 STp
->timeout
= value
* HZ
;
4010 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
4013 else if (code
== MT_ST_DEF_OPTIONS
) {
4014 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
4015 value
= (options
& MT_ST_CLEAR_DEFAULT
);
4016 if (code
== MT_ST_DEF_DENSITY
) {
4017 if (value
== MT_ST_CLEAR_DEFAULT
) {
4018 STm
->default_density
= (-1);
4019 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
4022 STm
->default_density
= value
& 0xff;
4023 printk(KERN_INFO
"%s:I: Density default set to %x\n",
4024 name
, STm
->default_density
);
4027 else if (code
== MT_ST_DEF_DRVBUFFER
) {
4028 if (value
== MT_ST_CLEAR_DEFAULT
) {
4029 STp
->default_drvbuffer
= 0xff;
4030 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
4033 STp
->default_drvbuffer
= value
& 7;
4034 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
4035 name
, STp
->default_drvbuffer
);
4038 else if (code
== MT_ST_DEF_COMPRESSION
) {
4039 if (value
== MT_ST_CLEAR_DEFAULT
) {
4040 STm
->default_compression
= ST_DONT_TOUCH
;
4041 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
4044 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
4045 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
4057 /* Internal ioctl function */
4058 static int osst_int_ioctl(struct osst_tape
* STp
, struct osst_request
** aSRpnt
,
4059 unsigned int cmd_in
, unsigned long arg
)
4063 int i
, ioctl_result
;
4065 unsigned char cmd
[MAX_COMMAND_SIZE
];
4066 struct osst_request
* SRpnt
= * aSRpnt
;
4067 struct st_partstat
* STps
;
4068 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
4069 int datalen
= 0, direction
= DMA_NONE
;
4070 char * name
= tape_name(STp
);
4072 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
4073 if (STp
->ready
== ST_NO_TAPE
)
4074 return (-ENOMEDIUM
);
4078 timeout
= STp
->long_timeout
;
4079 STps
= &(STp
->ps
[STp
->partition
]);
4080 fileno
= STps
->drv_file
;
4081 blkno
= STps
->drv_block
;
4082 at_sm
= STps
->at_sm
;
4083 frame_seq_numbr
= STp
->frame_seq_number
;
4084 logical_blk_num
= STp
->logical_blk_num
;
4086 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4089 chg_eof
= 0; /* Changed from the FSF after this */
4093 if (STp
->linux_media
)
4094 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
4096 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
4100 at_sm
&= (arg
== 0);
4104 chg_eof
= 0; /* Changed from the FSF after this */
4108 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
4111 blkno
= (-1); /* We can't know the block number */
4112 at_sm
&= (arg
== 0);
4119 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
4120 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
4122 if (cmd_in
== MTFSR
) {
4123 logical_blk_num
+= arg
;
4124 if (blkno
>= 0) blkno
+= arg
;
4127 logical_blk_num
-= arg
;
4128 if (blkno
>= 0) blkno
-= arg
;
4130 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
4131 fileno
= STps
->drv_file
;
4132 blkno
= STps
->drv_block
;
4133 at_sm
&= (arg
== 0);
4138 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4139 cmd
[2] = (arg
>> 16);
4140 cmd
[3] = (arg
>> 8);
4144 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4145 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4148 blkno
= fileno
= (-1);
4154 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4156 cmd
[2] = (ltmp
>> 16);
4157 cmd
[3] = (ltmp
>> 8);
4163 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4164 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4169 blkno
= fileno
= (-1);
4174 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4175 STp
->write_type
= OS_WRITE_DATA
;
4176 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4181 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4183 for (i
=0; i
<arg
; i
++)
4184 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4185 if (fileno
>= 0) fileno
+= arg
;
4186 if (blkno
>= 0) blkno
= 0;
4190 if (STp
->write_prot
)
4194 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4195 if (cmd_in
== MTWSM
)
4197 cmd
[2] = (arg
>> 16);
4198 cmd
[3] = (arg
>> 8);
4200 timeout
= STp
->timeout
;
4203 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4204 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4209 at_sm
= (cmd_in
== MTWSM
);
4215 cmd
[0] = START_STOP
;
4216 cmd
[1] = 1; /* Don't wait for completion */
4217 if (cmd_in
== MTLOAD
) {
4218 if (STp
->ready
== ST_NO_TAPE
)
4219 cmd
[4] = 4; /* open tray */
4221 cmd
[4] = 1; /* load */
4223 if (cmd_in
== MTRETEN
)
4224 cmd
[4] = 3; /* retension then mount */
4225 if (cmd_in
== MTOFFL
)
4226 cmd
[4] = 4; /* rewind then eject */
4227 timeout
= STp
->timeout
;
4232 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4235 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4238 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4241 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4246 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4251 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4253 return 0; /* Should do something ? */
4258 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4260 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4261 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4262 ioctl_result
= -EIO
;
4265 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4267 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4269 ioctl_result
= -EIO
;
4272 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4273 fileno
= STp
->filemark_cnt
;
4278 if (STp
->write_prot
)
4280 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4281 i
= osst_write_eod(STp
, &SRpnt
);
4282 if (i
< ioctl_result
) ioctl_result
= i
;
4283 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4284 if (i
< ioctl_result
) ioctl_result
= i
;
4285 fileno
= blkno
= at_sm
= 0 ;
4289 cmd
[0] = REZERO_UNIT
; /* rewind */
4293 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4295 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4298 case MTSETBLK
: /* Set block length */
4299 if ((STps
->drv_block
== 0 ) &&
4301 ((STp
->buffer
)->buffer_bytes
== 0) &&
4302 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4303 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4304 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4306 * Only allowed to change the block size if you opened the
4307 * device at the beginning of a file before writing anything.
4308 * Note, that when reading, changing block_size is futile,
4309 * as the size used when writing overrides it.
4311 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4312 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4313 name
, STp
->block_size
);
4316 case MTSETDENSITY
: /* Set tape density */
4317 case MTSETDRVBUFFER
: /* Set drive buffering */
4318 case SET_DENS_AND_BLK
: /* Set density and block size */
4320 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4321 return (-EIO
); /* Not allowed if data in buffer */
4322 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4323 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4324 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4325 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4326 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4327 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4330 return 0; /* FIXME silently ignore if block size didn't change */
4336 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4338 ioctl_result
= (STp
->buffer
)->syscall_result
;
4342 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4344 return ioctl_result
;
4347 if (!ioctl_result
) { /* SCSI command successful */
4348 STp
->frame_seq_number
= frame_seq_numbr
;
4349 STp
->logical_blk_num
= logical_blk_num
;
4355 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4358 if (!ioctl_result
) { /* success */
4360 if (cmd_in
== MTFSFM
) {
4364 if (cmd_in
== MTBSFM
) {
4368 STps
->drv_block
= blkno
;
4369 STps
->drv_file
= fileno
;
4370 STps
->at_sm
= at_sm
;
4372 if (cmd_in
== MTEOM
)
4374 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4375 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4377 STp
->logical_blk_num
++;
4378 STp
->frame_seq_number
++;
4379 STp
->frame_in_buffer
= 0;
4380 STp
->buffer
->read_pointer
= 0;
4382 else if (cmd_in
== MTFSF
)
4383 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4385 STps
->eof
= ST_NOEOF
;
4387 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4388 STp
->rew_at_close
= 0;
4389 else if (cmd_in
== MTLOAD
) {
4390 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4391 STp
->ps
[i
].rw
= ST_IDLE
;
4392 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4397 if (cmd_in
== MTREW
) {
4398 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4399 if (ioctl_result
> 0)
4403 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4404 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4405 STps
->drv_file
= STps
->drv_block
= -1;
4407 STps
->drv_file
= STps
->drv_block
= 0;
4408 STps
->eof
= ST_NOEOF
;
4409 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4410 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4411 STps
->drv_file
= STps
->drv_block
= -1;
4413 STps
->drv_file
= STp
->filemark_cnt
;
4414 STps
->drv_block
= 0;
4417 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4418 STps
->drv_file
= STps
->drv_block
= (-1);
4419 STps
->eof
= ST_NOEOF
;
4421 } else if (cmd_in
== MTERASE
) {
4423 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4424 if (SRpnt
->sense
[2] & 0x40) {
4425 STps
->eof
= ST_EOM_OK
;
4426 STps
->drv_block
= 0;
4429 STps
->eof
= ST_NOEOF
;
4431 if ((SRpnt
->sense
[2] & 0x0f) == BLANK_CHECK
)
4434 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4435 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4439 return ioctl_result
;
4443 /* Open the device */
4444 static int __os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4446 unsigned short flags
;
4447 int i
, b_size
, new_session
= 0, retval
= 0;
4448 unsigned char cmd
[MAX_COMMAND_SIZE
];
4449 struct osst_request
* SRpnt
= NULL
;
4450 struct osst_tape
* STp
;
4451 struct st_modedef
* STm
;
4452 struct st_partstat
* STps
;
4454 int dev
= TAPE_NR(inode
);
4455 int mode
= TAPE_MODE(inode
);
4458 * We really want to do nonseekable_open(inode, filp); here, but some
4459 * versions of tar incorrectly call lseek on tapes and bail out if that
4460 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4462 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4464 write_lock(&os_scsi_tapes_lock
);
4465 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4466 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4467 write_unlock(&os_scsi_tapes_lock
);
4471 name
= tape_name(STp
);
4474 write_unlock(&os_scsi_tapes_lock
);
4476 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4480 if (scsi_device_get(STp
->device
)) {
4481 write_unlock(&os_scsi_tapes_lock
);
4483 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4487 filp
->private_data
= STp
;
4489 write_unlock(&os_scsi_tapes_lock
);
4490 STp
->rew_at_close
= TAPE_REWIND(inode
);
4492 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4496 if (mode
!= STp
->current_mode
) {
4499 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4500 name
, STp
->current_mode
, mode
);
4503 STp
->current_mode
= mode
;
4505 STm
= &(STp
->modes
[STp
->current_mode
]);
4507 flags
= filp
->f_flags
;
4508 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4510 STp
->raw
= TAPE_IS_RAW(inode
);
4514 /* Allocate data segments for this device's tape buffer */
4515 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4516 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4517 retval
= (-EOVERFLOW
);
4520 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4521 for (i
= 0, b_size
= 0;
4522 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4523 b_size
+= STp
->buffer
->sg
[i
++].length
);
4524 STp
->buffer
->aux
= (os_aux_t
*) (page_address(sg_page(&STp
->buffer
->sg
[i
])) + OS_DATA_SIZE
- b_size
);
4526 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4527 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4528 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4529 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4532 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4533 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4537 STp
->buffer
->writing
= 0;
4538 STp
->buffer
->syscall_result
= 0;
4540 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4541 STps
= &(STp
->ps
[i
]);
4544 STp
->ready
= ST_READY
;
4546 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4549 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4550 cmd
[0] = TEST_UNIT_READY
;
4552 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4554 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4557 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4558 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4559 SRpnt
->sense
[12] == 4 ) {
4561 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sense
[13]);
4563 if (filp
->f_flags
& O_NONBLOCK
) {
4567 if (SRpnt
->sense
[13] == 2) { /* initialize command required (LOAD) */
4568 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4569 cmd
[0] = START_STOP
;
4572 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4573 STp
->timeout
, MAX_RETRIES
, 1);
4575 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sense
[13]==1?15:3) * 60, 0);
4577 if ((SRpnt
->sense
[0] & 0x70) == 0x70 &&
4578 (SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4580 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4584 for (i
=0; i
< 10; i
++) {
4586 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4587 cmd
[0] = TEST_UNIT_READY
;
4589 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4590 STp
->timeout
, MAX_RETRIES
, 1);
4591 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4592 (SRpnt
->sense
[2] & 0x0f) != UNIT_ATTENTION
)
4596 STp
->pos_unknown
= 0;
4597 STp
->partition
= STp
->new_partition
= 0;
4598 if (STp
->can_partitions
)
4599 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4600 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4601 STps
= &(STp
->ps
[i
]);
4602 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4603 STps
->eof
= ST_NOEOF
;
4605 STps
->last_block_valid
= 0;
4606 STps
->drv_block
= 0;
4607 STps
->drv_file
= 0 ;
4610 STp
->recover_count
= 0;
4611 STp
->abort_count
= 0;
4614 * if we have valid headers from before, and the drive/tape seem untouched,
4615 * open without reconfiguring and re-reading the headers
4617 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4618 !SRpnt
->result
&& SRpnt
->sense
[0] == 0) {
4620 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4621 cmd
[0] = MODE_SENSE
;
4623 cmd
[2] = VENDOR_IDENT_PAGE
;
4624 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4626 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4628 if (STp
->buffer
->syscall_result
||
4629 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4630 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4631 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4632 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4634 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4635 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4636 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4637 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4638 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4642 i
= STp
->first_frame_position
;
4643 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4644 if (STp
->door_locked
== ST_UNLOCKED
) {
4645 if (do_door_lock(STp
, 1))
4646 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4648 STp
->door_locked
= ST_LOCKED_AUTO
;
4650 if (!STp
->frame_in_buffer
) {
4651 STp
->block_size
= (STm
->default_blksize
> 0) ?
4652 STm
->default_blksize
: OS_DATA_SIZE
;
4653 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4655 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4657 osst_release_request(SRpnt
);
4661 if (i
!= STp
->first_frame_position
)
4662 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4663 name
, i
, STp
->first_frame_position
);
4669 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4670 (SRpnt
->sense
[2] != 2 || SRpnt
->sense
[12] != 0x3A) ) {
4672 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4673 cmd
[0] = MODE_SELECT
;
4675 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4677 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4678 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4679 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4680 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4681 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4682 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4683 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4684 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4687 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4689 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4693 for (i
=0; i
< 10; i
++) {
4695 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4696 cmd
[0] = TEST_UNIT_READY
;
4698 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4699 STp
->timeout
, MAX_RETRIES
, 1);
4700 if ((SRpnt
->sense
[0] & 0x70) != 0x70 ||
4701 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
)
4704 if ((SRpnt
->sense
[2] & 0x0f) == UNIT_ATTENTION
) {
4707 STp
->pos_unknown
= 0;
4708 STp
->partition
= STp
->new_partition
= 0;
4709 if (STp
->can_partitions
)
4710 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4711 for (j
= 0; j
< ST_NBR_PARTITIONS
; j
++) {
4712 STps
= &(STp
->ps
[j
]);
4714 STps
->eof
= ST_NOEOF
;
4716 STps
->last_block_valid
= 0;
4717 STps
->drv_block
= 0;
4718 STps
->drv_file
= 0 ;
4725 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4726 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4728 if ((STp
->buffer
)->syscall_result
!= 0) {
4729 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4730 (SRpnt
->sense
[0] & 0x70) == 0x70 &&
4731 (SRpnt
->sense
[2] & 0x0f) == NOT_READY
&&
4732 SRpnt
->sense
[12] == 0x3a) { /* Check ASC */
4733 STp
->ready
= ST_NO_TAPE
;
4735 STp
->ready
= ST_NOT_READY
;
4736 osst_release_request(SRpnt
);
4738 STp
->density
= 0; /* Clear the erroneous "residue" */
4739 STp
->write_prot
= 0;
4740 STp
->block_size
= 0;
4741 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4742 STp
->partition
= STp
->new_partition
= 0;
4743 STp
->door_locked
= ST_UNLOCKED
;
4747 osst_configure_onstream(STp
, &SRpnt
);
4749 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4750 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4751 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4752 STp
->buffer
->buffer_bytes
=
4753 STp
->buffer
->read_pointer
=
4754 STp
->frame_in_buffer
= 0;
4758 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4759 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4760 (STp
->buffer
)->buffer_blocks
);
4763 if (STp
->drv_write_prot
) {
4764 STp
->write_prot
= 1;
4767 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4769 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4775 if (new_session
) { /* Change the drive parameters for the new mode */
4778 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4780 STp
->density_changed
= STp
->blksize_changed
= 0;
4781 STp
->compression_changed
= 0;
4785 * properly position the tape and check the ADR headers
4787 if (STp
->door_locked
== ST_UNLOCKED
) {
4788 if (do_door_lock(STp
, 1))
4789 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4791 STp
->door_locked
= ST_LOCKED_AUTO
;
4794 osst_analyze_headers(STp
, &SRpnt
);
4796 osst_release_request(SRpnt
);
4803 osst_release_request(SRpnt
);
4804 normalize_buffer(STp
->buffer
);
4807 scsi_device_put(STp
->device
);
4812 /* BKL pushdown: spaghetti avoidance wrapper */
4813 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4817 mutex_lock(&osst_int_mutex
);
4818 ret
= __os_scsi_tape_open(inode
, filp
);
4819 mutex_unlock(&osst_int_mutex
);
4825 /* Flush the tape buffer before close */
4826 static int os_scsi_tape_flush(struct file
* filp
, fl_owner_t id
)
4828 int result
= 0, result2
;
4829 struct osst_tape
* STp
= filp
->private_data
;
4830 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4831 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4832 struct osst_request
* SRpnt
= NULL
;
4833 char * name
= tape_name(STp
);
4835 if (file_count(filp
) > 1)
4838 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4839 STp
->write_type
= OS_WRITE_DATA
;
4840 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4841 if (result
!= 0 && result
!= (-ENOSPC
))
4844 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4848 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4849 name
, (long)(filp
->f_pos
));
4850 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4851 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4854 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4857 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4858 name
, 1+STp
->two_fm
);
4861 else if (!STp
->rew_at_close
) {
4862 STps
= &(STp
->ps
[STp
->partition
]);
4863 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4865 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4866 else if (STps
->eof
== ST_FM_HIT
) {
4867 result
= cross_eof(STp
, &SRpnt
, 0);
4869 if (STps
->drv_file
>= 0)
4871 STps
->drv_block
= 0;
4875 STps
->eof
= ST_NOEOF
;
4878 else if ((STps
->eof
== ST_NOEOF
&&
4879 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4880 STps
->eof
== ST_FM_HIT
) {
4881 if (STps
->drv_file
>= 0)
4883 STps
->drv_block
= 0;
4889 if (STp
->rew_at_close
) {
4890 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4891 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4892 if (result
== 0 && result2
< 0)
4895 if (SRpnt
) osst_release_request(SRpnt
);
4897 if (STp
->abort_count
|| STp
->recover_count
) {
4898 printk(KERN_INFO
"%s:I:", name
);
4899 if (STp
->abort_count
)
4900 printk(" %d unrecovered errors", STp
->abort_count
);
4901 if (STp
->recover_count
)
4902 printk(" %d recovered errors", STp
->recover_count
);
4903 if (STp
->write_count
)
4904 printk(" in %d frames written", STp
->write_count
);
4905 if (STp
->read_count
)
4906 printk(" in %d frames read", STp
->read_count
);
4908 STp
->recover_count
= 0;
4909 STp
->abort_count
= 0;
4911 STp
->write_count
= 0;
4912 STp
->read_count
= 0;
4918 /* Close the device and release it */
4919 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4922 struct osst_tape
* STp
= filp
->private_data
;
4924 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4925 do_door_lock(STp
, 0);
4930 normalize_buffer(STp
->buffer
);
4931 write_lock(&os_scsi_tapes_lock
);
4933 write_unlock(&os_scsi_tapes_lock
);
4935 scsi_device_put(STp
->device
);
4941 /* The ioctl command */
4942 static long osst_ioctl(struct file
* file
,
4943 unsigned int cmd_in
, unsigned long arg
)
4945 int i
, cmd_nr
, cmd_type
, blk
, retval
= 0;
4946 struct st_modedef
* STm
;
4947 struct st_partstat
* STps
;
4948 struct osst_request
* SRpnt
= NULL
;
4949 struct osst_tape
* STp
= file
->private_data
;
4950 char * name
= tape_name(STp
);
4951 void __user
* p
= (void __user
*)arg
;
4953 mutex_lock(&osst_int_mutex
);
4954 if (mutex_lock_interruptible(&STp
->lock
)) {
4955 mutex_unlock(&osst_int_mutex
);
4956 return -ERESTARTSYS
;
4960 if (debugging
&& !STp
->in_use
) {
4961 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4966 STm
= &(STp
->modes
[STp
->current_mode
]);
4967 STps
= &(STp
->ps
[STp
->partition
]);
4970 * If we are in the middle of error recovery, don't let anyone
4971 * else try and use this device. Also, if error recovery fails, it
4972 * may try and take the device offline, in which case all further
4973 * access to the device is prohibited.
4975 retval
= scsi_ioctl_block_when_processing_errors(STp
->device
, cmd_in
,
4976 file
->f_flags
& O_NDELAY
);
4980 cmd_type
= _IOC_TYPE(cmd_in
);
4981 cmd_nr
= _IOC_NR(cmd_in
);
4983 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4984 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4986 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4990 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4995 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
5001 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
5002 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
5007 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
5012 if (!STp
->pos_unknown
) {
5014 if (STps
->eof
== ST_FM_HIT
) {
5015 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
5017 if (STps
->drv_file
>= 0)
5018 STps
->drv_file
+= 1;
5020 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
5022 if (STps
->drv_file
>= 0)
5023 STps
->drv_file
+= 1;
5027 if (mtc
.mt_op
== MTSEEK
) {
5028 /* Old position must be restored if partition will be changed */
5029 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
5032 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
5033 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
5034 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
5035 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
5036 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
5037 mtc
.mt_op
== MTCOMPRESSION
;
5039 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
5047 * If there was a bus reset, block further access
5048 * to this device. If the user wants to rewind the tape,
5049 * then reset the flag and allow access again.
5051 if(mtc
.mt_op
!= MTREW
&&
5052 mtc
.mt_op
!= MTOFFL
&&
5053 mtc
.mt_op
!= MTRETEN
&&
5054 mtc
.mt_op
!= MTERASE
&&
5055 mtc
.mt_op
!= MTSEEK
&&
5056 mtc
.mt_op
!= MTEOM
) {
5061 /* remove this when the midlevel properly clears was_reset */
5062 STp
->device
->was_reset
= 0;
5065 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
5066 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
5067 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
5068 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
5069 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
5072 * The user tells us to move to another position on the tape.
5073 * If we were appending to the tape content, that would leave
5074 * the tape without proper end, in that case write EOD and
5075 * update the header to reflect its position.
5078 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
5079 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
5080 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
5081 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5083 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
5084 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
5085 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5086 i
= osst_write_trailer(STp
, &SRpnt
,
5087 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
5089 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5090 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
5091 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
5101 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
5102 do_door_lock(STp
, 0); /* Ignore result! */
5104 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
5105 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
5106 retval
= osst_set_options(STp
, mtc
.mt_count
);
5110 if (mtc
.mt_op
== MTSETPART
) {
5111 if (mtc
.mt_count
>= STp
->nbr_partitions
)
5114 STp
->new_partition
= mtc
.mt_count
;
5120 if (mtc
.mt_op
== MTMKPART
) {
5121 if (!STp
->can_partitions
) {
5125 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
5126 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5130 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5131 STp
->ps
[i
].rw
= ST_IDLE
;
5132 STp
->ps
[i
].at_sm
= 0;
5133 STp
->ps
[i
].last_block_valid
= 0;
5135 STp
->partition
= STp
->new_partition
= 0;
5136 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
5137 STps
->drv_block
= STps
->drv_file
= 0;
5142 if (mtc
.mt_op
== MTSEEK
) {
5144 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
5146 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
5147 if (!STp
->can_partitions
)
5148 STp
->ps
[0].rw
= ST_IDLE
;
5153 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
5154 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5159 cross_eof(STp
, &SRpnt
, 0);
5161 if (mtc
.mt_op
== MTCOMPRESSION
)
5162 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5164 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5165 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5166 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5170 if (!STm
->defined
) {
5175 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5180 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5181 struct mtget mt_status
;
5183 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5188 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5189 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5190 mt_status
.mt_dsreg
=
5191 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5192 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5193 mt_status
.mt_blkno
= STps
->drv_block
;
5194 mt_status
.mt_fileno
= STps
->drv_file
;
5195 if (STp
->block_size
!= 0) {
5196 if (STps
->rw
== ST_WRITING
)
5197 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5198 else if (STps
->rw
== ST_READING
)
5199 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5200 STp
->block_size
- 1) / STp
->block_size
;
5203 mt_status
.mt_gstat
= 0;
5204 if (STp
->drv_write_prot
)
5205 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5206 if (mt_status
.mt_blkno
== 0) {
5207 if (mt_status
.mt_fileno
== 0)
5208 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5210 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5212 mt_status
.mt_resid
= STp
->partition
;
5213 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5214 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5215 else if (STps
->eof
>= ST_EOM_OK
)
5216 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5217 if (STp
->density
== 1)
5218 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5219 else if (STp
->density
== 2)
5220 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5221 else if (STp
->density
== 3)
5222 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5223 if (STp
->ready
== ST_READY
)
5224 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5225 if (STp
->ready
== ST_NO_TAPE
)
5226 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5228 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5229 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5230 STp
->drv_buffer
!= 0)
5231 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5233 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5239 STp
->recover_erreg
= 0; /* Clear after read */
5242 } /* End of MTIOCGET */
5244 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5245 struct mtpos mt_pos
;
5247 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5252 blk
= osst_get_frame_position(STp
, &SRpnt
);
5254 blk
= osst_get_sector(STp
, &SRpnt
);
5259 mt_pos
.mt_blkno
= blk
;
5260 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5265 if (SRpnt
) osst_release_request(SRpnt
);
5267 mutex_unlock(&STp
->lock
);
5269 retval
= scsi_ioctl(STp
->device
, cmd_in
, p
);
5270 mutex_unlock(&osst_int_mutex
);
5274 if (SRpnt
) osst_release_request(SRpnt
);
5276 mutex_unlock(&STp
->lock
);
5277 mutex_unlock(&osst_int_mutex
);
5282 #ifdef CONFIG_COMPAT
5283 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5285 struct osst_tape
*STp
= file
->private_data
;
5286 struct scsi_device
*sdev
= STp
->device
;
5287 int ret
= -ENOIOCTLCMD
;
5288 if (sdev
->host
->hostt
->compat_ioctl
) {
5290 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5299 /* Memory handling routines */
5301 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5302 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5306 struct osst_buffer
*tb
;
5308 if (from_initialization
)
5309 priority
= GFP_ATOMIC
;
5311 priority
= GFP_KERNEL
;
5313 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5314 tb
= kzalloc(i
, priority
);
5316 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5320 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5321 tb
->use_sg
= max_sg
;
5324 tb
->buffer_size
= 0;
5328 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5329 i
, max_sg
, need_dma
);
5334 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5335 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5337 int segs
, nbr
, max_segs
, b_size
, order
, got
;
5340 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5343 if (STbuffer
->sg_segs
) {
5344 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5345 normalize_buffer(STbuffer
);
5347 /* See how many segments we can use -- need at least two */
5348 nbr
= max_segs
= STbuffer
->use_sg
;
5352 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5354 priority
|= GFP_DMA
;
5356 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5357 big enough to reach the goal (code assumes no segments in place) */
5358 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5359 struct page
*page
= alloc_pages(priority
, order
);
5361 STbuffer
->sg
[0].offset
= 0;
5363 sg_set_page(&STbuffer
->sg
[0], page
, b_size
, 0);
5364 STbuffer
->b_data
= page_address(page
);
5368 if (sg_page(&STbuffer
->sg
[0]) == NULL
) {
5369 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5372 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5373 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5374 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5375 struct page
*page
= alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5376 STbuffer
->sg
[segs
].offset
= 0;
5378 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5381 STbuffer
->buffer_size
= got
;
5383 normalize_buffer(STbuffer
);
5386 sg_set_page(&STbuffer
->sg
[segs
], page
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
, 0);
5387 got
+= STbuffer
->sg
[segs
].length
;
5388 STbuffer
->buffer_size
= got
;
5389 STbuffer
->sg_segs
= ++segs
;
5394 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5395 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5397 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5398 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5399 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5407 /* Release the segments */
5408 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5410 int i
, order
, b_size
;
5412 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5414 for (b_size
= PAGE_SIZE
, order
= 0;
5415 b_size
< STbuffer
->sg
[i
].length
;
5416 b_size
*= 2, order
++);
5418 __free_pages(sg_page(&STbuffer
->sg
[i
]), order
);
5419 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5422 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5423 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5424 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5426 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5430 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5431 negative error code. */
5432 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5434 int i
, cnt
, res
, offset
;
5436 for (i
=0, offset
=st_bp
->buffer_bytes
;
5437 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5438 offset
-= st_bp
->sg
[i
].length
;
5439 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5440 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5443 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5444 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5445 st_bp
->sg
[i
].length
- offset
: do_count
;
5446 res
= copy_from_user(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, ubp
, cnt
);
5450 st_bp
->buffer_bytes
+= cnt
;
5454 if (do_count
) { /* Should never happen */
5455 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5463 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5464 negative error code. */
5465 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5467 int i
, cnt
, res
, offset
;
5469 for (i
=0, offset
=st_bp
->read_pointer
;
5470 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5471 offset
-= st_bp
->sg
[i
].length
;
5472 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5473 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5476 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5477 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5478 st_bp
->sg
[i
].length
- offset
: do_count
;
5479 res
= copy_to_user(ubp
, page_address(sg_page(&st_bp
->sg
[i
])) + offset
, cnt
);
5483 st_bp
->buffer_bytes
-= cnt
;
5484 st_bp
->read_pointer
+= cnt
;
5488 if (do_count
) { /* Should never happen */
5489 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5495 /* Sets the tail of the buffer after fill point to zero.
5496 Returns zero (success) or negative error code. */
5497 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5499 int i
, offset
, do_count
, cnt
;
5501 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5502 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5503 offset
-= st_bp
->sg
[i
].length
;
5504 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5505 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5508 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5509 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5510 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5511 st_bp
->sg
[i
].length
- offset
: do_count
;
5512 memset(page_address(sg_page(&st_bp
->sg
[i
])) + offset
, 0, cnt
);
5516 if (do_count
) { /* Should never happen */
5517 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5523 /* Copy a osst 32K chunk of memory into the buffer.
5524 Returns zero (success) or negative error code. */
5525 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5527 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5529 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5530 cnt
= st_bp
->sg
[i
].length
< do_count
?
5531 st_bp
->sg
[i
].length
: do_count
;
5532 memcpy(page_address(sg_page(&st_bp
->sg
[i
])), ptr
, cnt
);
5536 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5537 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5544 /* Copy a osst 32K chunk of memory from the buffer.
5545 Returns zero (success) or negative error code. */
5546 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5548 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5550 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5551 cnt
= st_bp
->sg
[i
].length
< do_count
?
5552 st_bp
->sg
[i
].length
: do_count
;
5553 memcpy(ptr
, page_address(sg_page(&st_bp
->sg
[i
])), cnt
);
5557 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5558 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5566 /* Module housekeeping */
5568 static void validate_options (void)
5571 osst_max_dev
= max_dev
;
5572 if (write_threshold_kbs
> 0)
5573 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5574 if (osst_write_threshold
> osst_buffer_size
)
5575 osst_write_threshold
= osst_buffer_size
;
5576 if (max_sg_segs
>= OSST_FIRST_SG
)
5577 osst_max_sg_segs
= max_sg_segs
;
5579 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5580 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5585 /* Set the boot options. Syntax: osst=xxx,yyy,...
5586 where xxx is write threshold in 1024 byte blocks,
5587 and yyy is number of s/g segments to use. */
5588 static int __init
osst_setup (char *str
)
5593 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5596 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5597 *parms
[i
].val
= ints
[i
+ 1];
5599 while (stp
!= NULL
) {
5600 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5601 int len
= strlen(parms
[i
].name
);
5602 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5603 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5605 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5609 if (i
>= ARRAY_SIZE(parms
))
5610 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5612 stp
= strchr(stp
, ',');
5621 __setup("osst=", osst_setup
);
5625 static const struct file_operations osst_fops
= {
5626 .owner
= THIS_MODULE
,
5628 .write
= osst_write
,
5629 .unlocked_ioctl
= osst_ioctl
,
5630 #ifdef CONFIG_COMPAT
5631 .compat_ioctl
= osst_compat_ioctl
,
5633 .open
= os_scsi_tape_open
,
5634 .flush
= os_scsi_tape_flush
,
5635 .release
= os_scsi_tape_close
,
5636 .llseek
= noop_llseek
,
5639 static int osst_supports(struct scsi_device
* SDp
)
5641 struct osst_support_data
{
5645 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5648 static struct osst_support_data support_list
[] = {
5649 /* {"XXX", "Yy-", "", NULL}, example */
5653 struct osst_support_data
*rp
;
5655 /* We are willing to drive OnStream SC-x0 as well as the
5656 * * IDE, ParPort, FireWire, USB variants, if accessible by
5657 * * emulation layer (ide-scsi, usb-storage, ...) */
5659 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5660 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5661 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5662 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5668 * sysfs support for osst driver parameter information
5671 static ssize_t
osst_version_show(struct device_driver
*ddd
, char *buf
)
5673 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5676 static DRIVER_ATTR(version
, S_IRUGO
, osst_version_show
, NULL
);
5678 static int osst_create_sysfs_files(struct device_driver
*sysfs
)
5680 return driver_create_file(sysfs
, &driver_attr_version
);
5683 static void osst_remove_sysfs_files(struct device_driver
*sysfs
)
5685 driver_remove_file(sysfs
, &driver_attr_version
);
5689 * sysfs support for accessing ADR header information
5692 static ssize_t
osst_adr_rev_show(struct device
*dev
,
5693 struct device_attribute
*attr
, char *buf
)
5695 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5698 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5699 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5703 DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5705 static ssize_t
osst_linux_media_version_show(struct device
*dev
,
5706 struct device_attribute
*attr
,
5709 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5712 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5713 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5717 DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5719 static ssize_t
osst_capacity_show(struct device
*dev
,
5720 struct device_attribute
*attr
, char *buf
)
5722 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5725 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5726 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5730 DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5732 static ssize_t
osst_first_data_ppos_show(struct device
*dev
,
5733 struct device_attribute
*attr
,
5736 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5739 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5740 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5744 DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5746 static ssize_t
osst_eod_frame_ppos_show(struct device
*dev
,
5747 struct device_attribute
*attr
,
5750 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5753 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5754 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5758 DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5760 static ssize_t
osst_filemark_cnt_show(struct device
*dev
,
5761 struct device_attribute
*attr
, char *buf
)
5763 struct osst_tape
* STp
= (struct osst_tape
*) dev_get_drvdata (dev
);
5766 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5767 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5771 DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5773 static struct class *osst_sysfs_class
;
5775 static int osst_sysfs_init(void)
5777 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5778 if (IS_ERR(osst_sysfs_class
)) {
5779 printk(KERN_ERR
"osst :W: Unable to register sysfs class\n");
5780 return PTR_ERR(osst_sysfs_class
);
5786 static void osst_sysfs_destroy(dev_t dev
)
5788 device_destroy(osst_sysfs_class
, dev
);
5791 static int osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5793 struct device
*osst_member
;
5796 osst_member
= device_create(osst_sysfs_class
, device
, dev
, STp
,
5798 if (IS_ERR(osst_member
)) {
5799 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5800 return PTR_ERR(osst_member
);
5803 err
= device_create_file(osst_member
, &dev_attr_ADR_rev
);
5806 err
= device_create_file(osst_member
, &dev_attr_media_version
);
5809 err
= device_create_file(osst_member
, &dev_attr_capacity
);
5812 err
= device_create_file(osst_member
, &dev_attr_BOT_frame
);
5815 err
= device_create_file(osst_member
, &dev_attr_EOD_frame
);
5818 err
= device_create_file(osst_member
, &dev_attr_file_count
);
5825 osst_sysfs_destroy(dev
);
5829 static void osst_sysfs_cleanup(void)
5831 class_destroy(osst_sysfs_class
);
5835 * osst startup / cleanup code
5838 static int osst_probe(struct device
*dev
)
5840 struct scsi_device
* SDp
= to_scsi_device(dev
);
5841 struct osst_tape
* tpnt
;
5842 struct st_modedef
* STm
;
5843 struct st_partstat
* STps
;
5844 struct osst_buffer
* buffer
;
5845 struct gendisk
* drive
;
5846 int i
, dev_num
, err
= -ENODEV
;
5848 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5851 drive
= alloc_disk(1);
5853 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5857 /* if this is the first attach, build the infrastructure */
5858 write_lock(&os_scsi_tapes_lock
);
5859 if (os_scsi_tapes
== NULL
) {
5860 os_scsi_tapes
= kmalloc(osst_max_dev
* sizeof(struct osst_tape
*), GFP_ATOMIC
);
5861 if (os_scsi_tapes
== NULL
) {
5862 write_unlock(&os_scsi_tapes_lock
);
5863 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5866 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5869 if (osst_nr_dev
>= osst_max_dev
) {
5870 write_unlock(&os_scsi_tapes_lock
);
5871 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5875 /* find a free minor number */
5876 for (i
= 0; i
< osst_max_dev
&& os_scsi_tapes
[i
]; i
++)
5878 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5881 /* allocate a struct osst_tape for this device */
5882 tpnt
= kzalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5884 write_unlock(&os_scsi_tapes_lock
);
5885 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5889 /* allocate a buffer for this device */
5890 i
= SDp
->host
->sg_tablesize
;
5891 if (osst_max_sg_segs
< i
)
5892 i
= osst_max_sg_segs
;
5893 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5894 if (buffer
== NULL
) {
5895 write_unlock(&os_scsi_tapes_lock
);
5896 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5900 os_scsi_tapes
[dev_num
] = tpnt
;
5901 tpnt
->buffer
= buffer
;
5903 drive
->private_data
= &tpnt
->driver
;
5904 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5905 tpnt
->driver
= &osst_template
;
5906 tpnt
->drive
= drive
;
5908 tpnt
->capacity
= 0xfffff;
5910 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5911 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5913 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5914 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5915 tpnt
->can_partitions
= 0;
5916 tpnt
->two_fm
= OSST_TWO_FM
;
5917 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5918 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5919 tpnt
->write_threshold
= osst_write_threshold
;
5920 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5921 tpnt
->partition
= 0;
5922 tpnt
->new_partition
= 0;
5923 tpnt
->nbr_partitions
= 0;
5924 tpnt
->min_block
= 512;
5925 tpnt
->max_block
= OS_DATA_SIZE
;
5926 tpnt
->timeout
= OSST_TIMEOUT
;
5927 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5929 /* Recognize OnStream tapes */
5930 /* We don't need to test for OnStream, as this has been done in detect () */
5931 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5932 tpnt
->omit_blklims
= 1;
5934 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5935 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5936 tpnt
->frame_in_buffer
= 0;
5937 tpnt
->header_ok
= 0;
5938 tpnt
->linux_media
= 0;
5939 tpnt
->header_cache
= NULL
;
5941 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5942 STm
= &(tpnt
->modes
[i
]);
5944 STm
->sysv
= OSST_SYSV
;
5945 STm
->defaults_for_writes
= 0;
5946 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5947 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5948 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5949 STm
->default_compression
= ST_DONT_TOUCH
;
5950 STm
->default_blksize
= 512;
5951 STm
->default_density
= (-1); /* No forced density */
5954 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5955 STps
= &(tpnt
->ps
[i
]);
5957 STps
->eof
= ST_NOEOF
;
5959 STps
->last_block_valid
= 0;
5960 STps
->drv_block
= (-1);
5961 STps
->drv_file
= (-1);
5964 tpnt
->current_mode
= 0;
5965 tpnt
->modes
[0].defined
= 1;
5966 tpnt
->modes
[2].defined
= 1;
5967 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5969 mutex_init(&tpnt
->lock
);
5971 write_unlock(&os_scsi_tapes_lock
);
5977 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5979 goto out_free_buffer
;
5981 /* No-rewind entry */
5982 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5983 err
= osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5985 goto out_free_sysfs1
;
5988 sdev_printk(KERN_INFO
, SDp
,
5989 "osst :I: Attached OnStream %.5s tape as %s\n",
5990 SDp
->model
, tape_name(tpnt
));
5995 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, dev_num
));
6003 static int osst_remove(struct device
*dev
)
6005 struct scsi_device
* SDp
= to_scsi_device(dev
);
6006 struct osst_tape
* tpnt
;
6009 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
6012 write_lock(&os_scsi_tapes_lock
);
6013 for(i
=0; i
< osst_max_dev
; i
++) {
6014 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
6015 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
6016 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
6017 tpnt
->device
= NULL
;
6018 put_disk(tpnt
->drive
);
6019 os_scsi_tapes
[i
] = NULL
;
6021 write_unlock(&os_scsi_tapes_lock
);
6022 vfree(tpnt
->header_cache
);
6024 normalize_buffer(tpnt
->buffer
);
6025 kfree(tpnt
->buffer
);
6031 write_unlock(&os_scsi_tapes_lock
);
6035 static int __init
init_osst(void)
6039 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
6043 err
= osst_sysfs_init();
6047 err
= register_chrdev(OSST_MAJOR
, "osst", &osst_fops
);
6049 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
6053 err
= scsi_register_driver(&osst_template
.gendrv
);
6055 goto err_out_chrdev
;
6057 err
= osst_create_sysfs_files(&osst_template
.gendrv
);
6059 goto err_out_scsidrv
;
6064 scsi_unregister_driver(&osst_template
.gendrv
);
6066 unregister_chrdev(OSST_MAJOR
, "osst");
6068 osst_sysfs_cleanup();
6072 static void __exit
exit_osst (void)
6075 struct osst_tape
* STp
;
6077 osst_remove_sysfs_files(&osst_template
.gendrv
);
6078 scsi_unregister_driver(&osst_template
.gendrv
);
6079 unregister_chrdev(OSST_MAJOR
, "osst");
6080 osst_sysfs_cleanup();
6082 if (os_scsi_tapes
) {
6083 for (i
=0; i
< osst_max_dev
; ++i
) {
6084 if (!(STp
= os_scsi_tapes
[i
])) continue;
6085 /* This is defensive, supposed to happen during detach */
6086 vfree(STp
->header_cache
);
6088 normalize_buffer(STp
->buffer
);
6091 put_disk(STp
->drive
);
6094 kfree(os_scsi_tapes
);
6096 printk(KERN_INFO
"osst :I: Unloaded.\n");
6099 module_init(init_osst
);
6100 module_exit(exit_osst
);