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: /cvsroot/osst/Driver/osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid = "$Id: osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $";
27 const char * osst_version = "0.99.1";
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/blkdev.h>
49 #include <linux/devfs_fs_kernel.h>
50 #include <asm/uaccess.h>
52 #include <asm/system.h>
54 /* The driver prints some debugging information on the console if DEBUG
55 is defined and non-zero. */
58 /* The message level for the debug messages is currently set to KERN_NOTICE
59 so that people can easily see the messages. Later when the debugging messages
60 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
61 #define OSST_DEB_MSG KERN_NOTICE
64 #include <scsi/scsi_host.h>
65 #include <scsi/scsi_driver.h>
66 #include <scsi/scsi_ioctl.h>
68 #define ST_KILOBYTE 1024
72 #include "osst_options.h"
73 #include "osst_detect.h"
75 static int max_dev = 0;
76 static int write_threshold_kbs = 0;
77 static int max_sg_segs = 0;
80 MODULE_AUTHOR("Willem Riede");
81 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
82 MODULE_LICENSE("GPL");
84 MODULE_PARM(max_dev, "i");
85 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
87 MODULE_PARM(write_threshold_kbs, "i");
88 MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
90 MODULE_PARM(max_sg_segs, "i");
91 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
93 static struct osst_dev_parm {
96 } parms[] __initdata = {
97 { "max_dev", &max_dev },
98 { "write_threshold_kbs", &write_threshold_kbs },
99 { "max_sg_segs", &max_sg_segs }
103 static char *osst_formats[ST_NBR_MODES] ={"", "l", "m", "a"};
105 /* Some default definitions have been moved to osst_options.h */
106 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
107 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
109 /* The buffer size should fit into the 24 bits for length in the
110 6-byte SCSI read and write commands. */
111 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
112 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
116 static int debugging = 1;
117 /* uncomment define below to test error recovery */
118 // #define OSST_INJECT_ERRORS 1
121 #define MAX_RETRIES 2
122 #define MAX_READ_RETRIES 0
123 #define MAX_WRITE_RETRIES 0
124 #define MAX_READY_RETRIES 0
125 #define NO_TAPE NOT_READY
127 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
128 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
129 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
131 #define OSST_TIMEOUT (200 * HZ)
132 #define OSST_LONG_TIMEOUT (1800 * HZ)
134 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
135 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
136 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
137 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
139 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
141 #define SET_DENS_AND_BLK 0x10001
143 static int osst_buffer_size = OSST_BUFFER_SIZE;
144 static int osst_write_threshold = OSST_WRITE_THRESHOLD;
145 static int osst_max_sg_segs = OSST_MAX_SG;
146 static int osst_max_dev = OSST_MAX_TAPES;
147 static int osst_nr_dev;
149 static OS_Scsi_Tape **os_scsi_tapes = NULL;
150 static rwlock_t os_scsi_tapes_lock = RW_LOCK_UNLOCKED;
152 static int modes_defined = FALSE;
154 static OSST_buffer *new_tape_buffer(int, int, int);
155 static int enlarge_buffer(OSST_buffer *, int);
156 static void normalize_buffer(OSST_buffer *);
157 static int append_to_buffer(const char __user *, OSST_buffer *, int);
158 static int from_buffer(OSST_buffer *, char __user *, int);
159 static int osst_zero_buffer_tail(OSST_buffer *);
160 static int osst_copy_to_buffer(OSST_buffer *, unsigned char *);
161 static int osst_copy_from_buffer(OSST_buffer *, unsigned char *);
163 static int osst_probe(struct device *);
164 static int osst_remove(struct device *);
166 struct scsi_driver osst_template = {
167 .owner = THIS_MODULE,
171 .remove = osst_remove,
175 static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
177 static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int frame, int skip);
179 static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
181 static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
183 static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending);
185 static inline char *tape_name(OS_Scsi_Tape *tape)
187 return tape->drive->disk_name;
190 /* Routines that handle the interaction with mid-layer SCSI routines */
192 /* Convert the result to success code */
193 static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
195 char *name = tape_name(STp);
196 int result = SRpnt->sr_result;
197 unsigned char * sense = SRpnt->sr_sense_buffer, scode;
203 sense[0] = 0; /* We don't have sense data if this byte is zero */
206 if ((driver_byte(result) & DRIVER_MASK) == DRIVER_SENSE)
207 scode = sense[2] & 0x0f;
209 sense[0] = 0; /* We don't have sense data if this byte is zero */
214 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
216 SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
217 SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
219 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
220 name, scode, sense[12], sense[13]);
221 if (driver_byte(result) & DRIVER_SENSE)
222 print_req_sense("osst ", SRpnt);
226 if (!(driver_byte(result) & DRIVER_SENSE) ||
227 ((sense[0] & 0x70) == 0x70 &&
229 scode != RECOVERED_ERROR &&
230 /* scode != UNIT_ATTENTION && */
231 scode != BLANK_CHECK &&
232 scode != VOLUME_OVERFLOW &&
233 SRpnt->sr_cmnd[0] != MODE_SENSE &&
234 SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
235 if (driver_byte(result) & DRIVER_SENSE) {
236 printk(KERN_WARNING "%s:W: Command with sense data: ", name);
237 print_req_sense("osst:", SRpnt);
240 static int notyetprinted = 1;
243 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
244 name, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
249 "%s:I: This warning may be caused by your scsi controller,\n", name);
251 "%s:I: it has been reported with some Buslogic cards.\n", name);
255 STp->pos_unknown |= STp->device->was_reset;
257 if ((sense[0] & 0x70) == 0x70 &&
258 scode == RECOVERED_ERROR) {
259 STp->recover_count++;
260 STp->recover_erreg++;
263 if (SRpnt->sr_cmnd[0] == READ_6)
265 else if (SRpnt->sr_cmnd[0] == WRITE_6)
269 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
273 if ((sense[2] & 0xe0) == 0)
280 /* Wakeup from interrupt */
281 static void osst_sleep_done (Scsi_Cmnd * SCpnt)
283 OS_Scsi_Tape * STp = container_of(SCpnt->request->rq_disk->private_data, OS_Scsi_Tape, driver);
285 if ((STp->buffer)->writing &&
286 (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
287 (SCpnt->sense_buffer[2] & 0x40)) {
288 /* EOM at write-behind, has all been written? */
289 if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
290 STp->buffer->midlevel_result = SCpnt->result; /* Error */
292 STp->buffer->midlevel_result = INT_MAX; /* OK */
295 STp->buffer->midlevel_result = SCpnt->result;
296 SCpnt->request->rq_status = RQ_SCSI_DONE;
297 STp->buffer->last_SRpnt = SCpnt->sc_request;
300 STp->write_pending = 0;
302 complete(SCpnt->request->waiting);
306 /* Do the scsi command. Waits until command performed if do_wait is true.
307 Otherwise osst_write_behind_check() is used to check that the command
309 static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
310 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
313 #ifdef OSST_INJECT_ERRORS
314 static int inject = 0;
315 static int repeat = 0;
318 if ((SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC)) == NULL) {
319 printk(KERN_ERR "%s:E: Can't get SCSI request.\n", tape_name(STp));
320 if (signal_pending(current))
321 (STp->buffer)->syscall_result = (-EINTR);
323 (STp->buffer)->syscall_result = (-EBUSY);
328 init_completion(&STp->wait);
329 SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ?
330 (STp->buffer)->use_sg : 0;
331 if (SRpnt->sr_use_sg) {
332 bp = (char *)&(STp->buffer->sg[0]);
333 if (STp->buffer->sg_segs < SRpnt->sr_use_sg)
334 SRpnt->sr_use_sg = STp->buffer->sg_segs;
337 bp = (STp->buffer)->b_data;
338 SRpnt->sr_data_direction = direction;
339 SRpnt->sr_cmd_len = 0;
340 SRpnt->sr_request->waiting = &(STp->wait);
341 SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
342 SRpnt->sr_request->rq_disk = STp->drive;
344 scsi_do_req(SRpnt, (void *)cmd, bp, bytes, osst_sleep_done, timeout, retries);
347 wait_for_completion(SRpnt->sr_request->waiting);
348 SRpnt->sr_request->waiting = NULL;
349 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
350 #ifdef OSST_INJECT_ERRORS
351 if (STp->buffer->syscall_result == 0 &&
354 ( (++ inject % 83) == 29 ||
355 (STp->first_frame_position == 240
356 /* or STp->read_error_frame to fail again on the block calculated above */ &&
358 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
359 STp->buffer->last_result_fatal = 1;
367 /* Handle the write-behind checking (downs the semaphore) */
368 static void osst_write_behind_check(OS_Scsi_Tape *STp)
370 OSST_buffer * STbuffer;
372 STbuffer = STp->buffer;
375 if (STp->write_pending)
380 wait_for_completion(&(STp->wait));
381 (STp->buffer)->last_SRpnt->sr_request->waiting = NULL;
383 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
385 if ((STp->buffer)->syscall_result)
386 (STp->buffer)->syscall_result =
387 osst_write_error_recovery(STp, &((STp->buffer)->last_SRpnt), 1);
389 STp->first_frame_position++;
391 scsi_release_request((STp->buffer)->last_SRpnt);
393 if (STbuffer->writing < STbuffer->buffer_bytes)
394 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
396 STbuffer->buffer_bytes -= STbuffer->writing;
397 STbuffer->writing = 0;
404 /* Onstream specific Routines */
406 * Initialize the OnStream AUX
408 static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number,
409 int logical_blk_num, int blk_sz, int blk_cnt)
411 os_aux_t *aux = STp->buffer->aux;
412 os_partition_t *par = &aux->partition;
413 os_dat_t *dat = &aux->dat;
415 if (STp->raw) return;
417 memset(aux, 0, sizeof(*aux));
418 aux->format_id = htonl(0);
419 memcpy(aux->application_sig, "LIN4", 4);
420 aux->hdwr = htonl(0);
421 aux->frame_type = frame_type;
423 switch (frame_type) {
424 case OS_FRAME_TYPE_HEADER:
425 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
426 par->partition_num = OS_CONFIG_PARTITION;
427 par->par_desc_ver = OS_PARTITION_VERSION;
428 par->wrt_pass_cntr = htons(0xffff);
429 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
430 par->first_frame_ppos = htonl(0);
431 par->last_frame_ppos = htonl(0xbb7);
432 aux->frame_seq_num = htonl(0);
433 aux->logical_blk_num_high = htonl(0);
434 aux->logical_blk_num = htonl(0);
435 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
437 case OS_FRAME_TYPE_DATA:
438 case OS_FRAME_TYPE_MARKER:
443 dat->dat_list[0].blk_sz = htonl(blk_sz);
444 dat->dat_list[0].blk_cnt = htons(blk_cnt);
445 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
446 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
447 dat->dat_list[0].reserved = 0;
448 case OS_FRAME_TYPE_EOD:
449 aux->update_frame_cntr = htonl(0);
450 par->partition_num = OS_DATA_PARTITION;
451 par->par_desc_ver = OS_PARTITION_VERSION;
452 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
453 par->first_frame_ppos = htonl(STp->first_data_ppos);
454 par->last_frame_ppos = htonl(STp->capacity);
455 aux->frame_seq_num = htonl(frame_seq_number);
456 aux->logical_blk_num_high = htonl(0);
457 aux->logical_blk_num = htonl(logical_blk_num);
459 default: ; /* probably FILL */
461 aux->filemark_cnt = ntohl(STp->filemark_cnt);
462 aux->phys_fm = ntohl(0xffffffff);
463 aux->last_mark_ppos = ntohl(STp->last_mark_ppos);
464 aux->last_mark_lbn = ntohl(STp->last_mark_lbn);
468 * Verify that we have the correct tape frame
470 static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet)
472 char * name = tape_name(STp);
473 os_aux_t * aux = STp->buffer->aux;
474 os_partition_t * par = &(aux->partition);
475 ST_partstat * STps = &(STp->ps[STp->partition]);
476 int blk_cnt, blk_sz, i;
479 if (STp->buffer->syscall_result) {
480 for (i=0; i < STp->buffer->sg_segs; i++)
481 memset(page_address(STp->buffer->sg[i].page),
482 0, STp->buffer->sg[i].length);
483 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
485 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
488 if (STp->buffer->syscall_result) {
490 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
494 if (ntohl(aux->format_id) != 0) {
496 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
500 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
501 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
503 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
507 if (par->partition_num != OS_DATA_PARTITION) {
508 if (!STp->linux_media || STp->linux_media_version != 2) {
510 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
511 name, par->partition_num);
516 if (par->par_desc_ver != OS_PARTITION_VERSION) {
518 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
522 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
524 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
525 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
529 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
530 aux->frame_type != OS_FRAME_TYPE_EOD &&
531 aux->frame_type != OS_FRAME_TYPE_MARKER) {
534 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
538 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
539 STp->first_frame_position < STp->eod_frame_ppos) {
540 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
541 STp->first_frame_position);
544 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
547 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
548 name, ntohl(aux->frame_seq_num), frame_seq_number);
552 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
553 STps->eof = ST_FM_HIT;
555 i = ntohl(aux->filemark_cnt);
556 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
557 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
559 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
560 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
561 i, STp->first_frame_position - 1);
563 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
564 if (i >= STp->filemark_cnt)
565 STp->filemark_cnt = i+1;
568 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
569 STps->eof = ST_EOD_1;
570 STp->frame_in_buffer = 1;
572 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
573 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
574 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
575 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
576 STp->buffer->read_pointer = 0;
577 STp->frame_in_buffer = 1;
579 /* See what block size was used to write file */
580 if (STp->block_size != blk_sz && blk_sz > 0) {
582 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
583 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
584 STp->block_size<1024?STp->block_size:STp->block_size/1024,
585 STp->block_size<1024?'b':'k');
586 STp->block_size = blk_sz;
587 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
589 STps->eof = ST_NOEOF;
591 STp->frame_seq_number = ntohl(aux->frame_seq_num);
592 STp->logical_blk_num = ntohl(aux->logical_blk_num);
596 if (STp->read_error_frame == 0)
597 STp->read_error_frame = STp->first_frame_position - 1;
602 * Wait for the unit to become Ready
604 static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout, int initial_delay)
606 unsigned char cmd[MAX_COMMAND_SIZE];
607 Scsi_Request * SRpnt;
608 unsigned long startwait = jiffies;
611 char * name = tape_name(STp);
613 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
616 if (initial_delay > 0) {
617 set_current_state(TASK_INTERRUPTIBLE);
618 schedule_timeout(initial_delay);
621 memset(cmd, 0, MAX_COMMAND_SIZE);
622 cmd[0] = TEST_UNIT_READY;
624 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
626 if (!SRpnt) return (-EBUSY);
628 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
629 (( SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
630 (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) ||
631 ( SRpnt->sr_sense_buffer[2] == 6 && SRpnt->sr_sense_buffer[12] == 0x28 &&
632 SRpnt->sr_sense_buffer[13] == 0 ) )) {
635 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
636 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
640 set_current_state(TASK_INTERRUPTIBLE);
641 schedule_timeout(HZ / 10);
643 memset(cmd, 0, MAX_COMMAND_SIZE);
644 cmd[0] = TEST_UNIT_READY;
646 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
652 if ( STp->buffer->syscall_result &&
653 osst_write_error_recovery(STp, aSRpnt, 0) ) {
655 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
656 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
657 STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
658 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
663 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
669 * Wait for a tape to be inserted in the unit
671 static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
673 unsigned char cmd[MAX_COMMAND_SIZE];
674 Scsi_Request * SRpnt;
675 unsigned long startwait = jiffies;
678 char * name = tape_name(STp);
680 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
683 memset(cmd, 0, MAX_COMMAND_SIZE);
684 cmd[0] = TEST_UNIT_READY;
686 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
688 if (!SRpnt) return (-EBUSY);
690 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
691 SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 0x3a &&
692 SRpnt->sr_sense_buffer[13] == 0 ) {
695 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
696 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
700 set_current_state(TASK_INTERRUPTIBLE);
701 schedule_timeout(HZ / 10);
703 memset(cmd, 0, MAX_COMMAND_SIZE);
704 cmd[0] = TEST_UNIT_READY;
706 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
712 if ( STp->buffer->syscall_result && SRpnt->sr_sense_buffer[2] != 2 &&
713 SRpnt->sr_sense_buffer[12] != 4 && SRpnt->sr_sense_buffer[13] == 1) {
715 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
716 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
717 STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
718 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
723 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
728 static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame)
732 osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
733 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
734 if (retval) return (retval);
735 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
736 return (osst_get_frame_position(STp, aSRpnt));
740 * Wait for write(s) to complete
742 static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
744 unsigned char cmd[MAX_COMMAND_SIZE];
745 Scsi_Request * SRpnt;
748 int delay = OSST_WAIT_WRITE_COMPLETE;
750 char * name = tape_name(STp);
752 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
755 memset(cmd, 0, MAX_COMMAND_SIZE);
756 cmd[0] = WRITE_FILEMARKS;
759 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
761 if (!SRpnt) return (-EBUSY);
762 if (STp->buffer->syscall_result) {
763 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == 2 && SRpnt->sr_sense_buffer[12] == 4) {
764 if (SRpnt->sr_sense_buffer[13] == 8) {
765 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
768 result = osst_write_error_recovery(STp, aSRpnt, 0);
770 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
771 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
776 #define OSST_POLL_PER_SEC 10
777 static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to)
779 unsigned long startwait = jiffies;
780 char * name = tape_name(STp);
782 char notyetprinted = 1;
784 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
785 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
787 while (time_before (jiffies, startwait + to*HZ))
790 result = osst_get_frame_position (STp, aSRpnt);
792 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
793 return 0; /* successful recovery leaves drive ready for frame */
794 if (result < 0) break;
795 if (STp->first_frame_position == curr &&
797 (signed)STp->last_frame_position > (signed)curr + minlast) ||
798 (minlast >= 0 && STp->cur_frames > minlast)
802 if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC)
804 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
805 name, curr, curr+minlast, STp->first_frame_position,
806 STp->last_frame_position, STp->cur_frames,
807 result, (jiffies-startwait)/HZ,
808 (((jiffies-startwait)%HZ)*10)/HZ);
813 if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted)
815 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
816 name, curr, curr+minlast, STp->first_frame_position,
817 STp->last_frame_position, STp->cur_frames, result);
821 set_current_state(TASK_INTERRUPTIBLE);
822 schedule_timeout (HZ / OSST_POLL_PER_SEC);
825 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
826 name, curr, curr+minlast, STp->first_frame_position,
827 STp->last_frame_position, STp->cur_frames,
828 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
834 * Read the next OnStream tape frame at the current location
836 static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout)
838 unsigned char cmd[MAX_COMMAND_SIZE];
839 Scsi_Request * SRpnt;
842 os_aux_t * aux = STp->buffer->aux;
843 char * name = tape_name(STp);
846 /* TODO: Error handling */
848 retval = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout);
850 memset(cmd, 0, MAX_COMMAND_SIZE);
857 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
859 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
860 STp->timeout, MAX_READ_RETRIES, TRUE);
865 if ((STp->buffer)->syscall_result) {
867 if (STp->read_error_frame == 0) {
868 STp->read_error_frame = STp->first_frame_position;
870 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
875 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
877 SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],
878 SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
879 SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
880 SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]);
884 STp->first_frame_position++;
889 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
892 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
893 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
894 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
895 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
896 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
897 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
898 if (aux->frame_type==2)
899 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
900 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
901 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
907 static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
909 ST_partstat * STps = &(STp->ps[STp->partition]);
910 Scsi_Request * SRpnt ;
911 unsigned char cmd[MAX_COMMAND_SIZE];
914 char * name = tape_name(STp);
917 if (STps->rw != ST_READING) { /* Initialize read operation */
918 if (STps->rw == ST_WRITING || STp->dirty) {
919 STp->write_type = OS_WRITE_DATA;
920 osst_flush_write_buffer(STp, aSRpnt);
921 osst_flush_drive_buffer(STp, aSRpnt);
923 STps->rw = ST_READING;
924 STp->frame_in_buffer = 0;
927 * Issue a read 0 command to get the OnStream drive
928 * read frames into its buffer.
930 memset(cmd, 0, MAX_COMMAND_SIZE);
935 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
937 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READ_RETRIES, TRUE);
939 retval = STp->buffer->syscall_result;
945 static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet)
947 ST_partstat * STps = &(STp->ps[STp->partition]);
948 char * name = tape_name(STp);
956 * If we want just any frame (-1) and there is a frame in the buffer, return it
958 if (frame_seq_number == -1 && STp->frame_in_buffer) {
960 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
965 * Search and wait for the next logical tape frame
969 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
970 name, frame_seq_number);
971 if (STp->read_error_frame) {
972 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
974 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
975 name, STp->read_error_frame);
977 STp->read_error_frame = 0;
983 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
984 name, frame_seq_number, cnt);
986 if ( osst_initiate_read(STp, aSRpnt)
987 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
990 position = osst_get_frame_position(STp, aSRpnt);
991 if (position >= 0xbae && position < 0xbb8)
993 else if (position > STp->eod_frame_ppos || ++bad == 10) {
994 position = STp->read_error_frame - 1;
1001 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1004 osst_set_frame_position(STp, aSRpnt, position, 0);
1007 if (osst_verify_frame(STp, frame_seq_number, quiet))
1009 if (osst_verify_frame(STp, -1, quiet)) {
1010 x = ntohl(STp->buffer->aux->frame_seq_num);
1011 if (STp->fast_open) {
1013 "%s:W: Found logical frame %d instead of %d after fast open\n",
1014 name, x, frame_seq_number);
1016 STp->read_error_frame = 0;
1019 if (x > frame_seq_number) {
1021 /* positioning backwards did not bring us to the desired frame */
1022 position = STp->read_error_frame - 1;
1025 position = osst_get_frame_position(STp, aSRpnt)
1026 + frame_seq_number - x - 1;
1028 if (STp->first_frame_position >= 3000 && position < 3000)
1033 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1034 name, x, frame_seq_number,
1035 STp->first_frame_position - position);
1037 osst_set_frame_position(STp, aSRpnt, position, 0);
1043 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1045 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1047 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1050 STp->frame_in_buffer = 0;
1053 STp->recover_count++;
1054 STp->recover_erreg++;
1055 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1056 name, STp->read_error_frame);
1061 if (debugging || STps->eof)
1063 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1064 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1066 STp->fast_open = FALSE;
1067 STp->read_error_frame = 0;
1071 static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num)
1073 ST_partstat * STps = &(STp->ps[STp->partition]);
1074 char * name = tape_name(STp);
1076 int frame_seq_estimate, ppos_estimate, move;
1078 if (logical_blk_num < 0) logical_blk_num = 0;
1080 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1081 name, logical_blk_num, STp->logical_blk_num,
1082 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1083 STp->block_size<1024?'b':'k');
1085 /* Do we know where we are? */
1086 if (STps->drv_block >= 0) {
1087 move = logical_blk_num - STp->logical_blk_num;
1088 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1089 move /= (OS_DATA_SIZE / STp->block_size);
1090 frame_seq_estimate = STp->frame_seq_number + move;
1092 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1094 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1095 else ppos_estimate = frame_seq_estimate + 20;
1096 while (++retries < 10) {
1097 if (ppos_estimate > STp->eod_frame_ppos-2) {
1098 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1099 ppos_estimate = STp->eod_frame_ppos - 2;
1101 if (frame_seq_estimate < 0) {
1102 frame_seq_estimate = 0;
1105 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1106 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1107 /* we've located the estimated frame, now does it have our block? */
1108 if (logical_blk_num < STp->logical_blk_num ||
1109 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1110 if (STps->eof == ST_FM_HIT)
1111 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1113 move = logical_blk_num - STp->logical_blk_num;
1114 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1115 move /= (OS_DATA_SIZE / STp->block_size);
1117 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1120 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1121 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1122 STp->logical_blk_num, logical_blk_num, move);
1124 frame_seq_estimate += move;
1125 ppos_estimate += move;
1128 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1129 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1130 STp->logical_blk_num = logical_blk_num;
1133 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1134 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1135 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1138 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1139 if (STps->eof == ST_FM_HIT) {
1141 STps->drv_block = 0;
1143 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1144 STp->logical_blk_num -
1145 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1148 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1152 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1154 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1156 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1157 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1158 STp->logical_blk_num, logical_blk_num);
1160 if (frame_seq_estimate != STp->frame_seq_number)
1161 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1166 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1167 name, logical_blk_num, STp->logical_blk_num, retries);
1171 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1172 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1173 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1174 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1176 #define OSST_FRAME_SHIFT 6
1177 #define OSST_SECTOR_SHIFT 9
1178 #define OSST_SECTOR_MASK 0x03F
1180 static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
1184 char * name = tape_name(STp);
1187 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1188 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1189 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1190 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1191 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1192 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1194 /* do we know where we are inside a file? */
1195 if (STp->ps[STp->partition].drv_block >= 0) {
1196 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1197 STp->first_frame_position) << OSST_FRAME_SHIFT;
1198 if (STp->ps[STp->partition].rw == ST_WRITING)
1199 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1201 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1203 sector = osst_get_frame_position(STp, aSRpnt);
1205 sector <<= OSST_FRAME_SHIFT;
1210 static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector)
1212 ST_partstat * STps = &(STp->ps[STp->partition]);
1213 int frame = sector >> OSST_FRAME_SHIFT,
1214 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1217 char * name = tape_name(STp);
1219 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1220 name, sector, frame, offset);
1222 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1224 if (frame <= STp->first_data_ppos) {
1225 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1226 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1228 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1229 if (r < 0) return r;
1231 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1232 if (r < 0) return r;
1234 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1237 STp->logical_blk_num += offset / STp->block_size;
1238 STp->buffer->read_pointer = offset;
1239 STp->buffer->buffer_bytes -= offset;
1241 STp->frame_seq_number++;
1242 STp->frame_in_buffer = 0;
1243 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1244 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1246 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1247 if (STps->eof == ST_FM_HIT) {
1249 STps->drv_block = 0;
1251 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1252 STp->logical_blk_num -
1253 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1256 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1259 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1260 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1261 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1267 * Read back the drive's internal buffer contents, as a part
1268 * of the write error recovery mechanism for old OnStream
1269 * firmware revisions.
1270 * Precondition for this function to work: all frames in the
1271 * drive's buffer must be of one type (DATA, MARK or EOD)!
1273 static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1274 unsigned int frame, unsigned int skip, int pending)
1276 Scsi_Request * SRpnt = * aSRpnt;
1277 unsigned char * buffer, * p;
1278 unsigned char cmd[MAX_COMMAND_SIZE];
1279 int flag, new_frame, i;
1280 int nframes = STp->cur_frames;
1281 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1282 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1283 - (nframes + pending - 1);
1284 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1285 - (nframes + pending - 1) * blks_per_frame;
1286 char * name = tape_name(STp);
1287 unsigned long startwait = jiffies;
1289 int dbg = debugging;
1292 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1295 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1296 name, nframes, pending?" and one that was pending":"");
1298 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1300 if (pending && debugging)
1301 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1302 name, frame_seq_number + nframes,
1303 logical_blk_num + nframes * blks_per_frame,
1304 p[0], p[1], p[2], p[3]);
1306 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1308 memset(cmd, 0, MAX_COMMAND_SIZE);
1309 cmd[0] = 0x3C; /* Buffer Read */
1310 cmd[1] = 6; /* Retrieve Faulty Block */
1311 cmd[7] = 32768 >> 8;
1312 cmd[8] = 32768 & 0xff;
1314 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
1315 STp->timeout, MAX_READ_RETRIES, TRUE);
1317 if ((STp->buffer)->syscall_result || !SRpnt) {
1318 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1319 vfree((void *)buffer);
1323 osst_copy_from_buffer(STp->buffer, p);
1326 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1327 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1331 osst_get_frame_position(STp, aSRpnt);
1334 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1336 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1337 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1339 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1342 if (STp->write_type == OS_WRITE_HEADER) {
1344 p += skip * OS_DATA_SIZE;
1346 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1351 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1352 name, new_frame+i, frame_seq_number+i);
1354 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1355 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1356 osst_get_frame_position(STp, aSRpnt);
1359 if (new_frame > frame + 1000) {
1360 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1361 vfree((void *)buffer);
1365 if ( i >= nframes + pending ) break;
1367 osst_copy_to_buffer(STp->buffer, p);
1369 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1371 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1372 logical_blk_num + i*blks_per_frame,
1373 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1374 memset(cmd, 0, MAX_COMMAND_SIZE);
1382 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1383 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1384 p[0], p[1], p[2], p[3]);
1386 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
1387 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1389 if (STp->buffer->syscall_result)
1392 p += OS_DATA_SIZE; i++;
1394 /* if we just sent the last frame, wait till all successfully written */
1395 if ( i == nframes + pending ) {
1397 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1399 memset(cmd, 0, MAX_COMMAND_SIZE);
1400 cmd[0] = WRITE_FILEMARKS;
1402 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
1403 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1406 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1407 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1411 flag = STp->buffer->syscall_result;
1412 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1414 memset(cmd, 0, MAX_COMMAND_SIZE);
1415 cmd[0] = TEST_UNIT_READY;
1417 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
1418 MAX_READY_RETRIES, TRUE);
1420 if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
1421 (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {
1422 /* in the process of becoming ready */
1423 set_current_state(TASK_INTERRUPTIBLE);
1424 schedule_timeout(HZ / 10);
1427 if (STp->buffer->syscall_result)
1433 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1439 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&
1440 SRpnt->sr_sense_buffer[12] == 0 &&
1441 SRpnt->sr_sense_buffer[13] == 2) {
1442 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1443 vfree((void *)buffer);
1444 return (-EIO); /* hit end of tape = fail */
1446 i = ((SRpnt->sr_sense_buffer[3] << 24) |
1447 (SRpnt->sr_sense_buffer[4] << 16) |
1448 (SRpnt->sr_sense_buffer[5] << 8) |
1449 SRpnt->sr_sense_buffer[6] ) - new_frame;
1450 p = &buffer[i * OS_DATA_SIZE];
1452 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1454 osst_get_frame_position(STp, aSRpnt);
1456 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1457 name, STp->first_frame_position, STp->last_frame_position);
1462 osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
1463 vfree((void *)buffer);
1467 static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1468 unsigned int frame, unsigned int skip, int pending)
1470 unsigned char cmd[MAX_COMMAND_SIZE];
1471 Scsi_Request * SRpnt;
1472 char * name = tape_name(STp);
1474 int attempts = 1000 / skip;
1476 unsigned long startwait = jiffies;
1478 int dbg = debugging;
1481 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1486 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1488 expected = frame+skip+STp->cur_frames+pending;
1490 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1491 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1493 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1496 set_current_state(TASK_INTERRUPTIBLE);
1497 schedule_timeout(HZ / 10);
1499 if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
1501 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1502 name, STp->first_frame_position,
1503 STp->last_frame_position, STp->cur_frames);
1505 frame = STp->last_frame_position;
1509 if (pending && STp->cur_frames < 50) {
1511 memset(cmd, 0, MAX_COMMAND_SIZE);
1516 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1517 name, STp->frame_seq_number-1, STp->first_frame_position);
1519 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
1520 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1523 if (STp->buffer->syscall_result) { /* additional write error */
1524 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&
1525 SRpnt->sr_sense_buffer[12] == 0 &&
1526 SRpnt->sr_sense_buffer[13] == 2) {
1528 "%s:E: Volume overflow in write error recovery\n",
1530 break; /* hit end of tape = fail */
1539 if (STp->cur_frames == 0) {
1542 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1544 if (STp->first_frame_position != expected) {
1545 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1546 name, STp->first_frame_position, expected);
1553 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1554 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1558 schedule_timeout(HZ / 10);
1560 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1568 * Error recovery algorithm for the OnStream tape.
1571 static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending)
1573 Scsi_Request * SRpnt = * aSRpnt;
1574 ST_partstat * STps = & STp->ps[STp->partition];
1575 char * name = tape_name(STp);
1578 unsigned int frame, skip;
1580 rw_state = STps->rw;
1582 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) != 3
1583 || SRpnt->sr_sense_buffer[12] != 12
1584 || SRpnt->sr_sense_buffer[13] != 0) {
1586 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1587 SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
1591 frame = (SRpnt->sr_sense_buffer[3] << 24) |
1592 (SRpnt->sr_sense_buffer[4] << 16) |
1593 (SRpnt->sr_sense_buffer[5] << 8) |
1594 SRpnt->sr_sense_buffer[6];
1595 skip = SRpnt->sr_sense_buffer[9];
1598 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1600 osst_get_frame_position(STp, aSRpnt);
1602 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1603 name, STp->first_frame_position, STp->last_frame_position);
1605 switch (STp->write_type) {
1608 case OS_WRITE_NEW_MARK:
1610 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1611 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1612 if (STp->os_fw_rev >= 10600)
1613 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1615 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1616 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1618 retval?"" :"Don't worry, ",
1619 retval?" not ":" ");
1621 case OS_WRITE_LAST_MARK:
1622 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1623 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1626 case OS_WRITE_HEADER:
1627 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1628 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1631 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1632 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1634 osst_get_frame_position(STp, aSRpnt);
1636 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1637 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1638 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1641 STp->recover_count++;
1642 STp->recover_erreg++;
1644 STps->rw = rw_state;
1648 static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1649 int mt_op, int mt_count)
1651 char * name = tape_name(STp);
1653 int last_mark_ppos = -1;
1656 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1658 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1660 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1664 if (STp->linux_media_version >= 4) {
1666 * direct lookup in header filemark list
1668 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1669 if (STp->header_ok &&
1670 STp->header_cache != NULL &&
1671 (cnt - mt_count) >= 0 &&
1672 (cnt - mt_count) < OS_FM_TAB_MAX &&
1673 (cnt - mt_count) < STp->filemark_cnt &&
1674 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1676 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1678 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1679 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1680 STp->header_cache == NULL?"lack of header cache":"count out of range");
1682 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1684 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1685 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1686 STp->buffer->aux->last_mark_ppos))?"match":"error",
1687 mt_count, last_mark_ppos);
1689 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1690 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1691 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1694 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1698 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1699 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1700 name, last_mark_ppos);
1706 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1710 while (cnt != mt_count) {
1711 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1712 if (last_mark_ppos == -1)
1715 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1717 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1719 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1721 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1725 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1726 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1727 name, last_mark_ppos);
1732 if (mt_op == MTBSFM) {
1733 STp->frame_seq_number++;
1734 STp->frame_in_buffer = 0;
1735 STp->buffer->buffer_bytes = 0;
1736 STp->buffer->read_pointer = 0;
1737 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1743 * ADRL 1.1 compatible "slow" space filemarks fwd version
1745 * Just scans for the filemark sequentially.
1747 static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1748 int mt_op, int mt_count)
1752 char * name = tape_name(STp);
1754 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1756 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1758 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1763 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1765 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1769 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1771 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1773 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1775 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1777 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1778 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1780 STp->eod_frame_ppos = STp->first_frame_position-1;
1784 if (cnt == mt_count)
1786 STp->frame_in_buffer = 0;
1788 if (mt_op == MTFSF) {
1789 STp->frame_seq_number++;
1790 STp->frame_in_buffer = 0;
1791 STp->buffer->buffer_bytes = 0;
1792 STp->buffer->read_pointer = 0;
1793 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1799 * Fast linux specific version of OnStream FSF
1801 static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1802 int mt_op, int mt_count)
1804 char * name = tape_name(STp);
1806 next_mark_ppos = -1;
1809 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
1811 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1813 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1818 if (STp->linux_media_version >= 4) {
1820 * direct lookup in header filemark list
1822 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1823 if (STp->header_ok &&
1824 STp->header_cache != NULL &&
1825 (cnt + mt_count) < OS_FM_TAB_MAX &&
1826 (cnt + mt_count) < STp->filemark_cnt &&
1827 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1828 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1830 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1832 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1833 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1834 STp->header_cache == NULL?"lack of header cache":"count out of range");
1836 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1838 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1839 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1840 STp->buffer->aux->last_mark_ppos))?"match":"error",
1841 mt_count, next_mark_ppos);
1843 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1845 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1847 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1849 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1850 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1852 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
1857 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1858 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1859 name, next_mark_ppos);
1862 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1863 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
1864 name, cnt+mt_count, next_mark_ppos,
1865 ntohl(STp->buffer->aux->filemark_cnt));
1871 * Find nearest (usually previous) marker, then jump from marker to marker
1874 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1876 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1878 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1882 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
1883 if (STp->first_mark_ppos == -1) {
1885 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1887 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1889 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
1890 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1893 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
1898 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1899 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
1900 name, STp->first_mark_ppos);
1904 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
1910 while (cnt != mt_count) {
1911 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
1912 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
1914 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1916 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
1919 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
1921 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1923 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1925 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
1930 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1931 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1932 name, next_mark_ppos);
1937 if (mt_op == MTFSF) {
1938 STp->frame_seq_number++;
1939 STp->frame_in_buffer = 0;
1940 STp->buffer->buffer_bytes = 0;
1941 STp->buffer->read_pointer = 0;
1942 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1948 * In debug mode, we want to see as many errors as possible
1949 * to test the error recovery mechanism.
1952 static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int retries)
1954 unsigned char cmd[MAX_COMMAND_SIZE];
1955 Scsi_Request * SRpnt = * aSRpnt;
1956 char * name = tape_name(STp);
1958 memset(cmd, 0, MAX_COMMAND_SIZE);
1959 cmd[0] = MODE_SELECT;
1961 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
1963 (STp->buffer)->b_data[0] = cmd[4] - 1;
1964 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
1965 (STp->buffer)->b_data[2] = 0; /* Reserved */
1966 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
1967 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
1968 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
1969 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
1970 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
1973 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
1975 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
1978 if ((STp->buffer)->syscall_result)
1979 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
1984 static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
1987 int this_mark_ppos = STp->first_frame_position;
1988 int this_mark_lbn = STp->logical_blk_num;
1990 char * name = tape_name(STp);
1993 if (STp->raw) return 0;
1995 STp->write_type = OS_WRITE_NEW_MARK;
1997 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
1998 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2001 result = osst_flush_write_buffer(STp, aSRpnt);
2002 result |= osst_flush_drive_buffer(STp, aSRpnt);
2003 STp->last_mark_ppos = this_mark_ppos;
2004 STp->last_mark_lbn = this_mark_lbn;
2005 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2006 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2007 if (STp->filemark_cnt++ == 0)
2008 STp->first_mark_ppos = this_mark_ppos;
2012 static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2016 char * name = tape_name(STp);
2019 if (STp->raw) return 0;
2021 STp->write_type = OS_WRITE_EOD;
2022 STp->eod_frame_ppos = STp->first_frame_position;
2024 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2025 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2029 result = osst_flush_write_buffer(STp, aSRpnt);
2030 result |= osst_flush_drive_buffer(STp, aSRpnt);
2031 STp->eod_frame_lfa = --(STp->frame_seq_number);
2035 static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
2037 char * name = tape_name(STp);
2040 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2042 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2043 osst_set_frame_position(STp, aSRpnt, where, 0);
2044 STp->write_type = OS_WRITE_FILLER;
2046 memcpy(STp->buffer->b_data, "Filler", 6);
2047 STp->buffer->buffer_bytes = 6;
2049 if (osst_flush_write_buffer(STp, aSRpnt)) {
2050 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2055 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2057 return osst_flush_drive_buffer(STp, aSRpnt);
2060 static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
2062 char * name = tape_name(STp);
2066 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2068 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2069 osst_set_frame_position(STp, aSRpnt, where, 0);
2070 STp->write_type = OS_WRITE_HEADER;
2072 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2073 STp->buffer->buffer_bytes = sizeof(os_header_t);
2075 if (osst_flush_write_buffer(STp, aSRpnt)) {
2076 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2080 result = osst_flush_drive_buffer(STp, aSRpnt);
2082 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2087 static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int locate_eod)
2089 os_header_t * header;
2091 char * name = tape_name(STp);
2094 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2096 if (STp->raw) return 0;
2098 if (STp->header_cache == NULL) {
2099 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2100 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2103 memset(STp->header_cache, 0, sizeof(os_header_t));
2105 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2108 if (STp->header_ok) STp->update_frame_cntr++;
2109 else STp->update_frame_cntr = 0;
2111 header = STp->header_cache;
2112 strcpy(header->ident_str, "ADR_SEQ");
2113 header->major_rev = 1;
2114 header->minor_rev = 4;
2115 header->ext_trk_tb_off = htons(17192);
2116 header->pt_par_num = 1;
2117 header->partition[0].partition_num = OS_DATA_PARTITION;
2118 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2119 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2120 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2121 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2122 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2123 header->cfg_col_width = htonl(20);
2124 header->dat_col_width = htonl(1500);
2125 header->qfa_col_width = htonl(0);
2126 header->ext_track_tb.nr_stream_part = 1;
2127 header->ext_track_tb.et_ent_sz = 32;
2128 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2129 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2130 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2131 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2132 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2133 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2134 header->dat_fm_tab.fm_part_num = 0;
2135 header->dat_fm_tab.fm_tab_ent_sz = 4;
2136 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2137 STp->filemark_cnt:OS_FM_TAB_MAX);
2139 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2140 if (STp->update_frame_cntr == 0)
2141 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2142 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2146 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2148 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2151 printk(KERN_ERR "%s:E: Write header failed\n", name);
2153 memcpy(STp->application_sig, "LIN4", 4);
2154 STp->linux_media = 1;
2155 STp->linux_media_version = 4;
2161 static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2163 if (STp->header_cache != NULL)
2164 memset(STp->header_cache, 0, sizeof(os_header_t));
2166 STp->logical_blk_num = STp->frame_seq_number = 0;
2167 STp->frame_in_buffer = 0;
2168 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2169 STp->filemark_cnt = 0;
2170 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2171 return osst_write_header(STp, aSRpnt, 1);
2174 static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ppos)
2176 char * name = tape_name(STp);
2177 os_header_t * header;
2180 int linux_media_version,
2186 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2187 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2188 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2189 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2190 if (osst_initiate_read (STp, aSRpnt)) {
2191 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2195 if (osst_read_frame(STp, aSRpnt, 180)) {
2197 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2201 header = (os_header_t *) STp->buffer->b_data; /* warning: only first segment addressable */
2202 aux = STp->buffer->aux;
2203 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2205 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2209 if (ntohl(aux->frame_seq_num) != 0 ||
2210 ntohl(aux->logical_blk_num) != 0 ||
2211 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2212 ntohl(aux->partition.first_frame_ppos) != 0 ||
2213 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2215 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2216 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2217 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2218 ntohl(aux->partition.last_frame_ppos));
2222 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2223 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2224 strlcpy(id_string, header->ident_str, 8);
2226 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2230 update_frame_cntr = ntohl(aux->update_frame_cntr);
2231 if (update_frame_cntr < STp->update_frame_cntr) {
2233 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2234 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2238 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2240 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2241 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2242 header->minor_rev > 4 )? "Invalid" : "Warning:",
2243 header->major_rev, header->minor_rev);
2245 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2249 if (header->pt_par_num != 1)
2250 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2251 name, header->pt_par_num);
2253 memcpy(id_string, aux->application_sig, 4);
2255 if (memcmp(id_string, "LIN", 3) == 0) {
2256 STp->linux_media = 1;
2257 linux_media_version = id_string[3] - '0';
2258 if (linux_media_version != 4)
2259 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2260 name, linux_media_version);
2262 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2265 if (linux_media_version < STp->linux_media_version) {
2267 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2268 name, ppos, linux_media_version);
2272 if (linux_media_version > STp->linux_media_version) {
2274 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2275 name, ppos, linux_media_version);
2277 memcpy(STp->application_sig, id_string, 5);
2278 STp->linux_media_version = linux_media_version;
2279 STp->update_frame_cntr = -1;
2281 if (update_frame_cntr > STp->update_frame_cntr) {
2283 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2284 name, ppos, update_frame_cntr);
2286 if (STp->header_cache == NULL) {
2287 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2288 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2292 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2295 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2296 header = STp->header_cache; /* further accesses from cached (full) copy */
2298 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2299 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2300 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2301 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2302 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2303 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2304 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2305 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2306 STp->update_frame_cntr = update_frame_cntr;
2308 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2309 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2310 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2311 STp->first_data_ppos,
2312 ntohl(header->partition[0].last_frame_ppos),
2313 ntohl(header->partition[0].eod_frame_ppos));
2314 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2315 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2317 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2319 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2321 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2322 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2323 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2325 if (header->minor_rev == 4 &&
2326 (header->ext_trk_tb_off != htons(17192) ||
2327 header->partition[0].partition_num != OS_DATA_PARTITION ||
2328 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2329 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2330 header->cfg_col_width != htonl(20) ||
2331 header->dat_col_width != htonl(1500) ||
2332 header->qfa_col_width != htonl(0) ||
2333 header->ext_track_tb.nr_stream_part != 1 ||
2334 header->ext_track_tb.et_ent_sz != 32 ||
2335 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2336 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2337 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2338 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2339 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2340 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2341 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2342 header->dat_fm_tab.fm_tab_ent_cnt !=
2343 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2344 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2351 static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2356 char * name = tape_name(STp);
2358 position = osst_get_frame_position(STp, aSRpnt);
2361 STp->header_ok = STp->linux_media = 1;
2362 STp->linux_media_version = 0;
2365 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2366 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2367 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2368 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2370 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2373 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2374 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2376 first = position==10?0xbae: 5;
2377 last = position==10?0xbb3:10;
2379 for (ppos = first; ppos < last; ppos++)
2380 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2383 first = position==10? 5:0xbae;
2384 last = position==10?10:0xbb3;
2386 for (ppos = first; ppos < last; ppos++)
2387 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2391 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2392 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2393 osst_set_frame_position(STp, aSRpnt, 10, 0);
2396 if (position <= STp->first_data_ppos) {
2397 position = STp->first_data_ppos;
2398 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2400 osst_set_frame_position(STp, aSRpnt, position, 0);
2406 static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2408 int frame_position = STp->first_frame_position;
2409 int frame_seq_numbr = STp->frame_seq_number;
2410 int logical_blk_num = STp->logical_blk_num;
2411 int halfway_frame = STp->frame_in_buffer;
2412 int read_pointer = STp->buffer->read_pointer;
2413 int prev_mark_ppos = -1;
2414 int actual_mark_ppos, i, n;
2416 char * name = tape_name(STp);
2418 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2420 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2421 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2423 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2427 if (STp->linux_media_version >= 4) {
2428 for (i=0; i<STp->filemark_cnt; i++)
2429 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2432 prev_mark_ppos = frame_position - 1; /* usually - we don't really know */
2433 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2434 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2435 if (frame_position != STp->first_frame_position ||
2436 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2437 prev_mark_ppos != actual_mark_ppos ) {
2439 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2440 STp->first_frame_position, frame_position,
2441 STp->frame_seq_number + (halfway_frame?0:1),
2442 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2446 if (halfway_frame) {
2447 /* prepare buffer for append and rewrite on top of original */
2448 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2449 STp->buffer->buffer_bytes = read_pointer;
2450 STp->ps[STp->partition].rw = ST_WRITING;
2453 STp->frame_in_buffer = halfway_frame;
2454 STp->frame_seq_number = frame_seq_numbr;
2455 STp->logical_blk_num = logical_blk_num;
2459 /* Acc. to OnStream, the vers. numbering is the following:
2460 * X.XX for released versions (X=digit),
2461 * XXXY for unreleased versions (Y=letter)
2462 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2463 * This fn makes monoton numbers out of this scheme ...
2465 static unsigned int osst_parse_firmware_rev (const char * str)
2467 if (str[1] == '.') {
2468 return (str[0]-'0')*10000
2472 return (str[0]-'0')*10000
2474 +(str[2]-'0')*100 - 100
2480 * Configure the OnStream SCII tape drive for default operation
2482 static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2484 unsigned char cmd[MAX_COMMAND_SIZE];
2485 char * name = tape_name(STp);
2486 Scsi_Request * SRpnt = * aSRpnt;
2487 osst_mode_parameter_header_t * header;
2488 osst_block_size_page_t * bs;
2489 osst_capabilities_page_t * cp;
2490 osst_tape_paramtr_page_t * prm;
2491 int drive_buffer_size;
2493 if (STp->ready != ST_READY) {
2495 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2500 if (STp->os_fw_rev < 10600) {
2501 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2502 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2506 * Configure 32.5KB (data+aux) frame size.
2507 * Get the current frame size from the block size mode page
2509 memset(cmd, 0, MAX_COMMAND_SIZE);
2510 cmd[0] = MODE_SENSE;
2512 cmd[2] = BLOCK_SIZE_PAGE;
2513 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2515 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2516 if (SRpnt == NULL) {
2518 printk(OSST_DEB_MSG "osst :D: Busy\n");
2523 if ((STp->buffer)->syscall_result != 0) {
2524 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2528 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2529 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2532 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2533 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2534 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2535 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2539 * Configure default auto columns mode, 32.5KB transfer mode
2547 memset(cmd, 0, MAX_COMMAND_SIZE);
2548 cmd[0] = MODE_SELECT;
2550 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2552 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
2554 if ((STp->buffer)->syscall_result != 0) {
2555 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2560 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2562 * In debug mode, we want to see as many errors as possible
2563 * to test the error recovery mechanism.
2565 osst_set_retries(STp, aSRpnt, 0);
2570 * Set vendor name to 'LIN4' for "Linux support version 4".
2573 memset(cmd, 0, MAX_COMMAND_SIZE);
2574 cmd[0] = MODE_SELECT;
2576 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2578 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2579 header->medium_type = 0; /* Medium Type - ignoring */
2580 header->dsp = 0; /* Reserved */
2581 header->bdl = 0; /* Block Descriptor Length */
2583 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2584 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2585 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2586 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2587 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2588 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2589 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2590 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2592 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
2595 if ((STp->buffer)->syscall_result != 0) {
2596 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2597 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2601 memset(cmd, 0, MAX_COMMAND_SIZE);
2602 cmd[0] = MODE_SENSE;
2604 cmd[2] = CAPABILITIES_PAGE;
2605 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2607 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2610 if ((STp->buffer)->syscall_result != 0) {
2611 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2615 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2616 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2617 sizeof(osst_mode_parameter_header_t) + header->bdl);
2619 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2621 memset(cmd, 0, MAX_COMMAND_SIZE);
2622 cmd[0] = MODE_SENSE;
2624 cmd[2] = TAPE_PARAMTR_PAGE;
2625 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2627 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2630 if ((STp->buffer)->syscall_result != 0) {
2631 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2635 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2636 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2637 sizeof(osst_mode_parameter_header_t) + header->bdl);
2639 STp->density = prm->density;
2640 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2642 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2643 name, STp->density, STp->capacity / 32, drive_buffer_size);
2651 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2652 it messes up the block number). */
2653 static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
2656 char * name = tape_name(STp);
2660 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2661 name, forward ? "forward" : "backward");
2665 /* assumes that the filemark is already read by the drive, so this is low cost */
2666 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2669 /* assumes this is only called if we just read the filemark! */
2670 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2673 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2674 name, forward ? "forward" : "backward");
2680 /* Get the tape position. */
2682 static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2684 unsigned char scmd[MAX_COMMAND_SIZE];
2685 Scsi_Request * SRpnt;
2688 /* KG: We want to be able to use it for checking Write Buffer availability
2689 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2691 char * olddata = STp->buffer->b_data;
2692 int oldsize = STp->buffer->buffer_size;
2693 char * name = tape_name(STp);
2695 if (STp->ready != ST_READY) return (-EIO);
2697 memset (scmd, 0, MAX_COMMAND_SIZE);
2698 scmd[0] = READ_POSITION;
2700 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2701 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, SCSI_DATA_READ,
2702 STp->timeout, MAX_RETRIES, TRUE);
2704 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2709 if (STp->buffer->syscall_result)
2710 result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;
2712 if (result == -EINVAL)
2713 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2716 if (result == -EIO) { /* re-read position */
2717 unsigned char mysense[16];
2718 memcpy (mysense, SRpnt->sr_sense_buffer, 16);
2719 memset (scmd, 0, MAX_COMMAND_SIZE);
2720 scmd[0] = READ_POSITION;
2721 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2722 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, SCSI_DATA_READ,
2723 STp->timeout, MAX_RETRIES, TRUE);
2724 if (!STp->buffer->syscall_result)
2725 memcpy (SRpnt->sr_sense_buffer, mysense, 16);
2727 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2728 + ((STp->buffer)->b_data[5] << 16)
2729 + ((STp->buffer)->b_data[6] << 8)
2730 + (STp->buffer)->b_data[7];
2731 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2732 + ((STp->buffer)->b_data[ 9] << 16)
2733 + ((STp->buffer)->b_data[10] << 8)
2734 + (STp->buffer)->b_data[11];
2735 STp->cur_frames = (STp->buffer)->b_data[15];
2738 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2739 STp->first_frame_position, STp->last_frame_position,
2740 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2741 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2745 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2747 printk(KERN_WARNING "%s:D: Correcting read position %d, %d, %d\n", name,
2748 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2750 STp->first_frame_position = STp->last_frame_position;
2753 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2755 return (result == 0 ? STp->first_frame_position : result);
2759 /* Set the tape block */
2760 static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int ppos, int skip)
2762 unsigned char scmd[MAX_COMMAND_SIZE];
2763 Scsi_Request * SRpnt;
2766 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2767 char * name = tape_name(STp);
2769 if (STp->ready != ST_READY) return (-EIO);
2771 STps = &(STp->ps[STp->partition]);
2773 if (ppos < 0 || ppos > STp->capacity) {
2774 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2775 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2782 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2784 memset (scmd, 0, MAX_COMMAND_SIZE);
2787 scmd[3] = (pp >> 24);
2788 scmd[4] = (pp >> 16);
2789 scmd[5] = (pp >> 8);
2794 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, SCSI_DATA_NONE, STp->long_timeout,
2800 if ((STp->buffer)->syscall_result != 0) {
2802 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
2803 name, STp->first_frame_position, pp);
2808 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
2809 } while ((pp != ppos) && (pp = ppos));
2810 STp->first_frame_position = STp->last_frame_position = ppos;
2811 STps->eof = ST_NOEOF;
2814 STp->frame_in_buffer = 0;
2818 static int osst_write_trailer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int leave_at_EOT)
2820 ST_partstat * STps = &(STp->ps[STp->partition]);
2823 if (STp->write_type != OS_WRITE_NEW_MARK) {
2824 /* true unless the user wrote the filemark for us */
2825 result = osst_flush_drive_buffer(STp, aSRpnt);
2826 if (result < 0) goto out;
2827 result = osst_write_filemark(STp, aSRpnt);
2828 if (result < 0) goto out;
2830 if (STps->drv_file >= 0)
2832 STps->drv_block = 0;
2834 result = osst_write_eod(STp, aSRpnt);
2835 osst_write_header(STp, aSRpnt, leave_at_EOT);
2842 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2844 /* Flush the write buffer (never need to write if variable blocksize). */
2845 static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2847 int offset, transfer, blks = 0;
2849 unsigned char cmd[MAX_COMMAND_SIZE];
2850 Scsi_Request * SRpnt = *aSRpnt;
2852 char * name = tape_name(STp);
2854 if ((STp->buffer)->writing) {
2855 if (SRpnt == (STp->buffer)->last_SRpnt)
2857 { printk(OSST_DEB_MSG
2858 "%s:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", name);
2860 *aSRpnt = SRpnt = NULL;
2864 "%s:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", name);
2866 osst_write_behind_check(STp);
2867 if ((STp->buffer)->syscall_result) {
2870 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
2871 name, (STp->buffer)->midlevel_result);
2873 if ((STp->buffer)->midlevel_result == INT_MAX)
2880 if (STp->dirty == 1) {
2883 STps = &(STp->ps[STp->partition]);
2884 STps->rw = ST_WRITING;
2885 offset = STp->buffer->buffer_bytes;
2886 blks = (offset + STp->block_size - 1) / STp->block_size;
2887 transfer = OS_FRAME_SIZE;
2889 if (offset < OS_DATA_SIZE)
2890 osst_zero_buffer_tail(STp->buffer);
2892 /* TODO: Error handling! */
2894 result = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120);
2896 memset(cmd, 0, MAX_COMMAND_SIZE);
2901 switch (STp->write_type) {
2905 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
2906 name, blks, STp->frame_seq_number,
2907 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
2909 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
2910 STp->logical_blk_num - blks, STp->block_size, blks);
2913 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
2914 STp->logical_blk_num, 0, 0);
2916 case OS_WRITE_NEW_MARK:
2917 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
2918 STp->logical_blk_num++, 0, blks=1);
2920 case OS_WRITE_HEADER:
2921 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
2923 default: /* probably FILLER */
2924 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
2928 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
2929 name, offset, transfer, blks);
2932 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
2933 STp->timeout, MAX_WRITE_RETRIES, TRUE);
2938 if ((STp->buffer)->syscall_result != 0) {
2941 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
2942 name, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
2943 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
2945 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
2946 (SRpnt->sr_sense_buffer[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
2947 (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) {
2949 (STp->buffer)->buffer_bytes = 0;
2953 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
2954 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
2958 STps->drv_block = (-1); /* FIXME - even if write recovery succeeds? */
2961 STp->first_frame_position++;
2963 (STp->buffer)->buffer_bytes = 0;
2967 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
2973 /* Flush the tape buffer. The tape will be positioned correctly unless
2974 seek_next is true. */
2975 static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next)
2978 int backspace = 0, result = 0;
2980 char * name = tape_name(STp);
2984 * If there was a bus reset, block further access
2987 if( STp->pos_unknown)
2990 if (STp->ready != ST_READY)
2993 STps = &(STp->ps[STp->partition]);
2994 if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
2995 STp->write_type = OS_WRITE_DATA;
2996 return osst_flush_write_buffer(STp, aSRpnt);
2998 if (STp->block_size == 0)
3002 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3005 if (!STp->can_bsr) {
3006 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3007 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3008 (STp->buffer)->buffer_bytes = 0;
3009 (STp->buffer)->read_pointer = 0;
3010 STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */
3014 if (STps->eof == ST_FM_HIT) {
3015 result = cross_eof(STp, aSRpnt, FALSE); /* Back over the EOF hit */
3017 STps->eof = ST_NOEOF;
3019 if (STps->drv_file >= 0)
3021 STps->drv_block = 0;
3024 if (!result && backspace > 0) /* TODO -- design and run a test case for this */
3025 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3027 else if (STps->eof == ST_FM_HIT) {
3028 if (STps->drv_file >= 0)
3030 STps->drv_block = 0;
3031 STps->eof = ST_NOEOF;
3037 static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int synchronous)
3039 unsigned char cmd[MAX_COMMAND_SIZE];
3040 Scsi_Request * SRpnt;
3043 char * name = tape_name(STp);
3046 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3048 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3050 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3053 /* error recovery may have bumped us past the header partition */
3054 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3056 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3058 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3063 osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 60);
3064 /* TODO: Check for an error ! */
3066 // osst_build_stats(STp, &SRpnt);
3068 STp->ps[STp->partition].rw = ST_WRITING;
3069 STp->write_type = OS_WRITE_DATA;
3071 memset(cmd, 0, MAX_COMMAND_SIZE);
3074 cmd[4] = 1; /* one frame at a time... */
3075 blks = STp->buffer->buffer_bytes / STp->block_size;
3078 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3079 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3081 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3082 STp->logical_blk_num - blks, STp->block_size, blks);
3086 STp->write_pending = 1;
3088 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout,
3089 MAX_WRITE_RETRIES, synchronous);
3095 if (STp->buffer->syscall_result != 0) {
3098 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3100 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
3101 (SRpnt->sr_sense_buffer[2] & 0x40)) {
3102 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
3106 if (osst_write_error_recovery(STp, aSRpnt, 1))
3111 STp->first_frame_position++;
3119 /* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */
3120 static int do_door_lock(OS_Scsi_Tape * STp, int do_lock)
3124 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3126 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3128 retval = scsi_ioctl(STp->device, cmd, NULL);
3130 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3133 STp->door_locked = ST_LOCK_FAILS;
3138 /* Set the internal state after reset */
3139 static void reset_state(OS_Scsi_Tape *STp)
3144 STp->pos_unknown = 0;
3145 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3146 STps = &(STp->ps[i]);
3148 STps->eof = ST_NOEOF;
3150 STps->last_block_valid = FALSE;
3151 STps->drv_block = -1;
3152 STps->drv_file = -1;
3157 /* Entry points to osst */
3160 static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3162 ssize_t total, retval = 0;
3163 ssize_t i, do_count, blks, transfer;
3164 int write_threshold;
3165 int doing_write = 0;
3166 const char __user * b_point;
3167 Scsi_Request * SRpnt = NULL;
3170 OS_Scsi_Tape * STp = filp->private_data;
3171 char * name = tape_name(STp);
3174 if (down_interruptible(&STp->lock))
3175 return (-ERESTARTSYS);
3178 * If we are in the middle of error recovery, don't let anyone
3179 * else try and use this device. Also, if error recovery fails, it
3180 * may try and take the device offline, in which case all further
3181 * access to the device is prohibited.
3183 if( !scsi_block_when_processing_errors(STp->device) ) {
3188 if (STp->ready != ST_READY) {
3189 if (STp->ready == ST_NO_TAPE)
3190 retval = (-ENOMEDIUM);
3195 STm = &(STp->modes[STp->current_mode]);
3196 if (!STm->defined) {
3204 * If there was a bus reset, block further access
3207 if (STp->pos_unknown) {
3214 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3220 if (STp->write_prot) {
3225 /* Write must be integral number of blocks */
3226 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3227 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3228 name, count, STp->block_size<1024?
3229 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3234 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3235 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3236 name, STp->first_frame_position);
3241 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3242 STp->door_locked = ST_LOCKED_AUTO;
3244 STps = &(STp->ps[STp->partition]);
3246 if (STps->rw == ST_READING) {
3248 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3249 STps->drv_file, STps->drv_block);
3251 retval = osst_flush_buffer(STp, &SRpnt, 0);
3256 if (STps->rw != ST_WRITING) {
3257 /* Are we totally rewriting this tape? */
3258 if (!STp->header_ok ||
3259 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3260 (STps->drv_file == 0 && STps->drv_block == 0)) {
3261 STp->wrt_pass_cntr++;
3263 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3264 name, STp->wrt_pass_cntr);
3266 osst_reset_header(STp, &SRpnt);
3267 STps->drv_file = STps->drv_block = 0;
3269 /* Do we know where we'll be writing on the tape? */
3271 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3272 STps->drv_file < 0 || STps->drv_block < 0) {
3273 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3274 STps->drv_file = STp->filemark_cnt;
3275 STps->drv_block = 0;
3278 /* We have no idea where the tape is positioned - give up */
3281 "%s:D: Cannot write at indeterminate position.\n", name);
3287 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3288 STp->filemark_cnt = STps->drv_file;
3289 STp->last_mark_ppos =
3290 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3292 "%s:W: Overwriting file %d with old write pass counter %d\n",
3293 name, STps->drv_file, STp->wrt_pass_cntr);
3295 "%s:W: may lead to stale data being accepted on reading back!\n",
3299 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3300 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3304 STp->fast_open = FALSE;
3306 if (!STp->header_ok) {
3308 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3314 if ((STp->buffer)->writing) {
3315 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3316 osst_write_behind_check(STp);
3317 if ((STp->buffer)->syscall_result) {
3320 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3321 (STp->buffer)->midlevel_result);
3323 if ((STp->buffer)->midlevel_result == INT_MAX)
3324 STps->eof = ST_EOM_OK;
3326 STps->eof = ST_EOM_ERROR;
3329 if (STps->eof == ST_EOM_OK) {
3333 else if (STps->eof == ST_EOM_ERROR) {
3338 /* Check the buffer readability in cases where copy_user might catch
3339 the problems after some tape movement. */
3340 if ((copy_from_user(&i, buf, 1) != 0 ||
3341 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3346 if (!STm->do_buffer_writes) {
3347 write_threshold = 1;
3350 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3351 if (!STm->do_async_writes)
3357 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3358 name, count, STps->drv_file, STps->drv_block,
3359 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3362 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3365 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3366 (STp->buffer)->buffer_bytes;
3367 if (do_count > count)
3370 i = append_to_buffer(b_point, STp->buffer, do_count);
3376 blks = do_count / STp->block_size;
3377 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3379 i = osst_write_frame(STp, &SRpnt, TRUE);
3381 if (i == (-ENOSPC)) {
3382 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3383 if (transfer <= do_count) {
3384 filp->f_pos += do_count - transfer;
3385 count -= do_count - transfer;
3386 if (STps->drv_block >= 0) {
3387 STps->drv_block += (do_count - transfer) / STp->block_size;
3389 STps->eof = ST_EOM_OK;
3390 retval = (-ENOSPC); /* EOM within current request */
3393 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3398 STps->eof = ST_EOM_ERROR;
3399 STps->drv_block = (-1); /* Too cautious? */
3400 retval = (-EIO); /* EOM for old data */
3403 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3411 if (SRpnt != NULL) {
3412 scsi_release_request(SRpnt);
3415 STp->buffer->buffer_bytes = 0;
3418 retval = total - count;
3422 filp->f_pos += do_count;
3423 b_point += do_count;
3425 if (STps->drv_block >= 0) {
3426 STps->drv_block += blks;
3428 STp->buffer->buffer_bytes = 0;
3430 } /* end while write threshold exceeded */
3434 i = append_to_buffer(b_point, STp->buffer, count);
3439 blks = count / STp->block_size;
3440 STp->logical_blk_num += blks;
3441 if (STps->drv_block >= 0) {
3442 STps->drv_block += blks;
3444 filp->f_pos += count;
3448 if (doing_write && (STp->buffer)->syscall_result != 0) {
3449 retval = (STp->buffer)->syscall_result;
3453 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3454 /* Schedule an asynchronous write */
3455 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3456 STp->block_size) * STp->block_size;
3457 STp->dirty = !((STp->buffer)->writing ==
3458 (STp->buffer)->buffer_bytes);
3460 i = osst_write_frame(STp, &SRpnt, FALSE);
3465 SRpnt = NULL; /* Prevent releasing this request! */
3467 STps->at_sm &= (total == 0);
3469 STps->eof = ST_NOEOF;
3474 if (SRpnt != NULL) scsi_release_request(SRpnt);
3483 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3485 ssize_t total, retval = 0;
3486 ssize_t i, transfer;
3490 Scsi_Request * SRpnt = NULL;
3491 OS_Scsi_Tape * STp = filp->private_data;
3492 char * name = tape_name(STp);
3495 if (down_interruptible(&STp->lock))
3496 return (-ERESTARTSYS);
3499 * If we are in the middle of error recovery, don't let anyone
3500 * else try and use this device. Also, if error recovery fails, it
3501 * may try and take the device offline, in which case all further
3502 * access to the device is prohibited.
3504 if( !scsi_block_when_processing_errors(STp->device) ) {
3509 if (STp->ready != ST_READY) {
3510 if (STp->ready == ST_NO_TAPE)
3511 retval = (-ENOMEDIUM);
3516 STm = &(STp->modes[STp->current_mode]);
3517 if (!STm->defined) {
3523 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3528 /* Must have initialized medium */
3529 if (!STp->header_ok) {
3534 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3535 STp->door_locked = ST_LOCKED_AUTO;
3537 STps = &(STp->ps[STp->partition]);
3538 if (STps->rw == ST_WRITING) {
3539 retval = osst_flush_buffer(STp, &SRpnt, 0);
3543 /* FIXME -- this may leave the tape without EOD and up2date headers */
3546 if ((count % STp->block_size) != 0) {
3548 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3549 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3553 if (debugging && STps->eof != ST_NOEOF)
3554 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3555 STps->eof, (STp->buffer)->buffer_bytes);
3557 if ((STp->buffer)->buffer_bytes == 0 &&
3558 STps->eof >= ST_EOD_1) {
3559 if (STps->eof < ST_EOD) {
3564 retval = (-EIO); /* EOM or Blank Check */
3568 /* Check the buffer writability before any tape movement. Don't alter
3570 if (copy_from_user(&i, buf, 1) != 0 ||
3571 copy_to_user (buf, &i, 1) != 0 ||
3572 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3573 copy_to_user (buf + count - 1, &i, 1) != 0) {
3578 /* Loop until enough data in buffer or a special condition found */
3579 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3581 /* Get new data if the buffer is empty */
3582 if ((STp->buffer)->buffer_bytes == 0) {
3583 if (STps->eof == ST_FM_HIT)
3585 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3586 if (special < 0) { /* No need to continue read */
3587 STp->frame_in_buffer = 0;
3593 /* Move the data from driver buffer to user buffer */
3594 if ((STp->buffer)->buffer_bytes > 0) {
3596 if (debugging && STps->eof != ST_NOEOF)
3597 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3598 STps->eof, (STp->buffer)->buffer_bytes, count - total);
3600 /* force multiple of block size, note block_size may have been adjusted */
3601 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3602 (STp->buffer)->buffer_bytes : count - total)/
3603 STp->block_size) * STp->block_size;
3605 if (transfer == 0) {
3607 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3608 name, count, STp->block_size < 1024?
3609 STp->block_size:STp->block_size/1024,
3610 STp->block_size<1024?'b':'k');
3613 i = from_buffer(STp->buffer, buf, transfer);
3618 STp->logical_blk_num += transfer / STp->block_size;
3619 STps->drv_block += transfer / STp->block_size;
3620 filp->f_pos += transfer;
3625 if ((STp->buffer)->buffer_bytes == 0) {
3628 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3629 name, STp->frame_seq_number);
3631 STp->frame_in_buffer = 0;
3632 STp->frame_seq_number++; /* frame to look for next time */
3634 } /* for (total = 0, special = 0; total < count && !special; ) */
3636 /* Change the eof state if no data from tape or buffer */
3638 if (STps->eof == ST_FM_HIT) {
3639 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3640 STps->drv_block = 0;
3641 if (STps->drv_file >= 0)
3644 else if (STps->eof == ST_EOD_1) {
3645 STps->eof = ST_EOD_2;
3646 if (STps->drv_block > 0 && STps->drv_file >= 0)
3648 STps->drv_block = 0;
3650 else if (STps->eof == ST_EOD_2)
3653 else if (STps->eof == ST_FM)
3654 STps->eof = ST_NOEOF;
3659 if (SRpnt != NULL) scsi_release_request(SRpnt);
3667 /* Set the driver options */
3668 static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, char *name)
3671 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3672 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3673 STm->do_read_ahead);
3675 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3676 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3678 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3679 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3680 STp->scsi2_logical);
3682 "%s:I: sysv: %d\n", name, STm->sysv);
3685 "%s:D: debugging: %d\n",
3691 static int osst_set_options(OS_Scsi_Tape *STp, long options)
3696 char * name = tape_name(STp);
3698 STm = &(STp->modes[STp->current_mode]);
3699 if (!STm->defined) {
3700 memcpy(STm, &(STp->modes[0]), sizeof(ST_mode));
3701 modes_defined = TRUE;
3704 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3705 name, STp->current_mode);
3709 code = options & MT_ST_OPTIONS;
3710 if (code == MT_ST_BOOLEANS) {
3711 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3712 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3713 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3714 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3715 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3716 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3717 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3718 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3719 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3720 if ((STp->device)->scsi_level >= SCSI_2)
3721 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3722 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3723 STm->sysv = (options & MT_ST_SYSV) != 0;
3725 debugging = (options & MT_ST_DEBUGGING) != 0;
3727 osst_log_options(STp, STm, name);
3729 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3730 value = (code == MT_ST_SETBOOLEANS);
3731 if ((options & MT_ST_BUFFER_WRITES) != 0)
3732 STm->do_buffer_writes = value;
3733 if ((options & MT_ST_ASYNC_WRITES) != 0)
3734 STm->do_async_writes = value;
3735 if ((options & MT_ST_DEF_WRITES) != 0)
3736 STm->defaults_for_writes = value;
3737 if ((options & MT_ST_READ_AHEAD) != 0)
3738 STm->do_read_ahead = value;
3739 if ((options & MT_ST_TWO_FM) != 0)
3740 STp->two_fm = value;
3741 if ((options & MT_ST_FAST_MTEOM) != 0)
3742 STp->fast_mteom = value;
3743 if ((options & MT_ST_AUTO_LOCK) != 0)
3744 STp->do_auto_lock = value;
3745 if ((options & MT_ST_CAN_BSR) != 0)
3746 STp->can_bsr = value;
3747 if ((options & MT_ST_NO_BLKLIMS) != 0)
3748 STp->omit_blklims = value;
3749 if ((STp->device)->scsi_level >= SCSI_2 &&
3750 (options & MT_ST_CAN_PARTITIONS) != 0)
3751 STp->can_partitions = value;
3752 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3753 STp->scsi2_logical = value;
3754 if ((options & MT_ST_SYSV) != 0)
3757 if ((options & MT_ST_DEBUGGING) != 0)
3760 osst_log_options(STp, STm, name);
3762 else if (code == MT_ST_WRITE_THRESHOLD) {
3763 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3764 if (value < 1 || value > osst_buffer_size) {
3765 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3769 STp->write_threshold = value;
3770 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3773 else if (code == MT_ST_DEF_BLKSIZE) {
3774 value = (options & ~MT_ST_OPTIONS);
3775 if (value == ~MT_ST_OPTIONS) {
3776 STm->default_blksize = (-1);
3777 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3780 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3781 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3785 STm->default_blksize = value;
3786 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3787 name, STm->default_blksize);
3790 else if (code == MT_ST_TIMEOUTS) {
3791 value = (options & ~MT_ST_OPTIONS);
3792 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3793 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3794 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3795 (value & ~MT_ST_SET_LONG_TIMEOUT));
3798 STp->timeout = value * HZ;
3799 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3802 else if (code == MT_ST_DEF_OPTIONS) {
3803 code = (options & ~MT_ST_CLEAR_DEFAULT);
3804 value = (options & MT_ST_CLEAR_DEFAULT);
3805 if (code == MT_ST_DEF_DENSITY) {
3806 if (value == MT_ST_CLEAR_DEFAULT) {
3807 STm->default_density = (-1);
3808 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3811 STm->default_density = value & 0xff;
3812 printk(KERN_INFO "%s:I: Density default set to %x\n",
3813 name, STm->default_density);
3816 else if (code == MT_ST_DEF_DRVBUFFER) {
3817 if (value == MT_ST_CLEAR_DEFAULT) {
3818 STp->default_drvbuffer = 0xff;
3819 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3822 STp->default_drvbuffer = value & 7;
3823 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3824 name, STp->default_drvbuffer);
3827 else if (code == MT_ST_DEF_COMPRESSION) {
3828 if (value == MT_ST_CLEAR_DEFAULT) {
3829 STm->default_compression = ST_DONT_TOUCH;
3830 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3833 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3834 printk(KERN_INFO "%s:I: Compression default set to %x\n",
3846 /* Internal ioctl function */
3847 static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
3851 int i, ioctl_result;
3853 unsigned char cmd[MAX_COMMAND_SIZE];
3854 Scsi_Request * SRpnt = * aSRpnt;
3856 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3857 int datalen = 0, direction = SCSI_DATA_NONE;
3858 char * name = tape_name(STp);
3860 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3861 if (STp->ready == ST_NO_TAPE)
3862 return (-ENOMEDIUM);
3866 timeout = STp->long_timeout;
3867 STps = &(STp->ps[STp->partition]);
3868 fileno = STps->drv_file;
3869 blkno = STps->drv_block;
3870 at_sm = STps->at_sm;
3871 frame_seq_numbr = STp->frame_seq_number;
3872 logical_blk_num = STp->logical_blk_num;
3874 memset(cmd, 0, MAX_COMMAND_SIZE);
3877 chg_eof = FALSE; /* Changed from the FSF after this */
3881 if (STp->linux_media)
3882 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
3884 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
3888 at_sm &= (arg == 0);
3892 chg_eof = FALSE; /* Changed from the FSF after this */
3896 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
3899 blkno = (-1); /* We can't know the block number */
3900 at_sm &= (arg == 0);
3907 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
3908 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
3910 if (cmd_in == MTFSR) {
3911 logical_blk_num += arg;
3912 if (blkno >= 0) blkno += arg;
3915 logical_blk_num -= arg;
3916 if (blkno >= 0) blkno -= arg;
3918 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
3919 fileno = STps->drv_file;
3920 blkno = STps->drv_block;
3921 at_sm &= (arg == 0);
3926 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
3927 cmd[2] = (arg >> 16);
3928 cmd[3] = (arg >> 8);
3932 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
3933 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
3936 blkno = fileno = (-1);
3942 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
3944 cmd[2] = (ltmp >> 16);
3945 cmd[3] = (ltmp >> 8);
3951 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
3952 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
3957 blkno = fileno = (-1);
3962 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
3963 STp->write_type = OS_WRITE_DATA;
3964 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
3969 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
3971 for (i=0; i<arg; i++)
3972 ioctl_result |= osst_write_filemark(STp, &SRpnt);
3973 if (fileno >= 0) fileno += arg;
3974 if (blkno >= 0) blkno = 0;
3978 if (STp->write_prot)
3982 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
3983 if (cmd_in == MTWSM)
3985 cmd[2] = (arg >> 16);
3986 cmd[3] = (arg >> 8);
3988 timeout = STp->timeout;
3991 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
3992 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
3997 at_sm = (cmd_in == MTWSM);
4003 cmd[0] = START_STOP;
4004 cmd[1] = 1; /* Don't wait for completion */
4005 if (cmd_in == MTLOAD) {
4006 if (STp->ready == ST_NO_TAPE)
4007 cmd[4] = 4; /* open tray */
4009 cmd[4] = 1; /* load */
4011 if (cmd_in == MTRETEN)
4012 cmd[4] = 3; /* retension then mount */
4013 if (cmd_in == MTOFFL)
4014 cmd[4] = 4; /* rewind then eject */
4015 timeout = STp->timeout;
4020 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4023 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4026 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4029 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4034 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4039 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4041 return 0; /* Should do something ? */
4046 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4048 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4049 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4050 ioctl_result = -EIO;
4053 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4055 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4057 ioctl_result = -EIO;
4060 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4061 fileno = STp->filemark_cnt;
4066 if (STp->write_prot)
4068 ioctl_result = osst_reset_header(STp, &SRpnt);
4069 i = osst_write_eod(STp, &SRpnt);
4070 if (i < ioctl_result) ioctl_result = i;
4071 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4072 if (i < ioctl_result) ioctl_result = i;
4073 fileno = blkno = at_sm = 0 ;
4077 cmd[0] = REZERO_UNIT; /* rewind */
4081 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4083 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4086 case MTSETBLK: /* Set block length */
4087 if ((STps->drv_block == 0 ) &&
4089 ((STp->buffer)->buffer_bytes == 0) &&
4090 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4091 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4092 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4094 * Only allowed to change the block size if you opened the
4095 * device at the beginning of a file before writing anything.
4096 * Note, that when reading, changing block_size is futile,
4097 * as the size used when writing overrides it.
4099 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4100 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4101 name, STp->block_size);
4104 case MTSETDENSITY: /* Set tape density */
4105 case MTSETDRVBUFFER: /* Set drive buffering */
4106 case SET_DENS_AND_BLK: /* Set density and block size */
4108 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4109 return (-EIO); /* Not allowed if data in buffer */
4110 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4111 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4112 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4113 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4114 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4115 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4118 return 0; /* FIXME silently ignore if block size didn't change */
4124 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, TRUE);
4126 ioctl_result = (STp->buffer)->syscall_result;
4130 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4132 return ioctl_result;
4135 if (!ioctl_result) { /* SCSI command successful */
4136 STp->frame_seq_number = frame_seq_numbr;
4137 STp->logical_blk_num = logical_blk_num;
4143 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4146 if (!ioctl_result) { /* success */
4148 if (cmd_in == MTFSFM) {
4152 if (cmd_in == MTBSFM) {
4156 STps->drv_block = blkno;
4157 STps->drv_file = fileno;
4158 STps->at_sm = at_sm;
4160 if (cmd_in == MTEOM)
4162 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4163 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4165 STp->logical_blk_num++;
4166 STp->frame_seq_number++;
4167 STp->frame_in_buffer = 0;
4168 STp->buffer->read_pointer = 0;
4170 else if (cmd_in == MTFSF)
4171 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4173 STps->eof = ST_NOEOF;
4175 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4176 STp->rew_at_close = 0;
4177 else if (cmd_in == MTLOAD) {
4178 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4179 STp->ps[i].rw = ST_IDLE;
4180 STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */
4185 if (cmd_in == MTREW) {
4186 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4187 if (ioctl_result > 0)
4191 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4192 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4193 STps->drv_file = STps->drv_block = -1;
4195 STps->drv_file = STps->drv_block = 0;
4196 STps->eof = ST_NOEOF;
4197 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4198 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4199 STps->drv_file = STps->drv_block = -1;
4201 STps->drv_file = STp->filemark_cnt;
4202 STps->drv_block = 0;
4205 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4206 STps->drv_file = STps->drv_block = (-1);
4207 STps->eof = ST_NOEOF;
4209 } else if (cmd_in == MTERASE) {
4211 } else if (SRpnt) { /* SCSI command was not completely successful. */
4212 if (SRpnt->sr_sense_buffer[2] & 0x40) {
4213 STps->eof = ST_EOM_OK;
4214 STps->drv_block = 0;
4217 STps->eof = ST_NOEOF;
4219 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
4222 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4223 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4227 return ioctl_result;
4231 /* Open the device */
4232 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4234 unsigned short flags;
4235 int i, b_size, new_session = FALSE, retval = 0;
4236 unsigned char cmd[MAX_COMMAND_SIZE];
4237 Scsi_Request * SRpnt = NULL;
4242 int dev = TAPE_NR(inode);
4243 int mode = TAPE_MODE(inode);
4245 nonseekable_open(inode, filp);
4246 write_lock(&os_scsi_tapes_lock);
4247 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4248 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4249 write_unlock(&os_scsi_tapes_lock);
4253 name = tape_name(STp);
4256 write_unlock(&os_scsi_tapes_lock);
4258 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4262 if (scsi_device_get(STp->device)) {
4263 write_unlock(&os_scsi_tapes_lock);
4265 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4269 filp->private_data = STp;
4271 write_unlock(&os_scsi_tapes_lock);
4272 STp->rew_at_close = TAPE_REWIND(inode);
4274 if( !scsi_block_when_processing_errors(STp->device) ) {
4278 if (mode != STp->current_mode) {
4281 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4282 name, STp->current_mode, mode);
4285 STp->current_mode = mode;
4287 STm = &(STp->modes[STp->current_mode]);
4289 flags = filp->f_flags;
4290 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4292 STp->raw = TAPE_IS_RAW(inode);
4296 /* Allocate data segments for this device's tape buffer */
4297 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4298 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4299 retval = (-EOVERFLOW);
4302 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4303 for (i = 0, b_size = 0;
4304 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4305 b_size += STp->buffer->sg[i++].length);
4306 STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
4308 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4309 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4310 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4311 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4314 STp->buffer->aux = NULL; /* this had better never happen! */
4315 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4319 STp->buffer->writing = 0;
4320 STp->buffer->syscall_result = 0;
4322 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4323 STps = &(STp->ps[i]);
4326 STp->ready = ST_READY;
4328 STp->nbr_waits = STp->nbr_finished = 0;
4331 memset (cmd, 0, MAX_COMMAND_SIZE);
4332 cmd[0] = TEST_UNIT_READY;
4334 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
4336 retval = (STp->buffer)->syscall_result;
4339 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4340 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4341 SRpnt->sr_sense_buffer[12] == 4 ) {
4343 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sr_sense_buffer[13]);
4345 if (filp->f_flags & O_NONBLOCK) {
4349 if (SRpnt->sr_sense_buffer[13] == 2) { /* initialize command required (LOAD) */
4350 memset (cmd, 0, MAX_COMMAND_SIZE);
4351 cmd[0] = START_STOP;
4354 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4355 STp->timeout, MAX_READY_RETRIES, TRUE);
4357 osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
4359 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4360 (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4362 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4366 for (i=0; i < 10; i++) {
4368 memset (cmd, 0, MAX_COMMAND_SIZE);
4369 cmd[0] = TEST_UNIT_READY;
4371 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4372 STp->timeout, MAX_READY_RETRIES, TRUE);
4373 if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4374 (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
4378 STp->pos_unknown = 0;
4379 STp->partition = STp->new_partition = 0;
4380 if (STp->can_partitions)
4381 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4382 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4383 STps = &(STp->ps[i]);
4384 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4385 STps->eof = ST_NOEOF;
4387 STps->last_block_valid = FALSE;
4388 STps->drv_block = 0;
4389 STps->drv_file = 0 ;
4392 STp->recover_count = 0;
4395 * if we have valid headers from before, and the drive/tape seem untouched,
4396 * open without reconfiguring and re-reading the headers
4398 if (!STp->buffer->syscall_result && STp->header_ok &&
4399 !SRpnt->sr_result && SRpnt->sr_sense_buffer[0] == 0) {
4401 memset(cmd, 0, MAX_COMMAND_SIZE);
4402 cmd[0] = MODE_SENSE;
4404 cmd[2] = VENDOR_IDENT_PAGE;
4405 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4407 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
4409 if (STp->buffer->syscall_result ||
4410 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4411 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4412 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4413 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4415 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4416 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4417 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4418 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4419 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4423 i = STp->first_frame_position;
4424 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4425 if (STp->door_locked == ST_UNLOCKED) {
4426 if (do_door_lock(STp, 1))
4427 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4429 STp->door_locked = ST_LOCKED_AUTO;
4431 if (!STp->frame_in_buffer) {
4432 STp->block_size = (STm->default_blksize > 0) ?
4433 STm->default_blksize : OS_DATA_SIZE;
4434 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4436 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4437 STp->fast_open = TRUE;
4438 scsi_release_request(SRpnt);
4442 if (i != STp->first_frame_position)
4443 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4444 name, i, STp->first_frame_position);
4448 STp->fast_open = FALSE;
4450 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4451 (SRpnt->sr_sense_buffer[2] != 2 || SRpnt->sr_sense_buffer[12] != 0x3A) ) {
4453 memset(cmd, 0, MAX_COMMAND_SIZE);
4454 cmd[0] = MODE_SELECT;
4456 cmd[4] = 4 + MODE_HEADER_LENGTH;
4458 (STp->buffer)->b_data[0] = cmd[4] - 1;
4459 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4460 (STp->buffer)->b_data[2] = 0; /* Reserved */
4461 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4462 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4463 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4464 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4465 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4468 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4470 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
4474 for (i=0; i < 10; i++) {
4476 memset (cmd, 0, MAX_COMMAND_SIZE);
4477 cmd[0] = TEST_UNIT_READY;
4479 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4480 STp->timeout, MAX_READY_RETRIES, TRUE);
4481 if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4482 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
4485 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {
4486 STp->pos_unknown = 0;
4487 STp->partition = STp->new_partition = 0;
4488 if (STp->can_partitions)
4489 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4490 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4491 STps = &(STp->ps[i]);
4493 STps->eof = ST_NOEOF;
4495 STps->last_block_valid = FALSE;
4496 STps->drv_block = 0;
4497 STps->drv_file = 0 ;
4504 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4505 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4507 if ((STp->buffer)->syscall_result != 0) {
4508 if ((STp->device)->scsi_level >= SCSI_2 &&
4509 (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4510 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4511 SRpnt->sr_sense_buffer[12] == 0x3a) { /* Check ASC */
4512 STp->ready = ST_NO_TAPE;
4514 STp->ready = ST_NOT_READY;
4515 scsi_release_request(SRpnt);
4517 STp->density = 0; /* Clear the erroneous "residue" */
4518 STp->write_prot = 0;
4519 STp->block_size = 0;
4520 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4521 STp->partition = STp->new_partition = 0;
4522 STp->door_locked = ST_UNLOCKED;
4526 osst_configure_onstream(STp, &SRpnt);
4528 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4529 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4530 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4531 STp->buffer->buffer_bytes =
4532 STp->buffer->read_pointer =
4533 STp->frame_in_buffer = 0;
4537 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4538 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4539 (STp->buffer)->buffer_blocks);
4542 if (STp->drv_write_prot) {
4543 STp->write_prot = 1;
4546 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4548 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4554 if (new_session) { /* Change the drive parameters for the new mode */
4557 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4559 STp->density_changed = STp->blksize_changed = FALSE;
4560 STp->compression_changed = FALSE;
4564 * properly position the tape and check the ADR headers
4566 if (STp->door_locked == ST_UNLOCKED) {
4567 if (do_door_lock(STp, 1))
4568 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4570 STp->door_locked = ST_LOCKED_AUTO;
4573 osst_analyze_headers(STp, &SRpnt);
4575 scsi_release_request(SRpnt);
4582 scsi_release_request(SRpnt);
4583 normalize_buffer(STp->buffer);
4586 scsi_device_put(STp->device);
4592 /* Flush the tape buffer before close */
4593 static int os_scsi_tape_flush(struct file * filp)
4595 int result = 0, result2;
4596 OS_Scsi_Tape * STp = filp->private_data;
4597 ST_mode * STm = &(STp->modes[STp->current_mode]);
4598 ST_partstat * STps = &(STp->ps[STp->partition]);
4599 Scsi_Request * SRpnt = NULL;
4600 char * name = tape_name(STp);
4602 if (file_count(filp) > 1)
4605 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4606 STp->write_type = OS_WRITE_DATA;
4607 result = osst_flush_write_buffer(STp, &SRpnt);
4608 if (result != 0 && result != (-ENOSPC))
4611 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4615 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4616 name, (long)(filp->f_pos));
4617 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4618 name, STp->nbr_waits, STp->nbr_finished);
4621 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4624 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4625 name, 1+STp->two_fm);
4628 else if (!STp->rew_at_close) {
4629 STps = &(STp->ps[STp->partition]);
4630 if (!STm->sysv || STps->rw != ST_READING) {
4632 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4633 else if (STps->eof == ST_FM_HIT) {
4634 result = cross_eof(STp, &SRpnt, FALSE);
4636 if (STps->drv_file >= 0)
4638 STps->drv_block = 0;
4642 STps->eof = ST_NOEOF;
4645 else if ((STps->eof == ST_NOEOF &&
4646 !(result = cross_eof(STp, &SRpnt, TRUE))) ||
4647 STps->eof == ST_FM_HIT) {
4648 if (STps->drv_file >= 0)
4650 STps->drv_block = 0;
4656 if (STp->rew_at_close) {
4657 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4658 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4659 if (result == 0 && result2 < 0)
4662 if (SRpnt) scsi_release_request(SRpnt);
4664 if (STp->recover_count) {
4665 printk(KERN_INFO "%s:I: %d recovered errors in", name, STp->recover_count);
4666 if (STp->write_count)
4667 printk(" %d frames written", STp->write_count);
4668 if (STp->read_count)
4669 printk(" %d frames read", STp->read_count);
4671 STp->recover_count = 0;
4673 STp->write_count = 0;
4674 STp->read_count = 0;
4680 /* Close the device and release it */
4681 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4684 OS_Scsi_Tape * STp = filp->private_data;
4685 Scsi_Request * SRpnt = NULL;
4687 if (SRpnt) scsi_release_request(SRpnt);
4689 if (STp->door_locked == ST_LOCKED_AUTO)
4690 do_door_lock(STp, 0);
4695 normalize_buffer(STp->buffer);
4696 write_lock(&os_scsi_tapes_lock);
4698 write_unlock(&os_scsi_tapes_lock);
4700 scsi_device_put(STp->device);
4706 /* The ioctl command */
4707 static int osst_ioctl(struct inode * inode,struct file * file,
4708 unsigned int cmd_in, unsigned long arg)
4710 int i, cmd_nr, cmd_type, retval = 0;
4714 Scsi_Request * SRpnt = NULL;
4715 OS_Scsi_Tape * STp = file->private_data;
4716 char * name = tape_name(STp);
4717 void __user *p = (void __user *)arg;
4719 if (down_interruptible(&STp->lock))
4720 return -ERESTARTSYS;
4723 if (debugging && !STp->in_use) {
4724 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4729 STm = &(STp->modes[STp->current_mode]);
4730 STps = &(STp->ps[STp->partition]);
4733 * If we are in the middle of error recovery, don't let anyone
4734 * else try and use this device. Also, if error recovery fails, it
4735 * may try and take the device offline, in which case all further
4736 * access to the device is prohibited.
4738 if( !scsi_block_when_processing_errors(STp->device) ) {
4743 cmd_type = _IOC_TYPE(cmd_in);
4744 cmd_nr = _IOC_NR(cmd_in);
4746 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4747 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4749 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4753 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4758 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4764 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4765 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4770 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4775 if (!STp->pos_unknown) {
4777 if (STps->eof == ST_FM_HIT) {
4778 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4780 if (STps->drv_file >= 0)
4781 STps->drv_file += 1;
4783 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4785 if (STps->drv_file >= 0)
4786 STps->drv_file += 1;
4790 if (mtc.mt_op == MTSEEK) {
4791 /* Old position must be restored if partition will be changed */
4792 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4795 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
4796 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
4797 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
4798 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
4799 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
4800 mtc.mt_op == MTCOMPRESSION;
4802 i = osst_flush_buffer(STp, &SRpnt, i);
4810 * If there was a bus reset, block further access
4811 * to this device. If the user wants to rewind the tape,
4812 * then reset the flag and allow access again.
4814 if(mtc.mt_op != MTREW &&
4815 mtc.mt_op != MTOFFL &&
4816 mtc.mt_op != MTRETEN &&
4817 mtc.mt_op != MTERASE &&
4818 mtc.mt_op != MTSEEK &&
4819 mtc.mt_op != MTEOM) {
4824 /* remove this when the midlevel properly clears was_reset */
4825 STp->device->was_reset = 0;
4828 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
4829 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
4830 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
4831 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
4832 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
4835 * The user tells us to move to another position on the tape.
4836 * If we were appending to the tape content, that would leave
4837 * the tape without proper end, in that case write EOD and
4838 * update the header to reflect its position.
4841 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
4842 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
4843 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
4844 STp->logical_blk_num, STps->drv_file, STps->drv_block );
4846 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
4847 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
4848 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4849 i = osst_write_trailer(STp, &SRpnt,
4850 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4852 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4853 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
4854 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
4864 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
4865 do_door_lock(STp, 0); /* Ignore result! */
4867 if (mtc.mt_op == MTSETDRVBUFFER &&
4868 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
4869 retval = osst_set_options(STp, mtc.mt_count);
4873 if (mtc.mt_op == MTSETPART) {
4874 if (mtc.mt_count >= STp->nbr_partitions)
4877 STp->new_partition = mtc.mt_count;
4883 if (mtc.mt_op == MTMKPART) {
4884 if (!STp->can_partitions) {
4888 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
4889 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
4893 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4894 STp->ps[i].rw = ST_IDLE;
4895 STp->ps[i].at_sm = 0;
4896 STp->ps[i].last_block_valid = FALSE;
4898 STp->partition = STp->new_partition = 0;
4899 STp->nbr_partitions = 1; /* Bad guess ?-) */
4900 STps->drv_block = STps->drv_file = 0;
4905 if (mtc.mt_op == MTSEEK) {
4907 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
4909 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
4910 if (!STp->can_partitions)
4911 STp->ps[0].rw = ST_IDLE;
4916 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
4917 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
4922 cross_eof(STp, &SRpnt, FALSE);
4924 if (mtc.mt_op == MTCOMPRESSION)
4925 retval = -EINVAL; /* OnStream drives don't have compression hardware */
4927 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
4928 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
4929 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
4933 if (!STm->defined) {
4938 if ((i = osst_flush_buffer(STp, &SRpnt, FALSE)) < 0) {
4943 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
4944 struct mtget mt_status;
4946 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
4951 mt_status.mt_type = MT_ISONSTREAM_SC;
4952 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
4953 mt_status.mt_dsreg =
4954 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
4955 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
4956 mt_status.mt_blkno = STps->drv_block;
4957 mt_status.mt_fileno = STps->drv_file;
4958 if (STp->block_size != 0) {
4959 if (STps->rw == ST_WRITING)
4960 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
4961 else if (STps->rw == ST_READING)
4962 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
4963 STp->block_size - 1) / STp->block_size;
4966 mt_status.mt_gstat = 0;
4967 if (STp->drv_write_prot)
4968 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
4969 if (mt_status.mt_blkno == 0) {
4970 if (mt_status.mt_fileno == 0)
4971 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
4973 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
4975 mt_status.mt_resid = STp->partition;
4976 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
4977 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
4978 else if (STps->eof >= ST_EOM_OK)
4979 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
4980 if (STp->density == 1)
4981 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
4982 else if (STp->density == 2)
4983 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
4984 else if (STp->density == 3)
4985 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
4986 if (STp->ready == ST_READY)
4987 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
4988 if (STp->ready == ST_NO_TAPE)
4989 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
4991 mt_status.mt_gstat |= GMT_SM(0xffffffff);
4992 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
4993 STp->drv_buffer != 0)
4994 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
4996 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5002 STp->recover_erreg = 0; /* Clear after read */
5005 } /* End of MTIOCGET */
5007 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5008 struct mtpos mt_pos;
5010 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5015 blk = osst_get_frame_position(STp, &SRpnt);
5017 blk = osst_get_sector(STp, &SRpnt);
5022 mt_pos.mt_blkno = blk;
5023 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5028 if (SRpnt) scsi_release_request(SRpnt);
5032 return scsi_ioctl(STp->device, cmd_in, p);
5035 if (SRpnt) scsi_release_request(SRpnt);
5043 /* Memory handling routines */
5045 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5046 static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5051 if (from_initialization)
5052 priority = GFP_ATOMIC;
5054 priority = GFP_KERNEL;
5056 i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5057 tb = (OSST_buffer *)kmalloc(i, priority);
5059 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5063 tb->sg_segs = tb->orig_sg_segs = 0;
5064 tb->use_sg = max_sg;
5067 tb->buffer_size = 0;
5071 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5072 i, max_sg, need_dma);
5077 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5078 static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
5080 int segs, nbr, max_segs, b_size, priority, order, got;
5082 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5085 if (STbuffer->sg_segs) {
5086 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5087 normalize_buffer(STbuffer);
5089 /* See how many segments we can use -- need at least two */
5090 nbr = max_segs = STbuffer->use_sg;
5094 priority = GFP_KERNEL;
5096 priority |= GFP_DMA;
5098 priority |= __GFP_NOWARN;
5100 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5101 big enough to reach the goal (code assumes no segments in place) */
5102 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5103 STbuffer->sg[0].page = alloc_pages(priority, order);
5104 STbuffer->sg[0].offset = 0;
5105 if (STbuffer->sg[0].page != NULL) {
5106 STbuffer->sg[0].length = b_size;
5107 STbuffer->b_data = page_address(STbuffer->sg[0].page);
5111 if (STbuffer->sg[0].page == NULL) {
5112 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5115 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5116 for (segs=STbuffer->sg_segs=1, got=b_size;
5117 segs < max_segs && got < OS_FRAME_SIZE; ) {
5118 STbuffer->sg[segs].page =
5119 alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5120 STbuffer->sg[segs].offset = 0;
5121 if (STbuffer->sg[segs].page == NULL) {
5122 if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
5123 b_size /= 2; /* Large enough for the rest of the buffers */
5127 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5130 STbuffer->buffer_size = got;
5132 normalize_buffer(STbuffer);
5135 STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size;
5136 got += STbuffer->sg[segs].length;
5137 STbuffer->buffer_size = got;
5138 STbuffer->sg_segs = ++segs;
5143 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5144 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5146 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5147 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5148 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5156 /* Release the segments */
5157 static void normalize_buffer(OSST_buffer *STbuffer)
5159 int i, order, b_size;
5161 for (i=0; i < STbuffer->sg_segs; i++) {
5163 for (b_size = PAGE_SIZE, order = 0;
5164 b_size < STbuffer->sg[i].length;
5165 b_size *= 2, order++);
5167 __free_pages(STbuffer->sg[i].page, order);
5168 STbuffer->buffer_size -= STbuffer->sg[i].length;
5171 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5172 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5173 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5175 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5179 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5180 negative error code. */
5181 static int append_to_buffer(const char __user *ubp, OSST_buffer *st_bp, int do_count)
5183 int i, cnt, res, offset;
5185 for (i=0, offset=st_bp->buffer_bytes;
5186 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5187 offset -= st_bp->sg[i].length;
5188 if (i == st_bp->sg_segs) { /* Should never happen */
5189 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5192 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5193 cnt = st_bp->sg[i].length - offset < do_count ?
5194 st_bp->sg[i].length - offset : do_count;
5195 res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
5199 st_bp->buffer_bytes += cnt;
5203 if (do_count) { /* Should never happen */
5204 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5212 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5213 negative error code. */
5214 static int from_buffer(OSST_buffer *st_bp, char __user *ubp, int do_count)
5216 int i, cnt, res, offset;
5218 for (i=0, offset=st_bp->read_pointer;
5219 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5220 offset -= st_bp->sg[i].length;
5221 if (i == st_bp->sg_segs) { /* Should never happen */
5222 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5225 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5226 cnt = st_bp->sg[i].length - offset < do_count ?
5227 st_bp->sg[i].length - offset : do_count;
5228 res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
5232 st_bp->buffer_bytes -= cnt;
5233 st_bp->read_pointer += cnt;
5237 if (do_count) { /* Should never happen */
5238 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5244 /* Sets the tail of the buffer after fill point to zero.
5245 Returns zero (success) or negative error code. */
5246 static int osst_zero_buffer_tail(OSST_buffer *st_bp)
5248 int i, offset, do_count, cnt;
5250 for (i = 0, offset = st_bp->buffer_bytes;
5251 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5252 offset -= st_bp->sg[i].length;
5253 if (i == st_bp->sg_segs) { /* Should never happen */
5254 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5257 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5258 i < st_bp->sg_segs && do_count > 0; i++) {
5259 cnt = st_bp->sg[i].length - offset < do_count ?
5260 st_bp->sg[i].length - offset : do_count ;
5261 memset(page_address(st_bp->sg[i].page) + offset, 0, cnt);
5265 if (do_count) { /* Should never happen */
5266 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5272 /* Copy a osst 32K chunk of memory into the buffer.
5273 Returns zero (success) or negative error code. */
5274 static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5276 int i, cnt, do_count = OS_DATA_SIZE;
5278 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5279 cnt = st_bp->sg[i].length < do_count ?
5280 st_bp->sg[i].length : do_count ;
5281 memcpy(page_address(st_bp->sg[i].page), ptr, cnt);
5285 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5286 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5293 /* Copy a osst 32K chunk of memory from the buffer.
5294 Returns zero (success) or negative error code. */
5295 static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5297 int i, cnt, do_count = OS_DATA_SIZE;
5299 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5300 cnt = st_bp->sg[i].length < do_count ?
5301 st_bp->sg[i].length : do_count ;
5302 memcpy(ptr, page_address(st_bp->sg[i].page), cnt);
5306 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5307 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5315 /* Module housekeeping */
5317 static void validate_options (void)
5320 osst_max_dev = max_dev;
5321 if (write_threshold_kbs > 0)
5322 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5323 if (osst_write_threshold > osst_buffer_size)
5324 osst_write_threshold = osst_buffer_size;
5325 if (max_sg_segs >= OSST_FIRST_SG)
5326 osst_max_sg_segs = max_sg_segs;
5328 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5329 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5334 /* Set the boot options. Syntax: osst=xxx,yyy,...
5335 where xxx is write threshold in 1024 byte blocks,
5336 and yyy is number of s/g segments to use. */
5337 static int __init osst_setup (char *str)
5342 stp = get_options(str, ARRAY_SIZE(ints), ints);
5345 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5346 *parms[i].val = ints[i + 1];
5348 while (stp != NULL) {
5349 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5350 int len = strlen(parms[i].name);
5351 if (!strncmp(stp, parms[i].name, len) &&
5352 (*(stp + len) == ':' || *(stp + len) == '=')) {
5354 simple_strtoul(stp + len + 1, NULL, 0);
5358 if (i >= sizeof(parms) / sizeof(struct osst_dev_parm))
5359 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5361 stp = strchr(stp, ',');
5370 __setup("osst=", osst_setup);
5374 static struct file_operations osst_fops = {
5375 .owner = THIS_MODULE,
5377 .write = osst_write,
5378 .ioctl = osst_ioctl,
5379 .open = os_scsi_tape_open,
5380 .flush = os_scsi_tape_flush,
5381 .release = os_scsi_tape_close,
5384 static int osst_supports(Scsi_Device * SDp)
5386 struct osst_support_data {
5390 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5393 static struct osst_support_data support_list[] = {
5394 /* {"XXX", "Yy-", "", NULL}, example */
5398 struct osst_support_data *rp;
5400 /* We are willing to drive OnStream SC-x0 as well as the
5401 * * IDE, ParPort, FireWire, USB variants, if accessible by
5402 * * emulation layer (ide-scsi, usb-storage, ...) */
5404 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5405 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5406 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5407 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5413 * osst startup / cleanup code
5416 static int osst_probe(struct device *dev)
5418 Scsi_Device * SDp = to_scsi_device(dev);
5419 OS_Scsi_Tape * tpnt;
5422 OSST_buffer * buffer;
5423 struct gendisk * drive;
5424 int i, mode, dev_num;
5426 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5429 drive = alloc_disk(1);
5431 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5435 /* if this is the first attach, build the infrastructure */
5436 write_lock(&os_scsi_tapes_lock);
5437 if (os_scsi_tapes == NULL) {
5439 (OS_Scsi_Tape **)kmalloc(osst_max_dev * sizeof(OS_Scsi_Tape *),
5441 if (os_scsi_tapes == NULL) {
5442 write_unlock(&os_scsi_tapes_lock);
5443 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5446 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5449 if (osst_nr_dev >= osst_max_dev) {
5450 write_unlock(&os_scsi_tapes_lock);
5451 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5455 /* find a free minor number */
5456 for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++);
5457 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5460 /* allocate a OS_Scsi_Tape for this device */
5461 tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
5463 write_unlock(&os_scsi_tapes_lock);
5464 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5467 memset(tpnt, 0, sizeof(OS_Scsi_Tape));
5469 /* allocate a buffer for this device */
5470 i = SDp->host->sg_tablesize;
5471 if (osst_max_sg_segs < i)
5472 i = osst_max_sg_segs;
5473 buffer = new_tape_buffer(TRUE, SDp->host->unchecked_isa_dma, i);
5474 if (buffer == NULL) {
5475 write_unlock(&os_scsi_tapes_lock);
5476 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5480 os_scsi_tapes[dev_num] = tpnt;
5481 tpnt->buffer = buffer;
5483 drive->private_data = &tpnt->driver;
5484 sprintf(drive->disk_name, "osst%d", dev_num);
5485 tpnt->driver = &osst_template;
5486 tpnt->drive = drive;
5488 tpnt->capacity = 0xfffff;
5490 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
5491 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5493 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5494 tpnt->can_bsr = OSST_IN_FILE_POS;
5495 tpnt->can_partitions = 0;
5496 tpnt->two_fm = OSST_TWO_FM;
5497 tpnt->fast_mteom = OSST_FAST_MTEOM;
5498 tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5499 tpnt->write_threshold = osst_write_threshold;
5500 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5501 tpnt->partition = 0;
5502 tpnt->new_partition = 0;
5503 tpnt->nbr_partitions = 0;
5504 tpnt->min_block = 512;
5505 tpnt->max_block = OS_DATA_SIZE;
5506 tpnt->timeout = OSST_TIMEOUT;
5507 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5509 /* Recognize OnStream tapes */
5510 /* We don't need to test for OnStream, as this has been done in detect () */
5511 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5512 tpnt->omit_blklims = 1;
5514 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5515 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5516 tpnt->frame_in_buffer = 0;
5517 tpnt->header_ok = 0;
5518 tpnt->linux_media = 0;
5519 tpnt->header_cache = NULL;
5521 for (i=0; i < ST_NBR_MODES; i++) {
5522 STm = &(tpnt->modes[i]);
5523 STm->defined = FALSE;
5524 STm->sysv = OSST_SYSV;
5525 STm->defaults_for_writes = 0;
5526 STm->do_async_writes = OSST_ASYNC_WRITES;
5527 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5528 STm->do_read_ahead = OSST_READ_AHEAD;
5529 STm->default_compression = ST_DONT_TOUCH;
5530 STm->default_blksize = 512;
5531 STm->default_density = (-1); /* No forced density */
5534 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5535 STps = &(tpnt->ps[i]);
5537 STps->eof = ST_NOEOF;
5539 STps->last_block_valid = FALSE;
5540 STps->drv_block = (-1);
5541 STps->drv_file = (-1);
5544 tpnt->current_mode = 0;
5545 tpnt->modes[0].defined = TRUE;
5546 tpnt->modes[2].defined = TRUE;
5547 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = FALSE;
5549 init_MUTEX(&tpnt->lock);
5551 write_unlock(&os_scsi_tapes_lock);
5553 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5555 devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
5556 S_IFCHR | S_IRUGO | S_IWUGO,
5557 "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
5559 /* No-rewind entry */
5560 devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128),
5561 S_IFCHR | S_IRUGO | S_IWUGO,
5562 "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
5564 drive->number = devfs_register_tape(SDp->devfs_name);
5567 "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n",
5568 SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt));
5577 static int osst_remove(struct device *dev)
5579 Scsi_Device * SDp = to_scsi_device(dev);
5580 OS_Scsi_Tape * tpnt;
5583 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
5586 write_lock(&os_scsi_tapes_lock);
5587 for(i=0; i < osst_max_dev; i++) {
5588 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
5589 tpnt->device = NULL;
5590 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5591 devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
5592 devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
5594 devfs_unregister_tape(tpnt->drive->number);
5595 put_disk(tpnt->drive);
5596 os_scsi_tapes[i] = NULL;
5598 write_unlock(&os_scsi_tapes_lock);
5599 if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
5601 normalize_buffer(tpnt->buffer);
5602 kfree(tpnt->buffer);
5608 write_unlock(&os_scsi_tapes_lock);
5612 static int __init init_osst(void)
5614 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5618 if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
5619 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
5626 static void __exit exit_osst (void)
5631 scsi_unregister_driver(&osst_template.gendrv);
5632 unregister_chrdev(OSST_MAJOR, "osst");
5634 if (os_scsi_tapes) {
5635 for (i=0; i < osst_max_dev; ++i) {
5636 if (!(STp = os_scsi_tapes[i])) continue;
5637 /* This is defensive, supposed to happen during detach */
5638 if (STp->header_cache)
5639 vfree(STp->header_cache);
5641 normalize_buffer(STp->buffer);
5644 put_disk(STp->drive);
5647 kfree(os_scsi_tapes);
5649 printk(KERN_INFO "osst :I: Unloaded.\n");
5652 module_init(init_osst);
5653 module_exit(exit_osst);