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 / Willem Riede
17 email Kai.Makisara@metla.fi / osst@riede.org
19 $Header: /home/cvsroot/Driver/osst.c,v 1.68 2002/12/23 16:33:36 riede 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.68 2002/12/23 16:33:36 riede Exp $";
27 const char * osst_version
= "0.99.0";
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>
40 #include <linux/init.h>
41 #include <linux/string.h>
42 #include <linux/errno.h>
43 #include <linux/mtio.h>
44 #include <linux/ioctl.h>
45 #include <linux/fcntl.h>
46 #include <linux/spinlock.h>
47 #include <linux/vmalloc.h>
48 #include <linux/version.h>
49 #include <linux/blk.h>
50 #include <linux/devfs_fs_kernel.h>
51 #include <asm/uaccess.h>
53 #include <asm/system.h>
55 /* The driver prints some debugging information on the console if DEBUG
56 is defined and non-zero. */
59 /* The message level for the debug messages is currently set to KERN_NOTICE
60 so that people can easily see the messages. Later when the debugging messages
61 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
62 #define OSST_DEB_MSG KERN_NOTICE
66 #include <scsi/scsi_driver.h>
67 #include <scsi/scsi_ioctl.h>
69 #define ST_KILOBYTE 1024
73 #include "osst_options.h"
74 #include "osst_detect.h"
76 static int max_dev
= 0;
77 static int write_threshold_kbs
= 0;
78 static int max_sg_segs
= 0;
81 MODULE_AUTHOR("Willem Riede");
82 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
83 MODULE_LICENSE("GPL");
85 MODULE_PARM(max_dev
, "i");
86 MODULE_PARM_DESC(max_dev
, "Maximum number of OnStream Tape Drives to attach (4)");
88 MODULE_PARM(write_threshold_kbs
, "i");
89 MODULE_PARM_DESC(write_threshold_kbs
, "Asynchronous write threshold (KB; 32)");
91 MODULE_PARM(max_sg_segs
, "i");
92 MODULE_PARM_DESC(max_sg_segs
, "Maximum number of scatter/gather segments to use (9)");
94 static struct osst_dev_parm
{
97 } parms
[] __initdata
= {
98 { "max_dev", &max_dev
},
99 { "write_threshold_kbs", &write_threshold_kbs
},
100 { "max_sg_segs", &max_sg_segs
}
104 static char *osst_formats
[ST_NBR_MODES
] ={"", "l", "m", "a"};
106 /* Some default definitions have been moved to osst_options.h */
107 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
108 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
110 /* The buffer size should fit into the 24 bits for length in the
111 6-byte SCSI read and write commands. */
112 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
113 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
117 static int debugging
= 1;
118 /* uncomment define below to test error recovery */
119 // #define OSST_INJECT_ERRORS 1
122 #define MAX_RETRIES 2
123 #define MAX_READ_RETRIES 0
124 #define MAX_WRITE_RETRIES 0
125 #define MAX_READY_RETRIES 0
126 #define NO_TAPE NOT_READY
128 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
129 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
130 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
132 #define OSST_TIMEOUT (200 * HZ)
133 #define OSST_LONG_TIMEOUT (1800 * HZ)
135 #define TAPE_NR(x) (minor(x) & ~(-1 << ST_MODE_SHIFT))
136 #define TAPE_MODE(x) ((minor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
137 #define TAPE_REWIND(x) ((minor(x) & 0x80) == 0)
138 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
140 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
142 #define SET_DENS_AND_BLK 0x10001
144 static int osst_buffer_size
= OSST_BUFFER_SIZE
;
145 static int osst_write_threshold
= OSST_WRITE_THRESHOLD
;
146 static int osst_max_sg_segs
= OSST_MAX_SG
;
147 static int osst_max_dev
= OSST_MAX_TAPES
;
148 static int osst_nr_dev
;
150 static OS_Scsi_Tape
**os_scsi_tapes
= NULL
;
151 static rwlock_t os_scsi_tapes_lock
= RW_LOCK_UNLOCKED
;
153 static int modes_defined
= FALSE
;
155 static OSST_buffer
*new_tape_buffer(int, int, int);
156 static int enlarge_buffer(OSST_buffer
*, int);
157 static void normalize_buffer(OSST_buffer
*);
158 static int append_to_buffer(const char *, OSST_buffer
*, int);
159 static int from_buffer(OSST_buffer
*, char *, int);
160 static int osst_zero_buffer_tail(OSST_buffer
*);
161 static int osst_copy_to_buffer(OSST_buffer
*, unsigned char *);
162 static int osst_copy_from_buffer(OSST_buffer
*, unsigned char *);
164 static int osst_probe(struct device
*);
165 static int osst_remove(struct device
*);
167 struct scsi_driver osst_template
= {
168 .owner
= THIS_MODULE
,
172 .remove
= osst_remove
,
176 static int osst_int_ioctl(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
, unsigned int cmd_in
,unsigned long arg
);
178 static int osst_set_frame_position(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
, int frame
, int skip
);
180 static int osst_get_frame_position(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
);
182 static int osst_flush_write_buffer(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
);
184 static int osst_write_error_recovery(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int pending
);
186 static inline char *tape_name(OS_Scsi_Tape
*tape
)
188 return tape
->drive
->disk_name
;
191 /* Routines that handle the interaction with mid-layer SCSI routines */
193 /* Convert the result to success code */
194 static int osst_chk_result(OS_Scsi_Tape
* STp
, Scsi_Request
* SRpnt
)
196 char *name
= tape_name(STp
);
197 int result
= SRpnt
->sr_result
;
198 unsigned char * sense
= SRpnt
->sr_sense_buffer
, scode
;
204 sense
[0] = 0; /* We don't have sense data if this byte is zero */
207 if ((driver_byte(result
) & DRIVER_MASK
) == DRIVER_SENSE
)
208 scode
= sense
[2] & 0x0f;
210 sense
[0] = 0; /* We don't have sense data if this byte is zero */
215 printk(OSST_DEB_MSG
"%s:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
217 SRpnt
->sr_cmnd
[0], SRpnt
->sr_cmnd
[1], SRpnt
->sr_cmnd
[2],
218 SRpnt
->sr_cmnd
[3], SRpnt
->sr_cmnd
[4], SRpnt
->sr_cmnd
[5],
220 if (scode
) printk(OSST_DEB_MSG
"%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
221 name
, scode
, sense
[12], sense
[13]);
222 if (driver_byte(result
) & DRIVER_SENSE
)
223 print_req_sense("osst ", SRpnt
);
227 if (!(driver_byte(result
) & DRIVER_SENSE
) ||
228 ((sense
[0] & 0x70) == 0x70 &&
230 scode
!= RECOVERED_ERROR
&&
231 /* scode != UNIT_ATTENTION && */
232 scode
!= BLANK_CHECK
&&
233 scode
!= VOLUME_OVERFLOW
&&
234 SRpnt
->sr_cmnd
[0] != MODE_SENSE
&&
235 SRpnt
->sr_cmnd
[0] != TEST_UNIT_READY
)) { /* Abnormal conditions for tape */
236 if (driver_byte(result
) & DRIVER_SENSE
) {
237 printk(KERN_WARNING
"%s:W: Command with sense data: ", name
);
238 print_req_sense("osst:", SRpnt
);
241 static int notyetprinted
= 1;
244 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
245 name
, result
, suggestion(result
), driver_byte(result
) & DRIVER_MASK
,
250 "%s:I: This warning may be caused by your scsi controller,\n", name
);
252 "%s:I: it has been reported with some Buslogic cards.\n", name
);
256 STp
->pos_unknown
|= STp
->device
->was_reset
;
258 if ((sense
[0] & 0x70) == 0x70 &&
259 scode
== RECOVERED_ERROR
) {
260 STp
->recover_count
++;
261 STp
->recover_erreg
++;
264 if (SRpnt
->sr_cmnd
[0] == READ_6
)
266 else if (SRpnt
->sr_cmnd
[0] == WRITE_6
)
270 printk(OSST_DEB_MSG
"%s:D: Recovered %s error (%d).\n", name
, stp
,
274 if ((sense
[2] & 0xe0) == 0)
281 /* Wakeup from interrupt */
282 static void osst_sleep_done (Scsi_Cmnd
* SCpnt
)
284 OS_Scsi_Tape
* STp
= container_of(SCpnt
->request
->rq_disk
->private_data
, OS_Scsi_Tape
, driver
);
286 if ((STp
->buffer
)->writing
&&
287 (SCpnt
->sense_buffer
[0] & 0x70) == 0x70 &&
288 (SCpnt
->sense_buffer
[2] & 0x40)) {
289 /* EOM at write-behind, has all been written? */
290 if ((SCpnt
->sense_buffer
[2] & 0x0f) == VOLUME_OVERFLOW
)
291 STp
->buffer
->midlevel_result
= SCpnt
->result
; /* Error */
293 STp
->buffer
->midlevel_result
= INT_MAX
; /* OK */
296 STp
->buffer
->midlevel_result
= SCpnt
->result
;
297 SCpnt
->request
->rq_status
= RQ_SCSI_DONE
;
298 STp
->buffer
->last_SRpnt
= SCpnt
->sc_request
;
301 STp
->write_pending
= 0;
303 complete(SCpnt
->request
->waiting
);
307 /* Do the scsi command. Waits until command performed if do_wait is true.
308 Otherwise osst_write_behind_check() is used to check that the command
310 static Scsi_Request
* osst_do_scsi(Scsi_Request
*SRpnt
, OS_Scsi_Tape
*STp
,
311 unsigned char *cmd
, int bytes
, int direction
, int timeout
, int retries
, int do_wait
)
314 #ifdef OSST_INJECT_ERRORS
315 static int inject
= 0;
316 static int repeat
= 0;
319 if ((SRpnt
= scsi_allocate_request(STp
->device
)) == NULL
) {
320 printk(KERN_ERR
"%s:E: Can't get SCSI request.\n", tape_name(STp
));
321 if (signal_pending(current
))
322 (STp
->buffer
)->syscall_result
= (-EINTR
);
324 (STp
->buffer
)->syscall_result
= (-EBUSY
);
329 init_completion(&STp
->wait
);
330 SRpnt
->sr_use_sg
= (bytes
> (STp
->buffer
)->sg
[0].length
) ?
331 (STp
->buffer
)->use_sg
: 0;
332 if (SRpnt
->sr_use_sg
) {
333 bp
= (char *)&(STp
->buffer
->sg
[0]);
334 if (STp
->buffer
->sg_segs
< SRpnt
->sr_use_sg
)
335 SRpnt
->sr_use_sg
= STp
->buffer
->sg_segs
;
338 bp
= (STp
->buffer
)->b_data
;
339 SRpnt
->sr_data_direction
= direction
;
340 SRpnt
->sr_cmd_len
= 0;
341 SRpnt
->sr_request
->waiting
= &(STp
->wait
);
342 SRpnt
->sr_request
->rq_status
= RQ_SCSI_BUSY
;
343 SRpnt
->sr_request
->rq_disk
= STp
->drive
;
345 scsi_do_req(SRpnt
, (void *)cmd
, bp
, bytes
, osst_sleep_done
, timeout
, retries
);
348 wait_for_completion(SRpnt
->sr_request
->waiting
);
349 SRpnt
->sr_request
->waiting
= NULL
;
350 STp
->buffer
->syscall_result
= osst_chk_result(STp
, SRpnt
);
351 #ifdef OSST_INJECT_ERRORS
352 if (STp
->buffer
->syscall_result
== 0 &&
355 ( (++ inject
% 83) == 29 ||
356 (STp
->first_frame_position
== 240
357 /* or STp->read_error_frame to fail again on the block calculated above */ &&
359 printk(OSST_DEB_MSG
"%s:D: Injecting read error\n", tape_name(STp
));
360 STp
->buffer
->last_result_fatal
= 1;
368 /* Handle the write-behind checking (downs the semaphore) */
369 static void osst_write_behind_check(OS_Scsi_Tape
*STp
)
371 OSST_buffer
* STbuffer
;
373 STbuffer
= STp
->buffer
;
376 if (STp
->write_pending
)
381 wait_for_completion(&(STp
->wait
));
382 (STp
->buffer
)->last_SRpnt
->sr_request
->waiting
= NULL
;
384 STp
->buffer
->syscall_result
= osst_chk_result(STp
, STp
->buffer
->last_SRpnt
);
386 if ((STp
->buffer
)->syscall_result
)
387 (STp
->buffer
)->syscall_result
=
388 osst_write_error_recovery(STp
, &((STp
->buffer
)->last_SRpnt
), 1);
390 STp
->first_frame_position
++;
392 scsi_release_request((STp
->buffer
)->last_SRpnt
);
394 if (STbuffer
->writing
< STbuffer
->buffer_bytes
)
395 printk(KERN_WARNING
"osst :A: write_behind_check: something left in buffer!\n");
397 STbuffer
->buffer_bytes
-= STbuffer
->writing
;
398 STbuffer
->writing
= 0;
405 /* Onstream specific Routines */
407 * Initialize the OnStream AUX
409 static void osst_init_aux(OS_Scsi_Tape
* STp
, int frame_type
, int frame_seq_number
,
410 int logical_blk_num
, int blk_sz
, int blk_cnt
)
412 os_aux_t
*aux
= STp
->buffer
->aux
;
413 os_partition_t
*par
= &aux
->partition
;
414 os_dat_t
*dat
= &aux
->dat
;
416 if (STp
->raw
) return;
418 memset(aux
, 0, sizeof(*aux
));
419 aux
->format_id
= htonl(0);
420 memcpy(aux
->application_sig
, "LIN4", 4);
421 aux
->hdwr
= htonl(0);
422 aux
->frame_type
= frame_type
;
424 switch (frame_type
) {
425 case OS_FRAME_TYPE_HEADER
:
426 aux
->update_frame_cntr
= htonl(STp
->update_frame_cntr
);
427 par
->partition_num
= OS_CONFIG_PARTITION
;
428 par
->par_desc_ver
= OS_PARTITION_VERSION
;
429 par
->wrt_pass_cntr
= htons(0xffff);
430 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
431 par
->first_frame_ppos
= htonl(0);
432 par
->last_frame_ppos
= htonl(0xbb7);
433 aux
->frame_seq_num
= htonl(0);
434 aux
->logical_blk_num_high
= htonl(0);
435 aux
->logical_blk_num
= htonl(0);
436 aux
->next_mark_ppos
= htonl(STp
->first_mark_ppos
);
438 case OS_FRAME_TYPE_DATA
:
439 case OS_FRAME_TYPE_MARKER
:
444 dat
->dat_list
[0].blk_sz
= htonl(blk_sz
);
445 dat
->dat_list
[0].blk_cnt
= htons(blk_cnt
);
446 dat
->dat_list
[0].flags
= frame_type
==OS_FRAME_TYPE_MARKER
?
447 OS_DAT_FLAGS_MARK
:OS_DAT_FLAGS_DATA
;
448 dat
->dat_list
[0].reserved
= 0;
449 case OS_FRAME_TYPE_EOD
:
450 aux
->update_frame_cntr
= htonl(0);
451 par
->partition_num
= OS_DATA_PARTITION
;
452 par
->par_desc_ver
= OS_PARTITION_VERSION
;
453 par
->wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
454 par
->first_frame_ppos
= htonl(STp
->first_data_ppos
);
455 par
->last_frame_ppos
= htonl(STp
->capacity
);
456 aux
->frame_seq_num
= htonl(frame_seq_number
);
457 aux
->logical_blk_num_high
= htonl(0);
458 aux
->logical_blk_num
= htonl(logical_blk_num
);
460 default: ; /* probably FILL */
462 aux
->filemark_cnt
= ntohl(STp
->filemark_cnt
);
463 aux
->phys_fm
= ntohl(0xffffffff);
464 aux
->last_mark_ppos
= ntohl(STp
->last_mark_ppos
);
465 aux
->last_mark_lbn
= ntohl(STp
->last_mark_lbn
);
469 * Verify that we have the correct tape frame
471 static int osst_verify_frame(OS_Scsi_Tape
* STp
, int frame_seq_number
, int quiet
)
473 char * name
= tape_name(STp
);
474 os_aux_t
* aux
= STp
->buffer
->aux
;
475 os_partition_t
* par
= &(aux
->partition
);
476 ST_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
477 int blk_cnt
, blk_sz
, i
;
480 if (STp
->buffer
->syscall_result
) {
481 for (i
=0; i
< STp
->buffer
->sg_segs
; i
++)
482 memset(page_address(STp
->buffer
->sg
[i
].page
),
483 0, STp
->buffer
->sg
[i
].length
);
484 strcpy(STp
->buffer
->b_data
, "READ ERROR ON FRAME");
486 STp
->buffer
->buffer_bytes
= OS_FRAME_SIZE
;
489 if (STp
->buffer
->syscall_result
) {
491 printk(OSST_DEB_MSG
"%s:D: Skipping frame, read error\n", name
);
495 if (ntohl(aux
->format_id
) != 0) {
497 printk(OSST_DEB_MSG
"%s:D: Skipping frame, format_id %u\n", name
, ntohl(aux
->format_id
));
501 if (memcmp(aux
->application_sig
, STp
->application_sig
, 4) != 0 &&
502 (memcmp(aux
->application_sig
, "LIN3", 4) != 0 || STp
->linux_media_version
!= 4)) {
504 printk(OSST_DEB_MSG
"%s:D: Skipping frame, incorrect application signature\n", name
);
508 if (par
->partition_num
!= OS_DATA_PARTITION
) {
509 if (!STp
->linux_media
|| STp
->linux_media_version
!= 2) {
511 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition num %d\n",
512 name
, par
->partition_num
);
517 if (par
->par_desc_ver
!= OS_PARTITION_VERSION
) {
519 printk(OSST_DEB_MSG
"%s:D: Skipping frame, partition version %d\n", name
, par
->par_desc_ver
);
523 if (ntohs(par
->wrt_pass_cntr
) != STp
->wrt_pass_cntr
) {
525 printk(OSST_DEB_MSG
"%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
526 name
, ntohs(par
->wrt_pass_cntr
), STp
->wrt_pass_cntr
);
530 if (aux
->frame_type
!= OS_FRAME_TYPE_DATA
&&
531 aux
->frame_type
!= OS_FRAME_TYPE_EOD
&&
532 aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
535 printk(OSST_DEB_MSG
"%s:D: Skipping frame, frame type %x\n", name
, aux
->frame_type
);
539 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
&&
540 STp
->first_frame_position
< STp
->eod_frame_ppos
) {
541 printk(KERN_INFO
"%s:I: Skipping premature EOD frame %d\n", name
,
542 STp
->first_frame_position
);
545 if (frame_seq_number
!= -1 && ntohl(aux
->frame_seq_num
) != frame_seq_number
) {
548 printk(OSST_DEB_MSG
"%s:D: Skipping frame, sequence number %u (expected %d)\n",
549 name
, ntohl(aux
->frame_seq_num
), frame_seq_number
);
553 if (aux
->frame_type
== OS_FRAME_TYPE_MARKER
) {
554 STps
->eof
= ST_FM_HIT
;
556 i
= ntohl(aux
->filemark_cnt
);
557 if (STp
->header_cache
!= NULL
&& i
< OS_FM_TAB_MAX
&& (i
> STp
->filemark_cnt
||
558 STp
->first_frame_position
- 1 != ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
]))) {
560 printk(OSST_DEB_MSG
"%s:D: %s filemark %d at frame pos %d\n", name
,
561 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] == 0?"Learned":"Corrected",
562 i
, STp
->first_frame_position
- 1);
564 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
] = htonl(STp
->first_frame_position
- 1);
565 if (i
>= STp
->filemark_cnt
)
566 STp
->filemark_cnt
= i
+1;
569 if (aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
570 STps
->eof
= ST_EOD_1
;
571 STp
->frame_in_buffer
= 1;
573 if (aux
->frame_type
== OS_FRAME_TYPE_DATA
) {
574 blk_cnt
= ntohs(aux
->dat
.dat_list
[0].blk_cnt
);
575 blk_sz
= ntohl(aux
->dat
.dat_list
[0].blk_sz
);
576 STp
->buffer
->buffer_bytes
= blk_cnt
* blk_sz
;
577 STp
->buffer
->read_pointer
= 0;
578 STp
->frame_in_buffer
= 1;
580 /* See what block size was used to write file */
581 if (STp
->block_size
!= blk_sz
&& blk_sz
> 0) {
583 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
584 name
, blk_sz
<1024?blk_sz
:blk_sz
/1024,blk_sz
<1024?'b':'k',
585 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
586 STp
->block_size
<1024?'b':'k');
587 STp
->block_size
= blk_sz
;
588 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ blk_sz
;
590 STps
->eof
= ST_NOEOF
;
592 STp
->frame_seq_number
= ntohl(aux
->frame_seq_num
);
593 STp
->logical_blk_num
= ntohl(aux
->logical_blk_num
);
597 if (STp
->read_error_frame
== 0)
598 STp
->read_error_frame
= STp
->first_frame_position
- 1;
603 * Wait for the unit to become Ready
605 static int osst_wait_ready(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, unsigned timeout
, int initial_delay
)
607 unsigned char cmd
[MAX_COMMAND_SIZE
];
608 Scsi_Request
* SRpnt
;
609 unsigned long startwait
= jiffies
;
612 char * name
= tape_name(STp
);
614 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait ready\n", name
);
617 if (initial_delay
> 0) {
618 set_current_state(TASK_INTERRUPTIBLE
);
619 schedule_timeout(initial_delay
);
622 memset(cmd
, 0, MAX_COMMAND_SIZE
);
623 cmd
[0] = TEST_UNIT_READY
;
625 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
, STp
->timeout
, MAX_READY_RETRIES
, TRUE
);
627 if (!SRpnt
) return (-EBUSY
);
629 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
630 (( SRpnt
->sr_sense_buffer
[2] == 2 && SRpnt
->sr_sense_buffer
[12] == 4 &&
631 (SRpnt
->sr_sense_buffer
[13] == 1 || SRpnt
->sr_sense_buffer
[13] == 8) ) ||
632 ( SRpnt
->sr_sense_buffer
[2] == 6 && SRpnt
->sr_sense_buffer
[12] == 0x28 &&
633 SRpnt
->sr_sense_buffer
[13] == 0 ) )) {
636 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait ready\n", name
);
637 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
641 set_current_state(TASK_INTERRUPTIBLE
);
642 schedule_timeout(HZ
/ 10);
644 memset(cmd
, 0, MAX_COMMAND_SIZE
);
645 cmd
[0] = TEST_UNIT_READY
;
647 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
, STp
->timeout
, MAX_READY_RETRIES
, TRUE
);
653 if ( STp
->buffer
->syscall_result
&&
654 osst_write_error_recovery(STp
, aSRpnt
, 0) ) {
656 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait ready\n", name
);
657 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
658 STp
->buffer
->syscall_result
, SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[2],
659 SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
664 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait ready\n", name
);
670 * Wait for a tape to be inserted in the unit
672 static int osst_wait_for_medium(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, unsigned timeout
)
674 unsigned char cmd
[MAX_COMMAND_SIZE
];
675 Scsi_Request
* SRpnt
;
676 unsigned long startwait
= jiffies
;
679 char * name
= tape_name(STp
);
681 printk(OSST_DEB_MSG
"%s:D: Reached onstream wait for medium\n", name
);
684 memset(cmd
, 0, MAX_COMMAND_SIZE
);
685 cmd
[0] = TEST_UNIT_READY
;
687 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
, STp
->timeout
, MAX_READY_RETRIES
, TRUE
);
689 if (!SRpnt
) return (-EBUSY
);
691 while ( STp
->buffer
->syscall_result
&& time_before(jiffies
, startwait
+ timeout
*HZ
) &&
692 SRpnt
->sr_sense_buffer
[2] == 2 && SRpnt
->sr_sense_buffer
[12] == 0x3a &&
693 SRpnt
->sr_sense_buffer
[13] == 0 ) {
696 printk(OSST_DEB_MSG
"%s:D: Sleeping in onstream wait medium\n", name
);
697 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
701 set_current_state(TASK_INTERRUPTIBLE
);
702 schedule_timeout(HZ
/ 10);
704 memset(cmd
, 0, MAX_COMMAND_SIZE
);
705 cmd
[0] = TEST_UNIT_READY
;
707 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
, STp
->timeout
, MAX_READY_RETRIES
, TRUE
);
713 if ( STp
->buffer
->syscall_result
&& SRpnt
->sr_sense_buffer
[2] != 2 &&
714 SRpnt
->sr_sense_buffer
[12] != 4 && SRpnt
->sr_sense_buffer
[13] == 1) {
716 printk(OSST_DEB_MSG
"%s:D: Abnormal exit from onstream wait medium\n", name
);
717 printk(OSST_DEB_MSG
"%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name
,
718 STp
->buffer
->syscall_result
, SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[2],
719 SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
724 printk(OSST_DEB_MSG
"%s:D: Normal exit from onstream wait medium\n", name
);
729 static int osst_position_tape_and_confirm(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int frame
)
733 osst_wait_ready(STp
, aSRpnt
, 15 * 60, 0); /* TODO - can this catch a write error? */
734 retval
= osst_set_frame_position(STp
, aSRpnt
, frame
, 0);
735 if (retval
) return (retval
);
736 osst_wait_ready(STp
, aSRpnt
, 15 * 60, OSST_WAIT_POSITION_COMPLETE
);
737 return (osst_get_frame_position(STp
, aSRpnt
));
741 * Wait for write(s) to complete
743 static int osst_flush_drive_buffer(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
)
745 unsigned char cmd
[MAX_COMMAND_SIZE
];
746 Scsi_Request
* SRpnt
;
749 int delay
= OSST_WAIT_WRITE_COMPLETE
;
751 char * name
= tape_name(STp
);
753 printk(OSST_DEB_MSG
"%s:D: Reached onstream flush drive buffer (write filemark)\n", name
);
756 memset(cmd
, 0, MAX_COMMAND_SIZE
);
757 cmd
[0] = WRITE_FILEMARKS
;
760 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
, STp
->timeout
, MAX_WRITE_RETRIES
, TRUE
);
762 if (!SRpnt
) return (-EBUSY
);
763 if (STp
->buffer
->syscall_result
) {
764 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == 2 && SRpnt
->sr_sense_buffer
[12] == 4) {
765 if (SRpnt
->sr_sense_buffer
[13] == 8) {
766 delay
= OSST_WAIT_LONG_WRITE_COMPLETE
;
769 result
= osst_write_error_recovery(STp
, aSRpnt
, 0);
771 result
|= osst_wait_ready(STp
, aSRpnt
, 5 * 60, delay
);
772 STp
->ps
[STp
->partition
].rw
= OS_WRITING_COMPLETE
;
777 #define OSST_POLL_PER_SEC 10
778 static int osst_wait_frame(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int curr
, int minlast
, int to
)
780 unsigned long startwait
= jiffies
;
781 char * name
= tape_name(STp
);
783 char notyetprinted
= 1;
785 if (minlast
>= 0 && STp
->ps
[STp
->partition
].rw
!= ST_READING
)
786 printk(KERN_ERR
"%s:A: Waiting for frame without having initialized read!\n", name
);
788 while (time_before (jiffies
, startwait
+ to
*HZ
))
791 result
= osst_get_frame_position (STp
, aSRpnt
);
793 if ((result
= osst_write_error_recovery(STp
, aSRpnt
, 0)) == 0)
794 return 0; /* successful recovery leaves drive ready for frame */
795 if (result
< 0) break;
796 if (STp
->first_frame_position
== curr
&&
798 (signed)STp
->last_frame_position
> (signed)curr
+ minlast
) ||
799 (minlast
>= 0 && STp
->cur_frames
> minlast
)
803 if (debugging
|| jiffies
- startwait
>= 2*HZ
/OSST_POLL_PER_SEC
)
805 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
806 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
807 STp
->last_frame_position
, STp
->cur_frames
,
808 result
, (jiffies
-startwait
)/HZ
,
809 (((jiffies
-startwait
)%HZ
)*10)/HZ
);
814 if (jiffies
- startwait
>= 2*HZ
/OSST_POLL_PER_SEC
&& notyetprinted
)
816 printk (OSST_DEB_MSG
"%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
817 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
818 STp
->last_frame_position
, STp
->cur_frames
, result
);
822 set_current_state(TASK_INTERRUPTIBLE
);
823 schedule_timeout (HZ
/ OSST_POLL_PER_SEC
);
826 printk (OSST_DEB_MSG
"%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
827 name
, curr
, curr
+minlast
, STp
->first_frame_position
,
828 STp
->last_frame_position
, STp
->cur_frames
,
829 (jiffies
-startwait
)/HZ
, (((jiffies
-startwait
)%HZ
)*10)/HZ
);
835 * Read the next OnStream tape frame at the current location
837 static int osst_read_frame(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int timeout
)
839 unsigned char cmd
[MAX_COMMAND_SIZE
];
840 Scsi_Request
* SRpnt
;
843 os_aux_t
* aux
= STp
->buffer
->aux
;
844 char * name
= tape_name(STp
);
847 /* TODO: Error handling */
849 retval
= osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, 0, timeout
);
851 printk ("osst_read: wait for frame returned %i\n", retval
);
854 memset(cmd
, 0, MAX_COMMAND_SIZE
);
861 printk(OSST_DEB_MSG
"%s:D: Reading frame from OnStream tape\n", name
);
863 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, SCSI_DATA_READ
,
864 STp
->timeout
, MAX_READ_RETRIES
, TRUE
);
869 if ((STp
->buffer
)->syscall_result
) {
871 if (STp
->read_error_frame
== 0) {
872 STp
->read_error_frame
= STp
->first_frame_position
;
874 printk(OSST_DEB_MSG
"%s:D: Recording read error at %d\n", name
, STp
->read_error_frame
);
879 printk(OSST_DEB_MSG
"%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
881 SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[1],
882 SRpnt
->sr_sense_buffer
[2], SRpnt
->sr_sense_buffer
[3],
883 SRpnt
->sr_sense_buffer
[4], SRpnt
->sr_sense_buffer
[5],
884 SRpnt
->sr_sense_buffer
[6], SRpnt
->sr_sense_buffer
[7]);
888 STp
->first_frame_position
++;
893 sig
[i
] = aux
->application_sig
[i
]<32?'^':aux
->application_sig
[i
];
896 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name
, sig
,
897 ntohl(aux
->update_frame_cntr
), ntohs(aux
->partition
.wrt_pass_cntr
),
898 aux
->frame_type
==1?"EOD":aux
->frame_type
==2?"MARK":
899 aux
->frame_type
==8?"HEADR":aux
->frame_type
==0x80?"DATA":"FILL",
900 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
901 ntohs(aux
->dat
.dat_list
[0].blk_cnt
), ntohl(aux
->dat
.dat_list
[0].blk_sz
) );
902 if (aux
->frame_type
==2)
903 printk(OSST_DEB_MSG
"%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name
,
904 ntohl(aux
->filemark_cnt
), ntohl(aux
->last_mark_ppos
), ntohl(aux
->last_mark_lbn
));
905 printk(OSST_DEB_MSG
"%s:D: Exit read frame from OnStream tape with code %d\n", name
, retval
);
911 static int osst_initiate_read(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
)
913 ST_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
914 Scsi_Request
* SRpnt
;
915 unsigned char cmd
[MAX_COMMAND_SIZE
];
918 char * name
= tape_name(STp
);
921 if (STps
->rw
!= ST_READING
) { /* Initialize read operation */
922 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) {
923 STp
->write_type
= OS_WRITE_DATA
;
924 osst_flush_write_buffer(STp
, aSRpnt
);
925 osst_flush_drive_buffer(STp
, aSRpnt
);
927 STps
->rw
= ST_READING
;
928 STp
->frame_in_buffer
= 0;
931 * Issue a read 0 command to get the OnStream drive
932 * read frames into its buffer.
934 memset(cmd
, 0, MAX_COMMAND_SIZE
);
939 printk(OSST_DEB_MSG
"%s:D: Start Read Ahead on OnStream tape\n", name
);
941 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
, STp
->timeout
, MAX_READ_RETRIES
, TRUE
);
943 retval
= STp
->buffer
->syscall_result
;
949 static int osst_get_logical_frame(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int frame_seq_number
, int quiet
)
951 ST_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
952 char * name
= tape_name(STp
);
960 * If we want just any frame (-1) and there is a frame in the buffer, return it
962 if (frame_seq_number
== -1 && STp
->frame_in_buffer
) {
964 printk(OSST_DEB_MSG
"%s:D: Frame %d still in buffer\n", name
, STp
->frame_seq_number
);
969 * Search and wait for the next logical tape frame
973 printk(KERN_ERR
"%s:E: Couldn't find logical frame %d, aborting\n",
974 name
, frame_seq_number
);
975 if (STp
->read_error_frame
) {
976 osst_set_frame_position(STp
, aSRpnt
, STp
->read_error_frame
, 0);
978 printk(OSST_DEB_MSG
"%s:D: Repositioning tape to bad frame %d\n",
979 name
, STp
->read_error_frame
);
981 STp
->read_error_frame
= 0;
987 printk(OSST_DEB_MSG
"%s:D: Looking for frame %d, attempt %d\n",
988 name
, frame_seq_number
, cnt
);
990 if ( osst_initiate_read(STp
, aSRpnt
)
991 || ( (!STp
->frame_in_buffer
) && osst_read_frame(STp
, aSRpnt
, 30) ) ) {
994 position
= osst_get_frame_position(STp
, aSRpnt
);
995 if (position
>= 0xbae && position
< 0xbb8)
997 else if (position
> STp
->eod_frame_ppos
|| ++bad
== 10) {
998 position
= STp
->read_error_frame
- 1;
1005 printk(OSST_DEB_MSG
"%s:D: Bad frame detected, positioning tape to block %d\n",
1008 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1011 if (osst_verify_frame(STp
, frame_seq_number
, quiet
))
1013 if (osst_verify_frame(STp
, -1, quiet
)) {
1014 x
= ntohl(STp
->buffer
->aux
->frame_seq_num
);
1015 if (STp
->fast_open
) {
1017 "%s:W: Found logical frame %d instead of %d after fast open\n",
1018 name
, x
, frame_seq_number
);
1020 STp
->read_error_frame
= 0;
1023 if (x
> frame_seq_number
) {
1025 /* positioning backwards did not bring us to the desired frame */
1026 position
= STp
->read_error_frame
- 1;
1029 position
= osst_get_frame_position(STp
, aSRpnt
)
1030 + frame_seq_number
- x
- 1;
1032 if (STp
->first_frame_position
>= 3000 && position
< 3000)
1037 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1038 name
, x
, frame_seq_number
,
1039 STp
->first_frame_position
- position
);
1041 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
1047 if (osst_get_frame_position(STp
, aSRpnt
) == 0xbaf) {
1049 printk(OSST_DEB_MSG
"%s:D: Skipping config partition\n", name
);
1051 osst_set_frame_position(STp
, aSRpnt
, 0xbb8, 0);
1054 STp
->frame_in_buffer
= 0;
1057 STp
->recover_count
++;
1058 STp
->recover_erreg
++;
1059 printk(KERN_WARNING
"%s:I: Don't worry, Read error at position %d recovered\n",
1060 name
, STp
->read_error_frame
);
1065 if (debugging
|| STps
->eof
)
1067 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1068 name
, frame_seq_number
, STp
->frame_seq_number
, STps
->eof
);
1070 STp
->fast_open
= FALSE
;
1071 STp
->read_error_frame
= 0;
1075 static int osst_seek_logical_blk(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int logical_blk_num
)
1077 ST_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1078 char * name
= tape_name(STp
);
1080 int frame_seq_estimate
, ppos_estimate
, move
;
1082 if (logical_blk_num
< 0) logical_blk_num
= 0;
1084 printk(OSST_DEB_MSG
"%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1085 name
, logical_blk_num
, STp
->logical_blk_num
,
1086 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024,
1087 STp
->block_size
<1024?'b':'k');
1089 /* Do we know where we are? */
1090 if (STps
->drv_block
>= 0) {
1091 move
= logical_blk_num
- STp
->logical_blk_num
;
1092 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1093 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1094 frame_seq_estimate
= STp
->frame_seq_number
+ move
;
1096 frame_seq_estimate
= logical_blk_num
* STp
->block_size
/ OS_DATA_SIZE
;
1098 if (frame_seq_estimate
< 2980) ppos_estimate
= frame_seq_estimate
+ 10;
1099 else ppos_estimate
= frame_seq_estimate
+ 20;
1100 while (++retries
< 10) {
1101 if (ppos_estimate
> STp
->eod_frame_ppos
-2) {
1102 frame_seq_estimate
+= STp
->eod_frame_ppos
- 2 - ppos_estimate
;
1103 ppos_estimate
= STp
->eod_frame_ppos
- 2;
1105 if (frame_seq_estimate
< 0) {
1106 frame_seq_estimate
= 0;
1109 osst_set_frame_position(STp
, aSRpnt
, ppos_estimate
, 0);
1110 if (osst_get_logical_frame(STp
, aSRpnt
, frame_seq_estimate
, 1) >= 0) {
1111 /* we've located the estimated frame, now does it have our block? */
1112 if (logical_blk_num
< STp
->logical_blk_num
||
1113 logical_blk_num
>= STp
->logical_blk_num
+ ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
)) {
1114 if (STps
->eof
== ST_FM_HIT
)
1115 move
= logical_blk_num
< STp
->logical_blk_num
? -2 : 1;
1117 move
= logical_blk_num
- STp
->logical_blk_num
;
1118 if (move
< 0) move
-= (OS_DATA_SIZE
/ STp
->block_size
) - 1;
1119 move
/= (OS_DATA_SIZE
/ STp
->block_size
);
1121 if (!move
) move
= logical_blk_num
> STp
->logical_blk_num
? 1 : -1;
1124 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1125 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1126 STp
->logical_blk_num
, logical_blk_num
, move
);
1128 frame_seq_estimate
+= move
;
1129 ppos_estimate
+= move
;
1132 STp
->buffer
->read_pointer
= (logical_blk_num
- STp
->logical_blk_num
) * STp
->block_size
;
1133 STp
->buffer
->buffer_bytes
-= STp
->buffer
->read_pointer
;
1134 STp
->logical_blk_num
= logical_blk_num
;
1137 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1138 name
, ppos_estimate
, STp
->frame_seq_number
, STp
->frame_in_buffer
,
1139 STp
->buffer
->buffer_bytes
, STp
->buffer
->read_pointer
/ STp
->block_size
,
1142 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1143 if (STps
->eof
== ST_FM_HIT
) {
1145 STps
->drv_block
= 0;
1147 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1148 STp
->logical_blk_num
-
1149 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1152 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1156 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 1) < 0)
1158 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1160 printk(OSST_DEB_MSG
"%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1161 name
, retries
, ppos_estimate
, STp
->frame_seq_number
, frame_seq_estimate
,
1162 STp
->logical_blk_num
, logical_blk_num
);
1164 if (frame_seq_estimate
!= STp
->frame_seq_number
)
1165 ppos_estimate
+= frame_seq_estimate
- STp
->frame_seq_number
;
1170 printk(KERN_ERR
"%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1171 name
, logical_blk_num
, STp
->logical_blk_num
, retries
);
1175 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1176 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1177 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1178 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1180 #define OSST_FRAME_SHIFT 6
1181 #define OSST_SECTOR_SHIFT 9
1182 #define OSST_SECTOR_MASK 0x03F
1184 static int osst_get_sector(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
)
1188 char * name
= tape_name(STp
);
1191 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1192 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1193 STp
->ps
[STp
->partition
].drv_file
, STp
->ps
[STp
->partition
].drv_block
,
1194 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?'w':'r',
1195 STp
->ps
[STp
->partition
].rw
== ST_WRITING
?STp
->buffer
->buffer_bytes
:
1196 STp
->buffer
->read_pointer
, STp
->ps
[STp
->partition
].eof
);
1198 /* do we know where we are inside a file? */
1199 if (STp
->ps
[STp
->partition
].drv_block
>= 0) {
1200 sector
= (STp
->frame_in_buffer
? STp
->first_frame_position
-1 :
1201 STp
->first_frame_position
) << OSST_FRAME_SHIFT
;
1202 if (STp
->ps
[STp
->partition
].rw
== ST_WRITING
)
1203 sector
|= (STp
->buffer
->buffer_bytes
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1205 sector
|= (STp
->buffer
->read_pointer
>> OSST_SECTOR_SHIFT
) & OSST_SECTOR_MASK
;
1207 sector
= osst_get_frame_position(STp
, aSRpnt
);
1209 sector
<<= OSST_FRAME_SHIFT
;
1214 static int osst_seek_sector(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int sector
)
1216 ST_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
1217 int frame
= sector
>> OSST_FRAME_SHIFT
,
1218 offset
= (sector
& OSST_SECTOR_MASK
) << OSST_SECTOR_SHIFT
,
1221 char * name
= tape_name(STp
);
1223 printk(OSST_DEB_MSG
"%s:D: Seeking sector %d in frame %d at offset %d\n",
1224 name
, sector
, frame
, offset
);
1226 if (frame
< 0 || frame
>= STp
->capacity
) return (-ENXIO
);
1228 if (frame
<= STp
->first_data_ppos
) {
1229 STp
->frame_seq_number
= STp
->logical_blk_num
= STps
->drv_file
= STps
->drv_block
= 0;
1230 return (osst_set_frame_position(STp
, aSRpnt
, frame
, 0));
1232 r
= osst_set_frame_position(STp
, aSRpnt
, offset
?frame
:frame
-1, 0);
1233 if (r
< 0) return r
;
1235 r
= osst_get_logical_frame(STp
, aSRpnt
, -1, 1);
1236 if (r
< 0) return r
;
1238 if (osst_get_frame_position(STp
, aSRpnt
) != (offset
?frame
+1:frame
)) return (-EIO
);
1241 STp
->logical_blk_num
+= offset
/ STp
->block_size
;
1242 STp
->buffer
->read_pointer
= offset
;
1243 STp
->buffer
->buffer_bytes
-= offset
;
1245 STp
->frame_seq_number
++;
1246 STp
->frame_in_buffer
= 0;
1247 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1248 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
1250 STps
->drv_file
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1251 if (STps
->eof
== ST_FM_HIT
) {
1253 STps
->drv_block
= 0;
1255 STps
->drv_block
= ntohl(STp
->buffer
->aux
->last_mark_lbn
)?
1256 STp
->logical_blk_num
-
1257 (STps
->drv_file
? ntohl(STp
->buffer
->aux
->last_mark_lbn
) + 1 : 0):
1260 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_NOEOF
;
1263 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1264 name
, STp
->first_frame_position
, STp
->frame_seq_number
, STp
->logical_blk_num
,
1265 STps
->drv_file
, STps
->drv_block
, STp
->buffer
->read_pointer
, STps
->eof
);
1271 * Read back the drive's internal buffer contents, as a part
1272 * of the write error recovery mechanism for old OnStream
1273 * firmware revisions.
1274 * Precondition for this function to work: all frames in the
1275 * drive's buffer must be of one type (DATA, MARK or EOD)!
1277 static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
,
1278 unsigned int frame
, unsigned int skip
, int pending
)
1280 Scsi_Request
* SRpnt
= * aSRpnt
;
1281 unsigned char * buffer
, * p
;
1282 unsigned char cmd
[MAX_COMMAND_SIZE
];
1283 int flag
, new_frame
, i
;
1284 int nframes
= STp
->cur_frames
;
1285 int blks_per_frame
= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1286 int frame_seq_number
= ntohl(STp
->buffer
->aux
->frame_seq_num
)
1287 - (nframes
+ pending
- 1);
1288 int logical_blk_num
= ntohl(STp
->buffer
->aux
->logical_blk_num
)
1289 - (nframes
+ pending
- 1) * blks_per_frame
;
1290 char * name
= tape_name(STp
);
1291 unsigned long startwait
= jiffies
;
1293 int dbg
= debugging
;
1296 if ((buffer
= (unsigned char *)vmalloc((nframes
+ 1) * OS_DATA_SIZE
)) == NULL
)
1299 printk(KERN_INFO
"%s:I: Reading back %d frames from drive buffer%s\n",
1300 name
, nframes
, pending
?" and one that was pending":"");
1302 osst_copy_from_buffer(STp
->buffer
, (p
= &buffer
[nframes
* OS_DATA_SIZE
]));
1304 if (pending
&& debugging
)
1305 printk(OSST_DEB_MSG
"%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1306 name
, frame_seq_number
+ nframes
,
1307 logical_blk_num
+ nframes
* blks_per_frame
,
1308 p
[0], p
[1], p
[2], p
[3]);
1310 for (i
= 0, p
= buffer
; i
< nframes
; i
++, p
+= OS_DATA_SIZE
) {
1312 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1313 cmd
[0] = 0x3C; /* Buffer Read */
1314 cmd
[1] = 6; /* Retrieve Faulty Block */
1315 cmd
[7] = 32768 >> 8;
1316 cmd
[8] = 32768 & 0xff;
1318 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, SCSI_DATA_READ
,
1319 STp
->timeout
, MAX_READ_RETRIES
, TRUE
);
1321 if ((STp
->buffer
)->syscall_result
|| !SRpnt
) {
1322 printk(KERN_ERR
"%s:E: Failed to read frame back from OnStream buffer\n", name
);
1323 vfree((void *)buffer
);
1327 osst_copy_from_buffer(STp
->buffer
, p
);
1330 printk(OSST_DEB_MSG
"%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1331 name
, frame_seq_number
+ i
, p
[0], p
[1], p
[2], p
[3]);
1335 osst_get_frame_position(STp
, aSRpnt
);
1338 printk(OSST_DEB_MSG
"%s:D: Frames left in buffer: %d\n", name
, STp
->cur_frames
);
1340 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1341 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1343 for (flag
=1, new_frame
=frame
, p
=buffer
, i
=0; i
< nframes
+ pending
; ) {
1346 if (STp
->write_type
== OS_WRITE_HEADER
) {
1348 p
+= skip
* OS_DATA_SIZE
;
1350 else if (new_frame
< 2990 && new_frame
+skip
+nframes
+pending
>= 2990)
1355 printk(OSST_DEB_MSG
"%s:D: Position to frame %d, write fseq %d\n",
1356 name
, new_frame
+i
, frame_seq_number
+i
);
1358 osst_set_frame_position(STp
, aSRpnt
, new_frame
+ i
, 0);
1359 osst_wait_ready(STp
, aSRpnt
, 60, OSST_WAIT_POSITION_COMPLETE
);
1360 osst_get_frame_position(STp
, aSRpnt
);
1363 if (new_frame
> frame
+ 1000) {
1364 printk(KERN_ERR
"%s:E: Failed to find writable tape media\n", name
);
1365 vfree((void *)buffer
);
1369 if ( i
>= nframes
+ pending
) break;
1371 osst_copy_to_buffer(STp
->buffer
, p
);
1373 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1375 osst_init_aux(STp
, STp
->buffer
->aux
->frame_type
, frame_seq_number
+i
,
1376 logical_blk_num
+ i
*blks_per_frame
,
1377 ntohl(STp
->buffer
->aux
->dat
.dat_list
[0].blk_sz
), blks_per_frame
);
1378 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1386 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1387 name
, new_frame
+i
, frame_seq_number
+i
, logical_blk_num
+ i
*blks_per_frame
,
1388 p
[0], p
[1], p
[2], p
[3]);
1390 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, OS_FRAME_SIZE
, SCSI_DATA_WRITE
,
1391 STp
->timeout
, MAX_WRITE_RETRIES
, TRUE
);
1393 if (STp
->buffer
->syscall_result
)
1396 p
+= OS_DATA_SIZE
; i
++;
1398 /* if we just sent the last frame, wait till all successfully written */
1399 if ( i
== nframes
+ pending
) {
1401 printk(OSST_DEB_MSG
"%s:D: Check re-write successful\n", name
);
1403 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1404 cmd
[0] = WRITE_FILEMARKS
;
1406 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
,
1407 STp
->timeout
, MAX_WRITE_RETRIES
, TRUE
);
1410 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1411 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1415 flag
= STp
->buffer
->syscall_result
;
1416 while ( !flag
&& time_before(jiffies
, startwait
+ 60*HZ
) ) {
1418 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1419 cmd
[0] = TEST_UNIT_READY
;
1421 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
, STp
->timeout
,
1422 MAX_READY_RETRIES
, TRUE
);
1424 if (SRpnt
->sr_sense_buffer
[2] == 2 && SRpnt
->sr_sense_buffer
[12] == 4 &&
1425 (SRpnt
->sr_sense_buffer
[13] == 1 || SRpnt
->sr_sense_buffer
[13] == 8)) {
1426 /* in the process of becoming ready */
1427 set_current_state(TASK_INTERRUPTIBLE
);
1428 schedule_timeout(HZ
/ 10);
1431 if (STp
->buffer
->syscall_result
)
1437 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1443 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) == 13 &&
1444 SRpnt
->sr_sense_buffer
[12] == 0 &&
1445 SRpnt
->sr_sense_buffer
[13] == 2) {
1446 printk(KERN_ERR
"%s:E: Volume overflow in write error recovery\n", name
);
1447 vfree((void *)buffer
);
1448 return (-EIO
); /* hit end of tape = fail */
1450 i
= ((SRpnt
->sr_sense_buffer
[3] << 24) |
1451 (SRpnt
->sr_sense_buffer
[4] << 16) |
1452 (SRpnt
->sr_sense_buffer
[5] << 8) |
1453 SRpnt
->sr_sense_buffer
[6] ) - new_frame
;
1454 p
= &buffer
[i
* OS_DATA_SIZE
];
1456 printk(OSST_DEB_MSG
"%s:D: Additional write error at %d\n", name
, new_frame
+i
);
1458 osst_get_frame_position(STp
, aSRpnt
);
1460 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1461 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1466 osst_copy_to_buffer(STp
->buffer
, p
); /* so buffer content == at entry in all cases */
1467 vfree((void *)buffer
);
1471 static int osst_reposition_and_retry(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
,
1472 unsigned int frame
, unsigned int skip
, int pending
)
1474 unsigned char cmd
[MAX_COMMAND_SIZE
];
1475 Scsi_Request
* SRpnt
;
1476 char * name
= tape_name(STp
);
1478 int attempts
= 1000 / skip
;
1480 unsigned long startwait
= jiffies
;
1482 int dbg
= debugging
;
1485 while (attempts
&& time_before(jiffies
, startwait
+ 60*HZ
)) {
1490 if (frame
< 2990 && frame
+skip
+STp
->cur_frames
+pending
>= 2990)
1492 expected
= frame
+skip
+STp
->cur_frames
+pending
;
1494 printk(OSST_DEB_MSG
"%s:D: Position to fppos %d, re-write from fseq %d\n",
1495 name
, frame
+skip
, STp
->frame_seq_number
-STp
->cur_frames
-pending
);
1497 osst_set_frame_position(STp
, aSRpnt
, frame
+ skip
, 1);
1500 set_current_state(TASK_INTERRUPTIBLE
);
1501 schedule_timeout(HZ
/ 10);
1503 if (osst_get_frame_position(STp
, aSRpnt
) < 0) { /* additional write error */
1505 printk(OSST_DEB_MSG
"%s:D: Addl error, host %d, tape %d, buffer %d\n",
1506 name
, STp
->first_frame_position
,
1507 STp
->last_frame_position
, STp
->cur_frames
);
1509 frame
= STp
->last_frame_position
;
1513 if (pending
&& STp
->cur_frames
< 50) {
1515 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1520 printk(OSST_DEB_MSG
"%s:D: About to write pending fseq %d at fppos %d\n",
1521 name
, STp
->frame_seq_number
-1, STp
->first_frame_position
);
1523 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, SCSI_DATA_WRITE
,
1524 STp
->timeout
, MAX_WRITE_RETRIES
, TRUE
);
1527 if (STp
->buffer
->syscall_result
) { /* additional write error */
1528 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) == 13 &&
1529 SRpnt
->sr_sense_buffer
[12] == 0 &&
1530 SRpnt
->sr_sense_buffer
[13] == 2) {
1532 "%s:E: Volume overflow in write error recovery\n",
1534 break; /* hit end of tape = fail */
1543 if (STp
->cur_frames
== 0) {
1546 printk(OSST_DEB_MSG
"%s:D: Wait re-write finished\n", name
);
1548 if (STp
->first_frame_position
!= expected
) {
1549 printk(KERN_ERR
"%s:A: Actual position %d - expected %d\n",
1550 name
, STp
->first_frame_position
, expected
);
1557 printk(OSST_DEB_MSG
"%s:D: Sleeping in re-write wait ready\n", name
);
1558 printk(OSST_DEB_MSG
"%s:D: Turning off debugging for a while\n", name
);
1562 schedule_timeout(HZ
/ 10);
1564 printk(KERN_ERR
"%s:E: Failed to find valid tape media\n", name
);
1572 * Error recovery algorithm for the OnStream tape.
1575 static int osst_write_error_recovery(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int pending
)
1577 Scsi_Request
* SRpnt
= * aSRpnt
;
1578 ST_partstat
* STps
= & STp
->ps
[STp
->partition
];
1579 char * name
= tape_name(STp
);
1582 unsigned int frame
, skip
;
1584 rw_state
= STps
->rw
;
1586 if ((SRpnt
->sr_sense_buffer
[ 2] & 0x0f) != 3
1587 || SRpnt
->sr_sense_buffer
[12] != 12
1588 || SRpnt
->sr_sense_buffer
[13] != 0) {
1590 printk(OSST_DEB_MSG
"%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name
,
1591 SRpnt
->sr_sense_buffer
[2], SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
1595 frame
= (SRpnt
->sr_sense_buffer
[3] << 24) |
1596 (SRpnt
->sr_sense_buffer
[4] << 16) |
1597 (SRpnt
->sr_sense_buffer
[5] << 8) |
1598 SRpnt
->sr_sense_buffer
[6];
1599 skip
= SRpnt
->sr_sense_buffer
[9];
1602 printk(OSST_DEB_MSG
"%s:D: Detected physical bad frame at %u, advised to skip %d\n", name
, frame
, skip
);
1604 osst_get_frame_position(STp
, aSRpnt
);
1606 printk(OSST_DEB_MSG
"%s:D: reported frame positions: host = %d, tape = %d\n",
1607 name
, STp
->first_frame_position
, STp
->last_frame_position
);
1609 switch (STp
->write_type
) {
1612 case OS_WRITE_NEW_MARK
:
1614 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1615 name
, STp
->cur_frames
, frame
, (frame
+ skip
> 3000 && frame
< 3000)?3000:frame
+ skip
);
1616 if (STp
->os_fw_rev
>= 10600)
1617 retval
= osst_reposition_and_retry(STp
, aSRpnt
, frame
, skip
, pending
);
1619 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, skip
, pending
);
1620 printk(KERN_WARNING
"%s:%s: %sWrite error%srecovered\n", name
,
1622 retval
?"" :"Don't worry, ",
1623 retval
?" not ":" ");
1625 case OS_WRITE_LAST_MARK
:
1626 printk(KERN_ERR
"%s:E: Bad frame in update last marker, fatal\n", name
);
1627 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1630 case OS_WRITE_HEADER
:
1631 printk(KERN_WARNING
"%s:I: Bad frame in header partition, skipped\n", name
);
1632 retval
= osst_read_back_buffer_and_rewrite(STp
, aSRpnt
, frame
, 1, pending
);
1635 printk(KERN_INFO
"%s:I: Bad frame in filler, ignored\n", name
);
1636 osst_set_frame_position(STp
, aSRpnt
, frame
+ STp
->cur_frames
+ pending
, 0);
1638 osst_get_frame_position(STp
, aSRpnt
);
1640 printk(OSST_DEB_MSG
"%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1641 name
, STp
->cur_frames
, STp
->first_frame_position
, STp
->last_frame_position
);
1642 printk(OSST_DEB_MSG
"%s:D: next logical frame to write: %d\n", name
, STp
->logical_blk_num
);
1645 STp
->recover_count
++;
1646 STp
->recover_erreg
++;
1648 STps
->rw
= rw_state
;
1652 static int osst_space_over_filemarks_backward(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
,
1653 int mt_op
, int mt_count
)
1655 char * name
= tape_name(STp
);
1657 int last_mark_ppos
= -1;
1660 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_backwards %d %d\n", name
, mt_op
, mt_count
);
1662 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1664 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name
);
1668 if (STp
->linux_media_version
>= 4) {
1670 * direct lookup in header filemark list
1672 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
);
1673 if (STp
->header_ok
&&
1674 STp
->header_cache
!= NULL
&&
1675 (cnt
- mt_count
) >= 0 &&
1676 (cnt
- mt_count
) < OS_FM_TAB_MAX
&&
1677 (cnt
- mt_count
) < STp
->filemark_cnt
&&
1678 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] == STp
->buffer
->aux
->last_mark_ppos
)
1680 last_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
- mt_count
]);
1682 if (STp
->header_cache
== NULL
|| (cnt
- mt_count
) < 0 || (cnt
- mt_count
) >= OS_FM_TAB_MAX
)
1683 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1684 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1686 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1688 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1689 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
-1] ==
1690 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1691 mt_count
, last_mark_ppos
);
1693 if (last_mark_ppos
> 10 && last_mark_ppos
< STp
->eod_frame_ppos
) {
1694 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
1695 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1698 "%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1702 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1703 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1704 name
, last_mark_ppos
);
1710 printk(OSST_DEB_MSG
"%s:D: Reverting to scan filemark backwards\n", name
);
1714 while (cnt
!= mt_count
) {
1715 last_mark_ppos
= ntohl(STp
->buffer
->aux
->last_mark_ppos
);
1716 if (last_mark_ppos
== -1)
1719 printk(OSST_DEB_MSG
"%s:D: Positioning to last mark at %d\n", name
, last_mark_ppos
);
1721 osst_position_tape_and_confirm(STp
, aSRpnt
, last_mark_ppos
);
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\n", name
);
1729 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1730 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1731 name
, last_mark_ppos
);
1736 if (mt_op
== MTBSFM
) {
1737 STp
->frame_seq_number
++;
1738 STp
->frame_in_buffer
= 0;
1739 STp
->buffer
->buffer_bytes
= 0;
1740 STp
->buffer
->read_pointer
= 0;
1741 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1747 * ADRL 1.1 compatible "slow" space filemarks fwd version
1749 * Just scans for the filemark sequentially.
1751 static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
,
1752 int mt_op
, int mt_count
)
1756 char * name
= tape_name(STp
);
1758 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name
, mt_op
, mt_count
);
1760 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1762 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1767 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1769 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n", name
);
1773 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1775 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1777 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1779 if (STp
->first_frame_position
> STp
->eod_frame_ppos
+1) {
1781 printk(OSST_DEB_MSG
"%s:D: EOD position corrected (%d=>%d)\n",
1782 name
, STp
->eod_frame_ppos
, STp
->first_frame_position
-1);
1784 STp
->eod_frame_ppos
= STp
->first_frame_position
-1;
1788 if (cnt
== mt_count
)
1790 STp
->frame_in_buffer
= 0;
1792 if (mt_op
== MTFSF
) {
1793 STp
->frame_seq_number
++;
1794 STp
->frame_in_buffer
= 0;
1795 STp
->buffer
->buffer_bytes
= 0;
1796 STp
->buffer
->read_pointer
= 0;
1797 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1803 * Fast linux specific version of OnStream FSF
1805 static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
,
1806 int mt_op
, int mt_count
)
1808 char * name
= tape_name(STp
);
1810 next_mark_ppos
= -1;
1813 printk(OSST_DEB_MSG
"%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name
, mt_op
, mt_count
);
1815 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1817 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name
);
1822 if (STp
->linux_media_version
>= 4) {
1824 * direct lookup in header filemark list
1826 cnt
= ntohl(STp
->buffer
->aux
->filemark_cnt
) - 1;
1827 if (STp
->header_ok
&&
1828 STp
->header_cache
!= NULL
&&
1829 (cnt
+ mt_count
) < OS_FM_TAB_MAX
&&
1830 (cnt
+ mt_count
) < STp
->filemark_cnt
&&
1831 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1832 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] == STp
->buffer
->aux
->last_mark_ppos
)))
1834 next_mark_ppos
= ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
+ mt_count
]);
1836 if (STp
->header_cache
== NULL
|| (cnt
+ mt_count
) >= OS_FM_TAB_MAX
)
1837 printk(OSST_DEB_MSG
"%s:D: Filemark lookup fail due to %s\n", name
,
1838 STp
->header_cache
== NULL
?"lack of header cache":"count out of range");
1840 printk(OSST_DEB_MSG
"%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1842 ((cnt
== -1 && ntohl(STp
->buffer
->aux
->last_mark_ppos
) == -1) ||
1843 (STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[cnt
] ==
1844 STp
->buffer
->aux
->last_mark_ppos
))?"match":"error",
1845 mt_count
, next_mark_ppos
);
1847 if (next_mark_ppos
<= 10 || next_mark_ppos
> STp
->eod_frame_ppos
) {
1849 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1851 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
1853 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
1854 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1856 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
1861 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1862 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1863 name
, next_mark_ppos
);
1866 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) != cnt
+ mt_count
) {
1867 printk(KERN_WARNING
"%s:W: Expected to find marker %d at ppos %d, not %d\n",
1868 name
, cnt
+mt_count
, next_mark_ppos
,
1869 ntohl(STp
->buffer
->aux
->filemark_cnt
));
1875 * Find nearest (usually previous) marker, then jump from marker to marker
1878 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
)
1880 if (STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_EOD
) {
1882 printk(OSST_DEB_MSG
"%s:D: space_fwd: EOD reached\n", name
);
1886 if (ntohl(STp
->buffer
->aux
->filemark_cnt
) == 0) {
1887 if (STp
->first_mark_ppos
== -1) {
1889 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1891 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
);
1893 osst_position_tape_and_confirm(STp
, aSRpnt
, STp
->first_mark_ppos
);
1894 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1897 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
1902 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1903 printk(KERN_WARNING
"%s:W: Expected to find filemark at %d\n",
1904 name
, STp
->first_mark_ppos
);
1908 if (osst_space_over_filemarks_backward(STp
, aSRpnt
, MTBSF
, 1) < 0)
1914 while (cnt
!= mt_count
) {
1915 next_mark_ppos
= ntohl(STp
->buffer
->aux
->next_mark_ppos
);
1916 if (!next_mark_ppos
|| next_mark_ppos
> STp
->eod_frame_ppos
) {
1918 printk(OSST_DEB_MSG
"%s:D: Reverting to slow filemark space\n", name
);
1920 return osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, mt_op
, mt_count
- cnt
);
1923 else printk(OSST_DEB_MSG
"%s:D: Positioning to next mark at %d\n", name
, next_mark_ppos
);
1925 osst_position_tape_and_confirm(STp
, aSRpnt
, next_mark_ppos
);
1927 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
1929 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in space_filemarks\n",
1934 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_MARKER
) {
1935 printk(KERN_WARNING
"%s:W: Expected to find marker at ppos %d, not found\n",
1936 name
, next_mark_ppos
);
1941 if (mt_op
== MTFSF
) {
1942 STp
->frame_seq_number
++;
1943 STp
->frame_in_buffer
= 0;
1944 STp
->buffer
->buffer_bytes
= 0;
1945 STp
->buffer
->read_pointer
= 0;
1946 STp
->logical_blk_num
+= ntohs(STp
->buffer
->aux
->dat
.dat_list
[0].blk_cnt
);
1952 * In debug mode, we want to see as many errors as possible
1953 * to test the error recovery mechanism.
1956 static void osst_set_retries(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int retries
)
1958 unsigned char cmd
[MAX_COMMAND_SIZE
];
1959 Scsi_Request
* SRpnt
= * aSRpnt
;
1960 char * name
= tape_name(STp
);
1962 memset(cmd
, 0, MAX_COMMAND_SIZE
);
1963 cmd
[0] = MODE_SELECT
;
1965 cmd
[4] = NUMBER_RETRIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
1967 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
1968 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
1969 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
1970 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
1971 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = NUMBER_RETRIES_PAGE
| (1 << 7);
1972 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 2;
1973 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 4;
1974 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = retries
;
1977 printk(OSST_DEB_MSG
"%s:D: Setting number of retries on OnStream tape to %d\n", name
, retries
);
1979 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], SCSI_DATA_WRITE
, STp
->timeout
, 0, TRUE
);
1982 if ((STp
->buffer
)->syscall_result
)
1983 printk (KERN_ERR
"%s:D: Couldn't set retries to %d\n", name
, retries
);
1988 static int osst_write_filemark(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
)
1991 int this_mark_ppos
= STp
->first_frame_position
;
1992 int this_mark_lbn
= STp
->logical_blk_num
;
1994 char * name
= tape_name(STp
);
1997 if (STp
->raw
) return 0;
1999 STp
->write_type
= OS_WRITE_NEW_MARK
;
2001 printk(OSST_DEB_MSG
"%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2002 name
, STp
->filemark_cnt
, this_mark_ppos
, STp
->frame_seq_number
, this_mark_lbn
);
2005 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2006 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2007 STp
->last_mark_ppos
= this_mark_ppos
;
2008 STp
->last_mark_lbn
= this_mark_lbn
;
2009 if (STp
->header_cache
!= NULL
&& STp
->filemark_cnt
< OS_FM_TAB_MAX
)
2010 STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
] = htonl(this_mark_ppos
);
2011 if (STp
->filemark_cnt
++ == 0)
2012 STp
->first_mark_ppos
= this_mark_ppos
;
2016 static int osst_write_eod(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
)
2020 char * name
= tape_name(STp
);
2023 if (STp
->raw
) return 0;
2025 STp
->write_type
= OS_WRITE_EOD
;
2026 STp
->eod_frame_ppos
= STp
->first_frame_position
;
2028 printk(OSST_DEB_MSG
"%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name
,
2029 STp
->eod_frame_ppos
, STp
->frame_seq_number
, STp
->logical_blk_num
);
2033 result
= osst_flush_write_buffer(STp
, aSRpnt
);
2034 result
|= osst_flush_drive_buffer(STp
, aSRpnt
);
2035 STp
->eod_frame_lfa
= --(STp
->frame_seq_number
);
2039 static int osst_write_filler(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int where
, int count
)
2041 char * name
= tape_name(STp
);
2044 printk(OSST_DEB_MSG
"%s:D: Reached onstream write filler group %d\n", name
, where
);
2046 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2047 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2048 STp
->write_type
= OS_WRITE_FILLER
;
2050 memcpy(STp
->buffer
->b_data
, "Filler", 6);
2051 STp
->buffer
->buffer_bytes
= 6;
2053 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2054 printk(KERN_INFO
"%s:I: Couldn't write filler frame\n", name
);
2059 printk(OSST_DEB_MSG
"%s:D: Exiting onstream write filler group\n", name
);
2061 return osst_flush_drive_buffer(STp
, aSRpnt
);
2064 static int __osst_write_header(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int where
, int count
)
2066 char * name
= tape_name(STp
);
2070 printk(OSST_DEB_MSG
"%s:D: Reached onstream write header group %d\n", name
, where
);
2072 osst_wait_ready(STp
, aSRpnt
, 60 * 5, 0);
2073 osst_set_frame_position(STp
, aSRpnt
, where
, 0);
2074 STp
->write_type
= OS_WRITE_HEADER
;
2076 osst_copy_to_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2077 STp
->buffer
->buffer_bytes
= sizeof(os_header_t
);
2079 if (osst_flush_write_buffer(STp
, aSRpnt
)) {
2080 printk(KERN_INFO
"%s:I: Couldn't write header frame\n", name
);
2084 result
= osst_flush_drive_buffer(STp
, aSRpnt
);
2086 printk(OSST_DEB_MSG
"%s:D: Write onstream header group %s\n", name
, result
?"failed":"done");
2091 static int osst_write_header(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int locate_eod
)
2093 os_header_t
* header
;
2095 char * name
= tape_name(STp
);
2098 printk(OSST_DEB_MSG
"%s:D: Writing tape header\n", name
);
2100 if (STp
->raw
) return 0;
2102 if (STp
->header_cache
== NULL
) {
2103 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2104 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2107 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2109 printk(OSST_DEB_MSG
"%s:D: Allocated and cleared memory for header cache\n", name
);
2112 if (STp
->header_ok
) STp
->update_frame_cntr
++;
2113 else STp
->update_frame_cntr
= 0;
2115 header
= STp
->header_cache
;
2116 strcpy(header
->ident_str
, "ADR_SEQ");
2117 header
->major_rev
= 1;
2118 header
->minor_rev
= 4;
2119 header
->ext_trk_tb_off
= htons(17192);
2120 header
->pt_par_num
= 1;
2121 header
->partition
[0].partition_num
= OS_DATA_PARTITION
;
2122 header
->partition
[0].par_desc_ver
= OS_PARTITION_VERSION
;
2123 header
->partition
[0].wrt_pass_cntr
= htons(STp
->wrt_pass_cntr
);
2124 header
->partition
[0].first_frame_ppos
= htonl(STp
->first_data_ppos
);
2125 header
->partition
[0].last_frame_ppos
= htonl(STp
->capacity
);
2126 header
->partition
[0].eod_frame_ppos
= htonl(STp
->eod_frame_ppos
);
2127 header
->cfg_col_width
= htonl(20);
2128 header
->dat_col_width
= htonl(1500);
2129 header
->qfa_col_width
= htonl(0);
2130 header
->ext_track_tb
.nr_stream_part
= 1;
2131 header
->ext_track_tb
.et_ent_sz
= 32;
2132 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
= 0;
2133 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
= 1;
2134 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
= htons(17736);
2135 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
= 0;
2136 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
= htonl(STp
->eod_frame_lfa
);
2137 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
= htonl(STp
->eod_frame_ppos
);
2138 header
->dat_fm_tab
.fm_part_num
= 0;
2139 header
->dat_fm_tab
.fm_tab_ent_sz
= 4;
2140 header
->dat_fm_tab
.fm_tab_ent_cnt
= htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?
2141 STp
->filemark_cnt
:OS_FM_TAB_MAX
);
2143 result
= __osst_write_header(STp
, aSRpnt
, 0xbae, 5);
2144 if (STp
->update_frame_cntr
== 0)
2145 osst_write_filler(STp
, aSRpnt
, 0xbb3, 5);
2146 result
&= __osst_write_header(STp
, aSRpnt
, 5, 5);
2150 printk(OSST_DEB_MSG
"%s:D: Locating back to eod frame addr %d\n", name
, STp
->eod_frame_ppos
);
2152 osst_set_frame_position(STp
, aSRpnt
, STp
->eod_frame_ppos
, 0);
2155 printk(KERN_ERR
"%s:E: Write header failed\n", name
);
2157 memcpy(STp
->application_sig
, "LIN4", 4);
2158 STp
->linux_media
= 1;
2159 STp
->linux_media_version
= 4;
2165 static int osst_reset_header(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
)
2167 if (STp
->header_cache
!= NULL
)
2168 memset(STp
->header_cache
, 0, sizeof(os_header_t
));
2170 STp
->logical_blk_num
= STp
->frame_seq_number
= 0;
2171 STp
->frame_in_buffer
= 0;
2172 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0x0000000A;
2173 STp
->filemark_cnt
= 0;
2174 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2175 return osst_write_header(STp
, aSRpnt
, 1);
2178 static int __osst_analyze_headers(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int ppos
)
2180 char * name
= tape_name(STp
);
2181 os_header_t
* header
;
2184 int linux_media_version
,
2190 if (ppos
== 5 || ppos
== 0xbae || STp
->buffer
->syscall_result
) {
2191 if (osst_set_frame_position(STp
, aSRpnt
, ppos
, 0))
2192 printk(KERN_WARNING
"%s:W: Couldn't position tape\n", name
);
2193 if (osst_initiate_read (STp
, aSRpnt
)) {
2194 printk(KERN_WARNING
"%s:W: Couldn't initiate read\n", name
);
2198 if (osst_read_frame(STp
, aSRpnt
, 180)) {
2200 printk(OSST_DEB_MSG
"%s:D: Couldn't read header frame\n", name
);
2204 header
= (os_header_t
*) STp
->buffer
->b_data
; /* warning: only first segment addressable */
2205 aux
= STp
->buffer
->aux
;
2206 if (aux
->frame_type
!= OS_FRAME_TYPE_HEADER
) {
2208 printk(OSST_DEB_MSG
"%s:D: Skipping non-header frame (%d)\n", name
, ppos
);
2212 if (ntohl(aux
->frame_seq_num
) != 0 ||
2213 ntohl(aux
->logical_blk_num
) != 0 ||
2214 aux
->partition
.partition_num
!= OS_CONFIG_PARTITION
||
2215 ntohl(aux
->partition
.first_frame_ppos
) != 0 ||
2216 ntohl(aux
->partition
.last_frame_ppos
) != 0xbb7 ) {
2218 printk(OSST_DEB_MSG
"%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name
,
2219 ntohl(aux
->frame_seq_num
), ntohl(aux
->logical_blk_num
),
2220 aux
->partition
.partition_num
, ntohl(aux
->partition
.first_frame_ppos
),
2221 ntohl(aux
->partition
.last_frame_ppos
));
2225 if (strncmp(header
->ident_str
, "ADR_SEQ", 7) != 0 &&
2226 strncmp(header
->ident_str
, "ADR-SEQ", 7) != 0) {
2227 strlcpy(id_string
, header
->ident_str
, 8);
2229 printk(OSST_DEB_MSG
"%s:D: Invalid header identification string %s\n", name
, id_string
);
2233 update_frame_cntr
= ntohl(aux
->update_frame_cntr
);
2234 if (update_frame_cntr
< STp
->update_frame_cntr
) {
2236 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2237 name
, ppos
, update_frame_cntr
, STp
->update_frame_cntr
);
2241 if (header
->major_rev
!= 1 || header
->minor_rev
!= 4 ) {
2243 printk(OSST_DEB_MSG
"%s:D: %s revision %d.%d detected (1.4 supported)\n",
2244 name
, (header
->major_rev
!= 1 || header
->minor_rev
< 2 ||
2245 header
->minor_rev
> 4 )? "Invalid" : "Warning:",
2246 header
->major_rev
, header
->minor_rev
);
2248 if (header
->major_rev
!= 1 || header
->minor_rev
< 2 || header
->minor_rev
> 4)
2252 if (header
->pt_par_num
!= 1)
2253 printk(KERN_INFO
"%s:W: %d partitions defined, only one supported\n",
2254 name
, header
->pt_par_num
);
2256 memcpy(id_string
, aux
->application_sig
, 4);
2258 if (memcmp(id_string
, "LIN", 3) == 0) {
2259 STp
->linux_media
= 1;
2260 linux_media_version
= id_string
[3] - '0';
2261 if (linux_media_version
!= 4)
2262 printk(KERN_INFO
"%s:I: Linux media version %d detected (current 4)\n",
2263 name
, linux_media_version
);
2265 printk(KERN_WARNING
"%s:W: Non Linux media detected (%s)\n", name
, id_string
);
2268 if (linux_media_version
< STp
->linux_media_version
) {
2270 printk(OSST_DEB_MSG
"%s:D: Skipping frame %d with linux_media_version %d\n",
2271 name
, ppos
, linux_media_version
);
2275 if (linux_media_version
> STp
->linux_media_version
) {
2277 printk(OSST_DEB_MSG
"%s:D: Frame %d sets linux_media_version to %d\n",
2278 name
, ppos
, linux_media_version
);
2280 memcpy(STp
->application_sig
, id_string
, 5);
2281 STp
->linux_media_version
= linux_media_version
;
2282 STp
->update_frame_cntr
= -1;
2284 if (update_frame_cntr
> STp
->update_frame_cntr
) {
2286 printk(OSST_DEB_MSG
"%s:D: Frame %d sets update_frame_counter to %d\n",
2287 name
, ppos
, update_frame_cntr
);
2289 if (STp
->header_cache
== NULL
) {
2290 if ((STp
->header_cache
= (os_header_t
*)vmalloc(sizeof(os_header_t
))) == NULL
) {
2291 printk(KERN_ERR
"%s:E: Failed to allocate header cache\n", name
);
2295 printk(OSST_DEB_MSG
"%s:D: Allocated memory for header cache\n", name
);
2298 osst_copy_from_buffer(STp
->buffer
, (unsigned char *)STp
->header_cache
);
2299 header
= STp
->header_cache
; /* further accesses from cached (full) copy */
2301 STp
->wrt_pass_cntr
= ntohs(header
->partition
[0].wrt_pass_cntr
);
2302 STp
->first_data_ppos
= ntohl(header
->partition
[0].first_frame_ppos
);
2303 STp
->eod_frame_ppos
= ntohl(header
->partition
[0].eod_frame_ppos
);
2304 STp
->eod_frame_lfa
= ntohl(header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb
);
2305 STp
->filemark_cnt
= ntohl(aux
->filemark_cnt
);
2306 STp
->first_mark_ppos
= ntohl(aux
->next_mark_ppos
);
2307 STp
->last_mark_ppos
= ntohl(aux
->last_mark_ppos
);
2308 STp
->last_mark_lbn
= ntohl(aux
->last_mark_lbn
);
2309 STp
->update_frame_cntr
= update_frame_cntr
;
2311 printk(OSST_DEB_MSG
"%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2312 name
, STp
->wrt_pass_cntr
, STp
->update_frame_cntr
, STp
->filemark_cnt
);
2313 printk(OSST_DEB_MSG
"%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name
,
2314 STp
->first_data_ppos
,
2315 ntohl(header
->partition
[0].last_frame_ppos
),
2316 ntohl(header
->partition
[0].eod_frame_ppos
));
2317 printk(OSST_DEB_MSG
"%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2318 name
, STp
->first_mark_ppos
, STp
->last_mark_ppos
, STp
->eod_frame_ppos
);
2320 if (header
->minor_rev
< 4 && STp
->linux_media_version
== 4) {
2322 printk(OSST_DEB_MSG
"%s:D: Moving filemark list to ADR 1.4 location\n", name
);
2324 memcpy((void *)header
->dat_fm_tab
.fm_tab_ent
,
2325 (void *)header
->old_filemark_list
, sizeof(header
->dat_fm_tab
.fm_tab_ent
));
2326 memset((void *)header
->old_filemark_list
, 0, sizeof(header
->old_filemark_list
));
2328 if (header
->minor_rev
== 4 &&
2329 (header
->ext_trk_tb_off
!= htons(17192) ||
2330 header
->partition
[0].partition_num
!= OS_DATA_PARTITION
||
2331 header
->partition
[0].par_desc_ver
!= OS_PARTITION_VERSION
||
2332 header
->partition
[0].last_frame_ppos
!= htonl(STp
->capacity
) ||
2333 header
->cfg_col_width
!= htonl(20) ||
2334 header
->dat_col_width
!= htonl(1500) ||
2335 header
->qfa_col_width
!= htonl(0) ||
2336 header
->ext_track_tb
.nr_stream_part
!= 1 ||
2337 header
->ext_track_tb
.et_ent_sz
!= 32 ||
2338 header
->ext_track_tb
.dat_ext_trk_ey
.et_part_num
!= OS_DATA_PARTITION
||
2339 header
->ext_track_tb
.dat_ext_trk_ey
.fmt
!= 1 ||
2340 header
->ext_track_tb
.dat_ext_trk_ey
.fm_tab_off
!= htons(17736) ||
2341 header
->ext_track_tb
.dat_ext_trk_ey
.last_hlb_hi
!= 0 ||
2342 header
->ext_track_tb
.dat_ext_trk_ey
.last_pp
!= htonl(STp
->eod_frame_ppos
) ||
2343 header
->dat_fm_tab
.fm_part_num
!= OS_DATA_PARTITION
||
2344 header
->dat_fm_tab
.fm_tab_ent_sz
!= 4 ||
2345 header
->dat_fm_tab
.fm_tab_ent_cnt
!=
2346 htons(STp
->filemark_cnt
<OS_FM_TAB_MAX
?STp
->filemark_cnt
:OS_FM_TAB_MAX
)))
2347 printk(KERN_WARNING
"%s:W: Failed consistency check ADR 1.4 format\n", name
);
2354 static int osst_analyze_headers(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
)
2359 char * name
= tape_name(STp
);
2361 position
= osst_get_frame_position(STp
, aSRpnt
);
2364 STp
->header_ok
= STp
->linux_media
= 1;
2365 STp
->linux_media_version
= 0;
2368 STp
->header_ok
= STp
->linux_media
= STp
->linux_media_version
= 0;
2369 STp
->wrt_pass_cntr
= STp
->update_frame_cntr
= -1;
2370 STp
->eod_frame_ppos
= STp
->first_data_ppos
= -1;
2371 STp
->first_mark_ppos
= STp
->last_mark_ppos
= STp
->last_mark_lbn
= -1;
2373 printk(OSST_DEB_MSG
"%s:D: Reading header\n", name
);
2376 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2377 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2379 first
= position
==10?0xbae: 5;
2380 last
= position
==10?0xbb3:10;
2382 for (ppos
= first
; ppos
< last
; ppos
++)
2383 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2386 first
= position
==10? 5:0xbae;
2387 last
= position
==10?10:0xbb3;
2389 for (ppos
= first
; ppos
< last
; ppos
++)
2390 if (__osst_analyze_headers(STp
, aSRpnt
, ppos
))
2394 printk(KERN_ERR
"%s:E: Failed to find valid ADRL header, new media?\n", name
);
2395 STp
->eod_frame_ppos
= STp
->first_data_ppos
= 0;
2396 osst_set_frame_position(STp
, aSRpnt
, 10, 0);
2399 if (position
<= STp
->first_data_ppos
) {
2400 position
= STp
->first_data_ppos
;
2401 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
2403 osst_set_frame_position(STp
, aSRpnt
, position
, 0);
2409 static int osst_verify_position(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
)
2411 int frame_position
= STp
->first_frame_position
;
2412 int frame_seq_numbr
= STp
->frame_seq_number
;
2413 int logical_blk_num
= STp
->logical_blk_num
;
2414 int halfway_frame
= STp
->frame_in_buffer
;
2415 int read_pointer
= STp
->buffer
->read_pointer
;
2416 int prev_mark_ppos
= -1;
2417 int actual_mark_ppos
, i
, n
;
2419 char * name
= tape_name(STp
);
2421 printk(OSST_DEB_MSG
"%s:D: Verify that the tape is really the one we think before writing\n", name
);
2423 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2424 if (osst_get_logical_frame(STp
, aSRpnt
, -1, 0) < 0) {
2426 printk(OSST_DEB_MSG
"%s:D: Couldn't get logical blk num in verify_position\n", name
);
2430 if (STp
->linux_media_version
>= 4) {
2431 for (i
=0; i
<STp
->filemark_cnt
; i
++)
2432 if ((n
=ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[i
])) < frame_position
)
2435 prev_mark_ppos
= frame_position
- 1; /* usually - we don't really know */
2436 actual_mark_ppos
= STp
->buffer
->aux
->frame_type
== OS_FRAME_TYPE_MARKER
?
2437 frame_position
- 1 : ntohl(STp
->buffer
->aux
->last_mark_ppos
);
2438 if (frame_position
!= STp
->first_frame_position
||
2439 frame_seq_numbr
!= STp
->frame_seq_number
+ (halfway_frame
?0:1) ||
2440 prev_mark_ppos
!= actual_mark_ppos
) {
2442 printk(OSST_DEB_MSG
"%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name
,
2443 STp
->first_frame_position
, frame_position
,
2444 STp
->frame_seq_number
+ (halfway_frame
?0:1),
2445 frame_seq_numbr
, actual_mark_ppos
, prev_mark_ppos
);
2449 if (halfway_frame
) {
2450 /* prepare buffer for append and rewrite on top of original */
2451 osst_set_frame_position(STp
, aSRpnt
, frame_position
- 1, 0);
2452 STp
->buffer
->buffer_bytes
= read_pointer
;
2453 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
2456 STp
->frame_in_buffer
= halfway_frame
;
2457 STp
->frame_seq_number
= frame_seq_numbr
;
2458 STp
->logical_blk_num
= logical_blk_num
;
2462 /* Acc. to OnStream, the vers. numbering is the following:
2463 * X.XX for released versions (X=digit),
2464 * XXXY for unreleased versions (Y=letter)
2465 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2466 * This fn makes monoton numbers out of this scheme ...
2468 static unsigned int osst_parse_firmware_rev (const char * str
)
2470 if (str
[1] == '.') {
2471 return (str
[0]-'0')*10000
2475 return (str
[0]-'0')*10000
2477 +(str
[2]-'0')*100 - 100
2483 * Configure the OnStream SCII tape drive for default operation
2485 static int osst_configure_onstream(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
)
2487 unsigned char cmd
[MAX_COMMAND_SIZE
];
2488 char * name
= tape_name(STp
);
2489 Scsi_Request
* SRpnt
= * aSRpnt
;
2490 osst_mode_parameter_header_t
* header
;
2491 osst_block_size_page_t
* bs
;
2492 osst_capabilities_page_t
* cp
;
2493 osst_tape_paramtr_page_t
* prm
;
2494 int drive_buffer_size
;
2496 if (STp
->ready
!= ST_READY
) {
2498 printk(OSST_DEB_MSG
"%s:D: Not Ready\n", name
);
2503 if (STp
->os_fw_rev
< 10600) {
2504 printk(KERN_INFO
"%s:I: Old OnStream firmware revision detected (%s),\n", name
, STp
->device
->rev
);
2505 printk(KERN_INFO
"%s:I: an upgrade to version 1.06 or above is recommended\n", name
);
2509 * Configure 32.5KB (data+aux) frame size.
2510 * Get the current frame size from the block size mode page
2512 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2513 cmd
[0] = MODE_SENSE
;
2515 cmd
[2] = BLOCK_SIZE_PAGE
;
2516 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2518 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], SCSI_DATA_READ
, STp
->timeout
, 0, TRUE
);
2519 if (SRpnt
== NULL
) {
2521 printk(OSST_DEB_MSG
"osst :D: Busy\n");
2526 if ((STp
->buffer
)->syscall_result
!= 0) {
2527 printk (KERN_ERR
"%s:E: Can't get tape block size mode page\n", name
);
2531 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2532 bs
= (osst_block_size_page_t
*) ((STp
->buffer
)->b_data
+ sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2535 printk(OSST_DEB_MSG
"%s:D: 32KB play back: %s\n", name
, bs
->play32
? "Yes" : "No");
2536 printk(OSST_DEB_MSG
"%s:D: 32.5KB play back: %s\n", name
, bs
->play32_5
? "Yes" : "No");
2537 printk(OSST_DEB_MSG
"%s:D: 32KB record: %s\n", name
, bs
->record32
? "Yes" : "No");
2538 printk(OSST_DEB_MSG
"%s:D: 32.5KB record: %s\n", name
, bs
->record32_5
? "Yes" : "No");
2542 * Configure default auto columns mode, 32.5KB transfer mode
2550 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2551 cmd
[0] = MODE_SELECT
;
2553 cmd
[4] = BLOCK_SIZE_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2555 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], SCSI_DATA_WRITE
, STp
->timeout
, 0, TRUE
);
2557 if ((STp
->buffer
)->syscall_result
!= 0) {
2558 printk (KERN_ERR
"%s:E: Couldn't set tape block size mode page\n", name
);
2563 printk(KERN_INFO
"%s:D: Drive Block Size changed to 32.5K\n", name
);
2565 * In debug mode, we want to see as many errors as possible
2566 * to test the error recovery mechanism.
2568 osst_set_retries(STp
, aSRpnt
, 0);
2573 * Set vendor name to 'LIN4' for "Linux support version 4".
2576 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2577 cmd
[0] = MODE_SELECT
;
2579 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2581 header
->mode_data_length
= VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
- 1;
2582 header
->medium_type
= 0; /* Medium Type - ignoring */
2583 header
->dsp
= 0; /* Reserved */
2584 header
->bdl
= 0; /* Block Descriptor Length */
2586 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = VENDOR_IDENT_PAGE
| (1 << 7);
2587 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 6;
2588 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 'L';
2589 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 'I';
2590 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 4] = 'N';
2591 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 5] = '4';
2592 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 6] = 0;
2593 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 7] = 0;
2595 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], SCSI_DATA_WRITE
, STp
->timeout
, 0, TRUE
);
2598 if ((STp
->buffer
)->syscall_result
!= 0) {
2599 printk (KERN_ERR
"%s:E: Couldn't set vendor name to %s\n", name
,
2600 (char *) ((STp
->buffer
)->b_data
+ MODE_HEADER_LENGTH
+ 2));
2604 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2605 cmd
[0] = MODE_SENSE
;
2607 cmd
[2] = CAPABILITIES_PAGE
;
2608 cmd
[4] = CAPABILITIES_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2610 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], SCSI_DATA_READ
, STp
->timeout
, 0, TRUE
);
2613 if ((STp
->buffer
)->syscall_result
!= 0) {
2614 printk (KERN_ERR
"%s:E: Can't get capabilities page\n", name
);
2618 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2619 cp
= (osst_capabilities_page_t
*) ((STp
->buffer
)->b_data
+
2620 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2622 drive_buffer_size
= ntohs(cp
->buffer_size
) / 2;
2624 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2625 cmd
[0] = MODE_SENSE
;
2627 cmd
[2] = TAPE_PARAMTR_PAGE
;
2628 cmd
[4] = TAPE_PARAMTR_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
2630 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], SCSI_DATA_READ
, STp
->timeout
, 0, TRUE
);
2633 if ((STp
->buffer
)->syscall_result
!= 0) {
2634 printk (KERN_ERR
"%s:E: Can't get tape parameter page\n", name
);
2638 header
= (osst_mode_parameter_header_t
*) (STp
->buffer
)->b_data
;
2639 prm
= (osst_tape_paramtr_page_t
*) ((STp
->buffer
)->b_data
+
2640 sizeof(osst_mode_parameter_header_t
) + header
->bdl
);
2642 STp
->density
= prm
->density
;
2643 STp
->capacity
= ntohs(prm
->segtrk
) * ntohs(prm
->trks
);
2645 printk(OSST_DEB_MSG
"%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2646 name
, STp
->density
, STp
->capacity
/ 32, drive_buffer_size
);
2654 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2655 it messes up the block number). */
2656 static int cross_eof(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
, int forward
)
2659 char * name
= tape_name(STp
);
2663 printk(OSST_DEB_MSG
"%s:D: Stepping over filemark %s.\n",
2664 name
, forward
? "forward" : "backward");
2668 /* assumes that the filemark is already read by the drive, so this is low cost */
2669 result
= osst_space_over_filemarks_forward_slow(STp
, aSRpnt
, MTFSF
, 1);
2672 /* assumes this is only called if we just read the filemark! */
2673 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- 1);
2676 printk(KERN_WARNING
"%s:W: Stepping over filemark %s failed.\n",
2677 name
, forward
? "forward" : "backward");
2683 /* Get the tape position. */
2685 static int osst_get_frame_position(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
)
2687 unsigned char scmd
[MAX_COMMAND_SIZE
];
2688 Scsi_Request
* SRpnt
;
2691 /* KG: We want to be able to use it for checking Write Buffer availability
2692 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2694 char * olddata
= STp
->buffer
->b_data
;
2695 int oldsize
= STp
->buffer
->buffer_size
;
2696 char * name
= tape_name(STp
);
2698 if (STp
->ready
!= ST_READY
) return (-EIO
);
2700 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2701 scmd
[0] = READ_POSITION
;
2703 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2704 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 20, SCSI_DATA_READ
,
2705 STp
->timeout
, MAX_RETRIES
, TRUE
);
2707 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2712 if (STp
->buffer
->syscall_result
)
2713 result
= ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == 3) ? -EIO
: -EINVAL
;
2715 if (result
== -EINVAL
)
2716 printk(KERN_ERR
"%s:E: Can't read tape position.\n", name
);
2719 if (result
== -EIO
) { /* re-read position */
2720 unsigned char mysense
[16];
2721 memcpy (mysense
, SRpnt
->sr_sense_buffer
, 16);
2722 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2723 scmd
[0] = READ_POSITION
;
2724 STp
->buffer
->b_data
= mybuf
; STp
->buffer
->buffer_size
= 24;
2725 SRpnt
= osst_do_scsi(SRpnt
, STp
, scmd
, 20, SCSI_DATA_READ
,
2726 STp
->timeout
, MAX_RETRIES
, TRUE
);
2727 if (!STp
->buffer
->syscall_result
)
2728 memcpy (SRpnt
->sr_sense_buffer
, mysense
, 16);
2730 STp
->first_frame_position
= ((STp
->buffer
)->b_data
[4] << 24)
2731 + ((STp
->buffer
)->b_data
[5] << 16)
2732 + ((STp
->buffer
)->b_data
[6] << 8)
2733 + (STp
->buffer
)->b_data
[7];
2734 STp
->last_frame_position
= ((STp
->buffer
)->b_data
[ 8] << 24)
2735 + ((STp
->buffer
)->b_data
[ 9] << 16)
2736 + ((STp
->buffer
)->b_data
[10] << 8)
2737 + (STp
->buffer
)->b_data
[11];
2738 STp
->cur_frames
= (STp
->buffer
)->b_data
[15];
2741 printk(OSST_DEB_MSG
"%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name
,
2742 STp
->first_frame_position
, STp
->last_frame_position
,
2743 ((STp
->buffer
)->b_data
[0]&0x80)?" (BOP)":
2744 ((STp
->buffer
)->b_data
[0]&0x40)?" (EOP)":"",
2748 if (STp
->cur_frames
== 0 && STp
->first_frame_position
!= STp
->last_frame_position
) {
2750 printk(KERN_WARNING
"%s:D: Correcting read position %d, %d, %d\n", name
,
2751 STp
->first_frame_position
, STp
->last_frame_position
, STp
->cur_frames
);
2753 STp
->first_frame_position
= STp
->last_frame_position
;
2756 STp
->buffer
->b_data
= olddata
; STp
->buffer
->buffer_size
= oldsize
;
2758 return (result
== 0 ? STp
->first_frame_position
: result
);
2762 /* Set the tape block */
2763 static int osst_set_frame_position(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
, int ppos
, int skip
)
2765 unsigned char scmd
[MAX_COMMAND_SIZE
];
2766 Scsi_Request
* SRpnt
;
2769 int pp
= (ppos
== 3000 && !skip
)? 0 : ppos
;
2770 char * name
= tape_name(STp
);
2772 if (STp
->ready
!= ST_READY
) return (-EIO
);
2774 STps
= &(STp
->ps
[STp
->partition
]);
2776 if (ppos
< 0 || ppos
> STp
->capacity
) {
2777 printk(KERN_WARNING
"%s:W: Reposition request %d out of range\n", name
, ppos
);
2778 pp
= ppos
= ppos
< 0 ? 0 : (STp
->capacity
- 1);
2785 printk(OSST_DEB_MSG
"%s:D: Setting ppos to %d.\n", name
, pp
);
2787 memset (scmd
, 0, MAX_COMMAND_SIZE
);
2790 scmd
[3] = (pp
>> 24);
2791 scmd
[4] = (pp
>> 16);
2792 scmd
[5] = (pp
>> 8);
2797 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, scmd
, 0, SCSI_DATA_NONE
, STp
->long_timeout
,
2803 if ((STp
->buffer
)->syscall_result
!= 0) {
2805 printk(OSST_DEB_MSG
"%s:D: SEEK command from %d to %d failed.\n",
2806 name
, STp
->first_frame_position
, pp
);
2811 osst_wait_ready(STp
, aSRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
2812 } while ((pp
!= ppos
) && (pp
= ppos
));
2813 STp
->first_frame_position
= STp
->last_frame_position
= ppos
;
2814 STps
->eof
= ST_NOEOF
;
2817 STp
->frame_in_buffer
= 0;
2823 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2825 /* Flush the write buffer (never need to write if variable blocksize). */
2826 static int osst_flush_write_buffer(OS_Scsi_Tape
*STp
, Scsi_Request
** aSRpnt
)
2828 int offset
, transfer
, blks
= 0;
2830 unsigned char cmd
[MAX_COMMAND_SIZE
];
2831 Scsi_Request
* SRpnt
= *aSRpnt
;
2833 char * name
= tape_name(STp
);
2835 if ((STp
->buffer
)->writing
) {
2836 if (SRpnt
== (STp
->buffer
)->last_SRpnt
)
2838 { printk(OSST_DEB_MSG
2839 "%s:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", name
);
2841 *aSRpnt
= SRpnt
= NULL
;
2845 "%s:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", name
);
2847 osst_write_behind_check(STp
);
2848 if ((STp
->buffer
)->syscall_result
) {
2851 printk(OSST_DEB_MSG
"%s:D: Async write error (flush) %x.\n",
2852 name
, (STp
->buffer
)->midlevel_result
);
2854 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
2861 if (STp
->dirty
== 1) {
2864 STps
= &(STp
->ps
[STp
->partition
]);
2865 STps
->rw
= ST_WRITING
;
2866 offset
= STp
->buffer
->buffer_bytes
;
2867 blks
= (offset
+ STp
->block_size
- 1) / STp
->block_size
;
2868 transfer
= OS_FRAME_SIZE
;
2870 if (offset
< OS_DATA_SIZE
)
2871 osst_zero_buffer_tail(STp
->buffer
);
2873 /* TODO: Error handling! */
2875 result
= osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 120);
2877 memset(cmd
, 0, MAX_COMMAND_SIZE
);
2882 switch (STp
->write_type
) {
2886 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
2887 name
, blks
, STp
->frame_seq_number
,
2888 STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
2890 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
2891 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
2894 osst_init_aux(STp
, OS_FRAME_TYPE_EOD
, STp
->frame_seq_number
++,
2895 STp
->logical_blk_num
, 0, 0);
2897 case OS_WRITE_NEW_MARK
:
2898 osst_init_aux(STp
, OS_FRAME_TYPE_MARKER
, STp
->frame_seq_number
++,
2899 STp
->logical_blk_num
++, 0, blks
=1);
2901 case OS_WRITE_HEADER
:
2902 osst_init_aux(STp
, OS_FRAME_TYPE_HEADER
, 0, 0, 0, blks
=0);
2904 default: /* probably FILLER */
2905 osst_init_aux(STp
, OS_FRAME_TYPE_FILL
, 0, 0, 0, 0);
2909 printk(OSST_DEB_MSG
"%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
2910 name
, offset
, transfer
, blks
);
2913 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, transfer
, SCSI_DATA_WRITE
,
2914 STp
->timeout
, MAX_WRITE_RETRIES
, TRUE
);
2919 if ((STp
->buffer
)->syscall_result
!= 0) {
2922 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
2923 name
, SRpnt
->sr_sense_buffer
[0], SRpnt
->sr_sense_buffer
[2],
2924 SRpnt
->sr_sense_buffer
[12], SRpnt
->sr_sense_buffer
[13]);
2926 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
2927 (SRpnt
->sr_sense_buffer
[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
2928 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NO_SENSE
) {
2930 (STp
->buffer
)->buffer_bytes
= 0;
2934 if (osst_write_error_recovery(STp
, aSRpnt
, 1)) {
2935 printk(KERN_ERR
"%s:E: Error on flush write.\n", name
);
2939 STps
->drv_block
= (-1);
2942 STp
->first_frame_position
++;
2944 (STp
->buffer
)->buffer_bytes
= 0;
2948 printk(OSST_DEB_MSG
"%s:D: Exit flush write buffer with code %d\n", name
, result
);
2954 /* Flush the tape buffer. The tape will be positioned correctly unless
2955 seek_next is true. */
2956 static int osst_flush_buffer(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int seek_next
)
2959 int backspace
= 0, result
= 0;
2961 char * name
= tape_name(STp
);
2965 * If there was a bus reset, block further access
2968 if( STp
->pos_unknown
)
2971 if (STp
->ready
!= ST_READY
)
2974 STps
= &(STp
->ps
[STp
->partition
]);
2975 if (STps
->rw
== ST_WRITING
|| STp
->dirty
) { /* Writing */
2976 STp
->write_type
= OS_WRITE_DATA
;
2977 return osst_flush_write_buffer(STp
, aSRpnt
);
2979 if (STp
->block_size
== 0)
2983 printk(OSST_DEB_MSG
"%s:D: Reached flush (read) buffer\n", name
);
2986 if (!STp
->can_bsr
) {
2987 backspace
= ((STp
->buffer
)->buffer_bytes
+ (STp
->buffer
)->read_pointer
) / STp
->block_size
-
2988 ((STp
->buffer
)->read_pointer
+ STp
->block_size
- 1 ) / STp
->block_size
;
2989 (STp
->buffer
)->buffer_bytes
= 0;
2990 (STp
->buffer
)->read_pointer
= 0;
2991 STp
->frame_in_buffer
= 0; /* FIXME is this relevant w. OSST? */
2995 if (STps
->eof
== ST_FM_HIT
) {
2996 result
= cross_eof(STp
, aSRpnt
, FALSE
); /* Back over the EOF hit */
2998 STps
->eof
= ST_NOEOF
;
3000 if (STps
->drv_file
>= 0)
3002 STps
->drv_block
= 0;
3005 if (!result
&& backspace
> 0) /* TODO -- design and run a test case for this */
3006 result
= osst_seek_logical_blk(STp
, aSRpnt
, STp
->logical_blk_num
- backspace
);
3008 else if (STps
->eof
== ST_FM_HIT
) {
3009 if (STps
->drv_file
>= 0)
3011 STps
->drv_block
= 0;
3012 STps
->eof
= ST_NOEOF
;
3018 static int osst_write_frame(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, int synchronous
)
3020 unsigned char cmd
[MAX_COMMAND_SIZE
];
3021 Scsi_Request
* SRpnt
;
3024 char * name
= tape_name(STp
);
3027 if ((!STp
-> raw
) && (STp
->first_frame_position
== 0xbae)) { /* _must_ preserve buffer! */
3029 printk(OSST_DEB_MSG
"%s:D: Reaching config partition.\n", name
);
3031 if (osst_flush_drive_buffer(STp
, aSRpnt
) < 0) {
3034 /* error recovery may have bumped us past the header partition */
3035 if (osst_get_frame_position(STp
, aSRpnt
) < 0xbb8) {
3037 printk(OSST_DEB_MSG
"%s:D: Skipping over config partition.\n", name
);
3039 osst_position_tape_and_confirm(STp
, aSRpnt
, 0xbb8);
3044 osst_wait_frame (STp
, aSRpnt
, STp
->first_frame_position
, -50, 60);
3045 /* TODO: Check for an error ! */
3047 // osst_build_stats(STp, &SRpnt);
3049 STp
->ps
[STp
->partition
].rw
= ST_WRITING
;
3050 STp
->write_type
= OS_WRITE_DATA
;
3052 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3055 cmd
[4] = 1; /* one frame at a time... */
3056 blks
= STp
->buffer
->buffer_bytes
/ STp
->block_size
;
3059 printk(OSST_DEB_MSG
"%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name
, blks
,
3060 STp
->frame_seq_number
, STp
->logical_blk_num
- blks
, STp
->logical_blk_num
- 1);
3062 osst_init_aux(STp
, OS_FRAME_TYPE_DATA
, STp
->frame_seq_number
++,
3063 STp
->logical_blk_num
- blks
, STp
->block_size
, blks
);
3067 STp
->write_pending
= 1;
3069 SRpnt
= osst_do_scsi(*aSRpnt
, STp
, cmd
, OS_FRAME_SIZE
, SCSI_DATA_WRITE
, STp
->timeout
,
3070 MAX_WRITE_RETRIES
, synchronous
);
3076 if (STp
->buffer
->syscall_result
!= 0) {
3079 printk(OSST_DEB_MSG
"%s:D: Error on write:\n", name
);
3081 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
3082 (SRpnt
->sr_sense_buffer
[2] & 0x40)) {
3083 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == VOLUME_OVERFLOW
)
3087 if (osst_write_error_recovery(STp
, aSRpnt
, 1))
3092 STp
->first_frame_position
++;
3100 /* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */
3101 static int do_door_lock(OS_Scsi_Tape
* STp
, int do_lock
)
3105 cmd
= do_lock
? SCSI_IOCTL_DOORLOCK
: SCSI_IOCTL_DOORUNLOCK
;
3107 printk(OSST_DEB_MSG
"%s:D: %socking drive door.\n", tape_name(STp
), do_lock
? "L" : "Unl");
3109 retval
= scsi_ioctl(STp
->device
, cmd
, NULL
);
3111 STp
->door_locked
= do_lock
? ST_LOCKED_EXPLICIT
: ST_UNLOCKED
;
3114 STp
->door_locked
= ST_LOCK_FAILS
;
3119 /* Set the internal state after reset */
3120 static void reset_state(OS_Scsi_Tape
*STp
)
3125 STp
->pos_unknown
= 0;
3126 for (i
= 0; i
< ST_NBR_PARTITIONS
; i
++) {
3127 STps
= &(STp
->ps
[i
]);
3129 STps
->eof
= ST_NOEOF
;
3131 STps
->last_block_valid
= FALSE
;
3132 STps
->drv_block
= -1;
3133 STps
->drv_file
= -1;
3138 /* Entry points to osst */
3141 static ssize_t
osst_write(struct file
* filp
, const char * buf
, size_t count
, loff_t
*ppos
)
3143 ssize_t total
, retval
= 0;
3144 ssize_t i
, do_count
, blks
, transfer
;
3145 int write_threshold
;
3146 int doing_write
= 0;
3147 const char * b_point
;
3148 Scsi_Request
* SRpnt
= NULL
;
3151 OS_Scsi_Tape
* STp
= filp
->private_data
;
3152 char * name
= tape_name(STp
);
3155 if (down_interruptible(&STp
->lock
))
3156 return (-ERESTARTSYS
);
3159 * If we are in the middle of error recovery, don't let anyone
3160 * else try and use this device. Also, if error recovery fails, it
3161 * may try and take the device offline, in which case all further
3162 * access to the device is prohibited.
3164 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3169 if (ppos
!= &filp
->f_pos
) {
3170 /* "A request was outside the capabilities of the device." */
3175 if (STp
->ready
!= ST_READY
) {
3176 if (STp
->ready
== ST_NO_TAPE
)
3177 retval
= (-ENOMEDIUM
);
3182 STm
= &(STp
->modes
[STp
->current_mode
]);
3183 if (!STm
->defined
) {
3191 * If there was a bus reset, block further access
3194 if (STp
->pos_unknown
) {
3201 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3207 if (STp
->write_prot
) {
3212 /* Write must be integral number of blocks */
3213 if (STp
->block_size
!= 0 && (count
% STp
->block_size
) != 0) {
3214 printk(KERN_ERR
"%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3215 name
, count
, STp
->block_size
<1024?
3216 STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3221 if (STp
->first_frame_position
>= STp
->capacity
- OSST_EOM_RESERVE
) {
3222 printk(KERN_ERR
"%s:E: Write truncated at EOM early warning (frame %d).\n",
3223 name
, STp
->first_frame_position
);
3228 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3229 STp
->door_locked
= ST_LOCKED_AUTO
;
3231 STps
= &(STp
->ps
[STp
->partition
]);
3233 if (STps
->rw
== ST_READING
) {
3235 printk(OSST_DEB_MSG
"%s:D: Switching from read to write at file %d, block %d\n", name
,
3236 STps
->drv_file
, STps
->drv_block
);
3238 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3243 if (STps
->rw
!= ST_WRITING
) {
3244 /* Are we totally rewriting this tape? */
3245 if (!STp
->header_ok
||
3246 (STp
->first_frame_position
== STp
->first_data_ppos
&& STps
->drv_block
< 0) ||
3247 (STps
->drv_file
== 0 && STps
->drv_block
== 0)) {
3248 STp
->wrt_pass_cntr
++;
3250 printk(OSST_DEB_MSG
"%s:D: Allocating next write pass counter: %d\n",
3251 name
, STp
->wrt_pass_cntr
);
3253 osst_reset_header(STp
, &SRpnt
);
3254 STps
->drv_file
= STps
->drv_block
= 0;
3256 /* Do we know where we'll be writing on the tape? */
3258 if ((STp
->fast_open
&& osst_verify_position(STp
, &SRpnt
)) ||
3259 STps
->drv_file
< 0 || STps
->drv_block
< 0) {
3260 if (STp
->first_frame_position
== STp
->eod_frame_ppos
) { /* at EOD */
3261 STps
->drv_file
= STp
->filemark_cnt
;
3262 STps
->drv_block
= 0;
3265 /* We have no idea where the tape is positioned - give up */
3268 "%s:D: Cannot write at indeterminate position.\n", name
);
3274 if ((STps
->drv_file
+ STps
->drv_block
) > 0 && STps
->drv_file
< STp
->filemark_cnt
) {
3275 STp
->filemark_cnt
= STps
->drv_file
;
3276 STp
->last_mark_ppos
=
3277 ntohl(STp
->header_cache
->dat_fm_tab
.fm_tab_ent
[STp
->filemark_cnt
-1]);
3279 "%s:W: Overwriting file %d with old write pass counter %d\n",
3280 name
, STps
->drv_file
, STp
->wrt_pass_cntr
);
3282 "%s:W: may lead to stale data being accepted on reading back!\n",
3286 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3287 name
, STp
->filemark_cnt
, STp
->last_mark_ppos
, STp
->last_mark_lbn
);
3291 STp
->fast_open
= FALSE
;
3293 if (!STp
->header_ok
) {
3295 printk(OSST_DEB_MSG
"%s:D: Write cannot proceed without valid headers\n", name
);
3301 if ((STp
->buffer
)->writing
) {
3302 if (SRpnt
) printk(KERN_ERR
"%s:A: Not supposed to have SRpnt at line %d\n", name
, __LINE__
);
3303 osst_write_behind_check(STp
);
3304 if ((STp
->buffer
)->syscall_result
) {
3307 printk(OSST_DEB_MSG
"%s:D: Async write error (write) %x.\n", name
,
3308 (STp
->buffer
)->midlevel_result
);
3310 if ((STp
->buffer
)->midlevel_result
== INT_MAX
)
3311 STps
->eof
= ST_EOM_OK
;
3313 STps
->eof
= ST_EOM_ERROR
;
3316 if (STps
->eof
== ST_EOM_OK
) {
3320 else if (STps
->eof
== ST_EOM_ERROR
) {
3325 /* Check the buffer readability in cases where copy_user might catch
3326 the problems after some tape movement. */
3327 if ((copy_from_user(&i
, buf
, 1) != 0 ||
3328 copy_from_user(&i
, buf
+ count
- 1, 1) != 0)) {
3333 if (!STm
->do_buffer_writes
) {
3334 write_threshold
= 1;
3337 write_threshold
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
;
3338 if (!STm
->do_async_writes
)
3344 printk(OSST_DEB_MSG
"%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3345 name
, count
, STps
->drv_file
, STps
->drv_block
,
3346 STp
->logical_blk_num
, STp
->frame_seq_number
, STp
->first_frame_position
);
3349 while ((STp
->buffer
)->buffer_bytes
+ count
> write_threshold
)
3352 do_count
= (STp
->buffer
)->buffer_blocks
* STp
->block_size
-
3353 (STp
->buffer
)->buffer_bytes
;
3354 if (do_count
> count
)
3357 i
= append_to_buffer(b_point
, STp
->buffer
, do_count
);
3363 blks
= do_count
/ STp
->block_size
;
3364 STp
->logical_blk_num
+= blks
; /* logical_blk_num is incremented as data is moved from user */
3366 i
= osst_write_frame(STp
, &SRpnt
, TRUE
);
3368 if (i
== (-ENOSPC
)) {
3369 transfer
= STp
->buffer
->writing
; /* FIXME -- check this logic */
3370 if (transfer
<= do_count
) {
3371 filp
->f_pos
+= do_count
- transfer
;
3372 count
-= do_count
- transfer
;
3373 if (STps
->drv_block
>= 0) {
3374 STps
->drv_block
+= (do_count
- transfer
) / STp
->block_size
;
3376 STps
->eof
= ST_EOM_OK
;
3377 retval
= (-ENOSPC
); /* EOM within current request */
3380 printk(OSST_DEB_MSG
"%s:D: EOM with %d bytes unwritten.\n",
3385 STps
->eof
= ST_EOM_ERROR
;
3386 STps
->drv_block
= (-1); /* Too cautious? */
3387 retval
= (-EIO
); /* EOM for old data */
3390 printk(OSST_DEB_MSG
"%s:D: EOM with lost data.\n", name
);
3398 if (SRpnt
!= NULL
) {
3399 scsi_release_request(SRpnt
);
3402 STp
->buffer
->buffer_bytes
= 0;
3405 retval
= total
- count
;
3409 filp
->f_pos
+= do_count
;
3410 b_point
+= do_count
;
3412 if (STps
->drv_block
>= 0) {
3413 STps
->drv_block
+= blks
;
3415 STp
->buffer
->buffer_bytes
= 0;
3417 } /* end while write threshold exceeded */
3421 i
= append_to_buffer(b_point
, STp
->buffer
, count
);
3426 blks
= count
/ STp
->block_size
;
3427 STp
->logical_blk_num
+= blks
;
3428 if (STps
->drv_block
>= 0) {
3429 STps
->drv_block
+= blks
;
3431 filp
->f_pos
+= count
;
3435 if (doing_write
&& (STp
->buffer
)->syscall_result
!= 0) {
3436 retval
= (STp
->buffer
)->syscall_result
;
3440 if (STm
->do_async_writes
&& ((STp
->buffer
)->buffer_bytes
>= STp
->write_threshold
)) {
3441 /* Schedule an asynchronous write */
3442 (STp
->buffer
)->writing
= ((STp
->buffer
)->buffer_bytes
/
3443 STp
->block_size
) * STp
->block_size
;
3444 STp
->dirty
= !((STp
->buffer
)->writing
==
3445 (STp
->buffer
)->buffer_bytes
);
3447 i
= osst_write_frame(STp
, &SRpnt
, FALSE
);
3452 SRpnt
= NULL
; /* Prevent releasing this request! */
3454 STps
->at_sm
&= (total
== 0);
3456 STps
->eof
= ST_NOEOF
;
3461 if (SRpnt
!= NULL
) scsi_release_request(SRpnt
);
3470 static ssize_t
osst_read(struct file
* filp
, char * buf
, size_t count
, loff_t
*ppos
)
3472 ssize_t total
, retval
= 0;
3473 ssize_t i
, transfer
;
3477 Scsi_Request
* SRpnt
= NULL
;
3478 OS_Scsi_Tape
* STp
= filp
->private_data
;
3479 char * name
= tape_name(STp
);
3482 if (down_interruptible(&STp
->lock
))
3483 return (-ERESTARTSYS
);
3486 * If we are in the middle of error recovery, don't let anyone
3487 * else try and use this device. Also, if error recovery fails, it
3488 * may try and take the device offline, in which case all further
3489 * access to the device is prohibited.
3491 if( !scsi_block_when_processing_errors(STp
->device
) ) {
3496 if (ppos
!= &filp
->f_pos
) {
3497 /* "A request was outside the capabilities of the device." */
3502 if (STp
->ready
!= ST_READY
) {
3503 if (STp
->ready
== ST_NO_TAPE
)
3504 retval
= (-ENOMEDIUM
);
3509 STm
= &(STp
->modes
[STp
->current_mode
]);
3510 if (!STm
->defined
) {
3516 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
3521 /* Must have initialized medium */
3522 if (!STp
->header_ok
) {
3527 if (STp
->do_auto_lock
&& STp
->door_locked
== ST_UNLOCKED
&& !do_door_lock(STp
, 1))
3528 STp
->door_locked
= ST_LOCKED_AUTO
;
3530 STps
= &(STp
->ps
[STp
->partition
]);
3531 if (STps
->rw
== ST_WRITING
) {
3532 retval
= osst_flush_buffer(STp
, &SRpnt
, 0);
3536 /* FIXME -- this may leave the tape without EOD and up2date headers */
3539 if ((count
% STp
->block_size
) != 0) {
3541 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name
, count
,
3542 STp
->block_size
<1024?STp
->block_size
:STp
->block_size
/1024, STp
->block_size
<1024?'b':'k');
3546 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3547 printk(OSST_DEB_MSG
"%s:D: EOF/EOM flag up (%d). Bytes %d\n", name
,
3548 STps
->eof
, (STp
->buffer
)->buffer_bytes
);
3550 if ((STp
->buffer
)->buffer_bytes
== 0 &&
3551 STps
->eof
>= ST_EOD_1
) {
3552 if (STps
->eof
< ST_EOD
) {
3557 retval
= (-EIO
); /* EOM or Blank Check */
3561 /* Check the buffer writability before any tape movement. Don't alter
3563 if (copy_from_user(&i
, buf
, 1) != 0 ||
3564 copy_to_user (buf
, &i
, 1) != 0 ||
3565 copy_from_user(&i
, buf
+ count
- 1, 1) != 0 ||
3566 copy_to_user (buf
+ count
- 1, &i
, 1) != 0) {
3571 /* Loop until enough data in buffer or a special condition found */
3572 for (total
= 0, special
= 0; total
< count
- STp
->block_size
+ 1 && !special
; ) {
3574 /* Get new data if the buffer is empty */
3575 if ((STp
->buffer
)->buffer_bytes
== 0) {
3576 if (STps
->eof
== ST_FM_HIT
)
3578 special
= osst_get_logical_frame(STp
, &SRpnt
, STp
->frame_seq_number
, 0);
3579 if (special
< 0) { /* No need to continue read */
3580 STp
->frame_in_buffer
= 0;
3586 /* Move the data from driver buffer to user buffer */
3587 if ((STp
->buffer
)->buffer_bytes
> 0) {
3589 if (debugging
&& STps
->eof
!= ST_NOEOF
)
3590 printk(OSST_DEB_MSG
"%s:D: EOF up (%d). Left %d, needed %d.\n", name
,
3591 STps
->eof
, (STp
->buffer
)->buffer_bytes
, count
- total
);
3593 /* force multiple of block size, note block_size may have been adjusted */
3594 transfer
= (((STp
->buffer
)->buffer_bytes
< count
- total
?
3595 (STp
->buffer
)->buffer_bytes
: count
- total
)/
3596 STp
->block_size
) * STp
->block_size
;
3598 if (transfer
== 0) {
3600 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3601 name
, count
, STp
->block_size
< 1024?
3602 STp
->block_size
:STp
->block_size
/1024,
3603 STp
->block_size
<1024?'b':'k');
3606 i
= from_buffer(STp
->buffer
, buf
, transfer
);
3611 STp
->logical_blk_num
+= transfer
/ STp
->block_size
;
3612 STps
->drv_block
+= transfer
/ STp
->block_size
;
3613 filp
->f_pos
+= transfer
;
3618 if ((STp
->buffer
)->buffer_bytes
== 0) {
3621 printk(OSST_DEB_MSG
"%s:D: Finished with frame %d\n",
3622 name
, STp
->frame_seq_number
);
3624 STp
->frame_in_buffer
= 0;
3625 STp
->frame_seq_number
++; /* frame to look for next time */
3627 } /* for (total = 0, special = 0; total < count && !special; ) */
3629 /* Change the eof state if no data from tape or buffer */
3631 if (STps
->eof
== ST_FM_HIT
) {
3632 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
3633 STps
->drv_block
= 0;
3634 if (STps
->drv_file
>= 0)
3637 else if (STps
->eof
== ST_EOD_1
) {
3638 STps
->eof
= ST_EOD_2
;
3639 if (STps
->drv_block
> 0 && STps
->drv_file
>= 0)
3641 STps
->drv_block
= 0;
3643 else if (STps
->eof
== ST_EOD_2
)
3646 else if (STps
->eof
== ST_FM
)
3647 STps
->eof
= ST_NOEOF
;
3652 if (SRpnt
!= NULL
) scsi_release_request(SRpnt
);
3660 /* Set the driver options */
3661 static void osst_log_options(OS_Scsi_Tape
*STp
, ST_mode
*STm
, char *name
)
3664 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3665 name
, STp
->current_mode
, STm
->do_buffer_writes
, STm
->do_async_writes
,
3666 STm
->do_read_ahead
);
3668 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3669 name
, STp
->can_bsr
, STp
->two_fm
, STp
->fast_mteom
, STp
->do_auto_lock
);
3671 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3672 name
, STm
->defaults_for_writes
, STp
->omit_blklims
, STp
->can_partitions
,
3673 STp
->scsi2_logical
);
3675 "%s:I: sysv: %d\n", name
, STm
->sysv
);
3678 "%s:D: debugging: %d\n",
3684 static int osst_set_options(OS_Scsi_Tape
*STp
, long options
)
3689 char * name
= tape_name(STp
);
3691 STm
= &(STp
->modes
[STp
->current_mode
]);
3692 if (!STm
->defined
) {
3693 memcpy(STm
, &(STp
->modes
[0]), sizeof(ST_mode
));
3694 modes_defined
= TRUE
;
3697 printk(OSST_DEB_MSG
"%s:D: Initialized mode %d definition from mode 0\n",
3698 name
, STp
->current_mode
);
3702 code
= options
& MT_ST_OPTIONS
;
3703 if (code
== MT_ST_BOOLEANS
) {
3704 STm
->do_buffer_writes
= (options
& MT_ST_BUFFER_WRITES
) != 0;
3705 STm
->do_async_writes
= (options
& MT_ST_ASYNC_WRITES
) != 0;
3706 STm
->defaults_for_writes
= (options
& MT_ST_DEF_WRITES
) != 0;
3707 STm
->do_read_ahead
= (options
& MT_ST_READ_AHEAD
) != 0;
3708 STp
->two_fm
= (options
& MT_ST_TWO_FM
) != 0;
3709 STp
->fast_mteom
= (options
& MT_ST_FAST_MTEOM
) != 0;
3710 STp
->do_auto_lock
= (options
& MT_ST_AUTO_LOCK
) != 0;
3711 STp
->can_bsr
= (options
& MT_ST_CAN_BSR
) != 0;
3712 STp
->omit_blklims
= (options
& MT_ST_NO_BLKLIMS
) != 0;
3713 if ((STp
->device
)->scsi_level
>= SCSI_2
)
3714 STp
->can_partitions
= (options
& MT_ST_CAN_PARTITIONS
) != 0;
3715 STp
->scsi2_logical
= (options
& MT_ST_SCSI2LOGICAL
) != 0;
3716 STm
->sysv
= (options
& MT_ST_SYSV
) != 0;
3718 debugging
= (options
& MT_ST_DEBUGGING
) != 0;
3720 osst_log_options(STp
, STm
, name
);
3722 else if (code
== MT_ST_SETBOOLEANS
|| code
== MT_ST_CLEARBOOLEANS
) {
3723 value
= (code
== MT_ST_SETBOOLEANS
);
3724 if ((options
& MT_ST_BUFFER_WRITES
) != 0)
3725 STm
->do_buffer_writes
= value
;
3726 if ((options
& MT_ST_ASYNC_WRITES
) != 0)
3727 STm
->do_async_writes
= value
;
3728 if ((options
& MT_ST_DEF_WRITES
) != 0)
3729 STm
->defaults_for_writes
= value
;
3730 if ((options
& MT_ST_READ_AHEAD
) != 0)
3731 STm
->do_read_ahead
= value
;
3732 if ((options
& MT_ST_TWO_FM
) != 0)
3733 STp
->two_fm
= value
;
3734 if ((options
& MT_ST_FAST_MTEOM
) != 0)
3735 STp
->fast_mteom
= value
;
3736 if ((options
& MT_ST_AUTO_LOCK
) != 0)
3737 STp
->do_auto_lock
= value
;
3738 if ((options
& MT_ST_CAN_BSR
) != 0)
3739 STp
->can_bsr
= value
;
3740 if ((options
& MT_ST_NO_BLKLIMS
) != 0)
3741 STp
->omit_blklims
= value
;
3742 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
3743 (options
& MT_ST_CAN_PARTITIONS
) != 0)
3744 STp
->can_partitions
= value
;
3745 if ((options
& MT_ST_SCSI2LOGICAL
) != 0)
3746 STp
->scsi2_logical
= value
;
3747 if ((options
& MT_ST_SYSV
) != 0)
3750 if ((options
& MT_ST_DEBUGGING
) != 0)
3753 osst_log_options(STp
, STm
, name
);
3755 else if (code
== MT_ST_WRITE_THRESHOLD
) {
3756 value
= (options
& ~MT_ST_OPTIONS
) * ST_KILOBYTE
;
3757 if (value
< 1 || value
> osst_buffer_size
) {
3758 printk(KERN_WARNING
"%s:W: Write threshold %d too small or too large.\n",
3762 STp
->write_threshold
= value
;
3763 printk(KERN_INFO
"%s:I: Write threshold set to %d bytes.\n",
3766 else if (code
== MT_ST_DEF_BLKSIZE
) {
3767 value
= (options
& ~MT_ST_OPTIONS
);
3768 if (value
== ~MT_ST_OPTIONS
) {
3769 STm
->default_blksize
= (-1);
3770 printk(KERN_INFO
"%s:I: Default block size disabled.\n", name
);
3773 if (value
< 512 || value
> OS_DATA_SIZE
|| OS_DATA_SIZE
% value
) {
3774 printk(KERN_WARNING
"%s:W: Default block size cannot be set to %d.\n",
3778 STm
->default_blksize
= value
;
3779 printk(KERN_INFO
"%s:I: Default block size set to %d bytes.\n",
3780 name
, STm
->default_blksize
);
3783 else if (code
== MT_ST_TIMEOUTS
) {
3784 value
= (options
& ~MT_ST_OPTIONS
);
3785 if ((value
& MT_ST_SET_LONG_TIMEOUT
) != 0) {
3786 STp
->long_timeout
= (value
& ~MT_ST_SET_LONG_TIMEOUT
) * HZ
;
3787 printk(KERN_INFO
"%s:I: Long timeout set to %d seconds.\n", name
,
3788 (value
& ~MT_ST_SET_LONG_TIMEOUT
));
3791 STp
->timeout
= value
* HZ
;
3792 printk(KERN_INFO
"%s:I: Normal timeout set to %d seconds.\n", name
, value
);
3795 else if (code
== MT_ST_DEF_OPTIONS
) {
3796 code
= (options
& ~MT_ST_CLEAR_DEFAULT
);
3797 value
= (options
& MT_ST_CLEAR_DEFAULT
);
3798 if (code
== MT_ST_DEF_DENSITY
) {
3799 if (value
== MT_ST_CLEAR_DEFAULT
) {
3800 STm
->default_density
= (-1);
3801 printk(KERN_INFO
"%s:I: Density default disabled.\n", name
);
3804 STm
->default_density
= value
& 0xff;
3805 printk(KERN_INFO
"%s:I: Density default set to %x\n",
3806 name
, STm
->default_density
);
3809 else if (code
== MT_ST_DEF_DRVBUFFER
) {
3810 if (value
== MT_ST_CLEAR_DEFAULT
) {
3811 STp
->default_drvbuffer
= 0xff;
3812 printk(KERN_INFO
"%s:I: Drive buffer default disabled.\n", name
);
3815 STp
->default_drvbuffer
= value
& 7;
3816 printk(KERN_INFO
"%s:I: Drive buffer default set to %x\n",
3817 name
, STp
->default_drvbuffer
);
3820 else if (code
== MT_ST_DEF_COMPRESSION
) {
3821 if (value
== MT_ST_CLEAR_DEFAULT
) {
3822 STm
->default_compression
= ST_DONT_TOUCH
;
3823 printk(KERN_INFO
"%s:I: Compression default disabled.\n", name
);
3826 STm
->default_compression
= (value
& 1 ? ST_YES
: ST_NO
);
3827 printk(KERN_INFO
"%s:I: Compression default set to %x\n",
3839 /* Internal ioctl function */
3840 static int osst_int_ioctl(OS_Scsi_Tape
* STp
, Scsi_Request
** aSRpnt
, unsigned int cmd_in
, unsigned long arg
)
3844 int i
, ioctl_result
;
3846 unsigned char cmd
[MAX_COMMAND_SIZE
];
3847 Scsi_Request
* SRpnt
= * aSRpnt
;
3849 int fileno
, blkno
, at_sm
, frame_seq_numbr
, logical_blk_num
;
3850 int datalen
= 0, direction
= SCSI_DATA_NONE
;
3851 char * name
= tape_name(STp
);
3853 if (STp
->ready
!= ST_READY
&& cmd_in
!= MTLOAD
) {
3854 if (STp
->ready
== ST_NO_TAPE
)
3855 return (-ENOMEDIUM
);
3859 timeout
= STp
->long_timeout
;
3860 STps
= &(STp
->ps
[STp
->partition
]);
3861 fileno
= STps
->drv_file
;
3862 blkno
= STps
->drv_block
;
3863 at_sm
= STps
->at_sm
;
3864 frame_seq_numbr
= STp
->frame_seq_number
;
3865 logical_blk_num
= STp
->logical_blk_num
;
3867 memset(cmd
, 0, MAX_COMMAND_SIZE
);
3870 chg_eof
= FALSE
; /* Changed from the FSF after this */
3874 if (STp
->linux_media
)
3875 ioctl_result
= osst_space_over_filemarks_forward_fast(STp
, &SRpnt
, cmd_in
, arg
);
3877 ioctl_result
= osst_space_over_filemarks_forward_slow(STp
, &SRpnt
, cmd_in
, arg
);
3881 at_sm
&= (arg
== 0);
3885 chg_eof
= FALSE
; /* Changed from the FSF after this */
3889 ioctl_result
= osst_space_over_filemarks_backward(STp
, &SRpnt
, cmd_in
, arg
);
3892 blkno
= (-1); /* We can't know the block number */
3893 at_sm
&= (arg
== 0);
3900 printk(OSST_DEB_MSG
"%s:D: Skipping %lu blocks %s from logical block %d\n",
3901 name
, arg
, cmd_in
==MTFSR
?"forward":"backward", logical_blk_num
);
3903 if (cmd_in
== MTFSR
) {
3904 logical_blk_num
+= arg
;
3905 if (blkno
>= 0) blkno
+= arg
;
3908 logical_blk_num
-= arg
;
3909 if (blkno
>= 0) blkno
-= arg
;
3911 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, logical_blk_num
);
3912 fileno
= STps
->drv_file
;
3913 blkno
= STps
->drv_block
;
3914 at_sm
&= (arg
== 0);
3919 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
3920 cmd
[2] = (arg
>> 16);
3921 cmd
[3] = (arg
>> 8);
3925 printk(OSST_DEB_MSG
"%s:D: Spacing tape forward %d setmarks.\n", name
,
3926 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
3929 blkno
= fileno
= (-1);
3935 cmd
[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
3937 cmd
[2] = (ltmp
>> 16);
3938 cmd
[3] = (ltmp
>> 8);
3944 ltmp
= ltmp
| (cmd
[2] << 16) | (cmd
[3] << 8) | cmd
[4];
3945 printk(OSST_DEB_MSG
"%s:D: Spacing tape backward %ld setmarks.\n",
3950 blkno
= fileno
= (-1);
3955 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
3956 STp
->write_type
= OS_WRITE_DATA
;
3957 ioctl_result
= osst_flush_write_buffer(STp
, &SRpnt
);
3962 printk(OSST_DEB_MSG
"%s:D: Writing %ld filemark(s).\n", name
, arg
);
3964 for (i
=0; i
<arg
; i
++)
3965 ioctl_result
|= osst_write_filemark(STp
, &SRpnt
);
3966 if (fileno
>= 0) fileno
+= arg
;
3967 if (blkno
>= 0) blkno
= 0;
3971 if (STp
->write_prot
)
3975 cmd
[0] = WRITE_FILEMARKS
; /* FIXME -- need OS version */
3976 if (cmd_in
== MTWSM
)
3978 cmd
[2] = (arg
>> 16);
3979 cmd
[3] = (arg
>> 8);
3981 timeout
= STp
->timeout
;
3984 printk(OSST_DEB_MSG
"%s:D: Writing %d setmark(s).\n", name
,
3985 cmd
[2] * 65536 + cmd
[3] * 256 + cmd
[4]);
3990 at_sm
= (cmd_in
== MTWSM
);
3996 cmd
[0] = START_STOP
;
3997 cmd
[1] = 1; /* Don't wait for completion */
3998 if (cmd_in
== MTLOAD
) {
3999 if (STp
->ready
== ST_NO_TAPE
)
4000 cmd
[4] = 4; /* open tray */
4002 cmd
[4] = 1; /* load */
4004 if (cmd_in
== MTRETEN
)
4005 cmd
[4] = 3; /* retension then mount */
4006 if (cmd_in
== MTOFFL
)
4007 cmd
[4] = 4; /* rewind then eject */
4008 timeout
= STp
->timeout
;
4013 printk(OSST_DEB_MSG
"%s:D: Unloading tape.\n", name
);
4016 printk(OSST_DEB_MSG
"%s:D: Loading tape.\n", name
);
4019 printk(OSST_DEB_MSG
"%s:D: Retensioning tape.\n", name
);
4022 printk(OSST_DEB_MSG
"%s:D: Ejecting tape.\n", name
);
4027 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4032 printk(OSST_DEB_MSG
"%s:D: No-op on tape.\n", name
);
4034 return 0; /* Should do something ? */
4039 printk(OSST_DEB_MSG
"%s:D: Spacing to end of recorded medium.\n", name
);
4041 osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4042 if (osst_get_logical_frame(STp
, &SRpnt
, -1, 0) < 0) {
4043 ioctl_result
= -EIO
;
4046 if (STp
->buffer
->aux
->frame_type
!= OS_FRAME_TYPE_EOD
) {
4048 printk(OSST_DEB_MSG
"%s:D: No EOD frame found where expected.\n", name
);
4050 ioctl_result
= -EIO
;
4053 ioctl_result
= osst_set_frame_position(STp
, &SRpnt
, STp
->eod_frame_ppos
, 0);
4054 fileno
= STp
->filemark_cnt
;
4059 if (STp
->write_prot
)
4061 ioctl_result
= osst_reset_header(STp
, &SRpnt
);
4062 i
= osst_write_eod(STp
, &SRpnt
);
4063 if (i
< ioctl_result
) ioctl_result
= i
;
4064 i
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
);
4065 if (i
< ioctl_result
) ioctl_result
= i
;
4066 fileno
= blkno
= at_sm
= 0 ;
4070 cmd
[0] = REZERO_UNIT
; /* rewind */
4074 printk(OSST_DEB_MSG
"%s:D: Rewinding tape, Immed=%d.\n", name
, cmd
[1]);
4076 fileno
= blkno
= at_sm
= frame_seq_numbr
= logical_blk_num
= 0 ;
4079 case MTSETBLK
: /* Set block length */
4080 case MTSETDENSITY
: /* Set tape density */
4081 case MTSETDRVBUFFER
: /* Set drive buffering */
4082 case SET_DENS_AND_BLK
: /* Set density and block size */
4084 if (STp
->dirty
|| (STp
->buffer
)->buffer_bytes
!= 0)
4085 return (-EIO
); /* Not allowed if data in buffer */
4086 if ((cmd_in
== MTSETBLK
|| cmd_in
== SET_DENS_AND_BLK
) &&
4087 (arg
& MT_ST_BLKSIZE_MASK
) != 0 &&
4088 ((arg
& MT_ST_BLKSIZE_MASK
) < STp
->min_block
||
4089 (arg
& MT_ST_BLKSIZE_MASK
) > STp
->max_block
||
4090 (arg
& MT_ST_BLKSIZE_MASK
) > osst_buffer_size
)) {
4091 printk(KERN_WARNING
"%s:W: Illegal block size.\n", name
);
4094 return 0; /* FIXME silently ignore if block size didn't change */
4100 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, datalen
, direction
, timeout
, MAX_RETRIES
, TRUE
);
4102 ioctl_result
= (STp
->buffer
)->syscall_result
;
4106 printk(OSST_DEB_MSG
"%s:D: Couldn't exec scsi cmd for IOCTL\n", name
);
4108 return ioctl_result
;
4111 if (!ioctl_result
) { /* SCSI command successful */
4112 STp
->frame_seq_number
= frame_seq_numbr
;
4113 STp
->logical_blk_num
= logical_blk_num
;
4119 printk(OSST_DEB_MSG
"%s:D: IOCTL (%d) Result=%d\n", name
, cmd_in
, ioctl_result
);
4122 if (!ioctl_result
) { /* success */
4124 if (cmd_in
== MTFSFM
) {
4128 if (cmd_in
== MTBSFM
) {
4132 STps
->drv_block
= blkno
;
4133 STps
->drv_file
= fileno
;
4134 STps
->at_sm
= at_sm
;
4136 if (cmd_in
== MTEOM
)
4138 else if ((cmd_in
== MTFSFM
|| cmd_in
== MTBSF
) && STps
->eof
== ST_FM_HIT
) {
4139 ioctl_result
= osst_seek_logical_blk(STp
, &SRpnt
, STp
->logical_blk_num
-1);
4141 STp
->logical_blk_num
++;
4142 STp
->frame_seq_number
++;
4143 STp
->frame_in_buffer
= 0;
4144 STp
->buffer
->read_pointer
= 0;
4146 else if (cmd_in
== MTFSF
)
4147 STps
->eof
= (STp
->first_frame_position
>= STp
->eod_frame_ppos
)?ST_EOD
:ST_FM
;
4149 STps
->eof
= ST_NOEOF
;
4151 if (cmd_in
== MTOFFL
|| cmd_in
== MTUNLOAD
)
4152 STp
->rew_at_close
= 0;
4153 else if (cmd_in
== MTLOAD
) {
4154 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4155 STp
->ps
[i
].rw
= ST_IDLE
;
4156 STp
->ps
[i
].last_block_valid
= FALSE
;/* FIXME - where else is this field maintained? */
4161 if (cmd_in
== MTREW
) {
4162 ioctl_result
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4163 if (ioctl_result
> 0)
4167 } else if (cmd_in
== MTBSF
|| cmd_in
== MTBSFM
) {
4168 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
) < 0)
4169 STps
->drv_file
= STps
->drv_block
= -1;
4171 STps
->drv_file
= STps
->drv_block
= 0;
4172 STps
->eof
= ST_NOEOF
;
4173 } else if (cmd_in
== MTFSF
|| cmd_in
== MTFSFM
) {
4174 if (osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->eod_frame_ppos
) < 0)
4175 STps
->drv_file
= STps
->drv_block
= -1;
4177 STps
->drv_file
= STp
->filemark_cnt
;
4178 STps
->drv_block
= 0;
4181 } else if (cmd_in
== MTBSR
|| cmd_in
== MTFSR
|| cmd_in
== MTWEOF
|| cmd_in
== MTEOM
) {
4182 STps
->drv_file
= STps
->drv_block
= (-1);
4183 STps
->eof
= ST_NOEOF
;
4185 } else if (cmd_in
== MTERASE
) {
4187 } else if (SRpnt
) { /* SCSI command was not completely successful. */
4188 if (SRpnt
->sr_sense_buffer
[2] & 0x40) {
4189 STps
->eof
= ST_EOM_OK
;
4190 STps
->drv_block
= 0;
4193 STps
->eof
= ST_NOEOF
;
4195 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == BLANK_CHECK
)
4198 if (cmd_in
== MTLOAD
&& osst_wait_for_medium(STp
, &SRpnt
, 60))
4199 ioctl_result
= osst_wait_ready(STp
, &SRpnt
, 5 * 60, OSST_WAIT_POSITION_COMPLETE
);
4203 return ioctl_result
;
4207 /* Open the device */
4208 static int os_scsi_tape_open(struct inode
* inode
, struct file
* filp
)
4210 unsigned short flags
;
4211 int i
, b_size
, new_session
= FALSE
, retval
= 0;
4212 unsigned char cmd
[MAX_COMMAND_SIZE
];
4213 Scsi_Request
* SRpnt
= NULL
;
4218 int dev
= TAPE_NR(inode
->i_rdev
);
4219 int mode
= TAPE_MODE(inode
->i_rdev
);
4221 write_lock(&os_scsi_tapes_lock
);
4222 if (dev
>= osst_max_dev
|| os_scsi_tapes
== NULL
||
4223 (STp
= os_scsi_tapes
[dev
]) == NULL
|| !STp
->device
) {
4224 write_unlock(&os_scsi_tapes_lock
);
4228 name
= tape_name(STp
);
4231 write_unlock(&os_scsi_tapes_lock
);
4233 printk(OSST_DEB_MSG
"%s:D: Device already in use.\n", name
);
4237 if (scsi_device_get(STp
->device
)) {
4238 write_unlock(&os_scsi_tapes_lock
);
4240 printk(OSST_DEB_MSG
"%s:D: Failed scsi_device_get.\n", name
);
4244 filp
->private_data
= STp
;
4246 write_unlock(&os_scsi_tapes_lock
);
4247 STp
->rew_at_close
= TAPE_REWIND(inode
->i_rdev
);
4249 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4253 if (mode
!= STp
->current_mode
) {
4256 printk(OSST_DEB_MSG
"%s:D: Mode change from %d to %d.\n",
4257 name
, STp
->current_mode
, mode
);
4260 STp
->current_mode
= mode
;
4262 STm
= &(STp
->modes
[STp
->current_mode
]);
4264 flags
= filp
->f_flags
;
4265 STp
->write_prot
= ((flags
& O_ACCMODE
) == O_RDONLY
);
4267 STp
->raw
= TAPE_IS_RAW(inode
->i_rdev
);
4271 /* Allocate data segments for this device's tape buffer */
4272 if (!enlarge_buffer(STp
->buffer
, STp
->restr_dma
)) {
4273 printk(KERN_ERR
"%s:E: Unable to allocate memory segments for tape buffer.\n", name
);
4274 retval
= (-EOVERFLOW
);
4277 if (STp
->buffer
->buffer_size
>= OS_FRAME_SIZE
) {
4278 for (i
= 0, b_size
= 0;
4279 (i
< STp
->buffer
->sg_segs
) && ((b_size
+ STp
->buffer
->sg
[i
].length
) <= OS_DATA_SIZE
);
4280 b_size
+= STp
->buffer
->sg
[i
++].length
);
4281 STp
->buffer
->aux
= (os_aux_t
*) (page_address(STp
->buffer
->sg
[i
].page
) + OS_DATA_SIZE
- b_size
);
4283 printk(OSST_DEB_MSG
"%s:D: b_data points to %p in segment 0 at %p\n", name
,
4284 STp
->buffer
->b_data
, page_address(STp
->buffer
->sg
[0].page
));
4285 printk(OSST_DEB_MSG
"%s:D: AUX points to %p in segment %d at %p\n", name
,
4286 STp
->buffer
->aux
, i
, page_address(STp
->buffer
->sg
[i
].page
));
4289 STp
->buffer
->aux
= NULL
; /* this had better never happen! */
4290 printk(KERN_NOTICE
"%s:A: Framesize %d too large for buffer.\n", name
, OS_FRAME_SIZE
);
4294 STp
->buffer
->writing
= 0;
4295 STp
->buffer
->syscall_result
= 0;
4297 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4298 STps
= &(STp
->ps
[i
]);
4301 STp
->ready
= ST_READY
;
4303 STp
->nbr_waits
= STp
->nbr_finished
= 0;
4306 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4307 cmd
[0] = TEST_UNIT_READY
;
4309 SRpnt
= osst_do_scsi(NULL
, STp
, cmd
, 0, SCSI_DATA_NONE
, STp
->timeout
, MAX_READY_RETRIES
, TRUE
);
4311 retval
= (STp
->buffer
)->syscall_result
;
4314 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4315 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
&&
4316 SRpnt
->sr_sense_buffer
[12] == 4 ) {
4318 printk(OSST_DEB_MSG
"%s:D: Unit not ready, cause %x\n", name
, SRpnt
->sr_sense_buffer
[13]);
4320 if (filp
->f_flags
& O_NONBLOCK
) {
4324 if (SRpnt
->sr_sense_buffer
[13] == 2) { /* initialize command required (LOAD) */
4325 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4326 cmd
[0] = START_STOP
;
4329 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
,
4330 STp
->timeout
, MAX_READY_RETRIES
, TRUE
);
4332 osst_wait_ready(STp
, &SRpnt
, (SRpnt
->sr_sense_buffer
[13]==1?15:3) * 60, 0);
4334 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4335 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == UNIT_ATTENTION
) { /* New media? */
4337 printk(OSST_DEB_MSG
"%s:D: Unit wants attention\n", name
);
4341 for (i
=0; i
< 10; i
++) {
4343 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4344 cmd
[0] = TEST_UNIT_READY
;
4346 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
,
4347 STp
->timeout
, MAX_READY_RETRIES
, TRUE
);
4348 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) != 0x70 ||
4349 (SRpnt
->sr_sense_buffer
[2] & 0x0f) != UNIT_ATTENTION
)
4353 STp
->pos_unknown
= 0;
4354 STp
->partition
= STp
->new_partition
= 0;
4355 if (STp
->can_partitions
)
4356 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4357 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4358 STps
= &(STp
->ps
[i
]);
4359 STps
->rw
= ST_IDLE
; /* FIXME - seems to be redundant... */
4360 STps
->eof
= ST_NOEOF
;
4362 STps
->last_block_valid
= FALSE
;
4363 STps
->drv_block
= 0;
4364 STps
->drv_file
= 0 ;
4367 STp
->recover_count
= 0;
4370 * if we have valid headers from before, and the drive/tape seem untouched,
4371 * open without reconfiguring and re-reading the headers
4373 if (!STp
->buffer
->syscall_result
&& STp
->header_ok
&&
4374 !SRpnt
->sr_result
&& SRpnt
->sr_sense_buffer
[0] == 0) {
4376 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4377 cmd
[0] = MODE_SENSE
;
4379 cmd
[2] = VENDOR_IDENT_PAGE
;
4380 cmd
[4] = VENDOR_IDENT_PAGE_LENGTH
+ MODE_HEADER_LENGTH
;
4382 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], SCSI_DATA_READ
, STp
->timeout
, 0, TRUE
);
4384 if (STp
->buffer
->syscall_result
||
4385 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2] != 'L' ||
4386 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3] != 'I' ||
4387 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4] != 'N' ||
4388 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5] != '4' ) {
4390 printk(OSST_DEB_MSG
"%s:D: Signature was changed to %c%c%c%c\n", name
,
4391 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 2],
4392 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 3],
4393 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 4],
4394 STp
->buffer
->b_data
[MODE_HEADER_LENGTH
+ 5]);
4398 i
= STp
->first_frame_position
;
4399 if (STp
->header_ok
&& i
== osst_get_frame_position(STp
, &SRpnt
)) {
4400 if (STp
->door_locked
== ST_UNLOCKED
) {
4401 if (do_door_lock(STp
, 1))
4402 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4404 STp
->door_locked
= ST_LOCKED_AUTO
;
4406 if (!STp
->frame_in_buffer
) {
4407 STp
->block_size
= (STm
->default_blksize
> 0) ?
4408 STm
->default_blksize
: OS_DATA_SIZE
;
4409 STp
->buffer
->buffer_bytes
= STp
->buffer
->read_pointer
= 0;
4411 STp
->buffer
->buffer_blocks
= OS_DATA_SIZE
/ STp
->block_size
;
4412 STp
->fast_open
= TRUE
;
4413 scsi_release_request(SRpnt
);
4417 if (i
!= STp
->first_frame_position
)
4418 printk(OSST_DEB_MSG
"%s:D: Tape position changed from %d to %d\n",
4419 name
, i
, STp
->first_frame_position
);
4423 STp
->fast_open
= FALSE
;
4425 if ((STp
->buffer
)->syscall_result
!= 0 && /* in all error conditions except no medium */
4426 (SRpnt
->sr_sense_buffer
[2] != 2 || SRpnt
->sr_sense_buffer
[12] != 0x3A) ) {
4428 memset(cmd
, 0, MAX_COMMAND_SIZE
);
4429 cmd
[0] = MODE_SELECT
;
4431 cmd
[4] = 4 + MODE_HEADER_LENGTH
;
4433 (STp
->buffer
)->b_data
[0] = cmd
[4] - 1;
4434 (STp
->buffer
)->b_data
[1] = 0; /* Medium Type - ignoring */
4435 (STp
->buffer
)->b_data
[2] = 0; /* Reserved */
4436 (STp
->buffer
)->b_data
[3] = 0; /* Block Descriptor Length */
4437 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 0] = 0x3f;
4438 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 1] = 1;
4439 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 2] = 2;
4440 (STp
->buffer
)->b_data
[MODE_HEADER_LENGTH
+ 3] = 3;
4443 printk(OSST_DEB_MSG
"%s:D: Applying soft reset\n", name
);
4445 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, cmd
[4], SCSI_DATA_WRITE
, STp
->timeout
, 0, TRUE
);
4449 for (i
=0; i
< 10; i
++) {
4451 memset (cmd
, 0, MAX_COMMAND_SIZE
);
4452 cmd
[0] = TEST_UNIT_READY
;
4454 SRpnt
= osst_do_scsi(SRpnt
, STp
, cmd
, 0, SCSI_DATA_NONE
,
4455 STp
->timeout
, MAX_READY_RETRIES
, TRUE
);
4456 if ((SRpnt
->sr_sense_buffer
[0] & 0x70) != 0x70 ||
4457 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
)
4460 if ((SRpnt
->sr_sense_buffer
[2] & 0x0f) == UNIT_ATTENTION
) {
4461 STp
->pos_unknown
= 0;
4462 STp
->partition
= STp
->new_partition
= 0;
4463 if (STp
->can_partitions
)
4464 STp
->nbr_partitions
= 1; /* This guess will be updated later if necessary */
4465 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4466 STps
= &(STp
->ps
[i
]);
4468 STps
->eof
= ST_NOEOF
;
4470 STps
->last_block_valid
= FALSE
;
4471 STps
->drv_block
= 0;
4472 STps
->drv_file
= 0 ;
4479 if (osst_wait_ready(STp
, &SRpnt
, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4480 printk(KERN_INFO
"%s:I: Device did not become Ready in open\n", name
);
4482 if ((STp
->buffer
)->syscall_result
!= 0) {
4483 if ((STp
->device
)->scsi_level
>= SCSI_2
&&
4484 (SRpnt
->sr_sense_buffer
[0] & 0x70) == 0x70 &&
4485 (SRpnt
->sr_sense_buffer
[2] & 0x0f) == NOT_READY
&&
4486 SRpnt
->sr_sense_buffer
[12] == 0x3a) { /* Check ASC */
4487 STp
->ready
= ST_NO_TAPE
;
4489 STp
->ready
= ST_NOT_READY
;
4490 scsi_release_request(SRpnt
);
4492 STp
->density
= 0; /* Clear the erroneous "residue" */
4493 STp
->write_prot
= 0;
4494 STp
->block_size
= 0;
4495 STp
->ps
[0].drv_file
= STp
->ps
[0].drv_block
= (-1);
4496 STp
->partition
= STp
->new_partition
= 0;
4497 STp
->door_locked
= ST_UNLOCKED
;
4501 osst_configure_onstream(STp
, &SRpnt
);
4503 STp
->block_size
= STp
->raw
? OS_FRAME_SIZE
: (
4504 (STm
->default_blksize
> 0) ? STm
->default_blksize
: OS_DATA_SIZE
);
4505 STp
->buffer
->buffer_blocks
= STp
->raw
? 1 : OS_DATA_SIZE
/ STp
->block_size
;
4506 STp
->buffer
->buffer_bytes
=
4507 STp
->buffer
->read_pointer
=
4508 STp
->frame_in_buffer
= 0;
4512 printk(OSST_DEB_MSG
"%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4513 name
, STp
->block_size
, OS_FRAME_SIZE
, (STp
->buffer
)->buffer_size
,
4514 (STp
->buffer
)->buffer_blocks
);
4517 if (STp
->drv_write_prot
) {
4518 STp
->write_prot
= 1;
4521 printk(OSST_DEB_MSG
"%s:D: Write protected\n", name
);
4523 if ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
) {
4529 if (new_session
) { /* Change the drive parameters for the new mode */
4532 printk(OSST_DEB_MSG
"%s:D: New Session\n", name
);
4534 STp
->density_changed
= STp
->blksize_changed
= FALSE
;
4535 STp
->compression_changed
= FALSE
;
4539 * properly position the tape and check the ADR headers
4541 if (STp
->door_locked
== ST_UNLOCKED
) {
4542 if (do_door_lock(STp
, 1))
4543 printk(KERN_INFO
"%s:I: Can't lock drive door\n", name
);
4545 STp
->door_locked
= ST_LOCKED_AUTO
;
4548 osst_analyze_headers(STp
, &SRpnt
);
4550 scsi_release_request(SRpnt
);
4557 scsi_release_request(SRpnt
);
4558 normalize_buffer(STp
->buffer
);
4561 scsi_device_put(STp
->device
);
4567 /* Flush the tape buffer before close */
4568 static int os_scsi_tape_flush(struct file
* filp
)
4570 int result
= 0, result2
;
4571 OS_Scsi_Tape
* STp
= filp
->private_data
;
4572 ST_mode
* STm
= &(STp
->modes
[STp
->current_mode
]);
4573 ST_partstat
* STps
= &(STp
->ps
[STp
->partition
]);
4574 Scsi_Request
* SRpnt
= NULL
;
4575 char * name
= tape_name(STp
);
4577 if (file_count(filp
) > 1)
4580 if ((STps
->rw
== ST_WRITING
|| STp
->dirty
) && !STp
->pos_unknown
) {
4581 STp
->write_type
= OS_WRITE_DATA
;
4582 result
= osst_flush_write_buffer(STp
, &SRpnt
);
4583 if (result
!= 0 && result
!= (-ENOSPC
))
4586 if ( STps
->rw
>= ST_WRITING
&& !STp
->pos_unknown
) {
4590 printk(OSST_DEB_MSG
"%s:D: File length %ld bytes.\n",
4591 name
, (long)(filp
->f_pos
));
4592 printk(OSST_DEB_MSG
"%s:D: Async write waits %d, finished %d.\n",
4593 name
, STp
->nbr_waits
, STp
->nbr_finished
);
4596 if (STp
->write_type
!= OS_WRITE_NEW_MARK
) {
4597 /* true unless the user wrote the filemark for us */
4598 result
= osst_flush_drive_buffer(STp
, &SRpnt
);
4599 if (result
< 0) goto out
;
4600 result
= osst_write_filemark(STp
, &SRpnt
);
4601 if (result
< 0) goto out
;
4603 if (STps
->drv_file
>= 0)
4605 STps
->drv_block
= 0;
4607 result
= osst_write_eod(STp
, &SRpnt
);
4608 osst_write_header(STp
, &SRpnt
, !(STp
->rew_at_close
));
4614 printk(OSST_DEB_MSG
"%s:D: Buffer flushed, %d EOF(s) written\n",
4615 name
, 1+STp
->two_fm
);
4618 else if (!STp
->rew_at_close
) {
4619 STps
= &(STp
->ps
[STp
->partition
]);
4620 if (!STm
->sysv
|| STps
->rw
!= ST_READING
) {
4622 result
= osst_flush_buffer(STp
, &SRpnt
, 0); /* this is the default path */
4623 else if (STps
->eof
== ST_FM_HIT
) {
4624 result
= cross_eof(STp
, &SRpnt
, FALSE
);
4626 if (STps
->drv_file
>= 0)
4628 STps
->drv_block
= 0;
4632 STps
->eof
= ST_NOEOF
;
4635 else if ((STps
->eof
== ST_NOEOF
&&
4636 !(result
= cross_eof(STp
, &SRpnt
, TRUE
))) ||
4637 STps
->eof
== ST_FM_HIT
) {
4638 if (STps
->drv_file
>= 0)
4640 STps
->drv_block
= 0;
4646 if (STp
->rew_at_close
) {
4647 result2
= osst_position_tape_and_confirm(STp
, &SRpnt
, STp
->first_data_ppos
);
4648 STps
->drv_file
= STps
->drv_block
= STp
->frame_seq_number
= STp
->logical_blk_num
= 0;
4649 if (result
== 0 && result2
< 0)
4652 if (SRpnt
) scsi_release_request(SRpnt
);
4654 if (STp
->recover_count
) {
4655 printk(KERN_INFO
"%s:I: %d recovered errors in", name
, STp
->recover_count
);
4656 if (STp
->write_count
)
4657 printk(" %d frames written", STp
->write_count
);
4658 if (STp
->read_count
)
4659 printk(" %d frames read", STp
->read_count
);
4661 STp
->recover_count
= 0;
4663 STp
->write_count
= 0;
4664 STp
->read_count
= 0;
4670 /* Close the device and release it */
4671 static int os_scsi_tape_close(struct inode
* inode
, struct file
* filp
)
4674 OS_Scsi_Tape
* STp
= filp
->private_data
;
4675 Scsi_Request
* SRpnt
= NULL
;
4677 if (SRpnt
) scsi_release_request(SRpnt
);
4679 if (STp
->door_locked
== ST_LOCKED_AUTO
)
4680 do_door_lock(STp
, 0);
4685 normalize_buffer(STp
->buffer
);
4686 write_lock(&os_scsi_tapes_lock
);
4688 write_unlock(&os_scsi_tapes_lock
);
4690 scsi_device_put(STp
->device
);
4696 /* The ioctl command */
4697 static int osst_ioctl(struct inode
* inode
,struct file
* file
,
4698 unsigned int cmd_in
, unsigned long arg
)
4700 int i
, cmd_nr
, cmd_type
, retval
= 0;
4704 Scsi_Request
* SRpnt
= NULL
;
4705 OS_Scsi_Tape
* STp
= file
->private_data
;
4706 char * name
= tape_name(STp
);
4708 if (down_interruptible(&STp
->lock
))
4709 return -ERESTARTSYS
;
4712 if (debugging
&& !STp
->in_use
) {
4713 printk(OSST_DEB_MSG
"%s:D: Incorrect device.\n", name
);
4718 STm
= &(STp
->modes
[STp
->current_mode
]);
4719 STps
= &(STp
->ps
[STp
->partition
]);
4722 * If we are in the middle of error recovery, don't let anyone
4723 * else try and use this device. Also, if error recovery fails, it
4724 * may try and take the device offline, in which case all further
4725 * access to the device is prohibited.
4727 if( !scsi_block_when_processing_errors(STp
->device
) ) {
4732 cmd_type
= _IOC_TYPE(cmd_in
);
4733 cmd_nr
= _IOC_NR(cmd_in
);
4735 printk(OSST_DEB_MSG
"%s:D: Ioctl %d,%d in %s mode\n", name
,
4736 cmd_type
, cmd_nr
, STp
->raw
?"raw":"normal");
4738 if (cmd_type
== _IOC_TYPE(MTIOCTOP
) && cmd_nr
== _IOC_NR(MTIOCTOP
)) {
4741 if (_IOC_SIZE(cmd_in
) != sizeof(mtc
)) {
4746 i
= copy_from_user((char *) &mtc
, (char *)arg
, sizeof(struct mtop
));
4752 if (mtc
.mt_op
== MTSETDRVBUFFER
&& !capable(CAP_SYS_ADMIN
)) {
4753 printk(KERN_WARNING
"%s:W: MTSETDRVBUFFER only allowed for root.\n", name
);
4758 if (!STm
->defined
&& (mtc
.mt_op
!= MTSETDRVBUFFER
&& (mtc
.mt_count
& MT_ST_OPTIONS
) == 0)) {
4763 if (!STp
->pos_unknown
) {
4765 if (STps
->eof
== ST_FM_HIT
) {
4766 if (mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
|| mtc
.mt_op
== MTEOM
) {
4768 if (STps
->drv_file
>= 0)
4769 STps
->drv_file
+= 1;
4771 else if (mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
) {
4773 if (STps
->drv_file
>= 0)
4774 STps
->drv_file
+= 1;
4778 if (mtc
.mt_op
== MTSEEK
) {
4779 /* Old position must be restored if partition will be changed */
4780 i
= !STp
->can_partitions
|| (STp
->new_partition
!= STp
->partition
);
4783 i
= mtc
.mt_op
== MTREW
|| mtc
.mt_op
== MTOFFL
||
4784 mtc
.mt_op
== MTRETEN
|| mtc
.mt_op
== MTEOM
||
4785 mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTLOAD
||
4786 mtc
.mt_op
== MTFSF
|| mtc
.mt_op
== MTFSFM
||
4787 mtc
.mt_op
== MTBSF
|| mtc
.mt_op
== MTBSFM
||
4788 mtc
.mt_op
== MTCOMPRESSION
;
4790 i
= osst_flush_buffer(STp
, &SRpnt
, i
);
4798 * If there was a bus reset, block further access
4799 * to this device. If the user wants to rewind the tape,
4800 * then reset the flag and allow access again.
4802 if(mtc
.mt_op
!= MTREW
&&
4803 mtc
.mt_op
!= MTOFFL
&&
4804 mtc
.mt_op
!= MTRETEN
&&
4805 mtc
.mt_op
!= MTERASE
&&
4806 mtc
.mt_op
!= MTSEEK
&&
4807 mtc
.mt_op
!= MTEOM
) {
4812 /* remove this when the midlevel properly clears was_reset */
4813 STp
->device
->was_reset
= 0;
4816 if (mtc
.mt_op
!= MTNOP
&& mtc
.mt_op
!= MTWEOF
&& mtc
.mt_op
!= MTWSM
&&
4817 mtc
.mt_op
!= MTSETDENSITY
&& mtc
.mt_op
!= MTSETBLK
&&
4818 mtc
.mt_op
!= MTSETDRVBUFFER
&& mtc
.mt_op
!= MTSETPART
)
4819 STps
->rw
= ST_IDLE
; /* Prevent automatic WEOF and fsf */
4821 if (mtc
.mt_op
== MTOFFL
&& STp
->door_locked
!= ST_UNLOCKED
)
4822 do_door_lock(STp
, 0); /* Ignore result! */
4824 if (mtc
.mt_op
== MTSETDRVBUFFER
&&
4825 (mtc
.mt_count
& MT_ST_OPTIONS
) != 0) {
4826 retval
= osst_set_options(STp
, mtc
.mt_count
);
4830 if (mtc
.mt_op
== MTSETPART
) {
4831 if (mtc
.mt_count
>= STp
->nbr_partitions
)
4834 STp
->new_partition
= mtc
.mt_count
;
4840 if (mtc
.mt_op
== MTMKPART
) {
4841 if (!STp
->can_partitions
) {
4845 if ((i
= osst_int_ioctl(STp
, &SRpnt
, MTREW
, 0)) < 0 /*||
4846 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
4850 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
4851 STp
->ps
[i
].rw
= ST_IDLE
;
4852 STp
->ps
[i
].at_sm
= 0;
4853 STp
->ps
[i
].last_block_valid
= FALSE
;
4855 STp
->partition
= STp
->new_partition
= 0;
4856 STp
->nbr_partitions
= 1; /* Bad guess ?-) */
4857 STps
->drv_block
= STps
->drv_file
= 0;
4862 if (mtc
.mt_op
== MTSEEK
) {
4864 i
= osst_set_frame_position(STp
, &SRpnt
, mtc
.mt_count
, 0);
4866 i
= osst_seek_sector(STp
, &SRpnt
, mtc
.mt_count
);
4867 if (!STp
->can_partitions
)
4868 STp
->ps
[0].rw
= ST_IDLE
;
4873 if (mtc
.mt_op
== MTLOCK
|| mtc
.mt_op
== MTUNLOCK
) {
4874 retval
= do_door_lock(STp
, (mtc
.mt_op
== MTLOCK
));
4878 if (mtc
.mt_op
== MTCOMPRESSION
)
4879 retval
= -EINVAL
/*osst_compression(STp, (mtc.mt_count & 1))*/;
4882 retval
= osst_int_ioctl(STp
, &SRpnt
, mtc
.mt_op
, mtc
.mt_count
);
4886 if (!STm
->defined
) {
4891 if ((i
= osst_flush_buffer(STp
, &SRpnt
, FALSE
)) < 0) {
4896 if (cmd_type
== _IOC_TYPE(MTIOCGET
) && cmd_nr
== _IOC_NR(MTIOCGET
)) {
4897 struct mtget mt_status
;
4899 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtget
)) {
4904 mt_status
.mt_type
= MT_ISONSTREAM_SC
;
4905 mt_status
.mt_erreg
= STp
->recover_erreg
<< MT_ST_SOFTERR_SHIFT
;
4906 mt_status
.mt_dsreg
=
4907 ((STp
->block_size
<< MT_ST_BLKSIZE_SHIFT
) & MT_ST_BLKSIZE_MASK
) |
4908 ((STp
->density
<< MT_ST_DENSITY_SHIFT
) & MT_ST_DENSITY_MASK
);
4909 mt_status
.mt_blkno
= STps
->drv_block
;
4910 mt_status
.mt_fileno
= STps
->drv_file
;
4911 if (STp
->block_size
!= 0) {
4912 if (STps
->rw
== ST_WRITING
)
4913 mt_status
.mt_blkno
+= (STp
->buffer
)->buffer_bytes
/ STp
->block_size
;
4914 else if (STps
->rw
== ST_READING
)
4915 mt_status
.mt_blkno
-= ((STp
->buffer
)->buffer_bytes
+
4916 STp
->block_size
- 1) / STp
->block_size
;
4919 mt_status
.mt_gstat
= 0;
4920 if (STp
->drv_write_prot
)
4921 mt_status
.mt_gstat
|= GMT_WR_PROT(0xffffffff);
4922 if (mt_status
.mt_blkno
== 0) {
4923 if (mt_status
.mt_fileno
== 0)
4924 mt_status
.mt_gstat
|= GMT_BOT(0xffffffff);
4926 mt_status
.mt_gstat
|= GMT_EOF(0xffffffff);
4928 mt_status
.mt_resid
= STp
->partition
;
4929 if (STps
->eof
== ST_EOM_OK
|| STps
->eof
== ST_EOM_ERROR
)
4930 mt_status
.mt_gstat
|= GMT_EOT(0xffffffff);
4931 else if (STps
->eof
>= ST_EOM_OK
)
4932 mt_status
.mt_gstat
|= GMT_EOD(0xffffffff);
4933 if (STp
->density
== 1)
4934 mt_status
.mt_gstat
|= GMT_D_800(0xffffffff);
4935 else if (STp
->density
== 2)
4936 mt_status
.mt_gstat
|= GMT_D_1600(0xffffffff);
4937 else if (STp
->density
== 3)
4938 mt_status
.mt_gstat
|= GMT_D_6250(0xffffffff);
4939 if (STp
->ready
== ST_READY
)
4940 mt_status
.mt_gstat
|= GMT_ONLINE(0xffffffff);
4941 if (STp
->ready
== ST_NO_TAPE
)
4942 mt_status
.mt_gstat
|= GMT_DR_OPEN(0xffffffff);
4944 mt_status
.mt_gstat
|= GMT_SM(0xffffffff);
4945 if (STm
->do_async_writes
|| (STm
->do_buffer_writes
&& STp
->block_size
!= 0) ||
4946 STp
->drv_buffer
!= 0)
4947 mt_status
.mt_gstat
|= GMT_IM_REP_EN(0xffffffff);
4949 i
= copy_to_user((char *)arg
, (char *)&mt_status
,
4950 sizeof(struct mtget
));
4956 STp
->recover_erreg
= 0; /* Clear after read */
4959 } /* End of MTIOCGET */
4961 if (cmd_type
== _IOC_TYPE(MTIOCPOS
) && cmd_nr
== _IOC_NR(MTIOCPOS
)) {
4962 struct mtpos mt_pos
;
4964 if (_IOC_SIZE(cmd_in
) != sizeof(struct mtpos
)) {
4969 blk
= osst_get_frame_position(STp
, &SRpnt
);
4971 blk
= osst_get_sector(STp
, &SRpnt
);
4976 mt_pos
.mt_blkno
= blk
;
4977 i
= copy_to_user((char *)arg
, (char *) (&mt_pos
), sizeof(struct mtpos
));
4982 if (SRpnt
) scsi_release_request(SRpnt
);
4986 return scsi_ioctl(STp
->device
, cmd_in
, (void *) arg
);
4989 if (SRpnt
) scsi_release_request(SRpnt
);
4997 /* Memory handling routines */
4999 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5000 static OSST_buffer
* new_tape_buffer( int from_initialization
, int need_dma
, int max_sg
)
5005 if (from_initialization
)
5006 priority
= GFP_ATOMIC
;
5008 priority
= GFP_KERNEL
;
5010 i
= sizeof(OSST_buffer
) + (osst_max_sg_segs
- 1) * sizeof(struct scatterlist
);
5011 tb
= (OSST_buffer
*)kmalloc(i
, priority
);
5013 printk(KERN_NOTICE
"osst :I: Can't allocate new tape buffer.\n");
5017 tb
->sg_segs
= tb
->orig_sg_segs
= 0;
5018 tb
->use_sg
= max_sg
;
5021 tb
->buffer_size
= 0;
5025 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5026 i
, max_sg
, need_dma
);
5031 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5032 static int enlarge_buffer(OSST_buffer
*STbuffer
, int need_dma
)
5034 int segs
, nbr
, max_segs
, b_size
, priority
, order
, got
;
5036 if (STbuffer
->buffer_size
>= OS_FRAME_SIZE
)
5039 if (STbuffer
->sg_segs
) {
5040 printk(KERN_WARNING
"osst :A: Buffer not previously normalized.\n");
5041 normalize_buffer(STbuffer
);
5043 /* See how many segments we can use -- need at least two */
5044 nbr
= max_segs
= STbuffer
->use_sg
;
5048 priority
= GFP_KERNEL
;
5050 priority
|= GFP_DMA
;
5052 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5053 big enough to reach the goal (code assumes no segments in place) */
5054 for (b_size
= OS_DATA_SIZE
, order
= OSST_FIRST_ORDER
; b_size
>= PAGE_SIZE
; order
--, b_size
/= 2) {
5055 STbuffer
->sg
[0].page
= alloc_pages(priority
, order
);
5056 STbuffer
->sg
[0].offset
= 0;
5057 if (STbuffer
->sg
[0].page
!= NULL
) {
5058 STbuffer
->sg
[0].length
= b_size
;
5059 STbuffer
->b_data
= page_address(STbuffer
->sg
[0].page
);
5063 if (STbuffer
->sg
[0].page
== NULL
) {
5064 printk(KERN_NOTICE
"osst :I: Can't allocate tape buffer main segment.\n");
5067 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5068 for (segs
=STbuffer
->sg_segs
=1, got
=b_size
;
5069 segs
< max_segs
&& got
< OS_FRAME_SIZE
; ) {
5070 STbuffer
->sg
[segs
].page
=
5071 alloc_pages(priority
, (OS_FRAME_SIZE
- got
<= PAGE_SIZE
) ? 0 : order
);
5072 STbuffer
->sg
[segs
].offset
= 0;
5073 if (STbuffer
->sg
[segs
].page
== NULL
) {
5074 if (OS_FRAME_SIZE
- got
<= (max_segs
- segs
) * b_size
/ 2 && order
) {
5075 b_size
/= 2; /* Large enough for the rest of the buffers */
5079 printk(KERN_WARNING
"osst :W: Failed to enlarge buffer to %d bytes.\n",
5082 STbuffer
->buffer_size
= got
;
5084 normalize_buffer(STbuffer
);
5087 STbuffer
->sg
[segs
].length
= (OS_FRAME_SIZE
- got
<= PAGE_SIZE
/ 2) ? (OS_FRAME_SIZE
- got
) : b_size
;
5088 got
+= STbuffer
->sg
[segs
].length
;
5089 STbuffer
->buffer_size
= got
;
5090 STbuffer
->sg_segs
= ++segs
;
5095 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5096 got
, STbuffer
->orig_sg_segs
, STbuffer
->sg_segs
, need_dma
, STbuffer
->b_data
);
5098 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5099 STbuffer
->sg
[0].length
, page_address(STbuffer
->sg
[0].page
),
5100 STbuffer
->sg
[segs
-1].length
, page_address(STbuffer
->sg
[segs
-1].page
));
5108 /* Release the segments */
5109 static void normalize_buffer(OSST_buffer
*STbuffer
)
5111 int i
, order
, b_size
;
5113 for (i
=0; i
< STbuffer
->sg_segs
; i
++) {
5115 for (b_size
= PAGE_SIZE
, order
= 0;
5116 b_size
< STbuffer
->sg
[i
].length
;
5117 b_size
*= 2, order
++);
5119 __free_pages(STbuffer
->sg
[i
].page
, order
);
5120 STbuffer
->buffer_size
-= STbuffer
->sg
[i
].length
;
5123 if (debugging
&& STbuffer
->orig_sg_segs
< STbuffer
->sg_segs
)
5124 printk(OSST_DEB_MSG
"osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5125 STbuffer
->b_data
, STbuffer
->buffer_size
, STbuffer
->sg_segs
);
5127 STbuffer
->sg_segs
= STbuffer
->orig_sg_segs
= 0;
5131 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5132 negative error code. */
5133 static int append_to_buffer(const char *ubp
, OSST_buffer
*st_bp
, int do_count
)
5135 int i
, cnt
, res
, offset
;
5137 for (i
=0, offset
=st_bp
->buffer_bytes
;
5138 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5139 offset
-= st_bp
->sg
[i
].length
;
5140 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5141 printk(KERN_WARNING
"osst :A: Append_to_buffer offset overflow.\n");
5144 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5145 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5146 st_bp
->sg
[i
].length
- offset
: do_count
;
5147 res
= copy_from_user(page_address(st_bp
->sg
[i
].page
) + offset
, ubp
, cnt
);
5151 st_bp
->buffer_bytes
+= cnt
;
5155 if (do_count
) { /* Should never happen */
5156 printk(KERN_WARNING
"osst :A: Append_to_buffer overflow (left %d).\n",
5164 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5165 negative error code. */
5166 static int from_buffer(OSST_buffer
*st_bp
, char *ubp
, int do_count
)
5168 int i
, cnt
, res
, offset
;
5170 for (i
=0, offset
=st_bp
->read_pointer
;
5171 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5172 offset
-= st_bp
->sg
[i
].length
;
5173 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5174 printk(KERN_WARNING
"osst :A: From_buffer offset overflow.\n");
5177 for ( ; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5178 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5179 st_bp
->sg
[i
].length
- offset
: do_count
;
5180 res
= copy_to_user(ubp
, page_address(st_bp
->sg
[i
].page
) + offset
, cnt
);
5184 st_bp
->buffer_bytes
-= cnt
;
5185 st_bp
->read_pointer
+= cnt
;
5189 if (do_count
) { /* Should never happen */
5190 printk(KERN_WARNING
"osst :A: From_buffer overflow (left %d).\n", do_count
);
5196 /* Sets the tail of the buffer after fill point to zero.
5197 Returns zero (success) or negative error code. */
5198 static int osst_zero_buffer_tail(OSST_buffer
*st_bp
)
5200 int i
, offset
, do_count
, cnt
;
5202 for (i
= 0, offset
= st_bp
->buffer_bytes
;
5203 i
< st_bp
->sg_segs
&& offset
>= st_bp
->sg
[i
].length
; i
++)
5204 offset
-= st_bp
->sg
[i
].length
;
5205 if (i
== st_bp
->sg_segs
) { /* Should never happen */
5206 printk(KERN_WARNING
"osst :A: Zero_buffer offset overflow.\n");
5209 for (do_count
= OS_DATA_SIZE
- st_bp
->buffer_bytes
;
5210 i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5211 cnt
= st_bp
->sg
[i
].length
- offset
< do_count
?
5212 st_bp
->sg
[i
].length
- offset
: do_count
;
5213 memset(page_address(st_bp
->sg
[i
].page
) + offset
, 0, cnt
);
5217 if (do_count
) { /* Should never happen */
5218 printk(KERN_WARNING
"osst :A: Zero_buffer overflow (left %d).\n", do_count
);
5224 /* Copy a osst 32K chunk of memory into the buffer.
5225 Returns zero (success) or negative error code. */
5226 static int osst_copy_to_buffer(OSST_buffer
*st_bp
, unsigned char *ptr
)
5228 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5230 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5231 cnt
= st_bp
->sg
[i
].length
< do_count
?
5232 st_bp
->sg
[i
].length
: do_count
;
5233 memcpy(page_address(st_bp
->sg
[i
].page
), ptr
, cnt
);
5237 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5238 printk(KERN_WARNING
"osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5245 /* Copy a osst 32K chunk of memory from the buffer.
5246 Returns zero (success) or negative error code. */
5247 static int osst_copy_from_buffer(OSST_buffer
*st_bp
, unsigned char *ptr
)
5249 int i
, cnt
, do_count
= OS_DATA_SIZE
;
5251 for (i
= 0; i
< st_bp
->sg_segs
&& do_count
> 0; i
++) {
5252 cnt
= st_bp
->sg
[i
].length
< do_count
?
5253 st_bp
->sg
[i
].length
: do_count
;
5254 memcpy(ptr
, page_address(st_bp
->sg
[i
].page
), cnt
);
5258 if (do_count
|| i
!= st_bp
->sg_segs
-1) { /* Should never happen */
5259 printk(KERN_WARNING
"osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5267 /* Module housekeeping */
5269 static void validate_options (void)
5272 osst_max_dev
= max_dev
;
5273 if (write_threshold_kbs
> 0)
5274 osst_write_threshold
= write_threshold_kbs
* ST_KILOBYTE
;
5275 if (osst_write_threshold
> osst_buffer_size
)
5276 osst_write_threshold
= osst_buffer_size
;
5277 if (max_sg_segs
>= OSST_FIRST_SG
)
5278 osst_max_sg_segs
= max_sg_segs
;
5280 printk(OSST_DEB_MSG
"osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5281 osst_max_dev
, osst_write_threshold
, osst_max_sg_segs
);
5286 /* Set the boot options. Syntax: osst=xxx,yyy,...
5287 where xxx is write threshold in 1024 byte blocks,
5288 and yyy is number of s/g segments to use. */
5289 static int __init
osst_setup (char *str
)
5294 stp
= get_options(str
, ARRAY_SIZE(ints
), ints
);
5297 for (i
= 0; i
< ints
[0] && i
< ARRAY_SIZE(parms
); i
++)
5298 *parms
[i
].val
= ints
[i
+ 1];
5300 while (stp
!= NULL
) {
5301 for (i
= 0; i
< ARRAY_SIZE(parms
); i
++) {
5302 int len
= strlen(parms
[i
].name
);
5303 if (!strncmp(stp
, parms
[i
].name
, len
) &&
5304 (*(stp
+ len
) == ':' || *(stp
+ len
) == '=')) {
5306 simple_strtoul(stp
+ len
+ 1, NULL
, 0);
5310 if (i
>= sizeof(parms
) / sizeof(struct osst_dev_parm
))
5311 printk(KERN_INFO
"osst :I: Illegal parameter in '%s'\n",
5313 stp
= strchr(stp
, ',');
5322 __setup("osst=", osst_setup
);
5326 static struct file_operations osst_fops
= {
5327 .owner
= THIS_MODULE
,
5329 .write
= osst_write
,
5330 .ioctl
= osst_ioctl
,
5331 .open
= os_scsi_tape_open
,
5332 .flush
= os_scsi_tape_flush
,
5333 .release
= os_scsi_tape_close
,
5336 static int osst_supports(Scsi_Device
* SDp
)
5338 struct osst_support_data
{
5342 char *driver_hint
; /* Name of the correct driver, NULL if unknown */
5345 static struct osst_support_data support_list
[] = {
5346 /* {"XXX", "Yy-", "", NULL}, example */
5350 struct osst_support_data
*rp
;
5352 /* We are willing to drive OnStream SC-x0 as well as the
5353 * * IDE, ParPort, FireWire, USB variants, if accessible by
5354 * * emulation layer (ide-scsi, usb-storage, ...) */
5356 for (rp
=&(support_list
[0]); rp
->vendor
!= NULL
; rp
++)
5357 if (!strncmp(rp
->vendor
, SDp
->vendor
, strlen(rp
->vendor
)) &&
5358 !strncmp(rp
->model
, SDp
->model
, strlen(rp
->model
)) &&
5359 !strncmp(rp
->rev
, SDp
->rev
, strlen(rp
->rev
)))
5365 * osst startup / cleanup code
5368 static int osst_probe(struct device
*dev
)
5370 Scsi_Device
* SDp
= to_scsi_device(dev
);
5371 OS_Scsi_Tape
* tpnt
;
5374 OSST_buffer
* buffer
;
5375 struct gendisk
* drive
;
5376 int i
, mode
, dev_num
;
5378 if (SDp
->type
!= TYPE_TAPE
|| !osst_supports(SDp
))
5381 drive
= alloc_disk(1);
5383 printk(KERN_ERR
"osst :E: Out of memory. Device not attached.\n");
5387 /* if this is the first attach, build the infrastructure */
5388 write_lock(&os_scsi_tapes_lock
);
5389 if (os_scsi_tapes
== NULL
) {
5391 (OS_Scsi_Tape
**)kmalloc(osst_max_dev
* sizeof(OS_Scsi_Tape
*),
5393 if (os_scsi_tapes
== NULL
) {
5394 write_unlock(&os_scsi_tapes_lock
);
5395 printk(KERN_ERR
"osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5398 for (i
=0; i
< osst_max_dev
; ++i
) os_scsi_tapes
[i
] = NULL
;
5401 if (osst_nr_dev
>= osst_max_dev
) {
5402 write_unlock(&os_scsi_tapes_lock
);
5403 printk(KERN_ERR
"osst :E: Too many tape devices (max. %d).\n", osst_max_dev
);
5407 /* find a free minor number */
5408 for (i
=0; os_scsi_tapes
[i
] && i
<osst_max_dev
; i
++);
5409 if(i
>= osst_max_dev
) panic ("Scsi_devices corrupt (osst)");
5412 /* allocate a OS_Scsi_Tape for this device */
5413 tpnt
= (OS_Scsi_Tape
*)kmalloc(sizeof(OS_Scsi_Tape
), GFP_ATOMIC
);
5415 write_unlock(&os_scsi_tapes_lock
);
5416 printk(KERN_ERR
"osst :E: Can't allocate device descriptor, device not attached.\n");
5419 memset(tpnt
, 0, sizeof(OS_Scsi_Tape
));
5421 /* allocate a buffer for this device */
5422 i
= SDp
->host
->sg_tablesize
;
5423 if (osst_max_sg_segs
< i
)
5424 i
= osst_max_sg_segs
;
5425 buffer
= new_tape_buffer(TRUE
, SDp
->host
->unchecked_isa_dma
, i
);
5426 if (buffer
== NULL
) {
5427 write_unlock(&os_scsi_tapes_lock
);
5428 printk(KERN_ERR
"osst :E: Unable to allocate a tape buffer, device not attached.\n");
5432 os_scsi_tapes
[dev_num
] = tpnt
;
5433 tpnt
->buffer
= buffer
;
5435 drive
->private_data
= &tpnt
->driver
;
5436 sprintf(drive
->disk_name
, "osst%d", dev_num
);
5437 tpnt
->driver
= &osst_template
;
5438 tpnt
->drive
= drive
;
5440 tpnt
->capacity
= 0xfffff;
5442 tpnt
->drv_buffer
= 1; /* Try buffering if no mode sense */
5443 tpnt
->restr_dma
= (SDp
->host
)->unchecked_isa_dma
;
5445 tpnt
->do_auto_lock
= OSST_AUTO_LOCK
;
5446 tpnt
->can_bsr
= OSST_IN_FILE_POS
;
5447 tpnt
->can_partitions
= 0;
5448 tpnt
->two_fm
= OSST_TWO_FM
;
5449 tpnt
->fast_mteom
= OSST_FAST_MTEOM
;
5450 tpnt
->scsi2_logical
= OSST_SCSI2LOGICAL
; /* FIXME */
5451 tpnt
->write_threshold
= osst_write_threshold
;
5452 tpnt
->default_drvbuffer
= 0xff; /* No forced buffering */
5453 tpnt
->partition
= 0;
5454 tpnt
->new_partition
= 0;
5455 tpnt
->nbr_partitions
= 0;
5456 tpnt
->min_block
= 512;
5457 tpnt
->max_block
= OS_DATA_SIZE
;
5458 tpnt
->timeout
= OSST_TIMEOUT
;
5459 tpnt
->long_timeout
= OSST_LONG_TIMEOUT
;
5461 /* Recognize OnStream tapes */
5462 /* We don't need to test for OnStream, as this has been done in detect () */
5463 tpnt
->os_fw_rev
= osst_parse_firmware_rev (SDp
->rev
);
5464 tpnt
->omit_blklims
= 1;
5466 tpnt
->poll
= (strncmp(SDp
->model
, "DI-", 3) == 0) ||
5467 (strncmp(SDp
->model
, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt
->os_fw_rev
,SDp
);
5468 tpnt
->frame_in_buffer
= 0;
5469 tpnt
->header_ok
= 0;
5470 tpnt
->linux_media
= 0;
5471 tpnt
->header_cache
= NULL
;
5473 for (i
=0; i
< ST_NBR_MODES
; i
++) {
5474 STm
= &(tpnt
->modes
[i
]);
5475 STm
->defined
= FALSE
;
5476 STm
->sysv
= OSST_SYSV
;
5477 STm
->defaults_for_writes
= 0;
5478 STm
->do_async_writes
= OSST_ASYNC_WRITES
;
5479 STm
->do_buffer_writes
= OSST_BUFFER_WRITES
;
5480 STm
->do_read_ahead
= OSST_READ_AHEAD
;
5481 STm
->default_compression
= ST_DONT_TOUCH
;
5482 STm
->default_blksize
= 512;
5483 STm
->default_density
= (-1); /* No forced density */
5486 for (i
=0; i
< ST_NBR_PARTITIONS
; i
++) {
5487 STps
= &(tpnt
->ps
[i
]);
5489 STps
->eof
= ST_NOEOF
;
5491 STps
->last_block_valid
= FALSE
;
5492 STps
->drv_block
= (-1);
5493 STps
->drv_file
= (-1);
5496 tpnt
->current_mode
= 0;
5497 tpnt
->modes
[0].defined
= TRUE
;
5498 tpnt
->modes
[2].defined
= TRUE
;
5499 tpnt
->density_changed
= tpnt
->compression_changed
= tpnt
->blksize_changed
= FALSE
;
5501 init_MUTEX(&tpnt
->lock
);
5503 write_unlock(&os_scsi_tapes_lock
);
5505 for (mode
= 0; mode
< ST_NBR_MODES
; ++mode
) {
5507 devfs_mk_cdev(MKDEV(OSST_MAJOR
, dev_num
+ (mode
<< 5)),
5508 S_IFCHR
| S_IRUGO
| S_IWUGO
,
5509 "%s/ot%s", SDp
->devfs_name
, osst_formats
[mode
]);
5511 /* No-rewind entry */
5512 devfs_mk_cdev(MKDEV(OSST_MAJOR
, dev_num
+ (mode
<< 5) + 128),
5513 S_IFCHR
| S_IRUGO
| S_IWUGO
,
5514 "%s/ot%sn", SDp
->devfs_name
, osst_formats
[mode
]);
5516 drive
->number
= devfs_register_tape(SDp
->devfs_name
);
5519 "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n",
5520 SDp
->model
, SDp
->host
->host_no
, SDp
->channel
, SDp
->id
, SDp
->lun
, tape_name(tpnt
));
5529 static int osst_remove(struct device
*dev
)
5531 Scsi_Device
* SDp
= to_scsi_device(dev
);
5532 OS_Scsi_Tape
* tpnt
;
5535 if ((SDp
->type
!= TYPE_TAPE
) || (osst_nr_dev
<= 0))
5538 write_lock(&os_scsi_tapes_lock
);
5539 for(i
=0; i
< osst_max_dev
; i
++) {
5540 if((tpnt
= os_scsi_tapes
[i
]) && (tpnt
->device
== SDp
)) {
5541 tpnt
->device
= NULL
;
5542 for (mode
= 0; mode
< ST_NBR_MODES
; ++mode
) {
5543 devfs_remove("%s/ot%s", SDp
->devfs_name
, osst_formats
[mode
]);
5544 devfs_remove("%s/ot%sn", SDp
->devfs_name
, osst_formats
[mode
]);
5546 devfs_unregister_tape(tpnt
->drive
->number
);
5547 put_disk(tpnt
->drive
);
5548 os_scsi_tapes
[i
] = NULL
;
5550 write_unlock(&os_scsi_tapes_lock
);
5551 if (tpnt
->header_cache
!= NULL
) vfree(tpnt
->header_cache
);
5553 normalize_buffer(tpnt
->buffer
);
5554 kfree(tpnt
->buffer
);
5560 write_unlock(&os_scsi_tapes_lock
);
5564 static int __init
init_osst(void)
5566 printk(KERN_INFO
"osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version
, cvsid
);
5570 if ((register_chrdev(OSST_MAJOR
,"osst", &osst_fops
) < 0) || scsi_register_driver(&osst_template
.gendrv
)) {
5571 printk(KERN_ERR
"osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR
);
5578 static void __exit
exit_osst (void)
5583 scsi_unregister_driver(&osst_template
.gendrv
);
5584 unregister_chrdev(OSST_MAJOR
, "osst");
5586 if (os_scsi_tapes
) {
5587 for (i
=0; i
< osst_max_dev
; ++i
) {
5588 if (!(STp
= os_scsi_tapes
[i
])) continue;
5589 /* This is defensive, supposed to happen during detach */
5590 if (STp
->header_cache
)
5591 vfree(STp
->header_cache
);
5593 normalize_buffer(STp
->buffer
);
5596 put_disk(STp
->drive
);
5599 kfree(os_scsi_tapes
);
5601 printk(KERN_INFO
"osst :I: Unloaded.\n");
5604 module_init(init_osst
);
5605 module_exit(exit_osst
);