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 schedule_timeout_interruptible(HZ
/ OSST_POLL_PER_SEC
);
867 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
868 memset(cmd
, 0, MAX_COMMAND_SIZE
);
869 cmd
[0] = READ_POSITION
;
871 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 20, DMA_FROM_DEVICE
, STp
->timeout
,
874 retval
= ( STp
->buffer
->syscall_result
|| (STp
->buffer
)->b_data
[15] > 25 );
875 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
878 printk(KERN_ERR
"%s:E: Device did not succeed to write buffered data\n", name
);
880 /* TODO - figure out which error conditions can be handled */
881 if (STp
->buffer
->syscall_result
)
883 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name
,
884 (*aSRpnt
)->sr_sense_buffer
[ 2] & 0x0f,
885 (*aSRpnt
)->sr_sense_buffer
[12],
886 (*aSRpnt
)->sr_sense_buffer
[13]);
892 * Read the next OnStream tape frame at the current location
894 static int osst_read_frame(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int timeout
)
896 unsigned char cmd
[MAX_COMMAND_SIZE
];
897 struct scsi_request
* SRpnt
;
900 os_aux_t
* aux
= STp
->buffer
->aux
;
901 char * name
= tape_name(STp
);
905 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
))
906 retval
= osst_recover_wait_frame(STp
, aSRpnt
, 0);
908 memset(cmd
, 0, MAX_COMMAND_SIZE
);
915 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
917 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
918 STp
->timeout
, MAX_RETRIES
, 1);
923 if ((STp
->buffer
)->syscall_result
) {
925 if (STp
->read_error_frame
== 0) {
926 STp
->read_error_frame
= STp
->first_frame_position
;
928 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
933 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
935 SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[1],
936 SRpnt
->sr_sense_buffer
[2], SRpnt
->sr_sense_buffer
[3],
937 SRpnt
->sr_sense_buffer
[4], SRpnt
->sr_sense_buffer
[5],
938 SRpnt
->sr_sense_buffer
[6], SRpnt
->sr_sense_buffer
[7]);
942 STp
->first_frame_position
++;
947 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
950 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
951 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
952 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
953 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
954 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
955 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
956 if (aux
->frame_type
==2)
957 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
958 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
959 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
965 static int osst_initiate_read(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
967 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
968 struct scsi_request
* SRpnt
;
969 unsigned char cmd
[MAX_COMMAND_SIZE
];
971 char * name
= tape_name(STp
);
973 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
974 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
975 STp
->write_type
= OS_WRITE_DATA
;
976 osst_flush_write_buffer(STp
, aSRpnt
);
977 osst_flush_drive_buffer(STp
, aSRpnt
);
979 STps
->rw
= ST_READING
;
980 STp
->frame_in_buffer
= 0;
983 * Issue a read 0 command to get the OnStream drive
984 * read frames into its buffer.
986 memset(cmd
, 0, MAX_COMMAND_SIZE
);
991 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
993 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
995 if ((retval
= STp
->buffer
->syscall_result
))
996 printk(KERN_WARNING
"%s:W: Error starting read ahead\n", name
);
1002 static int osst_get_logical_frame(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1003 int frame_seq_number
, int quiet
)
1005 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1006 char * name
= tape_name(STp
);
1014 * If we want just any frame (-1) and there is a frame in the buffer, return it
1016 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
1018 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
1023 * Search and wait for the next logical tape frame
1027 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
1028 name
, frame_seq_number
);
1029 if (STp
->read_error_frame
) {
1030 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
1032 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
1033 name
, STp
->read_error_frame
);
1035 STp
->read_error_frame
= 0;
1042 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
1043 name
, frame_seq_number
, cnt
);
1045 if ( osst_initiate_read(STp
, aSRpnt
)
1046 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
1049 position
= osst_get_frame_position(STp
, aSRpnt
);
1050 if (position
>= 0xbae && position
< 0xbb8)
1052 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
1053 position
= STp
->read_error_frame
- 1;
1061 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1064 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1067 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1069 if (osst_verify_frame(STp
, -1, quiet
)) {
1070 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1071 if (STp
->fast_open
) {
1073 "%s:W: Found logical frame %d instead of %d after fast open\n",
1074 name
, x
, frame_seq_number
);
1076 STp
->read_error_frame
= 0;
1079 if (x
> frame_seq_number
) {
1081 /* positioning backwards did not bring us to the desired frame */
1082 position
= STp
->read_error_frame
- 1;
1085 position
= osst_get_frame_position(STp
, aSRpnt
)
1086 + frame_seq_number
- x
- 1;
1088 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1093 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1094 name
, x
, frame_seq_number
,
1095 STp
->first_frame_position
- position
);
1097 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1103 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1105 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1107 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1110 STp
->frame_in_buffer
= 0;
1113 STp
->recover_count
++;
1114 STp
->recover_erreg
++;
1115 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1116 name
, STp
->read_error_frame
);
1121 if (debugging
|| STps
->eof
)
1123 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1124 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1127 STp
->read_error_frame
= 0;
1131 static int osst_seek_logical_blk(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int logical_blk_num
)
1133 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1134 char * name
= tape_name(STp
);
1136 int frame_seq_estimate
, ppos_estimate
, move
;
1138 if (logical_blk_num
< 0) logical_blk_num
= 0;
1140 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1141 name
, logical_blk_num
, STp
->logical_blk_num
,
1142 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1143 STp
->block_size
<1024?'b':'k');
1145 /* Do we know where we are? */
1146 if (STps
->drv_block
>= 0) {
1147 move
= logical_blk_num
- STp
->logical_blk_num
;
1148 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1149 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1150 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1152 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1154 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1155 else ppos_estimate
= frame_seq_estimate
+ 20;
1156 while (++retries
< 10) {
1157 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1158 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1159 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1161 if (frame_seq_estimate
< 0) {
1162 frame_seq_estimate
= 0;
1165 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1166 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1167 /* we've located the estimated frame, now does it have our block? */
1168 if (logical_blk_num
< STp
->logical_blk_num
||
1169 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1170 if (STps
->eof
== ST_FM_HIT
)
1171 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1173 move
= logical_blk_num
- STp
->logical_blk_num
;
1174 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1175 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1177 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1180 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1181 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1182 STp
->logical_blk_num
, logical_blk_num
, move
);
1184 frame_seq_estimate
+= move
;
1185 ppos_estimate
+= move
;
1188 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1189 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1190 STp
->logical_blk_num
= logical_blk_num
;
1193 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1194 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1195 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1198 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1199 if (STps
->eof
== ST_FM_HIT
) {
1201 STps
->drv_block
= 0;
1203 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1204 STp
->logical_blk_num
-
1205 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1208 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1212 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1214 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1216 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1217 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1218 STp
->logical_blk_num
, logical_blk_num
);
1220 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1221 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1226 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1227 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1231 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1232 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1233 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1234 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1236 #define OSST_FRAME_SHIFT 6
1237 #define OSST_SECTOR_SHIFT 9
1238 #define OSST_SECTOR_MASK 0x03F
1240 static int osst_get_sector(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
1244 char * name
= tape_name(STp
);
1247 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1248 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1249 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1250 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1251 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1252 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1254 /* do we know where we are inside a file? */
1255 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1256 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1257 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1258 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1259 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1261 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1263 sector
= osst_get_frame_position(STp
, aSRpnt
);
1265 sector
<<= OSST_FRAME_SHIFT
;
1270 static int osst_seek_sector(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int sector
)
1272 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1273 int frame
= sector
>> OSST_FRAME_SHIFT
,
1274 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1277 char * name
= tape_name(STp
);
1279 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1280 name
, sector
, frame
, offset
);
1282 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1284 if (frame
<= STp
->first_data_ppos
) {
1285 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1286 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1288 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1289 if (r
< 0) return r
;
1291 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1292 if (r
< 0) return r
;
1294 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1297 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1298 STp
->buffer
->read_pointer
= offset
;
1299 STp
->buffer
->buffer_bytes
-= offset
;
1301 STp
->frame_seq_number
++;
1302 STp
->frame_in_buffer
= 0;
1303 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1304 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1306 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1307 if (STps
->eof
== ST_FM_HIT
) {
1309 STps
->drv_block
= 0;
1311 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1312 STp
->logical_blk_num
-
1313 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1316 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1319 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1320 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1321 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1327 * Read back the drive's internal buffer contents, as a part
1328 * of the write error recovery mechanism for old OnStream
1329 * firmware revisions.
1330 * Precondition for this function to work: all frames in the
1331 * drive's buffer must be of one type (DATA, MARK or EOD)!
1333 static int osst_read_back_buffer_and_rewrite(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1334 unsigned int frame
, unsigned int skip
, int pending
)
1336 struct scsi_request
* SRpnt
= * aSRpnt
;
1337 unsigned char * buffer
, * p
;
1338 unsigned char cmd
[MAX_COMMAND_SIZE
];
1339 int flag
, new_frame
, i
;
1340 int nframes
= STp
->cur_frames
;
1341 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1342 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1343 - (nframes
+ pending
- 1);
1344 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1345 - (nframes
+ pending
- 1) * blks_per_frame
;
1346 char * name
= tape_name(STp
);
1347 unsigned long startwait
= jiffies
;
1349 int dbg
= debugging
;
1352 if ((buffer
= (unsigned char *)vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1355 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1356 name
, nframes
, pending
?" and one that was pending":"");
1358 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1360 if (pending
&& debugging
)
1361 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1362 name
, frame_seq_number
+ nframes
,
1363 logical_blk_num
+ nframes
* blks_per_frame
,
1364 p
[0], p
[1], p
[2], p
[3]);
1366 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1368 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1369 cmd
[0] = 0x3C; /* Buffer Read */
1370 cmd
[1] = 6; /* Retrieve Faulty Block */
1371 cmd
[7] = 32768 >> 8;
1372 cmd
[8] = 32768 & 0xff;
1374 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_FROM_DEVICE
,
1375 STp
->timeout
, MAX_RETRIES
, 1);
1377 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1378 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1383 osst_copy_from_buffer(STp
->buffer
, p
);
1386 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1387 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1391 osst_get_frame_position(STp
, aSRpnt
);
1394 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1396 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1397 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1399 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1402 if (STp
->write_type
== OS_WRITE_HEADER
) {
1404 p
+= skip
* OS_DATA_SIZE
;
1406 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1411 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1412 name
, new_frame
+i
, frame_seq_number
+i
);
1414 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1415 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1416 osst_get_frame_position(STp
, aSRpnt
);
1419 if (new_frame
> frame
+ 1000) {
1420 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1424 if ( i
>= nframes
+ pending
) break;
1427 osst_copy_to_buffer(STp
->buffer
, p
);
1429 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1431 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1432 logical_blk_num
+ i
*blks_per_frame
,
1433 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1434 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1442 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1443 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1444 p
[0], p
[1], p
[2], p
[3]);
1446 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1447 STp
->timeout
, MAX_RETRIES
, 1);
1449 if (STp
->buffer
->syscall_result
)
1452 p
+= OS_DATA_SIZE
; i
++;
1454 /* if we just sent the last frame, wait till all successfully written */
1455 if ( i
== nframes
+ pending
) {
1457 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1459 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1460 cmd
[0] = WRITE_FILEMARKS
;
1462 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
1463 STp
->timeout
, MAX_RETRIES
, 1);
1466 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1467 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1471 flag
= STp
->buffer
->syscall_result
;
1472 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1474 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1475 cmd
[0] = TEST_UNIT_READY
;
1477 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
,
1480 if (SRpnt
->sr_sense_buffer
[2] == 2 && SRpnt
->sr_sense_buffer
[12] == 4 &&
1481 (SRpnt
->sr_sense_buffer
[13] == 1 || SRpnt
->sr_sense_buffer
[13] == 8)) {
1482 /* in the process of becoming ready */
1486 if (STp
->buffer
->syscall_result
)
1492 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1498 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) == 13 &&
1499 SRpnt
->sr_sense_buffer
[12] == 0 &&
1500 SRpnt
->sr_sense_buffer
[13] == 2) {
1501 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1503 return (-EIO
); /* hit end of tape = fail */
1505 i
= ((SRpnt
->sr_sense_buffer
[3] << 24) |
1506 (SRpnt
->sr_sense_buffer
[4] << 16) |
1507 (SRpnt
->sr_sense_buffer
[5] << 8) |
1508 SRpnt
->sr_sense_buffer
[6] ) - new_frame
;
1509 p
= &buffer
[i
* OS_DATA_SIZE
];
1511 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1513 osst_get_frame_position(STp
, aSRpnt
);
1515 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1516 name
, STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
1521 /* error recovery did not successfully complete */
1522 printk(KERN_ERR
"%s:D: Write error recovery failed in %s\n", name
,
1523 STp
->write_type
== OS_WRITE_HEADER
?"header":"body");
1526 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1531 static int osst_reposition_and_retry(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1532 unsigned int frame
, unsigned int skip
, int pending
)
1534 unsigned char cmd
[MAX_COMMAND_SIZE
];
1535 struct scsi_request
* SRpnt
;
1536 char * name
= tape_name(STp
);
1538 int attempts
= 1000 / skip
;
1540 unsigned long startwait
= jiffies
;
1542 int dbg
= debugging
;
1545 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1550 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1552 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1554 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1555 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1557 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1560 schedule_timeout_interruptible(msecs_to_jiffies(100));
1562 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1564 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1565 name
, STp
->first_frame_position
,
1566 STp
->last_frame_position
, STp
->cur_frames
);
1568 frame
= STp
->last_frame_position
;
1572 if (pending
&& STp
->cur_frames
< 50) {
1574 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1579 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1580 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1582 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
,
1583 STp
->timeout
, MAX_RETRIES
, 1);
1586 if (STp
->buffer
->syscall_result
) { /* additional write error */
1587 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) == 13 &&
1588 SRpnt
->sr_sense_buffer
[12] == 0 &&
1589 SRpnt
->sr_sense_buffer
[13] == 2) {
1591 "%s:E: Volume overflow in write error recovery\n",
1593 break; /* hit end of tape = fail */
1602 if (STp
->cur_frames
== 0) {
1605 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1607 if (STp
->first_frame_position
!= expected
) {
1608 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1609 name
, STp
->first_frame_position
, expected
);
1616 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1617 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1621 schedule_timeout_interruptible(msecs_to_jiffies(100));
1623 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1631 * Error recovery algorithm for the OnStream tape.
1634 static int osst_write_error_recovery(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int pending
)
1636 struct scsi_request
* SRpnt
= * aSRpnt
;
1637 struct st_partstat
* STps
= & STp
->ps
[STp
->partition
];
1638 char * name
= tape_name(STp
);
1641 unsigned int frame
, skip
;
1643 rw_state
= STps
->rw
;
1645 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) != 3
1646 || SRpnt
->sr_sense_buffer
[12] != 12
1647 || SRpnt
->sr_sense_buffer
[13] != 0) {
1649 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1650 SRpnt
->sr_sense_buffer
[2], SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
1654 frame
= (SRpnt
->sr_sense_buffer
[3] << 24) |
1655 (SRpnt
->sr_sense_buffer
[4] << 16) |
1656 (SRpnt
->sr_sense_buffer
[5] << 8) |
1657 SRpnt
->sr_sense_buffer
[6];
1658 skip
= SRpnt
->sr_sense_buffer
[9];
1661 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1663 osst_get_frame_position(STp
, aSRpnt
);
1665 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1666 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1668 switch (STp
->write_type
) {
1671 case OS_WRITE_NEW_MARK
:
1673 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1674 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1675 if (STp
->os_fw_rev
>= 10600)
1676 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1678 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1679 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1681 retval
?"" :"Don't worry, ",
1682 retval
?" not ":" ");
1684 case OS_WRITE_LAST_MARK
:
1685 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1686 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1689 case OS_WRITE_HEADER
:
1690 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1691 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1694 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1695 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1697 osst_get_frame_position(STp
, aSRpnt
);
1699 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1700 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1701 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1704 STp
->recover_count
++;
1705 STp
->recover_erreg
++;
1709 STps
->rw
= rw_state
;
1713 static int osst_space_over_filemarks_backward(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1714 int mt_op
, int mt_count
)
1716 char * name
= tape_name(STp
);
1718 int last_mark_ppos
= -1;
1721 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1723 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1725 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1729 if (STp
->linux_media_version
>= 4) {
1731 * direct lookup in header filemark list
1733 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1734 if (STp
->header_ok
&&
1735 STp
->header_cache
!= NULL
&&
1736 (cnt
- mt_count
) >= 0 &&
1737 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1738 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1739 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1741 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1743 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1744 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1745 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1747 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1749 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1750 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1751 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1752 mt_count
, last_mark_ppos
);
1754 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1755 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1756 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1759 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1763 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1764 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1765 name
, last_mark_ppos
);
1771 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1775 while (cnt
!= mt_count
) {
1776 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1777 if (last_mark_ppos
== -1)
1780 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1782 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1784 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1786 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1790 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1791 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1792 name
, last_mark_ppos
);
1797 if (mt_op
== MTBSFM
) {
1798 STp
->frame_seq_number
++;
1799 STp
->frame_in_buffer
= 0;
1800 STp
->buffer
->buffer_bytes
= 0;
1801 STp
->buffer
->read_pointer
= 0;
1802 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1808 * ADRL 1.1 compatible "slow" space filemarks fwd version
1810 * Just scans for the filemark sequentially.
1812 static int osst_space_over_filemarks_forward_slow(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1813 int mt_op
, int mt_count
)
1817 char * name
= tape_name(STp
);
1819 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1821 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1823 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1828 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1830 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1834 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1836 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1838 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1840 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1842 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1843 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1845 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1849 if (cnt
== mt_count
)
1851 STp
->frame_in_buffer
= 0;
1853 if (mt_op
== MTFSF
) {
1854 STp
->frame_seq_number
++;
1855 STp
->frame_in_buffer
= 0;
1856 STp
->buffer
->buffer_bytes
= 0;
1857 STp
->buffer
->read_pointer
= 0;
1858 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1864 * Fast linux specific version of OnStream FSF
1866 static int osst_space_over_filemarks_forward_fast(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
1867 int mt_op
, int mt_count
)
1869 char * name
= tape_name(STp
);
1871 next_mark_ppos
= -1;
1874 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
1876 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1878 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1883 if (STp
->linux_media_version
>= 4) {
1885 * direct lookup in header filemark list
1887 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
1888 if (STp
->header_ok
&&
1889 STp
->header_cache
!= NULL
&&
1890 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
1891 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
1892 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1893 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
1895 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
1897 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
1898 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1899 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1901 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1903 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1904 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
1905 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1906 mt_count
, next_mark_ppos
);
1908 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
1910 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1912 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
1914 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
1915 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1917 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
1922 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1923 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1924 name
, next_mark_ppos
);
1927 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
1928 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
1929 name
, cnt
+mt_count
, next_mark_ppos
,
1930 ntohl(STp
->buffer
->aux
->filemark_cnt
));
1936 * Find nearest (usually previous) marker, then jump from marker to marker
1939 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1941 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1943 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1947 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
1948 if (STp
->first_mark_ppos
== -1) {
1950 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1952 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
1954 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
1955 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1958 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
1963 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1964 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
1965 name
, STp
->first_mark_ppos
);
1969 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
1975 while (cnt
!= mt_count
) {
1976 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
1977 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
1979 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1981 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
1984 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
1986 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
1988 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1990 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
1995 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1996 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1997 name
, next_mark_ppos
);
2002 if (mt_op
== MTFSF
) {
2003 STp
->frame_seq_number
++;
2004 STp
->frame_in_buffer
= 0;
2005 STp
->buffer
->buffer_bytes
= 0;
2006 STp
->buffer
->read_pointer
= 0;
2007 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
2013 * In debug mode, we want to see as many errors as possible
2014 * to test the error recovery mechanism.
2017 static void osst_set_retries(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int retries
)
2019 unsigned char cmd
[MAX_COMMAND_SIZE
];
2020 struct scsi_request
* SRpnt
= * aSRpnt
;
2021 char * name
= tape_name(STp
);
2023 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2024 cmd
[0] = MODE_SELECT
;
2026 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2028 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
2029 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
2030 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
2031 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
2032 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
2033 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
2034 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
2035 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
2038 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
2040 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2043 if ((STp
->buffer
)->syscall_result
)
2044 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
2049 static int osst_write_filemark(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2052 int this_mark_ppos
= STp
->first_frame_position
;
2053 int this_mark_lbn
= STp
->logical_blk_num
;
2055 char * name
= tape_name(STp
);
2058 if (STp
->raw
) return 0;
2060 STp
->write_type
= OS_WRITE_NEW_MARK
;
2062 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2063 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2066 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2067 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2068 STp
->last_mark_ppos
= this_mark_ppos
;
2069 STp
->last_mark_lbn
= this_mark_lbn
;
2070 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2071 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2072 if (STp
->filemark_cnt
++ == 0)
2073 STp
->first_mark_ppos
= this_mark_ppos
;
2077 static int osst_write_eod(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2081 char * name
= tape_name(STp
);
2084 if (STp
->raw
) return 0;
2086 STp
->write_type
= OS_WRITE_EOD
;
2087 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2089 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2090 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2094 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2095 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2096 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2100 static int osst_write_filler(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int where
, int count
)
2102 char * name
= tape_name(STp
);
2105 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2107 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2108 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2109 STp
->write_type
= OS_WRITE_FILLER
;
2111 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2112 STp
->buffer
->buffer_bytes
= 6;
2114 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2115 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2120 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2122 return osst_flush_drive_buffer(STp
, aSRpnt
);
2125 static int __osst_write_header(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int where
, int count
)
2127 char * name
= tape_name(STp
);
2131 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2133 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2134 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2135 STp
->write_type
= OS_WRITE_HEADER
;
2137 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2138 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2140 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2141 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2145 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2147 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2152 static int osst_write_header(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int locate_eod
)
2154 os_header_t
* header
;
2156 char * name
= tape_name(STp
);
2159 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2161 if (STp
->raw
) return 0;
2163 if (STp
->header_cache
== NULL
) {
2164 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2165 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2168 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2170 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2173 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2174 else STp
->update_frame_cntr
= 0;
2176 header
= STp
->header_cache
;
2177 strcpy(header
->ident_str
, "ADR_SEQ");
2178 header
->major_rev
= 1;
2179 header
->minor_rev
= 4;
2180 header
->ext_trk_tb_off
= htons(17192);
2181 header
->pt_par_num
= 1;
2182 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2183 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2184 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2185 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2186 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2187 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2188 header
->cfg_col_width
= htonl(20);
2189 header
->dat_col_width
= htonl(1500);
2190 header
->qfa_col_width
= htonl(0);
2191 header
->ext_track_tb
.nr_stream_part
= 1;
2192 header
->ext_track_tb
.et_ent_sz
= 32;
2193 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2194 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2195 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2196 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2197 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2198 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2199 header
->dat_fm_tab
.fm_part_num
= 0;
2200 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2201 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2202 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2204 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2205 if (STp
->update_frame_cntr
== 0)
2206 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2207 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2211 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2213 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2216 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2218 memcpy(STp
->application_sig
, "LIN4", 4);
2219 STp
->linux_media
= 1;
2220 STp
->linux_media_version
= 4;
2226 static int osst_reset_header(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2228 if (STp
->header_cache
!= NULL
)
2229 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2231 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2232 STp
->frame_in_buffer
= 0;
2233 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2234 STp
->filemark_cnt
= 0;
2235 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2236 return osst_write_header(STp
, aSRpnt
, 1);
2239 static int __osst_analyze_headers(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int ppos
)
2241 char * name
= tape_name(STp
);
2242 os_header_t
* header
;
2245 int linux_media_version
,
2251 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2252 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2253 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2254 osst_wait_ready(STp
, aSRpnt
, 60 * 15, 0);
2255 if (osst_initiate_read (STp
, aSRpnt
)) {
2256 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2260 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2262 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2266 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2267 aux
= STp
->buffer
->aux
;
2268 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2270 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2274 if (ntohl(aux
->frame_seq_num
) != 0 ||
2275 ntohl(aux
->logical_blk_num
) != 0 ||
2276 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2277 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2278 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2280 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2281 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2282 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2283 ntohl(aux
->partition
.last_frame_ppos
));
2287 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2288 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2289 strlcpy(id_string
, header
->ident_str
, 8);
2291 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2295 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2296 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2298 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2299 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2303 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2305 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2306 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2307 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2308 header
->major_rev
, header
->minor_rev
);
2310 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2314 if (header
->pt_par_num
!= 1)
2315 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2316 name
, header
->pt_par_num
);
2318 memcpy(id_string
, aux
->application_sig
, 4);
2320 if (memcmp(id_string
, "LIN", 3) == 0) {
2321 STp
->linux_media
= 1;
2322 linux_media_version
= id_string
[3] - '0';
2323 if (linux_media_version
!= 4)
2324 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2325 name
, linux_media_version
);
2327 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2330 if (linux_media_version
< STp
->linux_media_version
) {
2332 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2333 name
, ppos
, linux_media_version
);
2337 if (linux_media_version
> STp
->linux_media_version
) {
2339 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2340 name
, ppos
, linux_media_version
);
2342 memcpy(STp
->application_sig
, id_string
, 5);
2343 STp
->linux_media_version
= linux_media_version
;
2344 STp
->update_frame_cntr
= -1;
2346 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2348 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2349 name
, ppos
, update_frame_cntr
);
2351 if (STp
->header_cache
== NULL
) {
2352 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2353 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2357 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2360 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2361 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2363 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2364 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2365 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2366 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2367 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2368 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2369 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2370 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2371 STp
->update_frame_cntr
= update_frame_cntr
;
2373 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2374 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2375 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2376 STp
->first_data_ppos
,
2377 ntohl(header
->partition
[0].last_frame_ppos
),
2378 ntohl(header
->partition
[0].eod_frame_ppos
));
2379 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2380 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2382 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2384 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2386 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2387 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2388 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2390 if (header
->minor_rev
== 4 &&
2391 (header
->ext_trk_tb_off
!= htons(17192) ||
2392 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2393 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2394 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2395 header
->cfg_col_width
!= htonl(20) ||
2396 header
->dat_col_width
!= htonl(1500) ||
2397 header
->qfa_col_width
!= htonl(0) ||
2398 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2399 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2400 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2401 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2402 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2403 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2404 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2405 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2406 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2407 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2408 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2409 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2416 static int osst_analyze_headers(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2421 char * name
= tape_name(STp
);
2423 position
= osst_get_frame_position(STp
, aSRpnt
);
2426 STp
->header_ok
= STp
->linux_media
= 1;
2427 STp
->linux_media_version
= 0;
2430 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2431 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2432 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2433 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2435 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2438 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2439 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2441 first
= position
==10?0xbae: 5;
2442 last
= position
==10?0xbb3:10;
2444 for (ppos
= first
; ppos
< last
; ppos
++)
2445 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2448 first
= position
==10? 5:0xbae;
2449 last
= position
==10?10:0xbb3;
2451 for (ppos
= first
; ppos
< last
; ppos
++)
2452 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2456 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2457 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2458 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2461 if (position
<= STp
->first_data_ppos
) {
2462 position
= STp
->first_data_ppos
;
2463 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2465 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2471 static int osst_verify_position(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
)
2473 int frame_position
= STp
->first_frame_position
;
2474 int frame_seq_numbr
= STp
->frame_seq_number
;
2475 int logical_blk_num
= STp
->logical_blk_num
;
2476 int halfway_frame
= STp
->frame_in_buffer
;
2477 int read_pointer
= STp
->buffer
->read_pointer
;
2478 int prev_mark_ppos
= -1;
2479 int actual_mark_ppos
, i
, n
;
2481 char * name
= tape_name(STp
);
2483 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2485 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2486 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2488 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2492 if (STp
->linux_media_version
>= 4) {
2493 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2494 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2497 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2498 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2499 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2500 if (frame_position
!= STp
->first_frame_position
||
2501 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2502 prev_mark_ppos
!= actual_mark_ppos
) {
2504 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2505 STp
->first_frame_position
, frame_position
,
2506 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2507 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2511 if (halfway_frame
) {
2512 /* prepare buffer for append and rewrite on top of original */
2513 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2514 STp
->buffer
->buffer_bytes
= read_pointer
;
2515 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2518 STp
->frame_in_buffer
= halfway_frame
;
2519 STp
->frame_seq_number
= frame_seq_numbr
;
2520 STp
->logical_blk_num
= logical_blk_num
;
2524 /* Acc. to OnStream, the vers. numbering is the following:
2525 * X.XX for released versions (X=digit),
2526 * XXXY for unreleased versions (Y=letter)
2527 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2528 * This fn makes monoton numbers out of this scheme ...
2530 static unsigned int osst_parse_firmware_rev (const char * str
)
2532 if (str
[1] == '.') {
2533 return (str
[0]-'0')*10000
2537 return (str
[0]-'0')*10000
2539 +(str
[2]-'0')*100 - 100
2545 * Configure the OnStream SCII tape drive for default operation
2547 static int osst_configure_onstream(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
)
2549 unsigned char cmd
[MAX_COMMAND_SIZE
];
2550 char * name
= tape_name(STp
);
2551 struct scsi_request
* SRpnt
= * aSRpnt
;
2552 osst_mode_parameter_header_t
* header
;
2553 osst_block_size_page_t
* bs
;
2554 osst_capabilities_page_t
* cp
;
2555 osst_tape_paramtr_page_t
* prm
;
2556 int drive_buffer_size
;
2558 if (STp
->ready
!= ST_READY
) {
2560 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2565 if (STp
->os_fw_rev
< 10600) {
2566 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2567 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2571 * Configure 32.5KB (data+aux) frame size.
2572 * Get the current frame size from the block size mode page
2574 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2575 cmd
[0] = MODE_SENSE
;
2577 cmd
[2] = BLOCK_SIZE_PAGE
;
2578 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2580 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2581 if (SRpnt
== NULL
) {
2583 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2588 if ((STp
->buffer
)->syscall_result
!= 0) {
2589 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2593 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2594 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2597 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2598 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2599 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2600 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2604 * Configure default auto columns mode, 32.5KB transfer mode
2612 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2613 cmd
[0] = MODE_SELECT
;
2615 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2617 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2619 if ((STp
->buffer
)->syscall_result
!= 0) {
2620 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2625 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2627 * In debug mode, we want to see as many errors as possible
2628 * to test the error recovery mechanism.
2630 osst_set_retries(STp
, aSRpnt
, 0);
2635 * Set vendor name to 'LIN4' for "Linux support version 4".
2638 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2639 cmd
[0] = MODE_SELECT
;
2641 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2643 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2644 header
->medium_type
= 0; /* Medium Type - ignoring */
2645 header
->dsp
= 0; /* Reserved */
2646 header
->bdl
= 0; /* Block Descriptor Length */
2648 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2649 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2650 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2651 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2652 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2653 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2654 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2655 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2657 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
2660 if ((STp
->buffer
)->syscall_result
!= 0) {
2661 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2662 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2666 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2667 cmd
[0] = MODE_SENSE
;
2669 cmd
[2] = CAPABILITIES_PAGE
;
2670 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2672 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2675 if ((STp
->buffer
)->syscall_result
!= 0) {
2676 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2680 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2681 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2682 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2684 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2686 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2687 cmd
[0] = MODE_SENSE
;
2689 cmd
[2] = TAPE_PARAMTR_PAGE
;
2690 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2692 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
2695 if ((STp
->buffer
)->syscall_result
!= 0) {
2696 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2700 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2701 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2702 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2704 STp
->density
= prm
->density
;
2705 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2707 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2708 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2716 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2717 it messes up the block number). */
2718 static int cross_eof(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
, int forward
)
2721 char * name
= tape_name(STp
);
2725 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2726 name
, forward
? "forward" : "backward");
2730 /* assumes that the filemark is already read by the drive, so this is low cost */
2731 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2734 /* assumes this is only called if we just read the filemark! */
2735 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2738 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2739 name
, forward
? "forward" : "backward");
2745 /* Get the tape position. */
2747 static int osst_get_frame_position(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
)
2749 unsigned char scmd
[MAX_COMMAND_SIZE
];
2750 struct scsi_request
* SRpnt
;
2752 char * name
= tape_name(STp
);
2754 /* KG: We want to be able to use it for checking Write Buffer availability
2755 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2757 char * olddata
= STp
->buffer
->b_data
;
2758 int oldsize
= STp
->buffer
->buffer_size
;
2760 if (STp
->ready
!= ST_READY
) return (-EIO
);
2762 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2763 scmd
[0] = READ_POSITION
;
2765 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2766 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2767 STp
->timeout
, MAX_RETRIES
, 1);
2769 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2774 if (STp
->buffer
->syscall_result
)
2775 result
= ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
; /* 3: Write Error */
2777 if (result
== -EINVAL
)
2778 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2780 if (result
== -EIO
) { /* re-read position - this needs to preserve media errors */
2781 unsigned char mysense
[16];
2782 memcpy (mysense
, SRpnt
->sr_sense_buffer
, 16);
2783 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2784 scmd
[0] = READ_POSITION
;
2785 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2786 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, DMA_FROM_DEVICE
,
2787 STp
->timeout
, MAX_RETRIES
, 1);
2789 printk(OSST_DEB_MSG
"%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2790 name
, mysense
[2], mysense
[12], mysense
[13], STp
->buffer
->syscall_result
?"":"ok:",
2791 SRpnt
->sr_sense_buffer
[2],SRpnt
->sr_sense_buffer
[12],SRpnt
->sr_sense_buffer
[13]);
2793 if (!STp
->buffer
->syscall_result
)
2794 memcpy (SRpnt
->sr_sense_buffer
, mysense
, 16);
2796 printk(KERN_WARNING
"%s:W: Double error in get position\n", name
);
2798 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2799 + ((STp
->buffer
)->b_data
[5] << 16)
2800 + ((STp
->buffer
)->b_data
[6] << 8)
2801 + (STp
->buffer
)->b_data
[7];
2802 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2803 + ((STp
->buffer
)->b_data
[ 9] << 16)
2804 + ((STp
->buffer
)->b_data
[10] << 8)
2805 + (STp
->buffer
)->b_data
[11];
2806 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2809 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2810 STp
->first_frame_position
, STp
->last_frame_position
,
2811 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2812 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2816 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2818 printk(OSST_DEB_MSG
"%s:D: Correcting read position %d, %d, %d\n", name
,
2819 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2821 STp
->first_frame_position
= STp
->last_frame_position
;
2824 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2826 return (result
== 0 ? STp
->first_frame_position
: result
);
2830 /* Set the tape block */
2831 static int osst_set_frame_position(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
, int ppos
, int skip
)
2833 unsigned char scmd
[MAX_COMMAND_SIZE
];
2834 struct scsi_request
* SRpnt
;
2835 struct st_partstat
* STps
;
2837 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2838 char * name
= tape_name(STp
);
2840 if (STp
->ready
!= ST_READY
) return (-EIO
);
2842 STps
= &(STp
->ps
[STp
->partition
]);
2844 if (ppos
< 0 || ppos
> STp
->capacity
) {
2845 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2846 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2853 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2855 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2858 scmd
[3] = (pp
>> 24);
2859 scmd
[4] = (pp
>> 16);
2860 scmd
[5] = (pp
>> 8);
2865 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, DMA_NONE
, STp
->long_timeout
,
2871 if ((STp
->buffer
)->syscall_result
!= 0) {
2873 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
2874 name
, STp
->first_frame_position
, pp
);
2879 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
2880 } while ((pp
!= ppos
) && (pp
= ppos
));
2881 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
2882 STps
->eof
= ST_NOEOF
;
2885 STp
->frame_in_buffer
= 0;
2889 static int osst_write_trailer(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
, int leave_at_EOT
)
2891 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
2894 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
2895 /* true unless the user wrote the filemark for us */
2896 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2897 if (result
< 0) goto out
;
2898 result
= osst_write_filemark(STp
, aSRpnt
);
2899 if (result
< 0) goto out
;
2901 if (STps
->drv_file
>= 0)
2903 STps
->drv_block
= 0;
2905 result
= osst_write_eod(STp
, aSRpnt
);
2906 osst_write_header(STp
, aSRpnt
, leave_at_EOT
);
2913 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2915 /* Flush the write buffer (never need to write if variable blocksize). */
2916 static int osst_flush_write_buffer(struct osst_tape
*STp
, struct scsi_request
** aSRpnt
)
2918 int offset
, transfer
, blks
= 0;
2920 unsigned char cmd
[MAX_COMMAND_SIZE
];
2921 struct scsi_request
* SRpnt
= *aSRpnt
;
2922 struct st_partstat
* STps
;
2923 char * name
= tape_name(STp
);
2925 if ((STp
->buffer
)->writing
) {
2926 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
2928 { printk(OSST_DEB_MSG
2929 "%s:D: aSRpnt points to scsi_request that write_behind_check will release -- cleared\n", name
);
2931 *aSRpnt
= SRpnt
= NULL
;
2935 "%s:D: aSRpnt does not point to scsi_request that write_behind_check will release -- strange\n", name
);
2937 osst_write_behind_check(STp
);
2938 if ((STp
->buffer
)->syscall_result
) {
2941 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
2942 name
, (STp
->buffer
)->midlevel_result
);
2944 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
2951 if (STp
->dirty
== 1) {
2954 STps
= &(STp
->ps
[STp
->partition
]);
2955 STps
->rw
= ST_WRITING
;
2956 offset
= STp
->buffer
->buffer_bytes
;
2957 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
2958 transfer
= OS_FRAME_SIZE
;
2960 if (offset
< OS_DATA_SIZE
)
2961 osst_zero_buffer_tail(STp
->buffer
);
2964 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120))
2965 result
= osst_recover_wait_frame(STp
, aSRpnt
, 1);
2967 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2972 switch (STp
->write_type
) {
2976 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
2977 name
, blks
, STp
->frame_seq_number
,
2978 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
2980 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
2981 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
2984 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
2985 STp
->logical_blk_num
, 0, 0);
2987 case OS_WRITE_NEW_MARK
:
2988 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
2989 STp
->logical_blk_num
++, 0, blks
=1);
2991 case OS_WRITE_HEADER
:
2992 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
2994 default: /* probably FILLER */
2995 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
2999 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3000 name
, offset
, transfer
, blks
);
3003 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, DMA_TO_DEVICE
,
3004 STp
->timeout
, MAX_RETRIES
, 1);
3009 if ((STp
->buffer
)->syscall_result
!= 0) {
3012 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3013 name
, SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[2],
3014 SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
3016 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
3017 (SRpnt
->sr_sense_buffer
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3018 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NO_SENSE
) {
3020 (STp
->buffer
)->buffer_bytes
= 0;
3024 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
3025 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
3029 STps
->drv_block
= (-1); /* FIXME - even if write recovery succeeds? */
3032 STp
->first_frame_position
++;
3034 (STp
->buffer
)->buffer_bytes
= 0;
3038 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
3044 /* Flush the tape buffer. The tape will be positioned correctly unless
3045 seek_next is true. */
3046 static int osst_flush_buffer(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int seek_next
)
3048 struct st_partstat
* STps
;
3049 int backspace
= 0, result
= 0;
3051 char * name
= tape_name(STp
);
3055 * If there was a bus reset, block further access
3058 if( STp
->pos_unknown
)
3061 if (STp
->ready
!= ST_READY
)
3064 STps
= &(STp
->ps
[STp
->partition
]);
3065 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
3066 STp
->write_type
= OS_WRITE_DATA
;
3067 return osst_flush_write_buffer(STp
, aSRpnt
);
3069 if (STp
->block_size
== 0)
3073 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
3076 if (!STp
->can_bsr
) {
3077 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
3078 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
3079 (STp
->buffer
)->buffer_bytes
= 0;
3080 (STp
->buffer
)->read_pointer
= 0;
3081 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
3085 if (STps
->eof
== ST_FM_HIT
) {
3086 result
= cross_eof(STp
, aSRpnt
, 0); /* Back over the EOF hit */
3088 STps
->eof
= ST_NOEOF
;
3090 if (STps
->drv_file
>= 0)
3092 STps
->drv_block
= 0;
3095 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3096 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3098 else if (STps
->eof
== ST_FM_HIT
) {
3099 if (STps
->drv_file
>= 0)
3101 STps
->drv_block
= 0;
3102 STps
->eof
= ST_NOEOF
;
3108 static int osst_write_frame(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
, int synchronous
)
3110 unsigned char cmd
[MAX_COMMAND_SIZE
];
3111 struct scsi_request
* SRpnt
;
3114 char * name
= tape_name(STp
);
3117 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3119 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3121 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3124 /* error recovery may have bumped us past the header partition */
3125 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3127 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3129 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3134 if (osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -48, 120))
3135 if (osst_recover_wait_frame(STp
, aSRpnt
, 1))
3138 // osst_build_stats(STp, &SRpnt);
3140 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3141 STp
->write_type
= OS_WRITE_DATA
;
3143 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3146 cmd
[4] = 1; /* one frame at a time... */
3147 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3150 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3151 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3153 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3154 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3158 STp
->write_pending
= 1;
3160 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, DMA_TO_DEVICE
, STp
->timeout
,
3161 MAX_RETRIES
, synchronous
);
3167 if (STp
->buffer
->syscall_result
!= 0) {
3170 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3172 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
3173 (SRpnt
->sr_sense_buffer
[2] & 0x40)) {
3174 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == VOLUME_OVERFLOW
)
3178 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3183 STp
->first_frame_position
++;
3191 /* Lock or unlock the drive door. Don't use when struct scsi_request allocated. */
3192 static int do_door_lock(struct osst_tape
* STp
, int do_lock
)
3196 cmd
= do_lock
? SCSI_IOCTL_DOORLOCK
: SCSI_IOCTL_DOORUNLOCK
;
3198 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3200 retval
= scsi_ioctl(STp
->device
, cmd
, NULL
);
3202 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3205 STp
->door_locked
= ST_LOCK_FAILS
;
3210 /* Set the internal state after reset */
3211 static void reset_state(struct osst_tape
*STp
)
3214 struct st_partstat
*STps
;
3216 STp
->pos_unknown
= 0;
3217 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3218 STps
= &(STp
->ps
[i
]);
3220 STps
->eof
= ST_NOEOF
;
3222 STps
->last_block_valid
= 0;
3223 STps
->drv_block
= -1;
3224 STps
->drv_file
= -1;
3229 /* Entry points to osst */
3232 static ssize_t
osst_write(struct file
* filp
, const char __user
* buf
, size_t count
, loff_t
*ppos
)
3234 ssize_t total
, retval
= 0;
3235 ssize_t i
, do_count
, blks
, transfer
;
3236 int write_threshold
;
3237 int doing_write
= 0;
3238 const char __user
* b_point
;
3239 struct scsi_request
* SRpnt
= NULL
;
3240 struct st_modedef
* STm
;
3241 struct st_partstat
* STps
;
3242 struct osst_tape
* STp
= filp
->private_data
;
3243 char * name
= tape_name(STp
);
3246 if (down_interruptible(&STp
->lock
))
3247 return (-ERESTARTSYS
);
3250 * If we are in the middle of error recovery, don't let anyone
3251 * else try and use this device. Also, if error recovery fails, it
3252 * may try and take the device offline, in which case all further
3253 * access to the device is prohibited.
3255 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3260 if (STp
->ready
!= ST_READY
) {
3261 if (STp
->ready
== ST_NO_TAPE
)
3262 retval
= (-ENOMEDIUM
);
3267 STm
= &(STp
->modes
[STp
->current_mode
]);
3268 if (!STm
->defined
) {
3276 * If there was a bus reset, block further access
3279 if (STp
->pos_unknown
) {
3286 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3292 if (STp
->write_prot
) {
3297 /* Write must be integral number of blocks */
3298 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3299 printk(KERN_ERR
"%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3300 name
, count
, STp
->block_size
<1024?
3301 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3306 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3307 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3308 name
, STp
->first_frame_position
);
3313 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3314 STp
->door_locked
= ST_LOCKED_AUTO
;
3316 STps
= &(STp
->ps
[STp
->partition
]);
3318 if (STps
->rw
== ST_READING
) {
3320 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3321 STps
->drv_file
, STps
->drv_block
);
3323 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3328 if (STps
->rw
!= ST_WRITING
) {
3329 /* Are we totally rewriting this tape? */
3330 if (!STp
->header_ok
||
3331 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3332 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3333 STp
->wrt_pass_cntr
++;
3335 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3336 name
, STp
->wrt_pass_cntr
);
3338 osst_reset_header(STp
, &SRpnt
);
3339 STps
->drv_file
= STps
->drv_block
= 0;
3341 /* Do we know where we'll be writing on the tape? */
3343 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3344 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3345 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3346 STps
->drv_file
= STp
->filemark_cnt
;
3347 STps
->drv_block
= 0;
3350 /* We have no idea where the tape is positioned - give up */
3353 "%s:D: Cannot write at indeterminate position.\n", name
);
3359 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3360 STp
->filemark_cnt
= STps
->drv_file
;
3361 STp
->last_mark_ppos
=
3362 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3364 "%s:W: Overwriting file %d with old write pass counter %d\n",
3365 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3367 "%s:W: may lead to stale data being accepted on reading back!\n",
3371 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3372 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3378 if (!STp
->header_ok
) {
3380 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3386 if ((STp
->buffer
)->writing
) {
3387 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3388 osst_write_behind_check(STp
);
3389 if ((STp
->buffer
)->syscall_result
) {
3392 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3393 (STp
->buffer
)->midlevel_result
);
3395 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3396 STps
->eof
= ST_EOM_OK
;
3398 STps
->eof
= ST_EOM_ERROR
;
3401 if (STps
->eof
== ST_EOM_OK
) {
3405 else if (STps
->eof
== ST_EOM_ERROR
) {
3410 /* Check the buffer readability in cases where copy_user might catch
3411 the problems after some tape movement. */
3412 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3413 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3418 if (!STm
->do_buffer_writes
) {
3419 write_threshold
= 1;
3422 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3423 if (!STm
->do_async_writes
)
3429 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3430 name
, count
, STps
->drv_file
, STps
->drv_block
,
3431 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3434 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3437 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3438 (STp
->buffer
)->buffer_bytes
;
3439 if (do_count
> count
)
3442 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3448 blks
= do_count
/ STp
->block_size
;
3449 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3451 i
= osst_write_frame(STp
, &SRpnt
, 1);
3453 if (i
== (-ENOSPC
)) {
3454 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3455 if (transfer
<= do_count
) {
3456 filp
->f_pos
+= do_count
- transfer
;
3457 count
-= do_count
- transfer
;
3458 if (STps
->drv_block
>= 0) {
3459 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3461 STps
->eof
= ST_EOM_OK
;
3462 retval
= (-ENOSPC
); /* EOM within current request */
3465 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3470 STps
->eof
= ST_EOM_ERROR
;
3471 STps
->drv_block
= (-1); /* Too cautious? */
3472 retval
= (-EIO
); /* EOM for old data */
3475 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3483 if (SRpnt
!= NULL
) {
3484 scsi_release_request(SRpnt
);
3487 STp
->buffer
->buffer_bytes
= 0;
3490 retval
= total
- count
;
3494 filp
->f_pos
+= do_count
;
3495 b_point
+= do_count
;
3497 if (STps
->drv_block
>= 0) {
3498 STps
->drv_block
+= blks
;
3500 STp
->buffer
->buffer_bytes
= 0;
3502 } /* end while write threshold exceeded */
3506 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3511 blks
= count
/ STp
->block_size
;
3512 STp
->logical_blk_num
+= blks
;
3513 if (STps
->drv_block
>= 0) {
3514 STps
->drv_block
+= blks
;
3516 filp
->f_pos
+= count
;
3520 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3521 retval
= (STp
->buffer
)->syscall_result
;
3525 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3526 /* Schedule an asynchronous write */
3527 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3528 STp
->block_size
) * STp
->block_size
;
3529 STp
->dirty
= !((STp
->buffer
)->writing
==
3530 (STp
->buffer
)->buffer_bytes
);
3532 i
= osst_write_frame(STp
, &SRpnt
, 0);
3537 SRpnt
= NULL
; /* Prevent releasing this request! */
3539 STps
->at_sm
&= (total
== 0);
3541 STps
->eof
= ST_NOEOF
;
3546 if (SRpnt
!= NULL
) scsi_release_request(SRpnt
);
3555 static ssize_t
osst_read(struct file
* filp
, char __user
* buf
, size_t count
, loff_t
*ppos
)
3557 ssize_t total
, retval
= 0;
3558 ssize_t i
, transfer
;
3560 struct st_modedef
* STm
;
3561 struct st_partstat
* STps
;
3562 struct scsi_request
* SRpnt
= NULL
;
3563 struct osst_tape
* STp
= filp
->private_data
;
3564 char * name
= tape_name(STp
);
3567 if (down_interruptible(&STp
->lock
))
3568 return (-ERESTARTSYS
);
3571 * If we are in the middle of error recovery, don't let anyone
3572 * else try and use this device. Also, if error recovery fails, it
3573 * may try and take the device offline, in which case all further
3574 * access to the device is prohibited.
3576 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3581 if (STp
->ready
!= ST_READY
) {
3582 if (STp
->ready
== ST_NO_TAPE
)
3583 retval
= (-ENOMEDIUM
);
3588 STm
= &(STp
->modes
[STp
->current_mode
]);
3589 if (!STm
->defined
) {
3595 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3600 /* Must have initialized medium */
3601 if (!STp
->header_ok
) {
3606 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3607 STp
->door_locked
= ST_LOCKED_AUTO
;
3609 STps
= &(STp
->ps
[STp
->partition
]);
3610 if (STps
->rw
== ST_WRITING
) {
3611 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3615 /* FIXME -- this may leave the tape without EOD and up2date headers */
3618 if ((count
% STp
->block_size
) != 0) {
3620 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3621 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3625 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3626 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3627 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3629 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3630 STps
->eof
>= ST_EOD_1
) {
3631 if (STps
->eof
< ST_EOD
) {
3636 retval
= (-EIO
); /* EOM or Blank Check */
3640 /* Check the buffer writability before any tape movement. Don't alter
3642 if (copy_from_user(&i
, buf
, 1) != 0 ||
3643 copy_to_user (buf
, &i
, 1) != 0 ||
3644 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3645 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3650 /* Loop until enough data in buffer or a special condition found */
3651 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3653 /* Get new data if the buffer is empty */
3654 if ((STp
->buffer
)->buffer_bytes
== 0) {
3655 if (STps
->eof
== ST_FM_HIT
)
3657 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3658 if (special
< 0) { /* No need to continue read */
3659 STp
->frame_in_buffer
= 0;
3665 /* Move the data from driver buffer to user buffer */
3666 if ((STp
->buffer
)->buffer_bytes
> 0) {
3668 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3669 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3670 STps
->eof
, (STp
->buffer
)->buffer_bytes
, count
- total
);
3672 /* force multiple of block size, note block_size may have been adjusted */
3673 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3674 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3675 STp
->block_size
) * STp
->block_size
;
3677 if (transfer
== 0) {
3679 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3680 name
, count
, STp
->block_size
< 1024?
3681 STp
->block_size
:STp
->block_size
/1024,
3682 STp
->block_size
<1024?'b':'k');
3685 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3690 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3691 STps
->drv_block
+= transfer
/ STp
->block_size
;
3692 filp
->f_pos
+= transfer
;
3697 if ((STp
->buffer
)->buffer_bytes
== 0) {
3700 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3701 name
, STp
->frame_seq_number
);
3703 STp
->frame_in_buffer
= 0;
3704 STp
->frame_seq_number
++; /* frame to look for next time */
3706 } /* for (total = 0, special = 0; total < count && !special; ) */
3708 /* Change the eof state if no data from tape or buffer */
3710 if (STps
->eof
== ST_FM_HIT
) {
3711 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD_2
:ST_FM
;
3712 STps
->drv_block
= 0;
3713 if (STps
->drv_file
>= 0)
3716 else if (STps
->eof
== ST_EOD_1
) {
3717 STps
->eof
= ST_EOD_2
;
3718 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3720 STps
->drv_block
= 0;
3722 else if (STps
->eof
== ST_EOD_2
)
3725 else if (STps
->eof
== ST_FM
)
3726 STps
->eof
= ST_NOEOF
;
3731 if (SRpnt
!= NULL
) scsi_release_request(SRpnt
);
3739 /* Set the driver options */
3740 static void osst_log_options(struct osst_tape
*STp
, struct st_modedef
*STm
, char *name
)
3743 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3744 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3745 STm
->do_read_ahead
);
3747 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3748 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3750 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3751 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3752 STp
->scsi2_logical
);
3754 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3757 "%s:D: debugging: %d\n",
3763 static int osst_set_options(struct osst_tape
*STp
, long options
)
3767 struct st_modedef
* STm
;
3768 char * name
= tape_name(STp
);
3770 STm
= &(STp
->modes
[STp
->current_mode
]);
3771 if (!STm
->defined
) {
3772 memcpy(STm
, &(STp
->modes
[0]), sizeof(*STm
));
3776 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3777 name
, STp
->current_mode
);
3781 code
= options
& MT_ST_OPTIONS
;
3782 if (code
== MT_ST_BOOLEANS
) {
3783 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3784 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3785 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3786 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3787 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3788 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3789 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3790 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3791 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3792 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3793 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3794 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3795 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3797 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3799 osst_log_options(STp
, STm
, name
);
3801 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3802 value
= (code
== MT_ST_SETBOOLEANS
);
3803 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3804 STm
->do_buffer_writes
= value
;
3805 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3806 STm
->do_async_writes
= value
;
3807 if ((options
& MT_ST_DEF_WRITES
) != 0)
3808 STm
->defaults_for_writes
= value
;
3809 if ((options
& MT_ST_READ_AHEAD
) != 0)
3810 STm
->do_read_ahead
= value
;
3811 if ((options
& MT_ST_TWO_FM
) != 0)
3812 STp
->two_fm
= value
;
3813 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3814 STp
->fast_mteom
= value
;
3815 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3816 STp
->do_auto_lock
= value
;
3817 if ((options
& MT_ST_CAN_BSR
) != 0)
3818 STp
->can_bsr
= value
;
3819 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3820 STp
->omit_blklims
= value
;
3821 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3822 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3823 STp
->can_partitions
= value
;
3824 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3825 STp
->scsi2_logical
= value
;
3826 if ((options
& MT_ST_SYSV
) != 0)
3829 if ((options
& MT_ST_DEBUGGING
) != 0)
3832 osst_log_options(STp
, STm
, name
);
3834 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3835 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3836 if (value
< 1 || value
> osst_buffer_size
) {
3837 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3841 STp
->write_threshold
= value
;
3842 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3845 else if (code
== MT_ST_DEF_BLKSIZE
) {
3846 value
= (options
& ~MT_ST_OPTIONS
);
3847 if (value
== ~MT_ST_OPTIONS
) {
3848 STm
->default_blksize
= (-1);
3849 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3852 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3853 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3857 STm
->default_blksize
= value
;
3858 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3859 name
, STm
->default_blksize
);
3862 else if (code
== MT_ST_TIMEOUTS
) {
3863 value
= (options
& ~MT_ST_OPTIONS
);
3864 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
3865 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
3866 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
3867 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
3870 STp
->timeout
= value
* HZ
;
3871 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
3874 else if (code
== MT_ST_DEF_OPTIONS
) {
3875 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
3876 value
= (options
& MT_ST_CLEAR_DEFAULT
);
3877 if (code
== MT_ST_DEF_DENSITY
) {
3878 if (value
== MT_ST_CLEAR_DEFAULT
) {
3879 STm
->default_density
= (-1);
3880 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
3883 STm
->default_density
= value
& 0xff;
3884 printk(KERN_INFO
"%s:I: Density default set to %x\n",
3885 name
, STm
->default_density
);
3888 else if (code
== MT_ST_DEF_DRVBUFFER
) {
3889 if (value
== MT_ST_CLEAR_DEFAULT
) {
3890 STp
->default_drvbuffer
= 0xff;
3891 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
3894 STp
->default_drvbuffer
= value
& 7;
3895 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
3896 name
, STp
->default_drvbuffer
);
3899 else if (code
== MT_ST_DEF_COMPRESSION
) {
3900 if (value
== MT_ST_CLEAR_DEFAULT
) {
3901 STm
->default_compression
= ST_DONT_TOUCH
;
3902 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
3905 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
3906 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
3918 /* Internal ioctl function */
3919 static int osst_int_ioctl(struct osst_tape
* STp
, struct scsi_request
** aSRpnt
,
3920 unsigned int cmd_in
, unsigned long arg
)
3924 int i
, ioctl_result
;
3926 unsigned char cmd
[MAX_COMMAND_SIZE
];
3927 struct scsi_request
* SRpnt
= * aSRpnt
;
3928 struct st_partstat
* STps
;
3929 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
3930 int datalen
= 0, direction
= DMA_NONE
;
3931 char * name
= tape_name(STp
);
3933 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
3934 if (STp
->ready
== ST_NO_TAPE
)
3935 return (-ENOMEDIUM
);
3939 timeout
= STp
->long_timeout
;
3940 STps
= &(STp
->ps
[STp
->partition
]);
3941 fileno
= STps
->drv_file
;
3942 blkno
= STps
->drv_block
;
3943 at_sm
= STps
->at_sm
;
3944 frame_seq_numbr
= STp
->frame_seq_number
;
3945 logical_blk_num
= STp
->logical_blk_num
;
3947 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3950 chg_eof
= 0; /* Changed from the FSF after this */
3954 if (STp
->linux_media
)
3955 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
3957 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
3961 at_sm
&= (arg
== 0);
3965 chg_eof
= 0; /* Changed from the FSF after this */
3969 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
3972 blkno
= (-1); /* We can't know the block number */
3973 at_sm
&= (arg
== 0);
3980 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
3981 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
3983 if (cmd_in
== MTFSR
) {
3984 logical_blk_num
+= arg
;
3985 if (blkno
>= 0) blkno
+= arg
;
3988 logical_blk_num
-= arg
;
3989 if (blkno
>= 0) blkno
-= arg
;
3991 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
3992 fileno
= STps
->drv_file
;
3993 blkno
= STps
->drv_block
;
3994 at_sm
&= (arg
== 0);
3999 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4000 cmd
[2] = (arg
>> 16);
4001 cmd
[3] = (arg
>> 8);
4005 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
4006 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4009 blkno
= fileno
= (-1);
4015 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4017 cmd
[2] = (ltmp
>> 16);
4018 cmd
[3] = (ltmp
>> 8);
4024 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
4025 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
4030 blkno
= fileno
= (-1);
4035 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4036 STp
->write_type
= OS_WRITE_DATA
;
4037 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
4042 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
4044 for (i
=0; i
<arg
; i
++)
4045 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
4046 if (fileno
>= 0) fileno
+= arg
;
4047 if (blkno
>= 0) blkno
= 0;
4051 if (STp
->write_prot
)
4055 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
4056 if (cmd_in
== MTWSM
)
4058 cmd
[2] = (arg
>> 16);
4059 cmd
[3] = (arg
>> 8);
4061 timeout
= STp
->timeout
;
4064 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
4065 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
4070 at_sm
= (cmd_in
== MTWSM
);
4076 cmd
[0] = START_STOP
;
4077 cmd
[1] = 1; /* Don't wait for completion */
4078 if (cmd_in
== MTLOAD
) {
4079 if (STp
->ready
== ST_NO_TAPE
)
4080 cmd
[4] = 4; /* open tray */
4082 cmd
[4] = 1; /* load */
4084 if (cmd_in
== MTRETEN
)
4085 cmd
[4] = 3; /* retension then mount */
4086 if (cmd_in
== MTOFFL
)
4087 cmd
[4] = 4; /* rewind then eject */
4088 timeout
= STp
->timeout
;
4093 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4096 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4099 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4102 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4107 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4112 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4114 return 0; /* Should do something ? */
4119 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4121 if ((osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0) ||
4122 (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0)) {
4123 ioctl_result
= -EIO
;
4126 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4128 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4130 ioctl_result
= -EIO
;
4133 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4134 fileno
= STp
->filemark_cnt
;
4139 if (STp
->write_prot
)
4141 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4142 i
= osst_write_eod(STp
, &SRpnt
);
4143 if (i
< ioctl_result
) ioctl_result
= i
;
4144 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4145 if (i
< ioctl_result
) ioctl_result
= i
;
4146 fileno
= blkno
= at_sm
= 0 ;
4150 cmd
[0] = REZERO_UNIT
; /* rewind */
4154 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4156 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4159 case MTSETBLK
: /* Set block length */
4160 if ((STps
->drv_block
== 0 ) &&
4162 ((STp
->buffer
)->buffer_bytes
== 0) &&
4163 ((arg
& MT_ST_BLKSIZE_MASK
) >= 512 ) &&
4164 ((arg
& MT_ST_BLKSIZE_MASK
) <= OS_DATA_SIZE
) &&
4165 !(OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
)) ) {
4167 * Only allowed to change the block size if you opened the
4168 * device at the beginning of a file before writing anything.
4169 * Note, that when reading, changing block_size is futile,
4170 * as the size used when writing overrides it.
4172 STp
->block_size
= (arg
& MT_ST_BLKSIZE_MASK
);
4173 printk(KERN_INFO
"%s:I: Block size set to %d bytes.\n",
4174 name
, STp
->block_size
);
4177 case MTSETDENSITY
: /* Set tape density */
4178 case MTSETDRVBUFFER
: /* Set drive buffering */
4179 case SET_DENS_AND_BLK
: /* Set density and block size */
4181 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4182 return (-EIO
); /* Not allowed if data in buffer */
4183 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4184 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4185 (arg
& MT_ST_BLKSIZE_MASK
) != STp
->block_size
) {
4186 printk(KERN_WARNING
"%s:W: Illegal to set block size to %d%s.\n",
4187 name
, (int)(arg
& MT_ST_BLKSIZE_MASK
),
4188 (OS_DATA_SIZE
% (arg
& MT_ST_BLKSIZE_MASK
))?"":" now");
4191 return 0; /* FIXME silently ignore if block size didn't change */
4197 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, 1);
4199 ioctl_result
= (STp
->buffer
)->syscall_result
;
4203 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4205 return ioctl_result
;
4208 if (!ioctl_result
) { /* SCSI command successful */
4209 STp
->frame_seq_number
= frame_seq_numbr
;
4210 STp
->logical_blk_num
= logical_blk_num
;
4216 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4219 if (!ioctl_result
) { /* success */
4221 if (cmd_in
== MTFSFM
) {
4225 if (cmd_in
== MTBSFM
) {
4229 STps
->drv_block
= blkno
;
4230 STps
->drv_file
= fileno
;
4231 STps
->at_sm
= at_sm
;
4233 if (cmd_in
== MTEOM
)
4235 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4236 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4238 STp
->logical_blk_num
++;
4239 STp
->frame_seq_number
++;
4240 STp
->frame_in_buffer
= 0;
4241 STp
->buffer
->read_pointer
= 0;
4243 else if (cmd_in
== MTFSF
)
4244 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4246 STps
->eof
= ST_NOEOF
;
4248 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4249 STp
->rew_at_close
= 0;
4250 else if (cmd_in
== MTLOAD
) {
4251 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4252 STp
->ps
[i
].rw
= ST_IDLE
;
4253 STp
->ps
[i
].last_block_valid
= 0;/* FIXME - where else is this field maintained? */
4258 if (cmd_in
== MTREW
) {
4259 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4260 if (ioctl_result
> 0)
4264 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4265 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4266 STps
->drv_file
= STps
->drv_block
= -1;
4268 STps
->drv_file
= STps
->drv_block
= 0;
4269 STps
->eof
= ST_NOEOF
;
4270 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4271 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4272 STps
->drv_file
= STps
->drv_block
= -1;
4274 STps
->drv_file
= STp
->filemark_cnt
;
4275 STps
->drv_block
= 0;
4278 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4279 STps
->drv_file
= STps
->drv_block
= (-1);
4280 STps
->eof
= ST_NOEOF
;
4282 } else if (cmd_in
== MTERASE
) {
4284 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4285 if (SRpnt
->sr_sense_buffer
[2] & 0x40) {
4286 STps
->eof
= ST_EOM_OK
;
4287 STps
->drv_block
= 0;
4290 STps
->eof
= ST_NOEOF
;
4292 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == BLANK_CHECK
)
4295 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4296 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4300 return ioctl_result
;
4304 /* Open the device */
4305 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4307 unsigned short flags
;
4308 int i
, b_size
, new_session
= 0, retval
= 0;
4309 unsigned char cmd
[MAX_COMMAND_SIZE
];
4310 struct scsi_request
* SRpnt
= NULL
;
4311 struct osst_tape
* STp
;
4312 struct st_modedef
* STm
;
4313 struct st_partstat
* STps
;
4315 int dev
= TAPE_NR(inode
);
4316 int mode
= TAPE_MODE(inode
);
4319 * We really want to do nonseekable_open(inode, filp); here, but some
4320 * versions of tar incorrectly call lseek on tapes and bail out if that
4321 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4323 filp
->f_mode
&= ~(FMODE_PREAD
| FMODE_PWRITE
);
4325 write_lock(&os_scsi_tapes_lock
);
4326 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4327 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4328 write_unlock(&os_scsi_tapes_lock
);
4332 name
= tape_name(STp
);
4335 write_unlock(&os_scsi_tapes_lock
);
4337 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4341 if (scsi_device_get(STp
->device
)) {
4342 write_unlock(&os_scsi_tapes_lock
);
4344 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4348 filp
->private_data
= STp
;
4350 write_unlock(&os_scsi_tapes_lock
);
4351 STp
->rew_at_close
= TAPE_REWIND(inode
);
4353 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4357 if (mode
!= STp
->current_mode
) {
4360 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4361 name
, STp
->current_mode
, mode
);
4364 STp
->current_mode
= mode
;
4366 STm
= &(STp
->modes
[STp
->current_mode
]);
4368 flags
= filp
->f_flags
;
4369 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4371 STp
->raw
= TAPE_IS_RAW(inode
);
4375 /* Allocate data segments for this device's tape buffer */
4376 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4377 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4378 retval
= (-EOVERFLOW
);
4381 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4382 for (i
= 0, b_size
= 0;
4383 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4384 b_size
+= STp
->buffer
->sg
[i
++].length
);
4385 STp
->buffer
->aux
= (os_aux_t
*) (page_address(STp
->buffer
->sg
[i
].page
) + OS_DATA_SIZE
- b_size
);
4387 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4388 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4389 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4390 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4393 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4394 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4398 STp
->buffer
->writing
= 0;
4399 STp
->buffer
->syscall_result
= 0;
4401 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4402 STps
= &(STp
->ps
[i
]);
4405 STp
->ready
= ST_READY
;
4407 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4410 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4411 cmd
[0] = TEST_UNIT_READY
;
4413 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, DMA_NONE
, STp
->timeout
, MAX_RETRIES
, 1);
4415 retval
= (STp
->buffer
)->syscall_result
; /* FIXME - valid? */
4418 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4419 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
&&
4420 SRpnt
->sr_sense_buffer
[12] == 4 ) {
4422 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sr_sense_buffer
[13]);
4424 if (filp
->f_flags
& O_NONBLOCK
) {
4428 if (SRpnt
->sr_sense_buffer
[13] == 2) { /* initialize command required (LOAD) */
4429 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4430 cmd
[0] = START_STOP
;
4433 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4434 STp
->timeout
, MAX_RETRIES
, 1);
4436 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sr_sense_buffer
[13]==1?15:3) * 60, 0);
4438 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4439 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4441 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4445 for (i
=0; i
< 10; i
++) {
4447 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4448 cmd
[0] = TEST_UNIT_READY
;
4450 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4451 STp
->timeout
, MAX_RETRIES
, 1);
4452 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) != 0x70 ||
4453 (SRpnt
->sr_sense_buffer
[2] & 0x0f) != UNIT_ATTENTION
)
4457 STp
->pos_unknown
= 0;
4458 STp
->partition
= STp
->new_partition
= 0;
4459 if (STp
->can_partitions
)
4460 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4461 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4462 STps
= &(STp
->ps
[i
]);
4463 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4464 STps
->eof
= ST_NOEOF
;
4466 STps
->last_block_valid
= 0;
4467 STps
->drv_block
= 0;
4468 STps
->drv_file
= 0 ;
4471 STp
->recover_count
= 0;
4472 STp
->abort_count
= 0;
4475 * if we have valid headers from before, and the drive/tape seem untouched,
4476 * open without reconfiguring and re-reading the headers
4478 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4479 !SRpnt
->sr_result
&& SRpnt
->sr_sense_buffer
[0] == 0) {
4481 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4482 cmd
[0] = MODE_SENSE
;
4484 cmd
[2] = VENDOR_IDENT_PAGE
;
4485 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4487 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_FROM_DEVICE
, STp
->timeout
, 0, 1);
4489 if (STp
->buffer
->syscall_result
||
4490 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4491 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4492 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4493 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4495 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4496 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4497 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4498 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4499 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4503 i
= STp
->first_frame_position
;
4504 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4505 if (STp
->door_locked
== ST_UNLOCKED
) {
4506 if (do_door_lock(STp
, 1))
4507 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4509 STp
->door_locked
= ST_LOCKED_AUTO
;
4511 if (!STp
->frame_in_buffer
) {
4512 STp
->block_size
= (STm
->default_blksize
> 0) ?
4513 STm
->default_blksize
: OS_DATA_SIZE
;
4514 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4516 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4518 scsi_release_request(SRpnt
);
4522 if (i
!= STp
->first_frame_position
)
4523 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4524 name
, i
, STp
->first_frame_position
);
4530 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4531 (SRpnt
->sr_sense_buffer
[2] != 2 || SRpnt
->sr_sense_buffer
[12] != 0x3A) ) {
4533 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4534 cmd
[0] = MODE_SELECT
;
4536 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4538 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4539 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4540 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4541 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4542 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4543 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4544 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4545 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4548 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4550 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], DMA_TO_DEVICE
, STp
->timeout
, 0, 1);
4554 for (i
=0; i
< 10; i
++) {
4556 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4557 cmd
[0] = TEST_UNIT_READY
;
4559 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, DMA_NONE
,
4560 STp
->timeout
, MAX_RETRIES
, 1);
4561 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) != 0x70 ||
4562 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
)
4565 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == UNIT_ATTENTION
) {
4566 STp
->pos_unknown
= 0;
4567 STp
->partition
= STp
->new_partition
= 0;
4568 if (STp
->can_partitions
)
4569 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4570 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4571 STps
= &(STp
->ps
[i
]);
4573 STps
->eof
= ST_NOEOF
;
4575 STps
->last_block_valid
= 0;
4576 STps
->drv_block
= 0;
4577 STps
->drv_file
= 0 ;
4584 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4585 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4587 if ((STp
->buffer
)->syscall_result
!= 0) {
4588 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4589 (SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4590 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
&&
4591 SRpnt
->sr_sense_buffer
[12] == 0x3a) { /* Check ASC */
4592 STp
->ready
= ST_NO_TAPE
;
4594 STp
->ready
= ST_NOT_READY
;
4595 scsi_release_request(SRpnt
);
4597 STp
->density
= 0; /* Clear the erroneous "residue" */
4598 STp
->write_prot
= 0;
4599 STp
->block_size
= 0;
4600 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4601 STp
->partition
= STp
->new_partition
= 0;
4602 STp
->door_locked
= ST_UNLOCKED
;
4606 osst_configure_onstream(STp
, &SRpnt
);
4608 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4609 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4610 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4611 STp
->buffer
->buffer_bytes
=
4612 STp
->buffer
->read_pointer
=
4613 STp
->frame_in_buffer
= 0;
4617 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4618 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4619 (STp
->buffer
)->buffer_blocks
);
4622 if (STp
->drv_write_prot
) {
4623 STp
->write_prot
= 1;
4626 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4628 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4634 if (new_session
) { /* Change the drive parameters for the new mode */
4637 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4639 STp
->density_changed
= STp
->blksize_changed
= 0;
4640 STp
->compression_changed
= 0;
4644 * properly position the tape and check the ADR headers
4646 if (STp
->door_locked
== ST_UNLOCKED
) {
4647 if (do_door_lock(STp
, 1))
4648 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4650 STp
->door_locked
= ST_LOCKED_AUTO
;
4653 osst_analyze_headers(STp
, &SRpnt
);
4655 scsi_release_request(SRpnt
);
4662 scsi_release_request(SRpnt
);
4663 normalize_buffer(STp
->buffer
);
4666 scsi_device_put(STp
->device
);
4672 /* Flush the tape buffer before close */
4673 static int os_scsi_tape_flush(struct file
* filp
)
4675 int result
= 0, result2
;
4676 struct osst_tape
* STp
= filp
->private_data
;
4677 struct st_modedef
* STm
= &(STp
->modes
[STp
->current_mode
]);
4678 struct st_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4679 struct scsi_request
* SRpnt
= NULL
;
4680 char * name
= tape_name(STp
);
4682 if (file_count(filp
) > 1)
4685 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4686 STp
->write_type
= OS_WRITE_DATA
;
4687 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4688 if (result
!= 0 && result
!= (-ENOSPC
))
4691 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4695 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4696 name
, (long)(filp
->f_pos
));
4697 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4698 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4701 result
= osst_write_trailer(STp
, &SRpnt
, !(STp
->rew_at_close
));
4704 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4705 name
, 1+STp
->two_fm
);
4708 else if (!STp
->rew_at_close
) {
4709 STps
= &(STp
->ps
[STp
->partition
]);
4710 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4712 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4713 else if (STps
->eof
== ST_FM_HIT
) {
4714 result
= cross_eof(STp
, &SRpnt
, 0);
4716 if (STps
->drv_file
>= 0)
4718 STps
->drv_block
= 0;
4722 STps
->eof
= ST_NOEOF
;
4725 else if ((STps
->eof
== ST_NOEOF
&&
4726 !(result
= cross_eof(STp
, &SRpnt
, 1))) ||
4727 STps
->eof
== ST_FM_HIT
) {
4728 if (STps
->drv_file
>= 0)
4730 STps
->drv_block
= 0;
4736 if (STp
->rew_at_close
) {
4737 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4738 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4739 if (result
== 0 && result2
< 0)
4742 if (SRpnt
) scsi_release_request(SRpnt
);
4744 if (STp
->abort_count
|| STp
->recover_count
) {
4745 printk(KERN_INFO
"%s:I:", name
);
4746 if (STp
->abort_count
)
4747 printk(" %d unrecovered errors", STp
->abort_count
);
4748 if (STp
->recover_count
)
4749 printk(" %d recovered errors", STp
->recover_count
);
4750 if (STp
->write_count
)
4751 printk(" in %d frames written", STp
->write_count
);
4752 if (STp
->read_count
)
4753 printk(" in %d frames read", STp
->read_count
);
4755 STp
->recover_count
= 0;
4756 STp
->abort_count
= 0;
4758 STp
->write_count
= 0;
4759 STp
->read_count
= 0;
4765 /* Close the device and release it */
4766 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4769 struct osst_tape
* STp
= filp
->private_data
;
4771 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4772 do_door_lock(STp
, 0);
4777 normalize_buffer(STp
->buffer
);
4778 write_lock(&os_scsi_tapes_lock
);
4780 write_unlock(&os_scsi_tapes_lock
);
4782 scsi_device_put(STp
->device
);
4788 /* The ioctl command */
4789 static int osst_ioctl(struct inode
* inode
,struct file
* file
,
4790 unsigned int cmd_in
, unsigned long arg
)
4792 int i
, cmd_nr
, cmd_type
, retval
= 0;
4794 struct st_modedef
* STm
;
4795 struct st_partstat
* STps
;
4796 struct scsi_request
* SRpnt
= NULL
;
4797 struct osst_tape
* STp
= file
->private_data
;
4798 char * name
= tape_name(STp
);
4799 void __user
* p
= (void __user
*)arg
;
4801 if (down_interruptible(&STp
->lock
))
4802 return -ERESTARTSYS
;
4805 if (debugging
&& !STp
->in_use
) {
4806 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4811 STm
= &(STp
->modes
[STp
->current_mode
]);
4812 STps
= &(STp
->ps
[STp
->partition
]);
4815 * If we are in the middle of error recovery, don't let anyone
4816 * else try and use this device. Also, if error recovery fails, it
4817 * may try and take the device offline, in which case all further
4818 * access to the device is prohibited.
4820 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4825 cmd_type
= _IOC_TYPE(cmd_in
);
4826 cmd_nr
= _IOC_NR(cmd_in
);
4828 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4829 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4831 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4835 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4840 i
= copy_from_user((char *) &mtc
, p
, sizeof(struct mtop
));
4846 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
4847 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
4852 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
4857 if (!STp
->pos_unknown
) {
4859 if (STps
->eof
== ST_FM_HIT
) {
4860 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
4862 if (STps
->drv_file
>= 0)
4863 STps
->drv_file
+= 1;
4865 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
4867 if (STps
->drv_file
>= 0)
4868 STps
->drv_file
+= 1;
4872 if (mtc
.mt_op
== MTSEEK
) {
4873 /* Old position must be restored if partition will be changed */
4874 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
4877 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
4878 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
4879 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
4880 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
4881 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
4882 mtc
.mt_op
== MTCOMPRESSION
;
4884 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
4892 * If there was a bus reset, block further access
4893 * to this device. If the user wants to rewind the tape,
4894 * then reset the flag and allow access again.
4896 if(mtc
.mt_op
!= MTREW
&&
4897 mtc
.mt_op
!= MTOFFL
&&
4898 mtc
.mt_op
!= MTRETEN
&&
4899 mtc
.mt_op
!= MTERASE
&&
4900 mtc
.mt_op
!= MTSEEK
&&
4901 mtc
.mt_op
!= MTEOM
) {
4906 /* remove this when the midlevel properly clears was_reset */
4907 STp
->device
->was_reset
= 0;
4910 if (mtc
.mt_op
!= MTCOMPRESSION
&& mtc
.mt_op
!= MTLOCK
&&
4911 mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTSETBLK
&&
4912 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETDRVBUFFER
&&
4913 mtc
.mt_op
!= MTMKPART
&& mtc
.mt_op
!= MTSETPART
&&
4914 mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
) {
4917 * The user tells us to move to another position on the tape.
4918 * If we were appending to the tape content, that would leave
4919 * the tape without proper end, in that case write EOD and
4920 * update the header to reflect its position.
4923 printk(KERN_WARNING
"%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name
,
4924 STps
->rw
>= ST_WRITING
? "write" : STps
->rw
== ST_READING
? "read" : "idle",
4925 STp
->first_frame_position
, STp
->eod_frame_ppos
, STp
->frame_seq_number
,
4926 STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
4928 if (STps
->rw
>= ST_WRITING
&& STp
->first_frame_position
>= STp
->eod_frame_ppos
) {
4929 auto_weof
= ((STp
->write_type
!= OS_WRITE_NEW_MARK
) &&
4930 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
4931 i
= osst_write_trailer(STp
, &SRpnt
,
4932 !(mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
));
4934 printk(KERN_WARNING
"%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4935 name
, auto_weof
, STp
->first_frame_position
, STp
->eod_frame_ppos
,
4936 STp
->frame_seq_number
, STp
->logical_blk_num
, STps
->drv_file
, STps
->drv_block
);
4946 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
4947 do_door_lock(STp
, 0); /* Ignore result! */
4949 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
4950 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
4951 retval
= osst_set_options(STp
, mtc
.mt_count
);
4955 if (mtc
.mt_op
== MTSETPART
) {
4956 if (mtc
.mt_count
>= STp
->nbr_partitions
)
4959 STp
->new_partition
= mtc
.mt_count
;
4965 if (mtc
.mt_op
== MTMKPART
) {
4966 if (!STp
->can_partitions
) {
4970 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
4971 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
4975 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4976 STp
->ps
[i
].rw
= ST_IDLE
;
4977 STp
->ps
[i
].at_sm
= 0;
4978 STp
->ps
[i
].last_block_valid
= 0;
4980 STp
->partition
= STp
->new_partition
= 0;
4981 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
4982 STps
->drv_block
= STps
->drv_file
= 0;
4987 if (mtc
.mt_op
== MTSEEK
) {
4989 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
4991 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
4992 if (!STp
->can_partitions
)
4993 STp
->ps
[0].rw
= ST_IDLE
;
4998 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
4999 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
5004 cross_eof(STp
, &SRpnt
, 0);
5006 if (mtc
.mt_op
== MTCOMPRESSION
)
5007 retval
= -EINVAL
; /* OnStream drives don't have compression hardware */
5009 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5010 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5011 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
5015 if (!STm
->defined
) {
5020 if ((i
= osst_flush_buffer(STp
, &SRpnt
, 0)) < 0) {
5025 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
5026 struct mtget mt_status
;
5028 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
5033 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
5034 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
5035 mt_status
.mt_dsreg
=
5036 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
5037 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
5038 mt_status
.mt_blkno
= STps
->drv_block
;
5039 mt_status
.mt_fileno
= STps
->drv_file
;
5040 if (STp
->block_size
!= 0) {
5041 if (STps
->rw
== ST_WRITING
)
5042 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
5043 else if (STps
->rw
== ST_READING
)
5044 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
5045 STp
->block_size
- 1) / STp
->block_size
;
5048 mt_status
.mt_gstat
= 0;
5049 if (STp
->drv_write_prot
)
5050 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
5051 if (mt_status
.mt_blkno
== 0) {
5052 if (mt_status
.mt_fileno
== 0)
5053 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
5055 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
5057 mt_status
.mt_resid
= STp
->partition
;
5058 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
5059 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
5060 else if (STps
->eof
>= ST_EOM_OK
)
5061 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
5062 if (STp
->density
== 1)
5063 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
5064 else if (STp
->density
== 2)
5065 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
5066 else if (STp
->density
== 3)
5067 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
5068 if (STp
->ready
== ST_READY
)
5069 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
5070 if (STp
->ready
== ST_NO_TAPE
)
5071 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
5073 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
5074 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
5075 STp
->drv_buffer
!= 0)
5076 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
5078 i
= copy_to_user(p
, &mt_status
, sizeof(struct mtget
));
5084 STp
->recover_erreg
= 0; /* Clear after read */
5087 } /* End of MTIOCGET */
5089 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
5090 struct mtpos mt_pos
;
5092 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
5097 blk
= osst_get_frame_position(STp
, &SRpnt
);
5099 blk
= osst_get_sector(STp
, &SRpnt
);
5104 mt_pos
.mt_blkno
= blk
;
5105 i
= copy_to_user(p
, &mt_pos
, sizeof(struct mtpos
));
5110 if (SRpnt
) scsi_release_request(SRpnt
);
5114 return scsi_ioctl(STp
->device
, cmd_in
, p
);
5117 if (SRpnt
) scsi_release_request(SRpnt
);
5124 #ifdef CONFIG_COMPAT
5125 static long osst_compat_ioctl(struct file
* file
, unsigned int cmd_in
, unsigned long arg
)
5127 struct osst_tape
*STp
= file
->private_data
;
5128 struct scsi_device
*sdev
= STp
->device
;
5129 int ret
= -ENOIOCTLCMD
;
5130 if (sdev
->host
->hostt
->compat_ioctl
) {
5132 ret
= sdev
->host
->hostt
->compat_ioctl(sdev
, cmd_in
, (void __user
*)arg
);
5141 /* Memory handling routines */
5143 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5144 static struct osst_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5148 struct osst_buffer
*tb
;
5150 if (from_initialization
)
5151 priority
= GFP_ATOMIC
;
5153 priority
= GFP_KERNEL
;
5155 i
= sizeof(struct osst_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5156 tb
= (struct osst_buffer
*)kmalloc(i
, priority
);
5158 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5162 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5163 tb
->use_sg
= max_sg
;
5166 tb
->buffer_size
= 0;
5170 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5171 i
, max_sg
, need_dma
);
5176 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5177 static int enlarge_buffer(struct osst_buffer
*STbuffer
, int need_dma
)
5179 int segs
, nbr
, max_segs
, b_size
, order
, got
;
5182 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5185 if (STbuffer
->sg_segs
) {
5186 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5187 normalize_buffer(STbuffer
);
5189 /* See how many segments we can use -- need at least two */
5190 nbr
= max_segs
= STbuffer
->use_sg
;
5194 priority
= GFP_KERNEL
/* | __GFP_NOWARN */;
5196 priority
|= GFP_DMA
;
5198 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5199 big enough to reach the goal (code assumes no segments in place) */
5200 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5201 STbuffer
->sg
[0].page
= alloc_pages(priority
, order
);
5202 STbuffer
->sg
[0].offset
= 0;
5203 if (STbuffer
->sg
[0].page
!= NULL
) {
5204 STbuffer
->sg
[0].length
= b_size
;
5205 STbuffer
->b_data
= page_address(STbuffer
->sg
[0].page
);
5209 if (STbuffer
->sg
[0].page
== NULL
) {
5210 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5213 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5214 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5215 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5216 STbuffer
->sg
[segs
].page
=
5217 alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5218 STbuffer
->sg
[segs
].offset
= 0;
5219 if (STbuffer
->sg
[segs
].page
== NULL
) {
5220 if (OS_FRAME_SIZE
- got
<= (max_segs
- segs
) * b_size
/ 2 && order
) {
5221 b_size
/= 2; /* Large enough for the rest of the buffers */
5225 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5228 STbuffer
->buffer_size
= got
;
5230 normalize_buffer(STbuffer
);
5233 STbuffer
->sg
[segs
].length
= (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
;
5234 got
+= STbuffer
->sg
[segs
].length
;
5235 STbuffer
->buffer_size
= got
;
5236 STbuffer
->sg_segs
= ++segs
;
5241 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5242 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5244 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5245 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5246 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5254 /* Release the segments */
5255 static void normalize_buffer(struct osst_buffer
*STbuffer
)
5257 int i
, order
, b_size
;
5259 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5261 for (b_size
= PAGE_SIZE
, order
= 0;
5262 b_size
< STbuffer
->sg
[i
].length
;
5263 b_size
*= 2, order
++);
5265 __free_pages(STbuffer
->sg
[i
].page
, order
);
5266 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5269 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5270 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5271 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5273 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5277 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5278 negative error code. */
5279 static int append_to_buffer(const char __user
*ubp
, struct osst_buffer
*st_bp
, int do_count
)
5281 int i
, cnt
, res
, offset
;
5283 for (i
=0, offset
=st_bp
->buffer_bytes
;
5284 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5285 offset
-= st_bp
->sg
[i
].length
;
5286 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5287 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5290 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5291 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5292 st_bp
->sg
[i
].length
- offset
: do_count
;
5293 res
= copy_from_user(page_address(st_bp
->sg
[i
].page
) + offset
, ubp
, cnt
);
5297 st_bp
->buffer_bytes
+= cnt
;
5301 if (do_count
) { /* Should never happen */
5302 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5310 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5311 negative error code. */
5312 static int from_buffer(struct osst_buffer
*st_bp
, char __user
*ubp
, int do_count
)
5314 int i
, cnt
, res
, offset
;
5316 for (i
=0, offset
=st_bp
->read_pointer
;
5317 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5318 offset
-= st_bp
->sg
[i
].length
;
5319 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5320 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5323 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5324 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5325 st_bp
->sg
[i
].length
- offset
: do_count
;
5326 res
= copy_to_user(ubp
, page_address(st_bp
->sg
[i
].page
) + offset
, cnt
);
5330 st_bp
->buffer_bytes
-= cnt
;
5331 st_bp
->read_pointer
+= cnt
;
5335 if (do_count
) { /* Should never happen */
5336 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5342 /* Sets the tail of the buffer after fill point to zero.
5343 Returns zero (success) or negative error code. */
5344 static int osst_zero_buffer_tail(struct osst_buffer
*st_bp
)
5346 int i
, offset
, do_count
, cnt
;
5348 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5349 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5350 offset
-= st_bp
->sg
[i
].length
;
5351 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5352 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5355 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5356 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5357 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5358 st_bp
->sg
[i
].length
- offset
: do_count
;
5359 memset(page_address(st_bp
->sg
[i
].page
) + offset
, 0, cnt
);
5363 if (do_count
) { /* Should never happen */
5364 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5370 /* Copy a osst 32K chunk of memory into the buffer.
5371 Returns zero (success) or negative error code. */
5372 static int osst_copy_to_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5374 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5376 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5377 cnt
= st_bp
->sg
[i
].length
< do_count
?
5378 st_bp
->sg
[i
].length
: do_count
;
5379 memcpy(page_address(st_bp
->sg
[i
].page
), ptr
, cnt
);
5383 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5384 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5391 /* Copy a osst 32K chunk of memory from the buffer.
5392 Returns zero (success) or negative error code. */
5393 static int osst_copy_from_buffer(struct osst_buffer
*st_bp
, unsigned char *ptr
)
5395 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5397 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5398 cnt
= st_bp
->sg
[i
].length
< do_count
?
5399 st_bp
->sg
[i
].length
: do_count
;
5400 memcpy(ptr
, page_address(st_bp
->sg
[i
].page
), cnt
);
5404 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5405 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5413 /* Module housekeeping */
5415 static void validate_options (void)
5418 osst_max_dev
= max_dev
;
5419 if (write_threshold_kbs
> 0)
5420 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5421 if (osst_write_threshold
> osst_buffer_size
)
5422 osst_write_threshold
= osst_buffer_size
;
5423 if (max_sg_segs
>= OSST_FIRST_SG
)
5424 osst_max_sg_segs
= max_sg_segs
;
5426 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5427 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5432 /* Set the boot options. Syntax: osst=xxx,yyy,...
5433 where xxx is write threshold in 1024 byte blocks,
5434 and yyy is number of s/g segments to use. */
5435 static int __init
osst_setup (char *str
)
5440 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5443 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5444 *parms
[i
].val
= ints
[i
+ 1];
5446 while (stp
!= NULL
) {
5447 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5448 int len
= strlen(parms
[i
].name
);
5449 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5450 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5452 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5456 if (i
>= sizeof(parms
) / sizeof(struct osst_dev_parm
))
5457 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5459 stp
= strchr(stp
, ',');
5468 __setup("osst=", osst_setup
);
5472 static struct file_operations osst_fops
= {
5473 .owner
= THIS_MODULE
,
5475 .write
= osst_write
,
5476 .ioctl
= osst_ioctl
,
5477 #ifdef CONFIG_COMPAT
5478 .compat_ioctl
= osst_compat_ioctl
,
5480 .open
= os_scsi_tape_open
,
5481 .flush
= os_scsi_tape_flush
,
5482 .release
= os_scsi_tape_close
,
5485 static int osst_supports(struct scsi_device
* SDp
)
5487 struct osst_support_data
{
5491 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5494 static struct osst_support_data support_list
[] = {
5495 /* {"XXX", "Yy-", "", NULL}, example */
5499 struct osst_support_data
*rp
;
5501 /* We are willing to drive OnStream SC-x0 as well as the
5502 * * IDE, ParPort, FireWire, USB variants, if accessible by
5503 * * emulation layer (ide-scsi, usb-storage, ...) */
5505 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5506 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5507 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5508 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5514 * sysfs support for osst driver parameter information
5517 static ssize_t
osst_version_show(struct device_driver
*ddd
, char *buf
)
5519 return snprintf(buf
, PAGE_SIZE
, "%s\n", osst_version
);
5522 static DRIVER_ATTR(version
, S_IRUGO
, osst_version_show
, NULL
);
5524 static void osst_create_driverfs_files(struct device_driver
*driverfs
)
5526 driver_create_file(driverfs
, &driver_attr_version
);
5529 static void osst_remove_driverfs_files(struct device_driver
*driverfs
)
5531 driver_remove_file(driverfs
, &driver_attr_version
);
5535 * sysfs support for accessing ADR header information
5538 static ssize_t
osst_adr_rev_show(struct class_device
*class_dev
, char *buf
)
5540 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5543 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5544 l
= snprintf(buf
, PAGE_SIZE
, "%d.%d\n", STp
->header_cache
->major_rev
, STp
->header_cache
->minor_rev
);
5548 CLASS_DEVICE_ATTR(ADR_rev
, S_IRUGO
, osst_adr_rev_show
, NULL
);
5550 static ssize_t
osst_linux_media_version_show(struct class_device
*class_dev
, char *buf
)
5552 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5555 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5556 l
= snprintf(buf
, PAGE_SIZE
, "LIN%d\n", STp
->linux_media_version
);
5560 CLASS_DEVICE_ATTR(media_version
, S_IRUGO
, osst_linux_media_version_show
, NULL
);
5562 static ssize_t
osst_capacity_show(struct class_device
*class_dev
, char *buf
)
5564 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5567 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5568 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->capacity
);
5572 CLASS_DEVICE_ATTR(capacity
, S_IRUGO
, osst_capacity_show
, NULL
);
5574 static ssize_t
osst_first_data_ppos_show(struct class_device
*class_dev
, char *buf
)
5576 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5579 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5580 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->first_data_ppos
);
5584 CLASS_DEVICE_ATTR(BOT_frame
, S_IRUGO
, osst_first_data_ppos_show
, NULL
);
5586 static ssize_t
osst_eod_frame_ppos_show(struct class_device
*class_dev
, char *buf
)
5588 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5591 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5592 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->eod_frame_ppos
);
5596 CLASS_DEVICE_ATTR(EOD_frame
, S_IRUGO
, osst_eod_frame_ppos_show
, NULL
);
5598 static ssize_t
osst_filemark_cnt_show(struct class_device
*class_dev
, char *buf
)
5600 struct osst_tape
* STp
= (struct osst_tape
*) class_get_devdata (class_dev
);
5603 if (STp
&& STp
->header_ok
&& STp
->linux_media
)
5604 l
= snprintf(buf
, PAGE_SIZE
, "%d\n", STp
->filemark_cnt
);
5608 CLASS_DEVICE_ATTR(file_count
, S_IRUGO
, osst_filemark_cnt_show
, NULL
);
5610 static struct class *osst_sysfs_class
;
5612 static int osst_sysfs_valid
= 0;
5614 static void osst_sysfs_init(void)
5616 osst_sysfs_class
= class_create(THIS_MODULE
, "onstream_tape");
5617 if ( IS_ERR(osst_sysfs_class
) )
5618 printk(KERN_WARNING
"osst :W: Unable to register sysfs class\n");
5620 osst_sysfs_valid
= 1;
5623 static void osst_sysfs_add(dev_t dev
, struct device
*device
, struct osst_tape
* STp
, char * name
)
5625 struct class_device
*osst_class_member
;
5627 if (!osst_sysfs_valid
) return;
5629 osst_class_member
= class_device_create(osst_sysfs_class
, NULL
, dev
, device
, "%s", name
);
5630 if (IS_ERR(osst_class_member
)) {
5631 printk(KERN_WARNING
"osst :W: Unable to add sysfs class member %s\n", name
);
5634 class_set_devdata(osst_class_member
, STp
);
5635 class_device_create_file(osst_class_member
, &class_device_attr_ADR_rev
);
5636 class_device_create_file(osst_class_member
, &class_device_attr_media_version
);
5637 class_device_create_file(osst_class_member
, &class_device_attr_capacity
);
5638 class_device_create_file(osst_class_member
, &class_device_attr_BOT_frame
);
5639 class_device_create_file(osst_class_member
, &class_device_attr_EOD_frame
);
5640 class_device_create_file(osst_class_member
, &class_device_attr_file_count
);
5643 static void osst_sysfs_destroy(dev_t dev
)
5645 if (!osst_sysfs_valid
) return;
5647 class_device_destroy(osst_sysfs_class
, dev
);
5650 static void osst_sysfs_cleanup(void)
5652 if (osst_sysfs_valid
) {
5653 class_destroy(osst_sysfs_class
);
5654 osst_sysfs_valid
= 0;
5659 * osst startup / cleanup code
5662 static int osst_probe(struct device
*dev
)
5664 struct scsi_device
* SDp
= to_scsi_device(dev
);
5665 struct osst_tape
* tpnt
;
5666 struct st_modedef
* STm
;
5667 struct st_partstat
* STps
;
5668 struct osst_buffer
* buffer
;
5669 struct gendisk
* drive
;
5670 int i
, mode
, dev_num
;
5672 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5675 drive
= alloc_disk(1);
5677 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5681 /* if this is the first attach, build the infrastructure */
5682 write_lock(&os_scsi_tapes_lock
);
5683 if (os_scsi_tapes
== NULL
) {
5685 (struct osst_tape
**)kmalloc(osst_max_dev
* sizeof(struct osst_tape
*),
5687 if (os_scsi_tapes
== NULL
) {
5688 write_unlock(&os_scsi_tapes_lock
);
5689 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5692 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5695 if (osst_nr_dev
>= osst_max_dev
) {
5696 write_unlock(&os_scsi_tapes_lock
);
5697 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5701 /* find a free minor number */
5702 for (i
=0; os_scsi_tapes
[i
] && i
<osst_max_dev
; i
++);
5703 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5706 /* allocate a struct osst_tape for this device */
5707 tpnt
= (struct osst_tape
*)kmalloc(sizeof(struct osst_tape
), GFP_ATOMIC
);
5709 write_unlock(&os_scsi_tapes_lock
);
5710 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5713 memset(tpnt
, 0, sizeof(struct osst_tape
));
5715 /* allocate a buffer for this device */
5716 i
= SDp
->host
->sg_tablesize
;
5717 if (osst_max_sg_segs
< i
)
5718 i
= osst_max_sg_segs
;
5719 buffer
= new_tape_buffer(1, SDp
->host
->unchecked_isa_dma
, i
);
5720 if (buffer
== NULL
) {
5721 write_unlock(&os_scsi_tapes_lock
);
5722 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5726 os_scsi_tapes
[dev_num
] = tpnt
;
5727 tpnt
->buffer
= buffer
;
5729 drive
->private_data
= &tpnt
->driver
;
5730 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5731 tpnt
->driver
= &osst_template
;
5732 tpnt
->drive
= drive
;
5734 tpnt
->capacity
= 0xfffff;
5736 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5737 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5739 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5740 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5741 tpnt
->can_partitions
= 0;
5742 tpnt
->two_fm
= OSST_TWO_FM
;
5743 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5744 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5745 tpnt
->write_threshold
= osst_write_threshold
;
5746 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5747 tpnt
->partition
= 0;
5748 tpnt
->new_partition
= 0;
5749 tpnt
->nbr_partitions
= 0;
5750 tpnt
->min_block
= 512;
5751 tpnt
->max_block
= OS_DATA_SIZE
;
5752 tpnt
->timeout
= OSST_TIMEOUT
;
5753 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5755 /* Recognize OnStream tapes */
5756 /* We don't need to test for OnStream, as this has been done in detect () */
5757 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5758 tpnt
->omit_blklims
= 1;
5760 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5761 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5762 tpnt
->frame_in_buffer
= 0;
5763 tpnt
->header_ok
= 0;
5764 tpnt
->linux_media
= 0;
5765 tpnt
->header_cache
= NULL
;
5767 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5768 STm
= &(tpnt
->modes
[i
]);
5770 STm
->sysv
= OSST_SYSV
;
5771 STm
->defaults_for_writes
= 0;
5772 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5773 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5774 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5775 STm
->default_compression
= ST_DONT_TOUCH
;
5776 STm
->default_blksize
= 512;
5777 STm
->default_density
= (-1); /* No forced density */
5780 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5781 STps
= &(tpnt
->ps
[i
]);
5783 STps
->eof
= ST_NOEOF
;
5785 STps
->last_block_valid
= 0;
5786 STps
->drv_block
= (-1);
5787 STps
->drv_file
= (-1);
5790 tpnt
->current_mode
= 0;
5791 tpnt
->modes
[0].defined
= 1;
5792 tpnt
->modes
[2].defined
= 1;
5793 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= 0;
5795 init_MUTEX(&tpnt
->lock
);
5797 write_unlock(&os_scsi_tapes_lock
);
5801 osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
), dev
, tpnt
, tape_name(tpnt
));
5802 /* No-rewind entry */
5803 snprintf(name
, 8, "%s%s", "n", tape_name(tpnt
));
5804 osst_sysfs_add(MKDEV(OSST_MAJOR
, dev_num
+ 128), dev
, tpnt
, name
);
5806 for (mode
= 0; mode
< ST_NBR_MODES
; ++mode
) {
5808 devfs_mk_cdev(MKDEV(OSST_MAJOR
, dev_num
+ (mode
<< 5)),
5809 S_IFCHR
| S_IRUGO
| S_IWUGO
,
5810 "%s/ot%s", SDp
->devfs_name
, osst_formats
[mode
]);
5812 /* No-rewind entry */
5813 devfs_mk_cdev(MKDEV(OSST_MAJOR
, dev_num
+ (mode
<< 5) + 128),
5814 S_IFCHR
| S_IRUGO
| S_IWUGO
,
5815 "%s/ot%sn", SDp
->devfs_name
, osst_formats
[mode
]);
5817 drive
->number
= devfs_register_tape(SDp
->devfs_name
);
5819 sdev_printk(KERN_INFO
, SDp
,
5820 "osst :I: Attached OnStream %.5s tape as %s\n",
5821 SDp
->model
, tape_name(tpnt
));
5830 static int osst_remove(struct device
*dev
)
5832 struct scsi_device
* SDp
= to_scsi_device(dev
);
5833 struct osst_tape
* tpnt
;
5836 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
5839 write_lock(&os_scsi_tapes_lock
);
5840 for(i
=0; i
< osst_max_dev
; i
++) {
5841 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
5842 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
));
5843 osst_sysfs_destroy(MKDEV(OSST_MAJOR
, i
+128));
5844 tpnt
->device
= NULL
;
5845 for (mode
= 0; mode
< ST_NBR_MODES
; ++mode
) {
5846 devfs_remove("%s/ot%s", SDp
->devfs_name
, osst_formats
[mode
]);
5847 devfs_remove("%s/ot%sn", SDp
->devfs_name
, osst_formats
[mode
]);
5849 devfs_unregister_tape(tpnt
->drive
->number
);
5850 put_disk(tpnt
->drive
);
5851 os_scsi_tapes
[i
] = NULL
;
5853 write_unlock(&os_scsi_tapes_lock
);
5854 vfree(tpnt
->header_cache
);
5856 normalize_buffer(tpnt
->buffer
);
5857 kfree(tpnt
->buffer
);
5863 write_unlock(&os_scsi_tapes_lock
);
5867 static int __init
init_osst(void)
5869 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
5874 if ((register_chrdev(OSST_MAJOR
,"osst", &osst_fops
) < 0) || scsi_register_driver(&osst_template
.gendrv
)) {
5875 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
5876 osst_sysfs_cleanup();
5879 osst_create_driverfs_files(&osst_template
.gendrv
);
5884 static void __exit
exit_osst (void)
5887 struct osst_tape
* STp
;
5889 osst_remove_driverfs_files(&osst_template
.gendrv
);
5890 scsi_unregister_driver(&osst_template
.gendrv
);
5891 unregister_chrdev(OSST_MAJOR
, "osst");
5892 osst_sysfs_cleanup();
5894 if (os_scsi_tapes
) {
5895 for (i
=0; i
< osst_max_dev
; ++i
) {
5896 if (!(STp
= os_scsi_tapes
[i
])) continue;
5897 /* This is defensive, supposed to happen during detach */
5898 vfree(STp
->header_cache
);
5900 normalize_buffer(STp
->buffer
);
5903 put_disk(STp
->drive
);
5906 kfree(os_scsi_tapes
);
5908 printk(KERN_INFO
"osst :I: Unloaded.\n");
5911 module_init(init_osst
);
5912 module_exit(exit_osst
);