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 - 2004 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.3";
29 /* The "failure to reconnect" firmware bug */
30 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31 #define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
34 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
41 #include <linux/init.h>
42 #include <linux/string.h>
43 #include <linux/errno.h>
44 #include <linux/mtio.h>
45 #include <linux/ioctl.h>
46 #include <linux/fcntl.h>
47 #include <linux/spinlock.h>
48 #include <linux/vmalloc.h>
49 #include <linux/blkdev.h>
50 #include <linux/moduleparam.h>
51 #include <linux/devfs_fs_kernel.h>
52 #include <linux/delay.h>
53 #include <asm/uaccess.h>
55 #include <asm/system.h>
57 /* The driver prints some debugging information on the console if DEBUG
58 is defined and non-zero. */
61 /* The message level for the debug messages is currently set to KERN_NOTICE
62 so that people can easily see the messages. Later when the debugging messages
63 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
64 #define OSST_DEB_MSG KERN_NOTICE
66 #include <scsi/scsi.h>
67 #include <scsi/scsi_dbg.h>
68 #include <scsi/scsi_device.h>
69 #include <scsi/scsi_driver.h>
70 #include <scsi/scsi_eh.h>
71 #include <scsi/scsi_host.h>
72 #include <scsi/scsi_ioctl.h>
73 #include <scsi/scsi_request.h>
75 #define ST_KILOBYTE 1024
79 #include "osst_options.h"
80 #include "osst_detect.h"
82 static int max_dev
= 0;
83 static int write_threshold_kbs
= 0;
84 static int max_sg_segs
= 0;
87 MODULE_AUTHOR("Willem Riede");
88 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
89 MODULE_LICENSE("GPL");
91 module_param(max_dev
, int, 0444);
92 MODULE_PARM_DESC(max_dev
, "Maximum number of OnStream Tape Drives to attach (4)");
94 module_param(write_threshold_kbs
, int, 0644);
95 MODULE_PARM_DESC(write_threshold_kbs
, "Asynchronous write threshold (KB; 32)");
97 module_param(max_sg_segs
, int, 0644);
98 MODULE_PARM_DESC(max_sg_segs
, "Maximum number of scatter/gather segments to use (9)");
100 static struct osst_dev_parm
{
103 } parms
[] __initdata
= {
104 { "max_dev", &max_dev
},
105 { "write_threshold_kbs", &write_threshold_kbs
},
106 { "max_sg_segs", &max_sg_segs
}
110 static char *osst_formats
[ST_NBR_MODES
] ={"", "l", "m", "a"};
112 /* Some default definitions have been moved to osst_options.h */
113 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
114 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116 /* The buffer size should fit into the 24 bits for length in the
117 6-byte SCSI read and write commands. */
118 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
119 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
123 static int debugging
= 1;
124 /* uncomment define below to test error recovery */
125 // #define OSST_INJECT_ERRORS 1
128 /* Do not retry! The drive firmware already retries when appropriate,
129 and when it tries to tell us something, we had better listen... */
130 #define MAX_RETRIES 0
132 #define NO_TAPE NOT_READY
134 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
135 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
136 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
138 #define OSST_TIMEOUT (200 * HZ)
139 #define OSST_LONG_TIMEOUT (1800 * HZ)
141 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
142 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
143 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
144 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
146 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
148 #define SET_DENS_AND_BLK 0x10001
150 static int osst_buffer_size
= OSST_BUFFER_SIZE
;
151 static int osst_write_threshold
= OSST_WRITE_THRESHOLD
;
152 static int osst_max_sg_segs
= OSST_MAX_SG
;
153 static int osst_max_dev
= OSST_MAX_TAPES
;
154 static int osst_nr_dev
;
156 static struct osst_tape
**os_scsi_tapes
= NULL
;
157 static DEFINE_RWLOCK(os_scsi_tapes_lock
);
159 static int modes_defined
= 0;
161 static struct osst_buffer
*new_tape_buffer(int, int, int);
162 static int enlarge_buffer(struct osst_buffer
*, int);
163 static void normalize_buffer(struct osst_buffer
*);
164 static int append_to_buffer(const char __user
*, struct osst_buffer
*, int);
165 static int from_buffer(struct osst_buffer
*, char __user
*, int);
166 static int osst_zero_buffer_tail(struct osst_buffer
*);
167 static int osst_copy_to_buffer(struct osst_buffer
*, unsigned char *);
168 static int osst_copy_from_buffer(struct osst_buffer
*, unsigned char *);
170 static int osst_probe(struct device
*);
171 static int osst_remove(struct device
*);
173 static struct scsi_driver osst_template
= {
174 .owner
= THIS_MODULE
,
178 .remove
= osst_remove
,
182 static int osst_int_ioctl(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
,
183 unsigned int cmd_in
, unsigned long arg
);
185 static int osst_set_frame_position(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
, int frame
, int skip
);
187 static int osst_get_frame_position(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
);
189 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
);
191 static int osst_write_error_recovery(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int pending
);
193 static inline char *tape_name(struct osst_tape
*tape
)
195 return tape
->drive
->disk_name
;
198 /* Routines that handle the interaction with mid-layer SCSI routines */
200 /* Convert the result to success code */
201 static int osst_chk_result(struct osst_tape
* STp
, struct scsi_request
* SRpnt
)
203 char *name
= tape_name(STp
);
204 int result
= SRpnt
->sr_result
;
205 unsigned char * sense
= SRpnt
->sr_sense_buffer
, scode
;
211 sense
[0] = 0; /* We don't have sense data if this byte is zero */
214 if ((driver_byte(result
) & DRIVER_MASK
) == DRIVER_SENSE
)
215 scode
= sense
[2] & 0x0f;
217 sense
[0] = 0; /* We don't have sense data if this byte is zero */
222 printk(OSST_DEB_MSG
"%s:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
224 SRpnt
->sr_cmnd
[0], SRpnt
->sr_cmnd
[1], SRpnt
->sr_cmnd
[2],
225 SRpnt
->sr_cmnd
[3], SRpnt
->sr_cmnd
[4], SRpnt
->sr_cmnd
[5],
227 if (scode
) printk(OSST_DEB_MSG
"%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
228 name
, scode
, sense
[12], sense
[13]);
229 if (driver_byte(result
) & DRIVER_SENSE
)
230 scsi_print_req_sense("osst ", SRpnt
);
234 if (!(driver_byte(result
) & DRIVER_SENSE
) ||
235 ((sense
[0] & 0x70) == 0x70 &&
237 scode
!= RECOVERED_ERROR
&&
238 /* scode != UNIT_ATTENTION && */
239 scode
!= BLANK_CHECK
&&
240 scode
!= VOLUME_OVERFLOW
&&
241 SRpnt
->sr_cmnd
[0] != MODE_SENSE
&&
242 SRpnt
->sr_cmnd
[0] != TEST_UNIT_READY
)) { /* Abnormal conditions for tape */
243 if (driver_byte(result
) & DRIVER_SENSE
) {
244 printk(KERN_WARNING
"%s:W: Command with sense data:\n", name
);
245 scsi_print_req_sense("osst:", SRpnt
);
248 static int notyetprinted
= 1;
251 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
252 name
, result
, suggestion(result
), driver_byte(result
) & DRIVER_MASK
,
257 "%s:I: This warning may be caused by your scsi controller,\n", name
);
259 "%s:I: it has been reported with some Buslogic cards.\n", name
);
263 STp
->pos_unknown
|= STp
->device
->was_reset
;
265 if ((sense
[0] & 0x70) == 0x70 &&
266 scode
== RECOVERED_ERROR
) {
267 STp
->recover_count
++;
268 STp
->recover_erreg
++;
271 if (SRpnt
->sr_cmnd
[0] == READ_6
)
273 else if (SRpnt
->sr_cmnd
[0] == WRITE_6
)
277 printk(OSST_DEB_MSG
"%s:D: Recovered %s error (%d).\n", name
, stp
,
281 if ((sense
[2] & 0xe0) == 0)
288 /* Wakeup from interrupt */
289 static void osst_sleep_done (struct scsi_cmnd
* SCpnt
)
291 struct osst_tape
* STp
= container_of(SCpnt
->request
->rq_disk
->private_data
, struct osst_tape
, driver
);
293 if ((STp
->buffer
)->writing
&&
294 (SCpnt
->sense_buffer
[0] & 0x70) == 0x70 &&
295 (SCpnt
->sense_buffer
[2] & 0x40)) {
296 /* EOM at write-behind, has all been written? */
297 if ((SCpnt
->sense_buffer
[2] & 0x0f) == VOLUME_OVERFLOW
)
298 STp
->buffer
->midlevel_result
= SCpnt
->result
; /* Error */
300 STp
->buffer
->midlevel_result
= INT_MAX
; /* OK */
303 STp
->buffer
->midlevel_result
= SCpnt
->result
;
304 SCpnt
->request
->rq_status
= RQ_SCSI_DONE
;
305 STp
->buffer
->last_SRpnt
= SCpnt
->sc_request
;
308 STp
->write_pending
= 0;
310 complete(SCpnt
->request
->waiting
);
314 /* Do the scsi command. Waits until command performed if do_wait is true.
315 Otherwise osst_write_behind_check() is used to check that the command
317 static struct scsi_request
* osst_do_scsi(struct scsi_request
*SRpnt
, struct osst_tape
*STp
,
318 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
321 #ifdef OSST_INJECT_ERRORS
322 static int inject
= 0;
323 static int repeat
= 0;
326 if ((SRpnt
= scsi_allocate_request(STp
->device
, GFP_ATOMIC
)) == NULL
) {
327 printk(KERN_ERR
"%s:E: Can't get SCSI request.\n", tape_name(STp
));
328 if (signal_pending(current
))
329 (STp
->buffer
)->syscall_result
= (-EINTR
);
331 (STp
->buffer
)->syscall_result
= (-EBUSY
);
336 init_completion(&STp
->wait
);
337 SRpnt
->sr_use_sg
= (bytes
> (STp
->buffer
)->sg
[0].length
) ?
338 (STp
->buffer
)->use_sg
: 0;
339 if (SRpnt
->sr_use_sg
) {
340 bp
= (char *)&(STp
->buffer
->sg
[0]);
341 if (STp
->buffer
->sg_segs
< SRpnt
->sr_use_sg
)
342 SRpnt
->sr_use_sg
= STp
->buffer
->sg_segs
;
345 bp
= (STp
->buffer
)->b_data
;
346 SRpnt
->sr_data_direction
= direction
;
347 SRpnt
->sr_cmd_len
= 0;
348 SRpnt
->sr_request
->waiting
= &(STp
->wait
);
349 SRpnt
->sr_request
->rq_status
= RQ_SCSI_BUSY
;
350 SRpnt
->sr_request
->rq_disk
= STp
->drive
;
352 scsi_do_req(SRpnt
, (void *)cmd
, bp
, bytes
, osst_sleep_done
, timeout
, retries
);
355 wait_for_completion(SRpnt
->sr_request
->waiting
);
356 SRpnt
->sr_request
->waiting
= NULL
;
357 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
358 #ifdef OSST_INJECT_ERRORS
359 if (STp
->buffer
->syscall_result
== 0 &&
362 ( (++ inject
% 83) == 29 ||
363 (STp
->first_frame_position
== 240
364 /* or STp->read_error_frame to fail again on the block calculated above */ &&
366 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
367 STp
->buffer
->last_result_fatal
= 1;
375 /* Handle the write-behind checking (downs the semaphore) */
376 static void osst_write_behind_check(struct osst_tape
*STp
)
378 struct osst_buffer
* STbuffer
;
380 STbuffer
= STp
->buffer
;
383 if (STp
->write_pending
)
388 wait_for_completion(&(STp
->wait
));
389 (STp
->buffer
)->last_SRpnt
->sr_request
->waiting
= NULL
;
391 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
393 if ((STp
->buffer
)->syscall_result
)
394 (STp
->buffer
)->syscall_result
=
395 osst_write_error_recovery(STp
, &((STp
->buffer
)->last_SRpnt
), 1);
397 STp
->first_frame_position
++;
399 scsi_release_request((STp
->buffer
)->last_SRpnt
);
401 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
402 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
404 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
405 STbuffer
->writing
= 0;
412 /* Onstream specific Routines */
414 * Initialize the OnStream AUX
416 static void osst_init_aux(struct osst_tape
* STp
, int frame_type
, int frame_seq_number
,
417 int logical_blk_num
, int blk_sz
, int blk_cnt
)
419 os_aux_t
*aux
= STp
->buffer
->aux
;
420 os_partition_t
*par
= &aux
->partition
;
421 os_dat_t
*dat
= &aux
->dat
;
423 if (STp
->raw
) return;
425 memset(aux
, 0, sizeof(*aux
));
426 aux
->format_id
= htonl(0);
427 memcpy(aux
->application_sig
, "LIN4", 4);
428 aux
->hdwr
= htonl(0);
429 aux
->frame_type
= frame_type
;
431 switch (frame_type
) {
432 case OS_FRAME_TYPE_HEADER
:
433 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
434 par
->partition_num
= OS_CONFIG_PARTITION
;
435 par
->par_desc_ver
= OS_PARTITION_VERSION
;
436 par
->wrt_pass_cntr
= htons(0xffff);
437 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
438 par
->first_frame_ppos
= htonl(0);
439 par
->last_frame_ppos
= htonl(0xbb7);
440 aux
->frame_seq_num
= htonl(0);
441 aux
->logical_blk_num_high
= htonl(0);
442 aux
->logical_blk_num
= htonl(0);
443 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
445 case OS_FRAME_TYPE_DATA
:
446 case OS_FRAME_TYPE_MARKER
:
451 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
452 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
453 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
454 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
455 dat
->dat_list
[0].reserved
= 0;
456 case OS_FRAME_TYPE_EOD
:
457 aux
->update_frame_cntr
= htonl(0);
458 par
->partition_num
= OS_DATA_PARTITION
;
459 par
->par_desc_ver
= OS_PARTITION_VERSION
;
460 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
461 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
462 par
->last_frame_ppos
= htonl(STp
->capacity
);
463 aux
->frame_seq_num
= htonl(frame_seq_number
);
464 aux
->logical_blk_num_high
= htonl(0);
465 aux
->logical_blk_num
= htonl(logical_blk_num
);
467 default: ; /* probably FILL */
469 aux
->filemark_cnt
= ntohl(STp
->filemark_cnt
);
470 aux
->phys_fm
= ntohl(0xffffffff);
471 aux
->last_mark_ppos
= ntohl(STp
->last_mark_ppos
);
472 aux
->last_mark_lbn
= ntohl(STp
->last_mark_lbn
);
476 * Verify that we have the correct tape frame
478 static int osst_verify_frame(struct osst_tape
* STp
, int frame_seq_number
, int quiet
)
480 char * name
= tape_name(STp
);
481 os_aux_t
* aux
= STp
->buffer
->aux
;
482 os_partition_t
* par
= &(aux
->partition
);
483 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
484 int blk_cnt
, blk_sz
, i
;
487 if (STp
->buffer
->syscall_result
) {
488 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
489 memset(page_address(STp
->buffer
->sg
[i
].page
),
490 0, STp
->buffer
->sg
[i
].length
);
491 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
493 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
496 if (STp
->buffer
->syscall_result
) {
498 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
502 if (ntohl(aux
->format_id
) != 0) {
504 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
508 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
509 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
511 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
515 if (par
->partition_num
!= OS_DATA_PARTITION
) {
516 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
518 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
519 name
, par
->partition_num
);
524 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
526 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
530 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
532 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
533 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
537 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
538 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
539 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
542 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
546 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
547 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
548 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
549 STp
->first_frame_position
);
552 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
555 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
556 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
560 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
561 STps
->eof
= ST_FM_HIT
;
563 i
= ntohl(aux
->filemark_cnt
);
564 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
565 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
567 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
568 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
569 i
, STp
->first_frame_position
- 1);
571 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
572 if (i
>= STp
->filemark_cnt
)
573 STp
->filemark_cnt
= i
+1;
576 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
577 STps
->eof
= ST_EOD_1
;
578 STp
->frame_in_buffer
= 1;
580 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
581 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
582 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
583 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
584 STp
->buffer
->read_pointer
= 0;
585 STp
->frame_in_buffer
= 1;
587 /* See what block size was used to write file */
588 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
590 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
591 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
592 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
593 STp
->block_size
<1024?'b':'k');
594 STp
->block_size
= blk_sz
;
595 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
597 STps
->eof
= ST_NOEOF
;
599 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
600 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
604 if (STp
->read_error_frame
== 0)
605 STp
->read_error_frame
= STp
->first_frame_position
- 1;
610 * Wait for the unit to become Ready
612 static int osst_wait_ready(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
613 unsigned timeout
, int initial_delay
)
615 unsigned char cmd
[MAX_COMMAND_SIZE
];
616 struct scsi_request
* SRpnt
;
617 unsigned long startwait
= jiffies
;
620 char * name
= tape_name(STp
);
622 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
625 if (initial_delay
> 0)
626 msleep(jiffies_to_msecs(initial_delay
));
628 memset(cmd
, 0, MAX_COMMAND_SIZE
);
629 cmd
[0] = TEST_UNIT_READY
;
631 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
633 if (!SRpnt
) return (-EBUSY
);
635 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
636 (( SRpnt
->sr_sense_buffer
[2] == 2 && SRpnt
->sr_sense_buffer
[12] == 4 &&
637 (SRpnt
->sr_sense_buffer
[13] == 1 || SRpnt
->sr_sense_buffer
[13] == 8) ) ||
638 ( SRpnt
->sr_sense_buffer
[2] == 6 && SRpnt
->sr_sense_buffer
[12] == 0x28 &&
639 SRpnt
->sr_sense_buffer
[13] == 0 ) )) {
642 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
643 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
649 memset(cmd
, 0, MAX_COMMAND_SIZE
);
650 cmd
[0] = TEST_UNIT_READY
;
652 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
658 if ( STp
->buffer
->syscall_result
&&
659 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
661 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
662 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
663 STp
->buffer
->syscall_result
, SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[2],
664 SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
669 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
675 * Wait for a tape to be inserted in the unit
677 static int osst_wait_for_medium(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, unsigned timeout
)
679 unsigned char cmd
[MAX_COMMAND_SIZE
];
680 struct scsi_request
* SRpnt
;
681 unsigned long startwait
= jiffies
;
684 char * name
= tape_name(STp
);
686 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
689 memset(cmd
, 0, MAX_COMMAND_SIZE
);
690 cmd
[0] = TEST_UNIT_READY
;
692 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
694 if (!SRpnt
) return (-EBUSY
);
696 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
697 SRpnt
->sr_sense_buffer
[2] == 2 && SRpnt
->sr_sense_buffer
[12] == 0x3a &&
698 SRpnt
->sr_sense_buffer
[13] == 0 ) {
701 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
702 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
708 memset(cmd
, 0, MAX_COMMAND_SIZE
);
709 cmd
[0] = TEST_UNIT_READY
;
711 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
717 if ( STp
->buffer
->syscall_result
&& SRpnt
->sr_sense_buffer
[2] != 2 &&
718 SRpnt
->sr_sense_buffer
[12] != 4 && SRpnt
->sr_sense_buffer
[13] == 1) {
720 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
721 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
722 STp
->buffer
->syscall_result
, SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[2],
723 SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
728 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
733 static int osst_position_tape_and_confirm(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int frame
)
737 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
738 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
739 if (retval
) return (retval
);
740 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
741 return (osst_get_frame_position(STp
, aSRpnt
));
745 * Wait for write(s) to complete
747 static int osst_flush_drive_buffer(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
749 unsigned char cmd
[MAX_COMMAND_SIZE
];
750 struct scsi_request
* SRpnt
;
752 int delay
= OSST_WAIT_WRITE_COMPLETE
;
754 char * name
= tape_name(STp
);
756 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
759 memset(cmd
, 0, MAX_COMMAND_SIZE
);
760 cmd
[0] = WRITE_FILEMARKS
;
763 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
765 if (!SRpnt
) return (-EBUSY
);
766 if (STp
->buffer
->syscall_result
) {
767 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == 2 && SRpnt
->sr_sense_buffer
[12] == 4) {
768 if (SRpnt
->sr_sense_buffer
[13] == 8) {
769 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
772 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
774 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
775 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
780 #define OSST_POLL_PER_SEC 10
781 static int osst_wait_frame(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int curr
, int minlast
, int to
)
783 unsigned long startwait
= jiffies
;
784 char * name
= tape_name(STp
);
786 char notyetprinted
= 1;
788 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
789 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
791 while (time_before (jiffies
, startwait
+ to
*HZ
))
794 result
= osst_get_frame_position(STp
, aSRpnt
);
796 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
797 return 0; /* successful recovery leaves drive ready for frame */
798 if (result
< 0) break;
799 if (STp
->first_frame_position
== curr
&&
801 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
802 (minlast
>= 0 && STp
->cur_frames
> minlast
)
806 if (debugging
|| jiffies
- startwait
>= 2*HZ
/OSST_POLL_PER_SEC
)
808 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
809 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
810 STp
->last_frame_position
, STp
->cur_frames
,
811 result
, (jiffies
-startwait
)/HZ
,
812 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
817 if (jiffies
- startwait
>= 2*HZ
/OSST_POLL_PER_SEC
&& notyetprinted
)
819 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
820 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
821 STp
->last_frame_position
, STp
->cur_frames
, result
);
825 msleep(1000 / OSST_POLL_PER_SEC
);
828 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
829 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
830 STp
->last_frame_position
, STp
->cur_frames
,
831 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
836 static int osst_recover_wait_frame(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int writing
)
838 struct scsi_request
* SRpnt
;
839 unsigned char cmd
[MAX_COMMAND_SIZE
];
840 unsigned long startwait
= jiffies
;
842 char * name
= tape_name(STp
);
846 char * olddata
= STp
->buffer
->b_data
;
847 int oldsize
= STp
->buffer
->buffer_size
;
849 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
851 memset(cmd
, 0, MAX_COMMAND_SIZE
);
852 cmd
[0] = WRITE_FILEMARKS
;
854 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
857 while (retval
&& time_before (jiffies
, startwait
+ 5*60*HZ
)) {
859 if (STp
->buffer
->syscall_result
&& (SRpnt
->sr_sense_buffer
[2] & 0x0f) != 2) {
861 /* some failure - not just not-ready */
862 retval
= osst_write_error_recovery(STp
, aSRpnt
, 0);
865 set_current_state(TASK_INTERRUPTIBLE
);
866 schedule_timeout (HZ
/ OSST_POLL_PER_SEC
);
868 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
869 memset(cmd
, 0, MAX_COMMAND_SIZE
);
870 cmd
[0] = READ_POSITION
;
872 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
875 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
876 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
879 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
881 /* TODO - figure out which error conditions can be handled */
882 if (STp
->buffer
->syscall_result
)
884 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
885 (*aSRpnt
)->sr_sense_buffer
[ 2] & 0x0f,
886 (*aSRpnt
)->sr_sense_buffer
[12],
887 (*aSRpnt
)->sr_sense_buffer
[13]);
893 * Read the next OnStream tape frame at the current location
895 static int osst_read_frame(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int timeout
)
897 unsigned char cmd
[MAX_COMMAND_SIZE
];
898 struct scsi_request
* SRpnt
;
901 os_aux_t
* aux
= STp
->buffer
->aux
;
902 char * name
= tape_name(STp
);
906 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
907 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
909 memset(cmd
, 0, MAX_COMMAND_SIZE
);
916 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
918 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
919 STp
->timeout
, MAX_RETRIES
, 1);
924 if ((STp
->buffer
)->syscall_result
) {
926 if (STp
->read_error_frame
== 0) {
927 STp
->read_error_frame
= STp
->first_frame_position
;
929 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
934 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
936 SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[1],
937 SRpnt
->sr_sense_buffer
[2], SRpnt
->sr_sense_buffer
[3],
938 SRpnt
->sr_sense_buffer
[4], SRpnt
->sr_sense_buffer
[5],
939 SRpnt
->sr_sense_buffer
[6], SRpnt
->sr_sense_buffer
[7]);
943 STp
->first_frame_position
++;
948 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
951 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
952 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
953 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
954 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
955 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
956 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
957 if (aux
->frame_type
==2)
958 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
959 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
960 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
966 static int osst_initiate_read(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
968 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
969 struct scsi_request
* SRpnt
;
970 unsigned char cmd
[MAX_COMMAND_SIZE
];
972 char * name
= tape_name(STp
);
974 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
975 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
976 STp
->write_type
= OS_WRITE_DATA
;
977 osst_flush_write_buffer(STp
, aSRpnt
);
978 osst_flush_drive_buffer(STp
, aSRpnt
);
980 STps
->rw
= ST_READING
;
981 STp
->frame_in_buffer
= 0;
984 * Issue a read 0 command to get the OnStream drive
985 * read frames into its buffer.
987 memset(cmd
, 0, MAX_COMMAND_SIZE
);
992 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
994 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
996 if ((retval
= STp
->buffer
->syscall_result
))
997 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1003 static int osst_get_logical_frame(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1004 int frame_seq_number
, int quiet
)
1006 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1007 char * name
= tape_name(STp
);
1015 * If we want just any frame (-1) and there is a frame in the buffer, return it
1017 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1019 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1024 * Search and wait for the next logical tape frame
1028 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1029 name
, frame_seq_number
);
1030 if (STp
->read_error_frame
) {
1031 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1033 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1034 name
, STp
->read_error_frame
);
1036 STp
->read_error_frame
= 0;
1043 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1044 name
, frame_seq_number
, cnt
);
1046 if ( osst_initiate_read(STp
, aSRpnt
)
1047 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1050 position
= osst_get_frame_position(STp
, aSRpnt
);
1051 if (position
>= 0xbae && position
< 0xbb8)
1053 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1054 position
= STp
->read_error_frame
- 1;
1062 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1065 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1068 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1070 if (osst_verify_frame(STp
, -1, quiet
)) {
1071 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1072 if (STp
->fast_open
) {
1074 "%s:W: Found logical frame %d instead of %d after fast open\n",
1075 name
, x
, frame_seq_number
);
1077 STp
->read_error_frame
= 0;
1080 if (x
> frame_seq_number
) {
1082 /* positioning backwards did not bring us to the desired frame */
1083 position
= STp
->read_error_frame
- 1;
1086 position
= osst_get_frame_position(STp
, aSRpnt
)
1087 + frame_seq_number
- x
- 1;
1089 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1094 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1095 name
, x
, frame_seq_number
,
1096 STp
->first_frame_position
- position
);
1098 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1104 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1106 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1108 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1111 STp
->frame_in_buffer
= 0;
1114 STp
->recover_count
++;
1115 STp
->recover_erreg
++;
1116 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1117 name
, STp
->read_error_frame
);
1122 if (debugging
|| STps
->eof
)
1124 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1125 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1128 STp
->read_error_frame
= 0;
1132 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int logical_blk_num
)
1134 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1135 char * name
= tape_name(STp
);
1137 int frame_seq_estimate
, ppos_estimate
, move
;
1139 if (logical_blk_num
< 0) logical_blk_num
= 0;
1141 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1142 name
, logical_blk_num
, STp
->logical_blk_num
,
1143 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1144 STp
->block_size
<1024?'b':'k');
1146 /* Do we know where we are? */
1147 if (STps
->drv_block
>= 0) {
1148 move
= logical_blk_num
- STp
->logical_blk_num
;
1149 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1150 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1151 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1153 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1155 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1156 else ppos_estimate
= frame_seq_estimate
+ 20;
1157 while (++retries
< 10) {
1158 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1159 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1160 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1162 if (frame_seq_estimate
< 0) {
1163 frame_seq_estimate
= 0;
1166 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1167 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1168 /* we've located the estimated frame, now does it have our block? */
1169 if (logical_blk_num
< STp
->logical_blk_num
||
1170 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1171 if (STps
->eof
== ST_FM_HIT
)
1172 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1174 move
= logical_blk_num
- STp
->logical_blk_num
;
1175 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1176 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1178 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1181 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1182 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1183 STp
->logical_blk_num
, logical_blk_num
, move
);
1185 frame_seq_estimate
+= move
;
1186 ppos_estimate
+= move
;
1189 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1190 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1191 STp
->logical_blk_num
= logical_blk_num
;
1194 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1195 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1196 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1199 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1200 if (STps
->eof
== ST_FM_HIT
) {
1202 STps
->drv_block
= 0;
1204 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1205 STp
->logical_blk_num
-
1206 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1209 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1213 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1215 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1217 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1218 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1219 STp
->logical_blk_num
, logical_blk_num
);
1221 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1222 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1227 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1228 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1232 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1233 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1234 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1235 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1237 #define OSST_FRAME_SHIFT 6
1238 #define OSST_SECTOR_SHIFT 9
1239 #define OSST_SECTOR_MASK 0x03F
1241 static int osst_get_sector(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
1245 char * name
= tape_name(STp
);
1248 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1249 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1250 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1251 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1252 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1253 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1255 /* do we know where we are inside a file? */
1256 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1257 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1258 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1259 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1260 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1262 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1264 sector
= osst_get_frame_position(STp
, aSRpnt
);
1266 sector
<<= OSST_FRAME_SHIFT
;
1271 static int osst_seek_sector(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int sector
)
1273 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1274 int frame
= sector
>> OSST_FRAME_SHIFT
,
1275 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1278 char * name
= tape_name(STp
);
1280 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1281 name
, sector
, frame
, offset
);
1283 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1285 if (frame
<= STp
->first_data_ppos
) {
1286 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1287 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1289 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1290 if (r
< 0) return r
;
1292 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1293 if (r
< 0) return r
;
1295 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1298 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1299 STp
->buffer
->read_pointer
= offset
;
1300 STp
->buffer
->buffer_bytes
-= offset
;
1302 STp
->frame_seq_number
++;
1303 STp
->frame_in_buffer
= 0;
1304 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1305 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1307 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1308 if (STps
->eof
== ST_FM_HIT
) {
1310 STps
->drv_block
= 0;
1312 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1313 STp
->logical_blk_num
-
1314 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1317 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1320 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1321 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1322 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1328 * Read back the drive's internal buffer contents, as a part
1329 * of the write error recovery mechanism for old OnStream
1330 * firmware revisions.
1331 * Precondition for this function to work: all frames in the
1332 * drive's buffer must be of one type (DATA, MARK or EOD)!
1334 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1335 unsigned int frame
, unsigned int skip
, int pending
)
1337 struct scsi_request
* SRpnt
= * aSRpnt
;
1338 unsigned char * buffer
, * p
;
1339 unsigned char cmd
[MAX_COMMAND_SIZE
];
1340 int flag
, new_frame
, i
;
1341 int nframes
= STp
->cur_frames
;
1342 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1343 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1344 - (nframes
+ pending
- 1);
1345 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1346 - (nframes
+ pending
- 1) * blks_per_frame
;
1347 char * name
= tape_name(STp
);
1348 unsigned long startwait
= jiffies
;
1350 int dbg
= debugging
;
1353 if ((buffer
= (unsigned char *)vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1356 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1357 name
, nframes
, pending
?" and one that was pending":"");
1359 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1361 if (pending
&& debugging
)
1362 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1363 name
, frame_seq_number
+ nframes
,
1364 logical_blk_num
+ nframes
* blks_per_frame
,
1365 p
[0], p
[1], p
[2], p
[3]);
1367 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1369 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1370 cmd
[0] = 0x3C; /* Buffer Read */
1371 cmd
[1] = 6; /* Retrieve Faulty Block */
1372 cmd
[7] = 32768 >> 8;
1373 cmd
[8] = 32768 & 0xff;
1375 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1376 STp
->timeout
, MAX_RETRIES
, 1);
1378 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1379 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1380 vfree((void *)buffer
);
1384 osst_copy_from_buffer(STp
->buffer
, p
);
1387 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1388 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1392 osst_get_frame_position(STp
, aSRpnt
);
1395 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1397 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1398 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1400 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1403 if (STp
->write_type
== OS_WRITE_HEADER
) {
1405 p
+= skip
* OS_DATA_SIZE
;
1407 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1412 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1413 name
, new_frame
+i
, frame_seq_number
+i
);
1415 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1416 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1417 osst_get_frame_position(STp
, aSRpnt
);
1420 if (new_frame
> frame
+ 1000) {
1421 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1422 vfree((void *)buffer
);
1425 if ( i
>= nframes
+ pending
) break;
1428 osst_copy_to_buffer(STp
->buffer
, p
);
1430 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1432 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1433 logical_blk_num
+ i
*blks_per_frame
,
1434 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1435 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1443 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1444 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1445 p
[0], p
[1], p
[2], p
[3]);
1447 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1448 STp
->timeout
, MAX_RETRIES
, 1);
1450 if (STp
->buffer
->syscall_result
)
1453 p
+= OS_DATA_SIZE
; i
++;
1455 /* if we just sent the last frame, wait till all successfully written */
1456 if ( i
== nframes
+ pending
) {
1458 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1460 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1461 cmd
[0] = WRITE_FILEMARKS
;
1463 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1464 STp
->timeout
, MAX_RETRIES
, 1);
1467 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1468 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1472 flag
= STp
->buffer
->syscall_result
;
1473 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1475 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1476 cmd
[0] = TEST_UNIT_READY
;
1478 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1481 if (SRpnt
->sr_sense_buffer
[2] == 2 && SRpnt
->sr_sense_buffer
[12] == 4 &&
1482 (SRpnt
->sr_sense_buffer
[13] == 1 || SRpnt
->sr_sense_buffer
[13] == 8)) {
1483 /* in the process of becoming ready */
1487 if (STp
->buffer
->syscall_result
)
1493 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1499 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) == 13 &&
1500 SRpnt
->sr_sense_buffer
[12] == 0 &&
1501 SRpnt
->sr_sense_buffer
[13] == 2) {
1502 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1503 vfree((void *)buffer
);
1504 return (-EIO
); /* hit end of tape = fail */
1506 i
= ((SRpnt
->sr_sense_buffer
[3] << 24) |
1507 (SRpnt
->sr_sense_buffer
[4] << 16) |
1508 (SRpnt
->sr_sense_buffer
[5] << 8) |
1509 SRpnt
->sr_sense_buffer
[6] ) - new_frame
;
1510 p
= &buffer
[i
* OS_DATA_SIZE
];
1512 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1514 osst_get_frame_position(STp
, aSRpnt
);
1516 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1517 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1522 /* error recovery did not successfully complete */
1523 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1524 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1527 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1528 vfree((void *)buffer
);
1532 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1533 unsigned int frame
, unsigned int skip
, int pending
)
1535 unsigned char cmd
[MAX_COMMAND_SIZE
];
1536 struct scsi_request
* SRpnt
;
1537 char * name
= tape_name(STp
);
1539 int attempts
= 1000 / skip
;
1541 unsigned long startwait
= jiffies
;
1543 int dbg
= debugging
;
1546 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1551 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1553 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1555 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1556 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1558 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1561 set_current_state(TASK_INTERRUPTIBLE
);
1562 schedule_timeout(HZ
/ 10);
1564 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1566 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1567 name
, STp
->first_frame_position
,
1568 STp
->last_frame_position
, STp
->cur_frames
);
1570 frame
= STp
->last_frame_position
;
1574 if (pending
&& STp
->cur_frames
< 50) {
1576 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1581 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1582 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1584 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1585 STp
->timeout
, MAX_RETRIES
, 1);
1588 if (STp
->buffer
->syscall_result
) { /* additional write error */
1589 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) == 13 &&
1590 SRpnt
->sr_sense_buffer
[12] == 0 &&
1591 SRpnt
->sr_sense_buffer
[13] == 2) {
1593 "%s:E: Volume overflow in write error recovery\n",
1595 break; /* hit end of tape = fail */
1604 if (STp
->cur_frames
== 0) {
1607 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1609 if (STp
->first_frame_position
!= expected
) {
1610 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1611 name
, STp
->first_frame_position
, expected
);
1618 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1619 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1623 set_current_state(TASK_INTERRUPTIBLE
);
1624 schedule_timeout(HZ
/ 10);
1626 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1634 * Error recovery algorithm for the OnStream tape.
1637 static int osst_write_error_recovery(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int pending
)
1639 struct scsi_request
* SRpnt
= * aSRpnt
;
1640 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1641 char * name
= tape_name(STp
);
1644 unsigned int frame
, skip
;
1646 rw_state
= STps
->rw
;
1648 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) != 3
1649 || SRpnt
->sr_sense_buffer
[12] != 12
1650 || SRpnt
->sr_sense_buffer
[13] != 0) {
1652 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1653 SRpnt
->sr_sense_buffer
[2], SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
1657 frame
= (SRpnt
->sr_sense_buffer
[3] << 24) |
1658 (SRpnt
->sr_sense_buffer
[4] << 16) |
1659 (SRpnt
->sr_sense_buffer
[5] << 8) |
1660 SRpnt
->sr_sense_buffer
[6];
1661 skip
= SRpnt
->sr_sense_buffer
[9];
1664 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1666 osst_get_frame_position(STp
, aSRpnt
);
1668 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1669 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1671 switch (STp
->write_type
) {
1674 case OS_WRITE_NEW_MARK
:
1676 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1677 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1678 if (STp
->os_fw_rev
>= 10600)
1679 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1681 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1682 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1684 retval
?"" :"Don't worry, ",
1685 retval
?" not ":" ");
1687 case OS_WRITE_LAST_MARK
:
1688 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1689 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1692 case OS_WRITE_HEADER
:
1693 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1694 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1697 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1698 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1700 osst_get_frame_position(STp
, aSRpnt
);
1702 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1703 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1704 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1707 STp
->recover_count
++;
1708 STp
->recover_erreg
++;
1712 STps
->rw
= rw_state
;
1716 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1717 int mt_op
, int mt_count
)
1719 char * name
= tape_name(STp
);
1721 int last_mark_ppos
= -1;
1724 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1726 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1728 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1732 if (STp
->linux_media_version
>= 4) {
1734 * direct lookup in header filemark list
1736 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1737 if (STp
->header_ok
&&
1738 STp
->header_cache
!= NULL
&&
1739 (cnt
- mt_count
) >= 0 &&
1740 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1741 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1742 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1744 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1746 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1747 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1748 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1750 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1752 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1753 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1754 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1755 mt_count
, last_mark_ppos
);
1757 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1758 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1759 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1762 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1766 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1767 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1768 name
, last_mark_ppos
);
1774 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1778 while (cnt
!= mt_count
) {
1779 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1780 if (last_mark_ppos
== -1)
1783 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1785 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1787 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1789 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1793 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1794 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1795 name
, last_mark_ppos
);
1800 if (mt_op
== MTBSFM
) {
1801 STp
->frame_seq_number
++;
1802 STp
->frame_in_buffer
= 0;
1803 STp
->buffer
->buffer_bytes
= 0;
1804 STp
->buffer
->read_pointer
= 0;
1805 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1811 * ADRL 1.1 compatible "slow" space filemarks fwd version
1813 * Just scans for the filemark sequentially.
1815 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1816 int mt_op
, int mt_count
)
1820 char * name
= tape_name(STp
);
1822 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1824 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1826 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1831 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1833 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1837 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1839 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1841 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1843 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1845 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1846 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1848 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1852 if (cnt
== mt_count
)
1854 STp
->frame_in_buffer
= 0;
1856 if (mt_op
== MTFSF
) {
1857 STp
->frame_seq_number
++;
1858 STp
->frame_in_buffer
= 0;
1859 STp
->buffer
->buffer_bytes
= 0;
1860 STp
->buffer
->read_pointer
= 0;
1861 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1867 * Fast linux specific version of OnStream FSF
1869 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1870 int mt_op
, int mt_count
)
1872 char * name
= tape_name(STp
);
1874 next_mark_ppos
= -1;
1877 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
1879 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1881 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1886 if (STp
->linux_media_version
>= 4) {
1888 * direct lookup in header filemark list
1890 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
1891 if (STp
->header_ok
&&
1892 STp
->header_cache
!= NULL
&&
1893 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
1894 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
1895 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1896 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
1898 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
1900 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
1901 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1902 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1904 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1906 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1907 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
1908 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1909 mt_count
, next_mark_ppos
);
1911 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
1913 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1915 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
1917 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
1918 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1920 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
1925 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1926 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1927 name
, next_mark_ppos
);
1930 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
1931 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
1932 name
, cnt
+mt_count
, next_mark_ppos
,
1933 ntohl(STp
->buffer
->aux
->filemark_cnt
));
1939 * Find nearest (usually previous) marker, then jump from marker to marker
1942 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1944 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1946 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1950 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
1951 if (STp
->first_mark_ppos
== -1) {
1953 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1955 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
1957 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
1958 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1961 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
1966 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1967 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
1968 name
, STp
->first_mark_ppos
);
1972 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
1978 while (cnt
!= mt_count
) {
1979 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
1980 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
1982 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1984 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
1987 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
1989 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
1991 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1993 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
1998 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1999 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
2000 name
, next_mark_ppos
);
2005 if (mt_op
== MTFSF
) {
2006 STp
->frame_seq_number
++;
2007 STp
->frame_in_buffer
= 0;
2008 STp
->buffer
->buffer_bytes
= 0;
2009 STp
->buffer
->read_pointer
= 0;
2010 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2016 * In debug mode, we want to see as many errors as possible
2017 * to test the error recovery mechanism.
2020 static void osst_set_retries(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int retries
)
2022 unsigned char cmd
[MAX_COMMAND_SIZE
];
2023 struct scsi_request
* SRpnt
= * aSRpnt
;
2024 char * name
= tape_name(STp
);
2026 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2027 cmd
[0] = MODE_SELECT
;
2029 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2031 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2032 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2033 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2034 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2035 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2036 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2037 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2038 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2041 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2043 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2046 if ((STp
->buffer
)->syscall_result
)
2047 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2052 static int osst_write_filemark(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2055 int this_mark_ppos
= STp
->first_frame_position
;
2056 int this_mark_lbn
= STp
->logical_blk_num
;
2058 char * name
= tape_name(STp
);
2061 if (STp
->raw
) return 0;
2063 STp
->write_type
= OS_WRITE_NEW_MARK
;
2065 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2066 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2069 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2070 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2071 STp
->last_mark_ppos
= this_mark_ppos
;
2072 STp
->last_mark_lbn
= this_mark_lbn
;
2073 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2074 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2075 if (STp
->filemark_cnt
++ == 0)
2076 STp
->first_mark_ppos
= this_mark_ppos
;
2080 static int osst_write_eod(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2084 char * name
= tape_name(STp
);
2087 if (STp
->raw
) return 0;
2089 STp
->write_type
= OS_WRITE_EOD
;
2090 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2092 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2093 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2097 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2098 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2099 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2103 static int osst_write_filler(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int where
, int count
)
2105 char * name
= tape_name(STp
);
2108 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2110 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2111 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2112 STp
->write_type
= OS_WRITE_FILLER
;
2114 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2115 STp
->buffer
->buffer_bytes
= 6;
2117 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2118 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2123 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2125 return osst_flush_drive_buffer(STp
, aSRpnt
);
2128 static int __osst_write_header(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int where
, int count
)
2130 char * name
= tape_name(STp
);
2134 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2136 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2137 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2138 STp
->write_type
= OS_WRITE_HEADER
;
2140 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2141 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2143 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2144 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2148 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2150 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2155 static int osst_write_header(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int locate_eod
)
2157 os_header_t
* header
;
2159 char * name
= tape_name(STp
);
2162 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2164 if (STp
->raw
) return 0;
2166 if (STp
->header_cache
== NULL
) {
2167 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2168 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2171 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2173 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2176 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2177 else STp
->update_frame_cntr
= 0;
2179 header
= STp
->header_cache
;
2180 strcpy(header
->ident_str
, "ADR_SEQ");
2181 header
->major_rev
= 1;
2182 header
->minor_rev
= 4;
2183 header
->ext_trk_tb_off
= htons(17192);
2184 header
->pt_par_num
= 1;
2185 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2186 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2187 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2188 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2189 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2190 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2191 header
->cfg_col_width
= htonl(20);
2192 header
->dat_col_width
= htonl(1500);
2193 header
->qfa_col_width
= htonl(0);
2194 header
->ext_track_tb
.nr_stream_part
= 1;
2195 header
->ext_track_tb
.et_ent_sz
= 32;
2196 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2197 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2198 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2199 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2200 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2201 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2202 header
->dat_fm_tab
.fm_part_num
= 0;
2203 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2204 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2205 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2207 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2208 if (STp
->update_frame_cntr
== 0)
2209 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2210 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2214 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2216 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2219 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2221 memcpy(STp
->application_sig
, "LIN4", 4);
2222 STp
->linux_media
= 1;
2223 STp
->linux_media_version
= 4;
2229 static int osst_reset_header(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2231 if (STp
->header_cache
!= NULL
)
2232 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2234 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2235 STp
->frame_in_buffer
= 0;
2236 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2237 STp
->filemark_cnt
= 0;
2238 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2239 return osst_write_header(STp
, aSRpnt
, 1);
2242 static int __osst_analyze_headers(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int ppos
)
2244 char * name
= tape_name(STp
);
2245 os_header_t
* header
;
2248 int linux_media_version
,
2254 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2255 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2256 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2257 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2258 if (osst_initiate_read (STp
, aSRpnt
)) {
2259 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2263 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2265 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2269 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2270 aux
= STp
->buffer
->aux
;
2271 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2273 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2277 if (ntohl(aux
->frame_seq_num
) != 0 ||
2278 ntohl(aux
->logical_blk_num
) != 0 ||
2279 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2280 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2281 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2283 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2284 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2285 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2286 ntohl(aux
->partition
.last_frame_ppos
));
2290 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2291 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2292 strlcpy(id_string
, header
->ident_str
, 8);
2294 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2298 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2299 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2301 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2302 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2306 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2308 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2309 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2310 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2311 header
->major_rev
, header
->minor_rev
);
2313 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2317 if (header
->pt_par_num
!= 1)
2318 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2319 name
, header
->pt_par_num
);
2321 memcpy(id_string
, aux
->application_sig
, 4);
2323 if (memcmp(id_string
, "LIN", 3) == 0) {
2324 STp
->linux_media
= 1;
2325 linux_media_version
= id_string
[3] - '0';
2326 if (linux_media_version
!= 4)
2327 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2328 name
, linux_media_version
);
2330 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2333 if (linux_media_version
< STp
->linux_media_version
) {
2335 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2336 name
, ppos
, linux_media_version
);
2340 if (linux_media_version
> STp
->linux_media_version
) {
2342 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2343 name
, ppos
, linux_media_version
);
2345 memcpy(STp
->application_sig
, id_string
, 5);
2346 STp
->linux_media_version
= linux_media_version
;
2347 STp
->update_frame_cntr
= -1;
2349 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2351 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2352 name
, ppos
, update_frame_cntr
);
2354 if (STp
->header_cache
== NULL
) {
2355 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2356 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2360 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2363 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2364 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2366 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2367 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2368 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2369 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2370 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2371 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2372 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2373 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2374 STp
->update_frame_cntr
= update_frame_cntr
;
2376 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2377 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2378 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2379 STp
->first_data_ppos
,
2380 ntohl(header
->partition
[0].last_frame_ppos
),
2381 ntohl(header
->partition
[0].eod_frame_ppos
));
2382 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2383 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2385 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2387 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2389 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2390 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2391 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2393 if (header
->minor_rev
== 4 &&
2394 (header
->ext_trk_tb_off
!= htons(17192) ||
2395 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2396 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2397 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2398 header
->cfg_col_width
!= htonl(20) ||
2399 header
->dat_col_width
!= htonl(1500) ||
2400 header
->qfa_col_width
!= htonl(0) ||
2401 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2402 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2403 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2404 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2405 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2406 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2407 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2408 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2409 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2410 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2411 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2412 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2419 static int osst_analyze_headers(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2424 char * name
= tape_name(STp
);
2426 position
= osst_get_frame_position(STp
, aSRpnt
);
2429 STp
->header_ok
= STp
->linux_media
= 1;
2430 STp
->linux_media_version
= 0;
2433 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2434 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2435 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2436 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2438 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2441 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2442 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2444 first
= position
==10?0xbae: 5;
2445 last
= position
==10?0xbb3:10;
2447 for (ppos
= first
; ppos
< last
; ppos
++)
2448 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2451 first
= position
==10? 5:0xbae;
2452 last
= position
==10?10:0xbb3;
2454 for (ppos
= first
; ppos
< last
; ppos
++)
2455 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2459 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2460 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2461 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2464 if (position
<= STp
->first_data_ppos
) {
2465 position
= STp
->first_data_ppos
;
2466 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2468 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2474 static int osst_verify_position(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2476 int frame_position
= STp
->first_frame_position
;
2477 int frame_seq_numbr
= STp
->frame_seq_number
;
2478 int logical_blk_num
= STp
->logical_blk_num
;
2479 int halfway_frame
= STp
->frame_in_buffer
;
2480 int read_pointer
= STp
->buffer
->read_pointer
;
2481 int prev_mark_ppos
= -1;
2482 int actual_mark_ppos
, i
, n
;
2484 char * name
= tape_name(STp
);
2486 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2488 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2489 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2491 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2495 if (STp
->linux_media_version
>= 4) {
2496 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2497 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2500 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2501 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2502 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2503 if (frame_position
!= STp
->first_frame_position
||
2504 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2505 prev_mark_ppos
!= actual_mark_ppos
) {
2507 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2508 STp
->first_frame_position
, frame_position
,
2509 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2510 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2514 if (halfway_frame
) {
2515 /* prepare buffer for append and rewrite on top of original */
2516 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2517 STp
->buffer
->buffer_bytes
= read_pointer
;
2518 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2521 STp
->frame_in_buffer
= halfway_frame
;
2522 STp
->frame_seq_number
= frame_seq_numbr
;
2523 STp
->logical_blk_num
= logical_blk_num
;
2527 /* Acc. to OnStream, the vers. numbering is the following:
2528 * X.XX for released versions (X=digit),
2529 * XXXY for unreleased versions (Y=letter)
2530 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2531 * This fn makes monoton numbers out of this scheme ...
2533 static unsigned int osst_parse_firmware_rev (const char * str
)
2535 if (str
[1] == '.') {
2536 return (str
[0]-'0')*10000
2540 return (str
[0]-'0')*10000
2542 +(str
[2]-'0')*100 - 100
2548 * Configure the OnStream SCII tape drive for default operation
2550 static int osst_configure_onstream(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
)
2552 unsigned char cmd
[MAX_COMMAND_SIZE
];
2553 char * name
= tape_name(STp
);
2554 struct scsi_request
* SRpnt
= * aSRpnt
;
2555 osst_mode_parameter_header_t
* header
;
2556 osst_block_size_page_t
* bs
;
2557 osst_capabilities_page_t
* cp
;
2558 osst_tape_paramtr_page_t
* prm
;
2559 int drive_buffer_size
;
2561 if (STp
->ready
!= ST_READY
) {
2563 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2568 if (STp
->os_fw_rev
< 10600) {
2569 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2570 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2574 * Configure 32.5KB (data+aux) frame size.
2575 * Get the current frame size from the block size mode page
2577 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2578 cmd
[0] = MODE_SENSE
;
2580 cmd
[2] = BLOCK_SIZE_PAGE
;
2581 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2583 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2584 if (SRpnt
== NULL
) {
2586 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2591 if ((STp
->buffer
)->syscall_result
!= 0) {
2592 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2596 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2597 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2600 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2601 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2602 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2603 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2607 * Configure default auto columns mode, 32.5KB transfer mode
2615 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2616 cmd
[0] = MODE_SELECT
;
2618 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2620 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2622 if ((STp
->buffer
)->syscall_result
!= 0) {
2623 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2628 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2630 * In debug mode, we want to see as many errors as possible
2631 * to test the error recovery mechanism.
2633 osst_set_retries(STp
, aSRpnt
, 0);
2638 * Set vendor name to 'LIN4' for "Linux support version 4".
2641 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2642 cmd
[0] = MODE_SELECT
;
2644 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2646 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2647 header
->medium_type
= 0; /* Medium Type - ignoring */
2648 header
->dsp
= 0; /* Reserved */
2649 header
->bdl
= 0; /* Block Descriptor Length */
2651 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2652 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2653 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2654 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2655 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2656 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2657 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2658 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2660 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2663 if ((STp
->buffer
)->syscall_result
!= 0) {
2664 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2665 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2669 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2670 cmd
[0] = MODE_SENSE
;
2672 cmd
[2] = CAPABILITIES_PAGE
;
2673 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2675 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2678 if ((STp
->buffer
)->syscall_result
!= 0) {
2679 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2683 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2684 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2685 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2687 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2689 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2690 cmd
[0] = MODE_SENSE
;
2692 cmd
[2] = TAPE_PARAMTR_PAGE
;
2693 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2695 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2698 if ((STp
->buffer
)->syscall_result
!= 0) {
2699 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2703 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2704 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2705 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2707 STp
->density
= prm
->density
;
2708 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2710 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2711 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2719 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2720 it messes up the block number). */
2721 static int cross_eof(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
, int forward
)
2724 char * name
= tape_name(STp
);
2728 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2729 name
, forward
? "forward" : "backward");
2733 /* assumes that the filemark is already read by the drive, so this is low cost */
2734 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2737 /* assumes this is only called if we just read the filemark! */
2738 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2741 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2742 name
, forward
? "forward" : "backward");
2748 /* Get the tape position. */
2750 static int osst_get_frame_position(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
)
2752 unsigned char scmd
[MAX_COMMAND_SIZE
];
2753 struct scsi_request
* SRpnt
;
2755 char * name
= tape_name(STp
);
2757 /* KG: We want to be able to use it for checking Write Buffer availability
2758 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2760 char * olddata
= STp
->buffer
->b_data
;
2761 int oldsize
= STp
->buffer
->buffer_size
;
2763 if (STp
->ready
!= ST_READY
) return (-EIO
);
2765 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2766 scmd
[0] = READ_POSITION
;
2768 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2769 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2770 STp
->timeout
, MAX_RETRIES
, 1);
2772 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2777 if (STp
->buffer
->syscall_result
)
2778 result
= ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2780 if (result
== -EINVAL
)
2781 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2783 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2784 unsigned char mysense
[16];
2785 memcpy (mysense
, SRpnt
->sr_sense_buffer
, 16);
2786 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2787 scmd
[0] = READ_POSITION
;
2788 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2789 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2790 STp
->timeout
, MAX_RETRIES
, 1);
2792 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2793 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2794 SRpnt
->sr_sense_buffer
[2],SRpnt
->sr_sense_buffer
[12],SRpnt
->sr_sense_buffer
[13]);
2796 if (!STp
->buffer
->syscall_result
)
2797 memcpy (SRpnt
->sr_sense_buffer
, mysense
, 16);
2799 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2801 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2802 + ((STp
->buffer
)->b_data
[5] << 16)
2803 + ((STp
->buffer
)->b_data
[6] << 8)
2804 + (STp
->buffer
)->b_data
[7];
2805 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2806 + ((STp
->buffer
)->b_data
[ 9] << 16)
2807 + ((STp
->buffer
)->b_data
[10] << 8)
2808 + (STp
->buffer
)->b_data
[11];
2809 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2812 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2813 STp
->first_frame_position
, STp
->last_frame_position
,
2814 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2815 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2819 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2821 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2822 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2824 STp
->first_frame_position
= STp
->last_frame_position
;
2827 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2829 return (result
== 0 ? STp
->first_frame_position
: result
);
2833 /* Set the tape block */
2834 static int osst_set_frame_position(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
, int ppos
, int skip
)
2836 unsigned char scmd
[MAX_COMMAND_SIZE
];
2837 struct scsi_request
* SRpnt
;
2838 struct st_partstat
* STps
;
2840 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2841 char * name
= tape_name(STp
);
2843 if (STp
->ready
!= ST_READY
) return (-EIO
);
2845 STps
= &(STp
->ps
[STp
->partition
]);
2847 if (ppos
< 0 || ppos
> STp
->capacity
) {
2848 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2849 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2856 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2858 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2861 scmd
[3] = (pp
>> 24);
2862 scmd
[4] = (pp
>> 16);
2863 scmd
[5] = (pp
>> 8);
2868 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
2874 if ((STp
->buffer
)->syscall_result
!= 0) {
2876 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
2877 name
, STp
->first_frame_position
, pp
);
2882 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
2883 } while ((pp
!= ppos
) && (pp
= ppos
));
2884 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
2885 STps
->eof
= ST_NOEOF
;
2888 STp
->frame_in_buffer
= 0;
2892 static int osst_write_trailer(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
, int leave_at_EOT
)
2894 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
2897 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
2898 /* true unless the user wrote the filemark for us */
2899 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2900 if (result
< 0) goto out
;
2901 result
= osst_write_filemark(STp
, aSRpnt
);
2902 if (result
< 0) goto out
;
2904 if (STps
->drv_file
>= 0)
2906 STps
->drv_block
= 0;
2908 result
= osst_write_eod(STp
, aSRpnt
);
2909 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
2916 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2918 /* Flush the write buffer (never need to write if variable blocksize). */
2919 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
)
2921 int offset
, transfer
, blks
= 0;
2923 unsigned char cmd
[MAX_COMMAND_SIZE
];
2924 struct scsi_request
* SRpnt
= *aSRpnt
;
2925 struct st_partstat
* STps
;
2926 char * name
= tape_name(STp
);
2928 if ((STp
->buffer
)->writing
) {
2929 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
2931 { printk(OSST_DEB_MSG
2932 "%s:D: aSRpnt points to scsi_request that write_behind_check will release -- cleared\n", name
);
2934 *aSRpnt
= SRpnt
= NULL
;
2938 "%s:D: aSRpnt does not point to scsi_request that write_behind_check will release -- strange\n", name
);
2940 osst_write_behind_check(STp
);
2941 if ((STp
->buffer
)->syscall_result
) {
2944 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
2945 name
, (STp
->buffer
)->midlevel_result
);
2947 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
2954 if (STp
->dirty
== 1) {
2957 STps
= &(STp
->ps
[STp
->partition
]);
2958 STps
->rw
= ST_WRITING
;
2959 offset
= STp
->buffer
->buffer_bytes
;
2960 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
2961 transfer
= OS_FRAME_SIZE
;
2963 if (offset
< OS_DATA_SIZE
)
2964 osst_zero_buffer_tail(STp
->buffer
);
2967 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
2968 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
2970 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2975 switch (STp
->write_type
) {
2979 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
2980 name
, blks
, STp
->frame_seq_number
,
2981 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
2983 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
2984 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
2987 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
2988 STp
->logical_blk_num
, 0, 0);
2990 case OS_WRITE_NEW_MARK
:
2991 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
2992 STp
->logical_blk_num
++, 0, blks
=1);
2994 case OS_WRITE_HEADER
:
2995 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
2997 default: /* probably FILLER */
2998 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
3002 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3003 name
, offset
, transfer
, blks
);
3006 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3007 STp
->timeout
, MAX_RETRIES
, 1);
3012 if ((STp
->buffer
)->syscall_result
!= 0) {
3015 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3016 name
, SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[2],
3017 SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
3019 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
3020 (SRpnt
->sr_sense_buffer
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3021 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NO_SENSE
) {
3023 (STp
->buffer
)->buffer_bytes
= 0;
3027 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3028 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3032 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3035 STp
->first_frame_position
++;
3037 (STp
->buffer
)->buffer_bytes
= 0;
3041 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3047 /* Flush the tape buffer. The tape will be positioned correctly unless
3048 seek_next is true. */
3049 static int osst_flush_buffer(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int seek_next
)
3051 struct st_partstat
* STps
;
3052 int backspace
= 0, result
= 0;
3054 char * name
= tape_name(STp
);
3058 * If there was a bus reset, block further access
3061 if( STp
->pos_unknown
)
3064 if (STp
->ready
!= ST_READY
)
3067 STps
= &(STp
->ps
[STp
->partition
]);
3068 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3069 STp
->write_type
= OS_WRITE_DATA
;
3070 return osst_flush_write_buffer(STp
, aSRpnt
);
3072 if (STp
->block_size
== 0)
3076 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3079 if (!STp
->can_bsr
) {
3080 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3081 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3082 (STp
->buffer
)->buffer_bytes
= 0;
3083 (STp
->buffer
)->read_pointer
= 0;
3084 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3088 if (STps
->eof
== ST_FM_HIT
) {
3089 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3091 STps
->eof
= ST_NOEOF
;
3093 if (STps
->drv_file
>= 0)
3095 STps
->drv_block
= 0;
3098 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3099 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3101 else if (STps
->eof
== ST_FM_HIT
) {
3102 if (STps
->drv_file
>= 0)
3104 STps
->drv_block
= 0;
3105 STps
->eof
= ST_NOEOF
;
3111 static int osst_write_frame(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int synchronous
)
3113 unsigned char cmd
[MAX_COMMAND_SIZE
];
3114 struct scsi_request
* SRpnt
;
3117 char * name
= tape_name(STp
);
3120 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3122 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3124 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3127 /* error recovery may have bumped us past the header partition */
3128 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3130 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3132 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3137 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3138 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3141 // osst_build_stats(STp, &SRpnt);
3143 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3144 STp
->write_type
= OS_WRITE_DATA
;
3146 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3149 cmd
[4] = 1; /* one frame at a time... */
3150 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3153 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3154 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3156 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3157 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3161 STp
->write_pending
= 1;
3163 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3164 MAX_RETRIES
, synchronous
);
3170 if (STp
->buffer
->syscall_result
!= 0) {
3173 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3175 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
3176 (SRpnt
->sr_sense_buffer
[2] & 0x40)) {
3177 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == VOLUME_OVERFLOW
)
3181 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3186 STp
->first_frame_position
++;
3194 /* Lock or unlock the drive door. Don't use when struct scsi_request allocated. */
3195 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3199 cmd
= do_lock
? SCSI_IOCTL_DOORLOCK
: SCSI_IOCTL_DOORUNLOCK
;
3201 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3203 retval
= scsi_ioctl(STp
->device
, cmd
, NULL
);
3205 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3208 STp
->door_locked
= ST_LOCK_FAILS
;
3213 /* Set the internal state after reset */
3214 static void reset_state(struct osst_tape
*STp
)
3217 struct st_partstat
*STps
;
3219 STp
->pos_unknown
= 0;
3220 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3221 STps
= &(STp
->ps
[i
]);
3223 STps
->eof
= ST_NOEOF
;
3225 STps
->last_block_valid
= 0;
3226 STps
->drv_block
= -1;
3227 STps
->drv_file
= -1;
3232 /* Entry points to osst */
3235 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3237 ssize_t total
, retval
= 0;
3238 ssize_t i
, do_count
, blks
, transfer
;
3239 int write_threshold
;
3240 int doing_write
= 0;
3241 const char __user
* b_point
;
3242 struct scsi_request
* SRpnt
= NULL
;
3243 struct st_modedef
* STm
;
3244 struct st_partstat
* STps
;
3245 struct osst_tape
* STp
= filp
->private_data
;
3246 char * name
= tape_name(STp
);
3249 if (down_interruptible(&STp
->lock
))
3250 return (-ERESTARTSYS
);
3253 * If we are in the middle of error recovery, don't let anyone
3254 * else try and use this device. Also, if error recovery fails, it
3255 * may try and take the device offline, in which case all further
3256 * access to the device is prohibited.
3258 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3263 if (STp
->ready
!= ST_READY
) {
3264 if (STp
->ready
== ST_NO_TAPE
)
3265 retval
= (-ENOMEDIUM
);
3270 STm
= &(STp
->modes
[STp
->current_mode
]);
3271 if (!STm
->defined
) {
3279 * If there was a bus reset, block further access
3282 if (STp
->pos_unknown
) {
3289 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3295 if (STp
->write_prot
) {
3300 /* Write must be integral number of blocks */
3301 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3302 printk(KERN_ERR
"%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3303 name
, count
, STp
->block_size
<1024?
3304 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3309 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3310 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3311 name
, STp
->first_frame_position
);
3316 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3317 STp
->door_locked
= ST_LOCKED_AUTO
;
3319 STps
= &(STp
->ps
[STp
->partition
]);
3321 if (STps
->rw
== ST_READING
) {
3323 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3324 STps
->drv_file
, STps
->drv_block
);
3326 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3331 if (STps
->rw
!= ST_WRITING
) {
3332 /* Are we totally rewriting this tape? */
3333 if (!STp
->header_ok
||
3334 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3335 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3336 STp
->wrt_pass_cntr
++;
3338 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3339 name
, STp
->wrt_pass_cntr
);
3341 osst_reset_header(STp
, &SRpnt
);
3342 STps
->drv_file
= STps
->drv_block
= 0;
3344 /* Do we know where we'll be writing on the tape? */
3346 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3347 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3348 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3349 STps
->drv_file
= STp
->filemark_cnt
;
3350 STps
->drv_block
= 0;
3353 /* We have no idea where the tape is positioned - give up */
3356 "%s:D: Cannot write at indeterminate position.\n", name
);
3362 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3363 STp
->filemark_cnt
= STps
->drv_file
;
3364 STp
->last_mark_ppos
=
3365 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3367 "%s:W: Overwriting file %d with old write pass counter %d\n",
3368 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3370 "%s:W: may lead to stale data being accepted on reading back!\n",
3374 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3375 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3381 if (!STp
->header_ok
) {
3383 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3389 if ((STp
->buffer
)->writing
) {
3390 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3391 osst_write_behind_check(STp
);
3392 if ((STp
->buffer
)->syscall_result
) {
3395 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3396 (STp
->buffer
)->midlevel_result
);
3398 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3399 STps
->eof
= ST_EOM_OK
;
3401 STps
->eof
= ST_EOM_ERROR
;
3404 if (STps
->eof
== ST_EOM_OK
) {
3408 else if (STps
->eof
== ST_EOM_ERROR
) {
3413 /* Check the buffer readability in cases where copy_user might catch
3414 the problems after some tape movement. */
3415 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3416 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3421 if (!STm
->do_buffer_writes
) {
3422 write_threshold
= 1;
3425 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3426 if (!STm
->do_async_writes
)
3432 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3433 name
, count
, STps
->drv_file
, STps
->drv_block
,
3434 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3437 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3440 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3441 (STp
->buffer
)->buffer_bytes
;
3442 if (do_count
> count
)
3445 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3451 blks
= do_count
/ STp
->block_size
;
3452 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3454 i
= osst_write_frame(STp
, &SRpnt
, 1);
3456 if (i
== (-ENOSPC
)) {
3457 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3458 if (transfer
<= do_count
) {
3459 filp
->f_pos
+= do_count
- transfer
;
3460 count
-= do_count
- transfer
;
3461 if (STps
->drv_block
>= 0) {
3462 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3464 STps
->eof
= ST_EOM_OK
;
3465 retval
= (-ENOSPC
); /* EOM within current request */
3468 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3473 STps
->eof
= ST_EOM_ERROR
;
3474 STps
->drv_block
= (-1); /* Too cautious? */
3475 retval
= (-EIO
); /* EOM for old data */
3478 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3486 if (SRpnt
!= NULL
) {
3487 scsi_release_request(SRpnt
);
3490 STp
->buffer
->buffer_bytes
= 0;
3493 retval
= total
- count
;
3497 filp
->f_pos
+= do_count
;
3498 b_point
+= do_count
;
3500 if (STps
->drv_block
>= 0) {
3501 STps
->drv_block
+= blks
;
3503 STp
->buffer
->buffer_bytes
= 0;
3505 } /* end while write threshold exceeded */
3509 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3514 blks
= count
/ STp
->block_size
;
3515 STp
->logical_blk_num
+= blks
;
3516 if (STps
->drv_block
>= 0) {
3517 STps
->drv_block
+= blks
;
3519 filp
->f_pos
+= count
;
3523 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3524 retval
= (STp
->buffer
)->syscall_result
;
3528 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3529 /* Schedule an asynchronous write */
3530 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3531 STp
->block_size
) * STp
->block_size
;
3532 STp
->dirty
= !((STp
->buffer
)->writing
==
3533 (STp
->buffer
)->buffer_bytes
);
3535 i
= osst_write_frame(STp
, &SRpnt
, 0);
3540 SRpnt
= NULL
; /* Prevent releasing this request! */
3542 STps
->at_sm
&= (total
== 0);
3544 STps
->eof
= ST_NOEOF
;
3549 if (SRpnt
!= NULL
) scsi_release_request(SRpnt
);
3558 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3560 ssize_t total
, retval
= 0;
3561 ssize_t i
, transfer
;
3563 struct st_modedef
* STm
;
3564 struct st_partstat
* STps
;
3565 struct scsi_request
* SRpnt
= NULL
;
3566 struct osst_tape
* STp
= filp
->private_data
;
3567 char * name
= tape_name(STp
);
3570 if (down_interruptible(&STp
->lock
))
3571 return (-ERESTARTSYS
);
3574 * If we are in the middle of error recovery, don't let anyone
3575 * else try and use this device. Also, if error recovery fails, it
3576 * may try and take the device offline, in which case all further
3577 * access to the device is prohibited.
3579 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3584 if (STp
->ready
!= ST_READY
) {
3585 if (STp
->ready
== ST_NO_TAPE
)
3586 retval
= (-ENOMEDIUM
);
3591 STm
= &(STp
->modes
[STp
->current_mode
]);
3592 if (!STm
->defined
) {
3598 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3603 /* Must have initialized medium */
3604 if (!STp
->header_ok
) {
3609 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3610 STp
->door_locked
= ST_LOCKED_AUTO
;
3612 STps
= &(STp
->ps
[STp
->partition
]);
3613 if (STps
->rw
== ST_WRITING
) {
3614 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3618 /* FIXME -- this may leave the tape without EOD and up2date headers */
3621 if ((count
% STp
->block_size
) != 0) {
3623 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3624 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3628 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3629 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3630 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3632 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3633 STps
->eof
>= ST_EOD_1
) {
3634 if (STps
->eof
< ST_EOD
) {
3639 retval
= (-EIO
); /* EOM or Blank Check */
3643 /* Check the buffer writability before any tape movement. Don't alter
3645 if (copy_from_user(&i
, buf
, 1) != 0 ||
3646 copy_to_user (buf
, &i
, 1) != 0 ||
3647 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3648 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3653 /* Loop until enough data in buffer or a special condition found */
3654 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3656 /* Get new data if the buffer is empty */
3657 if ((STp
->buffer
)->buffer_bytes
== 0) {
3658 if (STps
->eof
== ST_FM_HIT
)
3660 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3661 if (special
< 0) { /* No need to continue read */
3662 STp
->frame_in_buffer
= 0;
3668 /* Move the data from driver buffer to user buffer */
3669 if ((STp
->buffer
)->buffer_bytes
> 0) {
3671 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3672 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3673 STps
->eof
, (STp
->buffer
)->buffer_bytes
, count
- total
);
3675 /* force multiple of block size, note block_size may have been adjusted */
3676 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3677 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3678 STp
->block_size
) * STp
->block_size
;
3680 if (transfer
== 0) {
3682 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3683 name
, count
, STp
->block_size
< 1024?
3684 STp
->block_size
:STp
->block_size
/1024,
3685 STp
->block_size
<1024?'b':'k');
3688 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3693 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3694 STps
->drv_block
+= transfer
/ STp
->block_size
;
3695 filp
->f_pos
+= transfer
;
3700 if ((STp
->buffer
)->buffer_bytes
== 0) {
3703 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3704 name
, STp
->frame_seq_number
);
3706 STp
->frame_in_buffer
= 0;
3707 STp
->frame_seq_number
++; /* frame to look for next time */
3709 } /* for (total = 0, special = 0; total < count && !special; ) */
3711 /* Change the eof state if no data from tape or buffer */
3713 if (STps
->eof
== ST_FM_HIT
) {
3714 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3715 STps
->drv_block
= 0;
3716 if (STps
->drv_file
>= 0)
3719 else if (STps
->eof
== ST_EOD_1
) {
3720 STps
->eof
= ST_EOD_2
;
3721 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3723 STps
->drv_block
= 0;
3725 else if (STps
->eof
== ST_EOD_2
)
3728 else if (STps
->eof
== ST_FM
)
3729 STps
->eof
= ST_NOEOF
;
3734 if (SRpnt
!= NULL
) scsi_release_request(SRpnt
);
3742 /* Set the driver options */
3743 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3746 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3747 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3748 STm
->do_read_ahead
);
3750 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3751 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3753 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3754 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3755 STp
->scsi2_logical
);
3757 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3760 "%s:D: debugging: %d\n",
3766 static int osst_set_options(struct osst_tape
*STp
, long options
)
3770 struct st_modedef
* STm
;
3771 char * name
= tape_name(STp
);
3773 STm
= &(STp
->modes
[STp
->current_mode
]);
3774 if (!STm
->defined
) {
3775 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3779 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3780 name
, STp
->current_mode
);
3784 code
= options
& MT_ST_OPTIONS
;
3785 if (code
== MT_ST_BOOLEANS
) {
3786 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3787 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3788 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3789 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3790 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3791 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3792 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3793 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3794 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3795 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3796 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3797 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3798 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3800 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3802 osst_log_options(STp
, STm
, name
);
3804 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3805 value
= (code
== MT_ST_SETBOOLEANS
);
3806 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3807 STm
->do_buffer_writes
= value
;
3808 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3809 STm
->do_async_writes
= value
;
3810 if ((options
& MT_ST_DEF_WRITES
) != 0)
3811 STm
->defaults_for_writes
= value
;
3812 if ((options
& MT_ST_READ_AHEAD
) != 0)
3813 STm
->do_read_ahead
= value
;
3814 if ((options
& MT_ST_TWO_FM
) != 0)
3815 STp
->two_fm
= value
;
3816 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3817 STp
->fast_mteom
= value
;
3818 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3819 STp
->do_auto_lock
= value
;
3820 if ((options
& MT_ST_CAN_BSR
) != 0)
3821 STp
->can_bsr
= value
;
3822 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3823 STp
->omit_blklims
= value
;
3824 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3825 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3826 STp
->can_partitions
= value
;
3827 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3828 STp
->scsi2_logical
= value
;
3829 if ((options
& MT_ST_SYSV
) != 0)
3832 if ((options
& MT_ST_DEBUGGING
) != 0)
3835 osst_log_options(STp
, STm
, name
);
3837 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3838 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3839 if (value
< 1 || value
> osst_buffer_size
) {
3840 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3844 STp
->write_threshold
= value
;
3845 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3848 else if (code
== MT_ST_DEF_BLKSIZE
) {
3849 value
= (options
& ~MT_ST_OPTIONS
);
3850 if (value
== ~MT_ST_OPTIONS
) {
3851 STm
->default_blksize
= (-1);
3852 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3855 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3856 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3860 STm
->default_blksize
= value
;
3861 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3862 name
, STm
->default_blksize
);
3865 else if (code
== MT_ST_TIMEOUTS
) {
3866 value
= (options
& ~MT_ST_OPTIONS
);
3867 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
3868 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
3869 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
3870 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
3873 STp
->timeout
= value
* HZ
;
3874 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
3877 else if (code
== MT_ST_DEF_OPTIONS
) {
3878 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
3879 value
= (options
& MT_ST_CLEAR_DEFAULT
);
3880 if (code
== MT_ST_DEF_DENSITY
) {
3881 if (value
== MT_ST_CLEAR_DEFAULT
) {
3882 STm
->default_density
= (-1);
3883 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
3886 STm
->default_density
= value
& 0xff;
3887 printk(KERN_INFO
"%s:I: Density default set to %x\n",
3888 name
, STm
->default_density
);
3891 else if (code
== MT_ST_DEF_DRVBUFFER
) {
3892 if (value
== MT_ST_CLEAR_DEFAULT
) {
3893 STp
->default_drvbuffer
= 0xff;
3894 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
3897 STp
->default_drvbuffer
= value
& 7;
3898 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
3899 name
, STp
->default_drvbuffer
);
3902 else if (code
== MT_ST_DEF_COMPRESSION
) {
3903 if (value
== MT_ST_CLEAR_DEFAULT
) {
3904 STm
->default_compression
= ST_DONT_TOUCH
;
3905 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
3908 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
3909 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
3921 /* Internal ioctl function */
3922 static int osst_int_ioctl(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
3923 unsigned int cmd_in
, unsigned long arg
)
3927 int i
, ioctl_result
;
3929 unsigned char cmd
[MAX_COMMAND_SIZE
];
3930 struct scsi_request
* SRpnt
= * aSRpnt
;
3931 struct st_partstat
* STps
;
3932 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
3933 int datalen
= 0, direction
= DMA_NONE
;
3934 char * name
= tape_name(STp
);
3936 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
3937 if (STp
->ready
== ST_NO_TAPE
)
3938 return (-ENOMEDIUM
);
3942 timeout
= STp
->long_timeout
;
3943 STps
= &(STp
->ps
[STp
->partition
]);
3944 fileno
= STps
->drv_file
;
3945 blkno
= STps
->drv_block
;
3946 at_sm
= STps
->at_sm
;
3947 frame_seq_numbr
= STp
->frame_seq_number
;
3948 logical_blk_num
= STp
->logical_blk_num
;
3950 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3953 chg_eof
= 0; /* Changed from the FSF after this */
3957 if (STp
->linux_media
)
3958 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
3960 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
3964 at_sm
&= (arg
== 0);
3968 chg_eof
= 0; /* Changed from the FSF after this */
3972 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
3975 blkno
= (-1); /* We can't know the block number */
3976 at_sm
&= (arg
== 0);
3983 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
3984 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
3986 if (cmd_in
== MTFSR
) {
3987 logical_blk_num
+= arg
;
3988 if (blkno
>= 0) blkno
+= arg
;
3991 logical_blk_num
-= arg
;
3992 if (blkno
>= 0) blkno
-= arg
;
3994 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
3995 fileno
= STps
->drv_file
;
3996 blkno
= STps
->drv_block
;
3997 at_sm
&= (arg
== 0);
4002 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4003 cmd
[2] = (arg
>> 16);
4004 cmd
[3] = (arg
>> 8);
4008 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4009 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4012 blkno
= fileno
= (-1);
4018 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4020 cmd
[2] = (ltmp
>> 16);
4021 cmd
[3] = (ltmp
>> 8);
4027 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4028 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4033 blkno
= fileno
= (-1);
4038 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4039 STp
->write_type
= OS_WRITE_DATA
;
4040 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4045 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4047 for (i
=0; i
<arg
; i
++)
4048 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4049 if (fileno
>= 0) fileno
+= arg
;
4050 if (blkno
>= 0) blkno
= 0;
4054 if (STp
->write_prot
)
4058 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4059 if (cmd_in
== MTWSM
)
4061 cmd
[2] = (arg
>> 16);
4062 cmd
[3] = (arg
>> 8);
4064 timeout
= STp
->timeout
;
4067 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4068 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4073 at_sm
= (cmd_in
== MTWSM
);
4079 cmd
[0] = START_STOP
;
4080 cmd
[1] = 1; /* Don't wait for completion */
4081 if (cmd_in
== MTLOAD
) {
4082 if (STp
->ready
== ST_NO_TAPE
)
4083 cmd
[4] = 4; /* open tray */
4085 cmd
[4] = 1; /* load */
4087 if (cmd_in
== MTRETEN
)
4088 cmd
[4] = 3; /* retension then mount */
4089 if (cmd_in
== MTOFFL
)
4090 cmd
[4] = 4; /* rewind then eject */
4091 timeout
= STp
->timeout
;
4096 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4099 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4102 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4105 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4110 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4115 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4117 return 0; /* Should do something ? */
4122 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4124 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4125 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4126 ioctl_result
= -EIO
;
4129 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4131 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4133 ioctl_result
= -EIO
;
4136 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4137 fileno
= STp
->filemark_cnt
;
4142 if (STp
->write_prot
)
4144 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4145 i
= osst_write_eod(STp
, &SRpnt
);
4146 if (i
< ioctl_result
) ioctl_result
= i
;
4147 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4148 if (i
< ioctl_result
) ioctl_result
= i
;
4149 fileno
= blkno
= at_sm
= 0 ;
4153 cmd
[0] = REZERO_UNIT
; /* rewind */
4157 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4159 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4162 case MTSETBLK
: /* Set block length */
4163 if ((STps
->drv_block
== 0 ) &&
4165 ((STp
->buffer
)->buffer_bytes
== 0) &&
4166 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4167 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4168 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4170 * Only allowed to change the block size if you opened the
4171 * device at the beginning of a file before writing anything.
4172 * Note, that when reading, changing block_size is futile,
4173 * as the size used when writing overrides it.
4175 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4176 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4177 name
, STp
->block_size
);
4180 case MTSETDENSITY
: /* Set tape density */
4181 case MTSETDRVBUFFER
: /* Set drive buffering */
4182 case SET_DENS_AND_BLK
: /* Set density and block size */
4184 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4185 return (-EIO
); /* Not allowed if data in buffer */
4186 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4187 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4188 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4189 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4190 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4191 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4194 return 0; /* FIXME silently ignore if block size didn't change */
4200 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4202 ioctl_result
= (STp
->buffer
)->syscall_result
;
4206 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4208 return ioctl_result
;
4211 if (!ioctl_result
) { /* SCSI command successful */
4212 STp
->frame_seq_number
= frame_seq_numbr
;
4213 STp
->logical_blk_num
= logical_blk_num
;
4219 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4222 if (!ioctl_result
) { /* success */
4224 if (cmd_in
== MTFSFM
) {
4228 if (cmd_in
== MTBSFM
) {
4232 STps
->drv_block
= blkno
;
4233 STps
->drv_file
= fileno
;
4234 STps
->at_sm
= at_sm
;
4236 if (cmd_in
== MTEOM
)
4238 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4239 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4241 STp
->logical_blk_num
++;
4242 STp
->frame_seq_number
++;
4243 STp
->frame_in_buffer
= 0;
4244 STp
->buffer
->read_pointer
= 0;
4246 else if (cmd_in
== MTFSF
)
4247 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4249 STps
->eof
= ST_NOEOF
;
4251 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4252 STp
->rew_at_close
= 0;
4253 else if (cmd_in
== MTLOAD
) {
4254 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4255 STp
->ps
[i
].rw
= ST_IDLE
;
4256 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4261 if (cmd_in
== MTREW
) {
4262 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4263 if (ioctl_result
> 0)
4267 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4268 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4269 STps
->drv_file
= STps
->drv_block
= -1;
4271 STps
->drv_file
= STps
->drv_block
= 0;
4272 STps
->eof
= ST_NOEOF
;
4273 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4274 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4275 STps
->drv_file
= STps
->drv_block
= -1;
4277 STps
->drv_file
= STp
->filemark_cnt
;
4278 STps
->drv_block
= 0;
4281 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4282 STps
->drv_file
= STps
->drv_block
= (-1);
4283 STps
->eof
= ST_NOEOF
;
4285 } else if (cmd_in
== MTERASE
) {
4287 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4288 if (SRpnt
->sr_sense_buffer
[2] & 0x40) {
4289 STps
->eof
= ST_EOM_OK
;
4290 STps
->drv_block
= 0;
4293 STps
->eof
= ST_NOEOF
;
4295 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == BLANK_CHECK
)
4298 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4299 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4303 return ioctl_result
;
4307 /* Open the device */
4308 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4310 unsigned short flags
;
4311 int i
, b_size
, new_session
= 0, retval
= 0;
4312 unsigned char cmd
[MAX_COMMAND_SIZE
];
4313 struct scsi_request
* SRpnt
= NULL
;
4314 struct osst_tape
* STp
;
4315 struct st_modedef
* STm
;
4316 struct st_partstat
* STps
;
4318 int dev
= TAPE_NR(inode
);
4319 int mode
= TAPE_MODE(inode
);
4322 * We really want to do nonseekable_open(inode, filp); here, but some
4323 * versions of tar incorrectly call lseek on tapes and bail out if that
4324 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4326 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4328 write_lock(&os_scsi_tapes_lock
);
4329 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4330 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4331 write_unlock(&os_scsi_tapes_lock
);
4335 name
= tape_name(STp
);
4338 write_unlock(&os_scsi_tapes_lock
);
4340 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4344 if (scsi_device_get(STp
->device
)) {
4345 write_unlock(&os_scsi_tapes_lock
);
4347 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4351 filp
->private_data
= STp
;
4353 write_unlock(&os_scsi_tapes_lock
);
4354 STp
->rew_at_close
= TAPE_REWIND(inode
);
4356 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4360 if (mode
!= STp
->current_mode
) {
4363 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4364 name
, STp
->current_mode
, mode
);
4367 STp
->current_mode
= mode
;
4369 STm
= &(STp
->modes
[STp
->current_mode
]);
4371 flags
= filp
->f_flags
;
4372 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4374 STp
->raw
= TAPE_IS_RAW(inode
);
4378 /* Allocate data segments for this device's tape buffer */
4379 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4380 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4381 retval
= (-EOVERFLOW
);
4384 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4385 for (i
= 0, b_size
= 0;
4386 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4387 b_size
+= STp
->buffer
->sg
[i
++].length
);
4388 STp
->buffer
->aux
= (os_aux_t
*) (page_address(STp
->buffer
->sg
[i
].page
) + OS_DATA_SIZE
- b_size
);
4390 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4391 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4392 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4393 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4396 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4397 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4401 STp
->buffer
->writing
= 0;
4402 STp
->buffer
->syscall_result
= 0;
4404 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4405 STps
= &(STp
->ps
[i
]);
4408 STp
->ready
= ST_READY
;
4410 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4413 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4414 cmd
[0] = TEST_UNIT_READY
;
4416 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4418 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4421 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4422 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
&&
4423 SRpnt
->sr_sense_buffer
[12] == 4 ) {
4425 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sr_sense_buffer
[13]);
4427 if (filp
->f_flags
& O_NONBLOCK
) {
4431 if (SRpnt
->sr_sense_buffer
[13] == 2) { /* initialize command required (LOAD) */
4432 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4433 cmd
[0] = START_STOP
;
4436 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4437 STp
->timeout
, MAX_RETRIES
, 1);
4439 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sr_sense_buffer
[13]==1?15:3) * 60, 0);
4441 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4442 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4444 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4448 for (i
=0; i
< 10; i
++) {
4450 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4451 cmd
[0] = TEST_UNIT_READY
;
4453 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4454 STp
->timeout
, MAX_RETRIES
, 1);
4455 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) != 0x70 ||
4456 (SRpnt
->sr_sense_buffer
[2] & 0x0f) != UNIT_ATTENTION
)
4460 STp
->pos_unknown
= 0;
4461 STp
->partition
= STp
->new_partition
= 0;
4462 if (STp
->can_partitions
)
4463 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4464 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4465 STps
= &(STp
->ps
[i
]);
4466 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4467 STps
->eof
= ST_NOEOF
;
4469 STps
->last_block_valid
= 0;
4470 STps
->drv_block
= 0;
4471 STps
->drv_file
= 0 ;
4474 STp
->recover_count
= 0;
4475 STp
->abort_count
= 0;
4478 * if we have valid headers from before, and the drive/tape seem untouched,
4479 * open without reconfiguring and re-reading the headers
4481 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4482 !SRpnt
->sr_result
&& SRpnt
->sr_sense_buffer
[0] == 0) {
4484 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4485 cmd
[0] = MODE_SENSE
;
4487 cmd
[2] = VENDOR_IDENT_PAGE
;
4488 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4490 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4492 if (STp
->buffer
->syscall_result
||
4493 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4494 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4495 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4496 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4498 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4499 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4500 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4501 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4502 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4506 i
= STp
->first_frame_position
;
4507 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4508 if (STp
->door_locked
== ST_UNLOCKED
) {
4509 if (do_door_lock(STp
, 1))
4510 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4512 STp
->door_locked
= ST_LOCKED_AUTO
;
4514 if (!STp
->frame_in_buffer
) {
4515 STp
->block_size
= (STm
->default_blksize
> 0) ?
4516 STm
->default_blksize
: OS_DATA_SIZE
;
4517 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4519 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4521 scsi_release_request(SRpnt
);
4525 if (i
!= STp
->first_frame_position
)
4526 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4527 name
, i
, STp
->first_frame_position
);
4533 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4534 (SRpnt
->sr_sense_buffer
[2] != 2 || SRpnt
->sr_sense_buffer
[12] != 0x3A) ) {
4536 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4537 cmd
[0] = MODE_SELECT
;
4539 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4541 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4542 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4543 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4544 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4545 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4546 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4547 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4548 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4551 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4553 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4557 for (i
=0; i
< 10; i
++) {
4559 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4560 cmd
[0] = TEST_UNIT_READY
;
4562 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4563 STp
->timeout
, MAX_RETRIES
, 1);
4564 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) != 0x70 ||
4565 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
)
4568 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == UNIT_ATTENTION
) {
4569 STp
->pos_unknown
= 0;
4570 STp
->partition
= STp
->new_partition
= 0;
4571 if (STp
->can_partitions
)
4572 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4573 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4574 STps
= &(STp
->ps
[i
]);
4576 STps
->eof
= ST_NOEOF
;
4578 STps
->last_block_valid
= 0;
4579 STps
->drv_block
= 0;
4580 STps
->drv_file
= 0 ;
4587 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4588 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4590 if ((STp
->buffer
)->syscall_result
!= 0) {
4591 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4592 (SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4593 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
&&
4594 SRpnt
->sr_sense_buffer
[12] == 0x3a) { /* Check ASC */
4595 STp
->ready
= ST_NO_TAPE
;
4597 STp
->ready
= ST_NOT_READY
;
4598 scsi_release_request(SRpnt
);
4600 STp
->density
= 0; /* Clear the erroneous "residue" */
4601 STp
->write_prot
= 0;
4602 STp
->block_size
= 0;
4603 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4604 STp
->partition
= STp
->new_partition
= 0;
4605 STp
->door_locked
= ST_UNLOCKED
;
4609 osst_configure_onstream(STp
, &SRpnt
);
4611 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4612 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4613 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4614 STp
->buffer
->buffer_bytes
=
4615 STp
->buffer
->read_pointer
=
4616 STp
->frame_in_buffer
= 0;
4620 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4621 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4622 (STp
->buffer
)->buffer_blocks
);
4625 if (STp
->drv_write_prot
) {
4626 STp
->write_prot
= 1;
4629 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4631 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4637 if (new_session
) { /* Change the drive parameters for the new mode */
4640 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4642 STp
->density_changed
= STp
->blksize_changed
= 0;
4643 STp
->compression_changed
= 0;
4647 * properly position the tape and check the ADR headers
4649 if (STp
->door_locked
== ST_UNLOCKED
) {
4650 if (do_door_lock(STp
, 1))
4651 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4653 STp
->door_locked
= ST_LOCKED_AUTO
;
4656 osst_analyze_headers(STp
, &SRpnt
);
4658 scsi_release_request(SRpnt
);
4665 scsi_release_request(SRpnt
);
4666 normalize_buffer(STp
->buffer
);
4669 scsi_device_put(STp
->device
);
4675 /* Flush the tape buffer before close */
4676 static int os_scsi_tape_flush(struct file
* filp
)
4678 int result
= 0, result2
;
4679 struct osst_tape
* STp
= filp
->private_data
;
4680 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4681 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4682 struct scsi_request
* SRpnt
= NULL
;
4683 char * name
= tape_name(STp
);
4685 if (file_count(filp
) > 1)
4688 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4689 STp
->write_type
= OS_WRITE_DATA
;
4690 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4691 if (result
!= 0 && result
!= (-ENOSPC
))
4694 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4698 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4699 name
, (long)(filp
->f_pos
));
4700 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4701 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4704 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4707 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4708 name
, 1+STp
->two_fm
);
4711 else if (!STp
->rew_at_close
) {
4712 STps
= &(STp
->ps
[STp
->partition
]);
4713 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4715 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4716 else if (STps
->eof
== ST_FM_HIT
) {
4717 result
= cross_eof(STp
, &SRpnt
, 0);
4719 if (STps
->drv_file
>= 0)
4721 STps
->drv_block
= 0;
4725 STps
->eof
= ST_NOEOF
;
4728 else if ((STps
->eof
== ST_NOEOF
&&
4729 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4730 STps
->eof
== ST_FM_HIT
) {
4731 if (STps
->drv_file
>= 0)
4733 STps
->drv_block
= 0;
4739 if (STp
->rew_at_close
) {
4740 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4741 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4742 if (result
== 0 && result2
< 0)
4745 if (SRpnt
) scsi_release_request(SRpnt
);
4747 if (STp
->abort_count
|| STp
->recover_count
) {
4748 printk(KERN_INFO
"%s:I:", name
);
4749 if (STp
->abort_count
)
4750 printk(" %d unrecovered errors", STp
->abort_count
);
4751 if (STp
->recover_count
)
4752 printk(" %d recovered errors", STp
->recover_count
);
4753 if (STp
->write_count
)
4754 printk(" in %d frames written", STp
->write_count
);
4755 if (STp
->read_count
)
4756 printk(" in %d frames read", STp
->read_count
);
4758 STp
->recover_count
= 0;
4759 STp
->abort_count
= 0;
4761 STp
->write_count
= 0;
4762 STp
->read_count
= 0;
4768 /* Close the device and release it */
4769 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4772 struct osst_tape
* STp
= filp
->private_data
;
4774 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4775 do_door_lock(STp
, 0);
4780 normalize_buffer(STp
->buffer
);
4781 write_lock(&os_scsi_tapes_lock
);
4783 write_unlock(&os_scsi_tapes_lock
);
4785 scsi_device_put(STp
->device
);
4791 /* The ioctl command */
4792 static int osst_ioctl(struct inode
* inode
,struct file
* file
,
4793 unsigned int cmd_in
, unsigned long arg
)
4795 int i
, cmd_nr
, cmd_type
, retval
= 0;
4797 struct st_modedef
* STm
;
4798 struct st_partstat
* STps
;
4799 struct scsi_request
* SRpnt
= NULL
;
4800 struct osst_tape
* STp
= file
->private_data
;
4801 char * name
= tape_name(STp
);
4802 void __user
* p
= (void __user
*)arg
;
4804 if (down_interruptible(&STp
->lock
))
4805 return -ERESTARTSYS
;
4808 if (debugging
&& !STp
->in_use
) {
4809 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4814 STm
= &(STp
->modes
[STp
->current_mode
]);
4815 STps
= &(STp
->ps
[STp
->partition
]);
4818 * If we are in the middle of error recovery, don't let anyone
4819 * else try and use this device. Also, if error recovery fails, it
4820 * may try and take the device offline, in which case all further
4821 * access to the device is prohibited.
4823 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4828 cmd_type
= _IOC_TYPE(cmd_in
);
4829 cmd_nr
= _IOC_NR(cmd_in
);
4831 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4832 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4834 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4838 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4843 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
4849 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
4850 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
4855 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
4860 if (!STp
->pos_unknown
) {
4862 if (STps
->eof
== ST_FM_HIT
) {
4863 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
4865 if (STps
->drv_file
>= 0)
4866 STps
->drv_file
+= 1;
4868 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
4870 if (STps
->drv_file
>= 0)
4871 STps
->drv_file
+= 1;
4875 if (mtc
.mt_op
== MTSEEK
) {
4876 /* Old position must be restored if partition will be changed */
4877 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
4880 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
4881 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
4882 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
4883 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
4884 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
4885 mtc
.mt_op
== MTCOMPRESSION
;
4887 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
4895 * If there was a bus reset, block further access
4896 * to this device. If the user wants to rewind the tape,
4897 * then reset the flag and allow access again.
4899 if(mtc
.mt_op
!= MTREW
&&
4900 mtc
.mt_op
!= MTOFFL
&&
4901 mtc
.mt_op
!= MTRETEN
&&
4902 mtc
.mt_op
!= MTERASE
&&
4903 mtc
.mt_op
!= MTSEEK
&&
4904 mtc
.mt_op
!= MTEOM
) {
4909 /* remove this when the midlevel properly clears was_reset */
4910 STp
->device
->was_reset
= 0;
4913 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
4914 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
4915 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
4916 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
4917 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
4920 * The user tells us to move to another position on the tape.
4921 * If we were appending to the tape content, that would leave
4922 * the tape without proper end, in that case write EOD and
4923 * update the header to reflect its position.
4926 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
4927 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
4928 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
4929 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
4931 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
4932 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
4933 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
4934 i
= osst_write_trailer(STp
, &SRpnt
,
4935 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
4937 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4938 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
4939 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
4949 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
4950 do_door_lock(STp
, 0); /* Ignore result! */
4952 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
4953 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
4954 retval
= osst_set_options(STp
, mtc
.mt_count
);
4958 if (mtc
.mt_op
== MTSETPART
) {
4959 if (mtc
.mt_count
>= STp
->nbr_partitions
)
4962 STp
->new_partition
= mtc
.mt_count
;
4968 if (mtc
.mt_op
== MTMKPART
) {
4969 if (!STp
->can_partitions
) {
4973 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
4974 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
4978 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4979 STp
->ps
[i
].rw
= ST_IDLE
;
4980 STp
->ps
[i
].at_sm
= 0;
4981 STp
->ps
[i
].last_block_valid
= 0;
4983 STp
->partition
= STp
->new_partition
= 0;
4984 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
4985 STps
->drv_block
= STps
->drv_file
= 0;
4990 if (mtc
.mt_op
== MTSEEK
) {
4992 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
4994 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
4995 if (!STp
->can_partitions
)
4996 STp
->ps
[0].rw
= ST_IDLE
;
5001 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
5002 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5007 cross_eof(STp
, &SRpnt
, 0);
5009 if (mtc
.mt_op
== MTCOMPRESSION
)
5010 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5012 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5013 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5014 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5018 if (!STm
->defined
) {
5023 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5028 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5029 struct mtget mt_status
;
5031 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5036 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5037 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5038 mt_status
.mt_dsreg
=
5039 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5040 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5041 mt_status
.mt_blkno
= STps
->drv_block
;
5042 mt_status
.mt_fileno
= STps
->drv_file
;
5043 if (STp
->block_size
!= 0) {
5044 if (STps
->rw
== ST_WRITING
)
5045 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5046 else if (STps
->rw
== ST_READING
)
5047 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5048 STp
->block_size
- 1) / STp
->block_size
;
5051 mt_status
.mt_gstat
= 0;
5052 if (STp
->drv_write_prot
)
5053 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5054 if (mt_status
.mt_blkno
== 0) {
5055 if (mt_status
.mt_fileno
== 0)
5056 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5058 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5060 mt_status
.mt_resid
= STp
->partition
;
5061 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5062 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5063 else if (STps
->eof
>= ST_EOM_OK
)
5064 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5065 if (STp
->density
== 1)
5066 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5067 else if (STp
->density
== 2)
5068 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5069 else if (STp
->density
== 3)
5070 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5071 if (STp
->ready
== ST_READY
)
5072 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5073 if (STp
->ready
== ST_NO_TAPE
)
5074 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5076 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5077 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5078 STp
->drv_buffer
!= 0)
5079 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5081 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5087 STp
->recover_erreg
= 0; /* Clear after read */
5090 } /* End of MTIOCGET */
5092 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5093 struct mtpos mt_pos
;
5095 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5100 blk
= osst_get_frame_position(STp
, &SRpnt
);
5102 blk
= osst_get_sector(STp
, &SRpnt
);
5107 mt_pos
.mt_blkno
= blk
;
5108 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5113 if (SRpnt
) scsi_release_request(SRpnt
);
5117 return scsi_ioctl(STp
->device
, cmd_in
, p
);
5120 if (SRpnt
) scsi_release_request(SRpnt
);
5127 #ifdef CONFIG_COMPAT
5128 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5130 struct osst_tape
*STp
= file
->private_data
;
5131 struct scsi_device
*sdev
= STp
->device
;
5132 int ret
= -ENOIOCTLCMD
;
5133 if (sdev
->host
->hostt
->compat_ioctl
) {
5135 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5144 /* Memory handling routines */
5146 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5147 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5150 struct osst_buffer
*tb
;
5152 if (from_initialization
)
5153 priority
= GFP_ATOMIC
;
5155 priority
= GFP_KERNEL
;
5157 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5158 tb
= (struct osst_buffer
*)kmalloc(i
, priority
);
5160 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5164 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5165 tb
->use_sg
= max_sg
;
5168 tb
->buffer_size
= 0;
5172 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5173 i
, max_sg
, need_dma
);
5178 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5179 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5181 int segs
, nbr
, max_segs
, b_size
, priority
, order
, got
;
5183 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5186 if (STbuffer
->sg_segs
) {
5187 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5188 normalize_buffer(STbuffer
);
5190 /* See how many segments we can use -- need at least two */
5191 nbr
= max_segs
= STbuffer
->use_sg
;
5195 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5197 priority
|= GFP_DMA
;
5199 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5200 big enough to reach the goal (code assumes no segments in place) */
5201 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5202 STbuffer
->sg
[0].page
= alloc_pages(priority
, order
);
5203 STbuffer
->sg
[0].offset
= 0;
5204 if (STbuffer
->sg
[0].page
!= NULL
) {
5205 STbuffer
->sg
[0].length
= b_size
;
5206 STbuffer
->b_data
= page_address(STbuffer
->sg
[0].page
);
5210 if (STbuffer
->sg
[0].page
== NULL
) {
5211 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5214 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5215 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5216 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5217 STbuffer
->sg
[segs
].page
=
5218 alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5219 STbuffer
->sg
[segs
].offset
= 0;
5220 if (STbuffer
->sg
[segs
].page
== NULL
) {
5221 if (OS_FRAME_SIZE
- got
<= (max_segs
- segs
) * b_size
/ 2 && order
) {
5222 b_size
/= 2; /* Large enough for the rest of the buffers */
5226 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5229 STbuffer
->buffer_size
= got
;
5231 normalize_buffer(STbuffer
);
5234 STbuffer
->sg
[segs
].length
= (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
;
5235 got
+= STbuffer
->sg
[segs
].length
;
5236 STbuffer
->buffer_size
= got
;
5237 STbuffer
->sg_segs
= ++segs
;
5242 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5243 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5245 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5246 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5247 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5255 /* Release the segments */
5256 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5258 int i
, order
, b_size
;
5260 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5262 for (b_size
= PAGE_SIZE
, order
= 0;
5263 b_size
< STbuffer
->sg
[i
].length
;
5264 b_size
*= 2, order
++);
5266 __free_pages(STbuffer
->sg
[i
].page
, order
);
5267 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5270 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5271 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5272 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5274 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5278 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5279 negative error code. */
5280 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5282 int i
, cnt
, res
, offset
;
5284 for (i
=0, offset
=st_bp
->buffer_bytes
;
5285 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5286 offset
-= st_bp
->sg
[i
].length
;
5287 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5288 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5291 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5292 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5293 st_bp
->sg
[i
].length
- offset
: do_count
;
5294 res
= copy_from_user(page_address(st_bp
->sg
[i
].page
) + offset
, ubp
, cnt
);
5298 st_bp
->buffer_bytes
+= cnt
;
5302 if (do_count
) { /* Should never happen */
5303 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5311 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5312 negative error code. */
5313 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5315 int i
, cnt
, res
, offset
;
5317 for (i
=0, offset
=st_bp
->read_pointer
;
5318 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5319 offset
-= st_bp
->sg
[i
].length
;
5320 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5321 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5324 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5325 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5326 st_bp
->sg
[i
].length
- offset
: do_count
;
5327 res
= copy_to_user(ubp
, page_address(st_bp
->sg
[i
].page
) + offset
, cnt
);
5331 st_bp
->buffer_bytes
-= cnt
;
5332 st_bp
->read_pointer
+= cnt
;
5336 if (do_count
) { /* Should never happen */
5337 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5343 /* Sets the tail of the buffer after fill point to zero.
5344 Returns zero (success) or negative error code. */
5345 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5347 int i
, offset
, do_count
, cnt
;
5349 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5350 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5351 offset
-= st_bp
->sg
[i
].length
;
5352 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5353 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5356 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5357 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5358 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5359 st_bp
->sg
[i
].length
- offset
: do_count
;
5360 memset(page_address(st_bp
->sg
[i
].page
) + offset
, 0, cnt
);
5364 if (do_count
) { /* Should never happen */
5365 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5371 /* Copy a osst 32K chunk of memory into the buffer.
5372 Returns zero (success) or negative error code. */
5373 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5375 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5377 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5378 cnt
= st_bp
->sg
[i
].length
< do_count
?
5379 st_bp
->sg
[i
].length
: do_count
;
5380 memcpy(page_address(st_bp
->sg
[i
].page
), ptr
, cnt
);
5384 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5385 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5392 /* Copy a osst 32K chunk of memory from the buffer.
5393 Returns zero (success) or negative error code. */
5394 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5396 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5398 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5399 cnt
= st_bp
->sg
[i
].length
< do_count
?
5400 st_bp
->sg
[i
].length
: do_count
;
5401 memcpy(ptr
, page_address(st_bp
->sg
[i
].page
), cnt
);
5405 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5406 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5414 /* Module housekeeping */
5416 static void validate_options (void)
5419 osst_max_dev
= max_dev
;
5420 if (write_threshold_kbs
> 0)
5421 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5422 if (osst_write_threshold
> osst_buffer_size
)
5423 osst_write_threshold
= osst_buffer_size
;
5424 if (max_sg_segs
>= OSST_FIRST_SG
)
5425 osst_max_sg_segs
= max_sg_segs
;
5427 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5428 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5433 /* Set the boot options. Syntax: osst=xxx,yyy,...
5434 where xxx is write threshold in 1024 byte blocks,
5435 and yyy is number of s/g segments to use. */
5436 static int __init
osst_setup (char *str
)
5441 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5444 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5445 *parms
[i
].val
= ints
[i
+ 1];
5447 while (stp
!= NULL
) {
5448 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5449 int len
= strlen(parms
[i
].name
);
5450 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5451 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5453 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5457 if (i
>= sizeof(parms
) / sizeof(struct osst_dev_parm
))
5458 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5460 stp
= strchr(stp
, ',');
5469 __setup("osst=", osst_setup
);
5473 static struct file_operations osst_fops
= {
5474 .owner
= THIS_MODULE
,
5476 .write
= osst_write
,
5477 .ioctl
= osst_ioctl
,
5478 #ifdef CONFIG_COMPAT
5479 .compat_ioctl
= osst_compat_ioctl
,
5481 .open
= os_scsi_tape_open
,
5482 .flush
= os_scsi_tape_flush
,
5483 .release
= os_scsi_tape_close
,
5486 static int osst_supports(struct scsi_device
* SDp
)
5488 struct osst_support_data
{
5492 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5495 static struct osst_support_data support_list
[] = {
5496 /* {"XXX", "Yy-", "", NULL}, example */
5500 struct osst_support_data
*rp
;
5502 /* We are willing to drive OnStream SC-x0 as well as the
5503 * * IDE, ParPort, FireWire, USB variants, if accessible by
5504 * * emulation layer (ide-scsi, usb-storage, ...) */
5506 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5507 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5508 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5509 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5515 * sysfs support for osst driver parameter information
5518 static ssize_t
osst_version_show(struct device_driver
*ddd
, char *buf
)
5520 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5523 static DRIVER_ATTR(version
, S_IRUGO
, osst_version_show
, NULL
);
5525 static void osst_create_driverfs_files(struct device_driver
*driverfs
)
5527 driver_create_file(driverfs
, &driver_attr_version
);
5530 static void osst_remove_driverfs_files(struct device_driver
*driverfs
)
5532 driver_remove_file(driverfs
, &driver_attr_version
);
5536 * sysfs support for accessing ADR header information
5539 static ssize_t
osst_adr_rev_show(struct class_device
*class_dev
, char *buf
)
5541 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5544 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5545 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5549 CLASS_DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5551 static ssize_t
osst_linux_media_version_show(struct class_device
*class_dev
, char *buf
)
5553 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5556 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5557 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5561 CLASS_DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5563 static ssize_t
osst_capacity_show(struct class_device
*class_dev
, char *buf
)
5565 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5568 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5569 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5573 CLASS_DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5575 static ssize_t
osst_first_data_ppos_show(struct class_device
*class_dev
, char *buf
)
5577 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5580 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5581 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5585 CLASS_DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5587 static ssize_t
osst_eod_frame_ppos_show(struct class_device
*class_dev
, char *buf
)
5589 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5592 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5593 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5597 CLASS_DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5599 static ssize_t
osst_filemark_cnt_show(struct class_device
*class_dev
, char *buf
)
5601 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5604 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5605 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5609 CLASS_DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5611 static struct class *osst_sysfs_class
;
5613 static int osst_sysfs_valid
= 0;
5615 static void osst_sysfs_init(void)
5617 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5618 if ( IS_ERR(osst_sysfs_class
) )
5619 printk(KERN_WARNING
"osst :W: Unable to register sysfs class\n");
5621 osst_sysfs_valid
= 1;
5624 static void osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5626 struct class_device
*osst_class_member
;
5628 if (!osst_sysfs_valid
) return;
5630 osst_class_member
= class_device_create(osst_sysfs_class
, dev
, device
, "%s", name
);
5631 if (IS_ERR(osst_class_member
)) {
5632 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5635 class_set_devdata(osst_class_member
, STp
);
5636 class_device_create_file(osst_class_member
, &class_device_attr_ADR_rev
);
5637 class_device_create_file(osst_class_member
, &class_device_attr_media_version
);
5638 class_device_create_file(osst_class_member
, &class_device_attr_capacity
);
5639 class_device_create_file(osst_class_member
, &class_device_attr_BOT_frame
);
5640 class_device_create_file(osst_class_member
, &class_device_attr_EOD_frame
);
5641 class_device_create_file(osst_class_member
, &class_device_attr_file_count
);
5644 static void osst_sysfs_destroy(dev_t dev
)
5646 if (!osst_sysfs_valid
) return;
5648 class_device_destroy(osst_sysfs_class
, dev
);
5651 static void osst_sysfs_cleanup(void)
5653 if (osst_sysfs_valid
) {
5654 class_destroy(osst_sysfs_class
);
5655 osst_sysfs_valid
= 0;
5660 * osst startup / cleanup code
5663 static int osst_probe(struct device
*dev
)
5665 struct scsi_device
* SDp
= to_scsi_device(dev
);
5666 struct osst_tape
* tpnt
;
5667 struct st_modedef
* STm
;
5668 struct st_partstat
* STps
;
5669 struct osst_buffer
* buffer
;
5670 struct gendisk
* drive
;
5671 int i
, mode
, dev_num
;
5673 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5676 drive
= alloc_disk(1);
5678 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5682 /* if this is the first attach, build the infrastructure */
5683 write_lock(&os_scsi_tapes_lock
);
5684 if (os_scsi_tapes
== NULL
) {
5686 (struct osst_tape
**)kmalloc(osst_max_dev
* sizeof(struct osst_tape
*),
5688 if (os_scsi_tapes
== NULL
) {
5689 write_unlock(&os_scsi_tapes_lock
);
5690 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5693 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5696 if (osst_nr_dev
>= osst_max_dev
) {
5697 write_unlock(&os_scsi_tapes_lock
);
5698 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5702 /* find a free minor number */
5703 for (i
=0; os_scsi_tapes
[i
] && i
<osst_max_dev
; i
++);
5704 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5707 /* allocate a struct osst_tape for this device */
5708 tpnt
= (struct osst_tape
*)kmalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5710 write_unlock(&os_scsi_tapes_lock
);
5711 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5714 memset(tpnt
, 0, sizeof(struct osst_tape
));
5716 /* allocate a buffer for this device */
5717 i
= SDp
->host
->sg_tablesize
;
5718 if (osst_max_sg_segs
< i
)
5719 i
= osst_max_sg_segs
;
5720 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5721 if (buffer
== NULL
) {
5722 write_unlock(&os_scsi_tapes_lock
);
5723 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5727 os_scsi_tapes
[dev_num
] = tpnt
;
5728 tpnt
->buffer
= buffer
;
5730 drive
->private_data
= &tpnt
->driver
;
5731 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5732 tpnt
->driver
= &osst_template
;
5733 tpnt
->drive
= drive
;
5735 tpnt
->capacity
= 0xfffff;
5737 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5738 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5740 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5741 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5742 tpnt
->can_partitions
= 0;
5743 tpnt
->two_fm
= OSST_TWO_FM
;
5744 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5745 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5746 tpnt
->write_threshold
= osst_write_threshold
;
5747 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5748 tpnt
->partition
= 0;
5749 tpnt
->new_partition
= 0;
5750 tpnt
->nbr_partitions
= 0;
5751 tpnt
->min_block
= 512;
5752 tpnt
->max_block
= OS_DATA_SIZE
;
5753 tpnt
->timeout
= OSST_TIMEOUT
;
5754 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5756 /* Recognize OnStream tapes */
5757 /* We don't need to test for OnStream, as this has been done in detect () */
5758 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5759 tpnt
->omit_blklims
= 1;
5761 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5762 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5763 tpnt
->frame_in_buffer
= 0;
5764 tpnt
->header_ok
= 0;
5765 tpnt
->linux_media
= 0;
5766 tpnt
->header_cache
= NULL
;
5768 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5769 STm
= &(tpnt
->modes
[i
]);
5771 STm
->sysv
= OSST_SYSV
;
5772 STm
->defaults_for_writes
= 0;
5773 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5774 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5775 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5776 STm
->default_compression
= ST_DONT_TOUCH
;
5777 STm
->default_blksize
= 512;
5778 STm
->default_density
= (-1); /* No forced density */
5781 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5782 STps
= &(tpnt
->ps
[i
]);
5784 STps
->eof
= ST_NOEOF
;
5786 STps
->last_block_valid
= 0;
5787 STps
->drv_block
= (-1);
5788 STps
->drv_file
= (-1);
5791 tpnt
->current_mode
= 0;
5792 tpnt
->modes
[0].defined
= 1;
5793 tpnt
->modes
[2].defined
= 1;
5794 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5796 init_MUTEX(&tpnt
->lock
);
5798 write_unlock(&os_scsi_tapes_lock
);
5802 osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5803 /* No-rewind entry */
5804 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5805 osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5807 for (mode
= 0; mode
< ST_NBR_MODES
; ++mode
) {
5809 devfs_mk_cdev(MKDEV(OSST_MAJOR
, dev_num
+ (mode
<< 5)),
5810 S_IFCHR
| S_IRUGO
| S_IWUGO
,
5811 "%s/ot%s", SDp
->devfs_name
, osst_formats
[mode
]);
5813 /* No-rewind entry */
5814 devfs_mk_cdev(MKDEV(OSST_MAJOR
, dev_num
+ (mode
<< 5) + 128),
5815 S_IFCHR
| S_IRUGO
| S_IWUGO
,
5816 "%s/ot%sn", SDp
->devfs_name
, osst_formats
[mode
]);
5818 drive
->number
= devfs_register_tape(SDp
->devfs_name
);
5821 "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n",
5822 SDp
->model
, SDp
->host
->host_no
, SDp
->channel
, SDp
->id
, SDp
->lun
, tape_name(tpnt
));
5831 static int osst_remove(struct device
*dev
)
5833 struct scsi_device
* SDp
= to_scsi_device(dev
);
5834 struct osst_tape
* tpnt
;
5837 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
5840 write_lock(&os_scsi_tapes_lock
);
5841 for(i
=0; i
< osst_max_dev
; i
++) {
5842 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
5843 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
5844 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
5845 tpnt
->device
= NULL
;
5846 for (mode
= 0; mode
< ST_NBR_MODES
; ++mode
) {
5847 devfs_remove("%s/ot%s", SDp
->devfs_name
, osst_formats
[mode
]);
5848 devfs_remove("%s/ot%sn", SDp
->devfs_name
, osst_formats
[mode
]);
5850 devfs_unregister_tape(tpnt
->drive
->number
);
5851 put_disk(tpnt
->drive
);
5852 os_scsi_tapes
[i
] = NULL
;
5854 write_unlock(&os_scsi_tapes_lock
);
5855 if (tpnt
->header_cache
!= NULL
) vfree(tpnt
->header_cache
);
5857 normalize_buffer(tpnt
->buffer
);
5858 kfree(tpnt
->buffer
);
5864 write_unlock(&os_scsi_tapes_lock
);
5868 static int __init
init_osst(void)
5870 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
5875 if ((register_chrdev(OSST_MAJOR
,"osst", &osst_fops
) < 0) || scsi_register_driver(&osst_template
.gendrv
)) {
5876 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
5877 osst_sysfs_cleanup();
5880 osst_create_driverfs_files(&osst_template
.gendrv
);
5885 static void __exit
exit_osst (void)
5888 struct osst_tape
* STp
;
5890 osst_remove_driverfs_files(&osst_template
.gendrv
);
5891 scsi_unregister_driver(&osst_template
.gendrv
);
5892 unregister_chrdev(OSST_MAJOR
, "osst");
5893 osst_sysfs_cleanup();
5895 if (os_scsi_tapes
) {
5896 for (i
=0; i
< osst_max_dev
; ++i
) {
5897 if (!(STp
= os_scsi_tapes
[i
])) continue;
5898 /* This is defensive, supposed to happen during detach */
5899 if (STp
->header_cache
)
5900 vfree(STp
->header_cache
);
5902 normalize_buffer(STp
->buffer
);
5905 put_disk(STp
->drive
);
5908 kfree(os_scsi_tapes
);
5910 printk(KERN_INFO
"osst :I: Unloaded.\n");
5913 module_init(init_osst
);
5914 module_exit(exit_osst
);