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
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 *, OSST_buffer *, int);
158 static int from_buffer(OSST_buffer *, char *, 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 * 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 * 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 (ppos != &filp->f_pos) {
3189 /* "A request was outside the capabilities of the device." */
3194 if (STp->ready != ST_READY) {
3195 if (STp->ready == ST_NO_TAPE)
3196 retval = (-ENOMEDIUM);
3201 STm = &(STp->modes[STp->current_mode]);
3202 if (!STm->defined) {
3210 * If there was a bus reset, block further access
3213 if (STp->pos_unknown) {
3220 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3226 if (STp->write_prot) {
3231 /* Write must be integral number of blocks */
3232 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3233 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3234 name, count, STp->block_size<1024?
3235 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3240 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3241 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3242 name, STp->first_frame_position);
3247 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3248 STp->door_locked = ST_LOCKED_AUTO;
3250 STps = &(STp->ps[STp->partition]);
3252 if (STps->rw == ST_READING) {
3254 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3255 STps->drv_file, STps->drv_block);
3257 retval = osst_flush_buffer(STp, &SRpnt, 0);
3262 if (STps->rw != ST_WRITING) {
3263 /* Are we totally rewriting this tape? */
3264 if (!STp->header_ok ||
3265 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3266 (STps->drv_file == 0 && STps->drv_block == 0)) {
3267 STp->wrt_pass_cntr++;
3269 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3270 name, STp->wrt_pass_cntr);
3272 osst_reset_header(STp, &SRpnt);
3273 STps->drv_file = STps->drv_block = 0;
3275 /* Do we know where we'll be writing on the tape? */
3277 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3278 STps->drv_file < 0 || STps->drv_block < 0) {
3279 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3280 STps->drv_file = STp->filemark_cnt;
3281 STps->drv_block = 0;
3284 /* We have no idea where the tape is positioned - give up */
3287 "%s:D: Cannot write at indeterminate position.\n", name);
3293 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3294 STp->filemark_cnt = STps->drv_file;
3295 STp->last_mark_ppos =
3296 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3298 "%s:W: Overwriting file %d with old write pass counter %d\n",
3299 name, STps->drv_file, STp->wrt_pass_cntr);
3301 "%s:W: may lead to stale data being accepted on reading back!\n",
3305 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3306 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3310 STp->fast_open = FALSE;
3312 if (!STp->header_ok) {
3314 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3320 if ((STp->buffer)->writing) {
3321 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3322 osst_write_behind_check(STp);
3323 if ((STp->buffer)->syscall_result) {
3326 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3327 (STp->buffer)->midlevel_result);
3329 if ((STp->buffer)->midlevel_result == INT_MAX)
3330 STps->eof = ST_EOM_OK;
3332 STps->eof = ST_EOM_ERROR;
3335 if (STps->eof == ST_EOM_OK) {
3339 else if (STps->eof == ST_EOM_ERROR) {
3344 /* Check the buffer readability in cases where copy_user might catch
3345 the problems after some tape movement. */
3346 if ((copy_from_user(&i, buf, 1) != 0 ||
3347 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3352 if (!STm->do_buffer_writes) {
3353 write_threshold = 1;
3356 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3357 if (!STm->do_async_writes)
3363 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3364 name, count, STps->drv_file, STps->drv_block,
3365 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3368 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3371 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3372 (STp->buffer)->buffer_bytes;
3373 if (do_count > count)
3376 i = append_to_buffer(b_point, STp->buffer, do_count);
3382 blks = do_count / STp->block_size;
3383 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3385 i = osst_write_frame(STp, &SRpnt, TRUE);
3387 if (i == (-ENOSPC)) {
3388 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3389 if (transfer <= do_count) {
3390 filp->f_pos += do_count - transfer;
3391 count -= do_count - transfer;
3392 if (STps->drv_block >= 0) {
3393 STps->drv_block += (do_count - transfer) / STp->block_size;
3395 STps->eof = ST_EOM_OK;
3396 retval = (-ENOSPC); /* EOM within current request */
3399 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3404 STps->eof = ST_EOM_ERROR;
3405 STps->drv_block = (-1); /* Too cautious? */
3406 retval = (-EIO); /* EOM for old data */
3409 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3417 if (SRpnt != NULL) {
3418 scsi_release_request(SRpnt);
3421 STp->buffer->buffer_bytes = 0;
3424 retval = total - count;
3428 filp->f_pos += do_count;
3429 b_point += do_count;
3431 if (STps->drv_block >= 0) {
3432 STps->drv_block += blks;
3434 STp->buffer->buffer_bytes = 0;
3436 } /* end while write threshold exceeded */
3440 i = append_to_buffer(b_point, STp->buffer, count);
3445 blks = count / STp->block_size;
3446 STp->logical_blk_num += blks;
3447 if (STps->drv_block >= 0) {
3448 STps->drv_block += blks;
3450 filp->f_pos += count;
3454 if (doing_write && (STp->buffer)->syscall_result != 0) {
3455 retval = (STp->buffer)->syscall_result;
3459 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3460 /* Schedule an asynchronous write */
3461 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3462 STp->block_size) * STp->block_size;
3463 STp->dirty = !((STp->buffer)->writing ==
3464 (STp->buffer)->buffer_bytes);
3466 i = osst_write_frame(STp, &SRpnt, FALSE);
3471 SRpnt = NULL; /* Prevent releasing this request! */
3473 STps->at_sm &= (total == 0);
3475 STps->eof = ST_NOEOF;
3480 if (SRpnt != NULL) scsi_release_request(SRpnt);
3489 static ssize_t osst_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
3491 ssize_t total, retval = 0;
3492 ssize_t i, transfer;
3496 Scsi_Request * SRpnt = NULL;
3497 OS_Scsi_Tape * STp = filp->private_data;
3498 char * name = tape_name(STp);
3501 if (down_interruptible(&STp->lock))
3502 return (-ERESTARTSYS);
3505 * If we are in the middle of error recovery, don't let anyone
3506 * else try and use this device. Also, if error recovery fails, it
3507 * may try and take the device offline, in which case all further
3508 * access to the device is prohibited.
3510 if( !scsi_block_when_processing_errors(STp->device) ) {
3515 if (ppos != &filp->f_pos) {
3516 /* "A request was outside the capabilities of the device." */
3521 if (STp->ready != ST_READY) {
3522 if (STp->ready == ST_NO_TAPE)
3523 retval = (-ENOMEDIUM);
3528 STm = &(STp->modes[STp->current_mode]);
3529 if (!STm->defined) {
3535 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3540 /* Must have initialized medium */
3541 if (!STp->header_ok) {
3546 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3547 STp->door_locked = ST_LOCKED_AUTO;
3549 STps = &(STp->ps[STp->partition]);
3550 if (STps->rw == ST_WRITING) {
3551 retval = osst_flush_buffer(STp, &SRpnt, 0);
3555 /* FIXME -- this may leave the tape without EOD and up2date headers */
3558 if ((count % STp->block_size) != 0) {
3560 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3561 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3565 if (debugging && STps->eof != ST_NOEOF)
3566 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3567 STps->eof, (STp->buffer)->buffer_bytes);
3569 if ((STp->buffer)->buffer_bytes == 0 &&
3570 STps->eof >= ST_EOD_1) {
3571 if (STps->eof < ST_EOD) {
3576 retval = (-EIO); /* EOM or Blank Check */
3580 /* Check the buffer writability before any tape movement. Don't alter
3582 if (copy_from_user(&i, buf, 1) != 0 ||
3583 copy_to_user (buf, &i, 1) != 0 ||
3584 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3585 copy_to_user (buf + count - 1, &i, 1) != 0) {
3590 /* Loop until enough data in buffer or a special condition found */
3591 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3593 /* Get new data if the buffer is empty */
3594 if ((STp->buffer)->buffer_bytes == 0) {
3595 if (STps->eof == ST_FM_HIT)
3597 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3598 if (special < 0) { /* No need to continue read */
3599 STp->frame_in_buffer = 0;
3605 /* Move the data from driver buffer to user buffer */
3606 if ((STp->buffer)->buffer_bytes > 0) {
3608 if (debugging && STps->eof != ST_NOEOF)
3609 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3610 STps->eof, (STp->buffer)->buffer_bytes, count - total);
3612 /* force multiple of block size, note block_size may have been adjusted */
3613 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3614 (STp->buffer)->buffer_bytes : count - total)/
3615 STp->block_size) * STp->block_size;
3617 if (transfer == 0) {
3619 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3620 name, count, STp->block_size < 1024?
3621 STp->block_size:STp->block_size/1024,
3622 STp->block_size<1024?'b':'k');
3625 i = from_buffer(STp->buffer, buf, transfer);
3630 STp->logical_blk_num += transfer / STp->block_size;
3631 STps->drv_block += transfer / STp->block_size;
3632 filp->f_pos += transfer;
3637 if ((STp->buffer)->buffer_bytes == 0) {
3640 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3641 name, STp->frame_seq_number);
3643 STp->frame_in_buffer = 0;
3644 STp->frame_seq_number++; /* frame to look for next time */
3646 } /* for (total = 0, special = 0; total < count && !special; ) */
3648 /* Change the eof state if no data from tape or buffer */
3650 if (STps->eof == ST_FM_HIT) {
3651 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3652 STps->drv_block = 0;
3653 if (STps->drv_file >= 0)
3656 else if (STps->eof == ST_EOD_1) {
3657 STps->eof = ST_EOD_2;
3658 if (STps->drv_block > 0 && STps->drv_file >= 0)
3660 STps->drv_block = 0;
3662 else if (STps->eof == ST_EOD_2)
3665 else if (STps->eof == ST_FM)
3666 STps->eof = ST_NOEOF;
3671 if (SRpnt != NULL) scsi_release_request(SRpnt);
3679 /* Set the driver options */
3680 static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, char *name)
3683 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3684 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3685 STm->do_read_ahead);
3687 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3688 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3690 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3691 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3692 STp->scsi2_logical);
3694 "%s:I: sysv: %d\n", name, STm->sysv);
3697 "%s:D: debugging: %d\n",
3703 static int osst_set_options(OS_Scsi_Tape *STp, long options)
3708 char * name = tape_name(STp);
3710 STm = &(STp->modes[STp->current_mode]);
3711 if (!STm->defined) {
3712 memcpy(STm, &(STp->modes[0]), sizeof(ST_mode));
3713 modes_defined = TRUE;
3716 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3717 name, STp->current_mode);
3721 code = options & MT_ST_OPTIONS;
3722 if (code == MT_ST_BOOLEANS) {
3723 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3724 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3725 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3726 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3727 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3728 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3729 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3730 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3731 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3732 if ((STp->device)->scsi_level >= SCSI_2)
3733 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3734 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3735 STm->sysv = (options & MT_ST_SYSV) != 0;
3737 debugging = (options & MT_ST_DEBUGGING) != 0;
3739 osst_log_options(STp, STm, name);
3741 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3742 value = (code == MT_ST_SETBOOLEANS);
3743 if ((options & MT_ST_BUFFER_WRITES) != 0)
3744 STm->do_buffer_writes = value;
3745 if ((options & MT_ST_ASYNC_WRITES) != 0)
3746 STm->do_async_writes = value;
3747 if ((options & MT_ST_DEF_WRITES) != 0)
3748 STm->defaults_for_writes = value;
3749 if ((options & MT_ST_READ_AHEAD) != 0)
3750 STm->do_read_ahead = value;
3751 if ((options & MT_ST_TWO_FM) != 0)
3752 STp->two_fm = value;
3753 if ((options & MT_ST_FAST_MTEOM) != 0)
3754 STp->fast_mteom = value;
3755 if ((options & MT_ST_AUTO_LOCK) != 0)
3756 STp->do_auto_lock = value;
3757 if ((options & MT_ST_CAN_BSR) != 0)
3758 STp->can_bsr = value;
3759 if ((options & MT_ST_NO_BLKLIMS) != 0)
3760 STp->omit_blklims = value;
3761 if ((STp->device)->scsi_level >= SCSI_2 &&
3762 (options & MT_ST_CAN_PARTITIONS) != 0)
3763 STp->can_partitions = value;
3764 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3765 STp->scsi2_logical = value;
3766 if ((options & MT_ST_SYSV) != 0)
3769 if ((options & MT_ST_DEBUGGING) != 0)
3772 osst_log_options(STp, STm, name);
3774 else if (code == MT_ST_WRITE_THRESHOLD) {
3775 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3776 if (value < 1 || value > osst_buffer_size) {
3777 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3781 STp->write_threshold = value;
3782 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3785 else if (code == MT_ST_DEF_BLKSIZE) {
3786 value = (options & ~MT_ST_OPTIONS);
3787 if (value == ~MT_ST_OPTIONS) {
3788 STm->default_blksize = (-1);
3789 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3792 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3793 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3797 STm->default_blksize = value;
3798 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3799 name, STm->default_blksize);
3802 else if (code == MT_ST_TIMEOUTS) {
3803 value = (options & ~MT_ST_OPTIONS);
3804 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3805 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3806 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3807 (value & ~MT_ST_SET_LONG_TIMEOUT));
3810 STp->timeout = value * HZ;
3811 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3814 else if (code == MT_ST_DEF_OPTIONS) {
3815 code = (options & ~MT_ST_CLEAR_DEFAULT);
3816 value = (options & MT_ST_CLEAR_DEFAULT);
3817 if (code == MT_ST_DEF_DENSITY) {
3818 if (value == MT_ST_CLEAR_DEFAULT) {
3819 STm->default_density = (-1);
3820 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3823 STm->default_density = value & 0xff;
3824 printk(KERN_INFO "%s:I: Density default set to %x\n",
3825 name, STm->default_density);
3828 else if (code == MT_ST_DEF_DRVBUFFER) {
3829 if (value == MT_ST_CLEAR_DEFAULT) {
3830 STp->default_drvbuffer = 0xff;
3831 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3834 STp->default_drvbuffer = value & 7;
3835 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3836 name, STp->default_drvbuffer);
3839 else if (code == MT_ST_DEF_COMPRESSION) {
3840 if (value == MT_ST_CLEAR_DEFAULT) {
3841 STm->default_compression = ST_DONT_TOUCH;
3842 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3845 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3846 printk(KERN_INFO "%s:I: Compression default set to %x\n",
3858 /* Internal ioctl function */
3859 static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
3863 int i, ioctl_result;
3865 unsigned char cmd[MAX_COMMAND_SIZE];
3866 Scsi_Request * SRpnt = * aSRpnt;
3868 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3869 int datalen = 0, direction = SCSI_DATA_NONE;
3870 char * name = tape_name(STp);
3872 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3873 if (STp->ready == ST_NO_TAPE)
3874 return (-ENOMEDIUM);
3878 timeout = STp->long_timeout;
3879 STps = &(STp->ps[STp->partition]);
3880 fileno = STps->drv_file;
3881 blkno = STps->drv_block;
3882 at_sm = STps->at_sm;
3883 frame_seq_numbr = STp->frame_seq_number;
3884 logical_blk_num = STp->logical_blk_num;
3886 memset(cmd, 0, MAX_COMMAND_SIZE);
3889 chg_eof = FALSE; /* Changed from the FSF after this */
3893 if (STp->linux_media)
3894 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
3896 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
3900 at_sm &= (arg == 0);
3904 chg_eof = FALSE; /* Changed from the FSF after this */
3908 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
3911 blkno = (-1); /* We can't know the block number */
3912 at_sm &= (arg == 0);
3919 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
3920 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
3922 if (cmd_in == MTFSR) {
3923 logical_blk_num += arg;
3924 if (blkno >= 0) blkno += arg;
3927 logical_blk_num -= arg;
3928 if (blkno >= 0) blkno -= arg;
3930 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
3931 fileno = STps->drv_file;
3932 blkno = STps->drv_block;
3933 at_sm &= (arg == 0);
3938 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
3939 cmd[2] = (arg >> 16);
3940 cmd[3] = (arg >> 8);
3944 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
3945 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
3948 blkno = fileno = (-1);
3954 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
3956 cmd[2] = (ltmp >> 16);
3957 cmd[3] = (ltmp >> 8);
3963 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
3964 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
3969 blkno = fileno = (-1);
3974 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
3975 STp->write_type = OS_WRITE_DATA;
3976 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
3981 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
3983 for (i=0; i<arg; i++)
3984 ioctl_result |= osst_write_filemark(STp, &SRpnt);
3985 if (fileno >= 0) fileno += arg;
3986 if (blkno >= 0) blkno = 0;
3990 if (STp->write_prot)
3994 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
3995 if (cmd_in == MTWSM)
3997 cmd[2] = (arg >> 16);
3998 cmd[3] = (arg >> 8);
4000 timeout = STp->timeout;
4003 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4004 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4009 at_sm = (cmd_in == MTWSM);
4015 cmd[0] = START_STOP;
4016 cmd[1] = 1; /* Don't wait for completion */
4017 if (cmd_in == MTLOAD) {
4018 if (STp->ready == ST_NO_TAPE)
4019 cmd[4] = 4; /* open tray */
4021 cmd[4] = 1; /* load */
4023 if (cmd_in == MTRETEN)
4024 cmd[4] = 3; /* retension then mount */
4025 if (cmd_in == MTOFFL)
4026 cmd[4] = 4; /* rewind then eject */
4027 timeout = STp->timeout;
4032 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4035 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4038 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4041 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4046 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4051 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4053 return 0; /* Should do something ? */
4058 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4060 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4061 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4062 ioctl_result = -EIO;
4065 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4067 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4069 ioctl_result = -EIO;
4072 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4073 fileno = STp->filemark_cnt;
4078 if (STp->write_prot)
4080 ioctl_result = osst_reset_header(STp, &SRpnt);
4081 i = osst_write_eod(STp, &SRpnt);
4082 if (i < ioctl_result) ioctl_result = i;
4083 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4084 if (i < ioctl_result) ioctl_result = i;
4085 fileno = blkno = at_sm = 0 ;
4089 cmd[0] = REZERO_UNIT; /* rewind */
4093 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4095 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4098 case MTSETBLK: /* Set block length */
4099 if ((STps->drv_block == 0 ) &&
4101 ((STp->buffer)->buffer_bytes == 0) &&
4102 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4103 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4104 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4106 * Only allowed to change the block size if you opened the
4107 * device at the beginning of a file before writing anything.
4108 * Note, that when reading, changing block_size is futile,
4109 * as the size used when writing overrides it.
4111 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4112 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4113 name, STp->block_size);
4116 case MTSETDENSITY: /* Set tape density */
4117 case MTSETDRVBUFFER: /* Set drive buffering */
4118 case SET_DENS_AND_BLK: /* Set density and block size */
4120 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4121 return (-EIO); /* Not allowed if data in buffer */
4122 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4123 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4124 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4125 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4126 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4127 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4130 return 0; /* FIXME silently ignore if block size didn't change */
4136 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, TRUE);
4138 ioctl_result = (STp->buffer)->syscall_result;
4142 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4144 return ioctl_result;
4147 if (!ioctl_result) { /* SCSI command successful */
4148 STp->frame_seq_number = frame_seq_numbr;
4149 STp->logical_blk_num = logical_blk_num;
4155 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4158 if (!ioctl_result) { /* success */
4160 if (cmd_in == MTFSFM) {
4164 if (cmd_in == MTBSFM) {
4168 STps->drv_block = blkno;
4169 STps->drv_file = fileno;
4170 STps->at_sm = at_sm;
4172 if (cmd_in == MTEOM)
4174 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4175 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4177 STp->logical_blk_num++;
4178 STp->frame_seq_number++;
4179 STp->frame_in_buffer = 0;
4180 STp->buffer->read_pointer = 0;
4182 else if (cmd_in == MTFSF)
4183 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4185 STps->eof = ST_NOEOF;
4187 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4188 STp->rew_at_close = 0;
4189 else if (cmd_in == MTLOAD) {
4190 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4191 STp->ps[i].rw = ST_IDLE;
4192 STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */
4197 if (cmd_in == MTREW) {
4198 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4199 if (ioctl_result > 0)
4203 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4204 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4205 STps->drv_file = STps->drv_block = -1;
4207 STps->drv_file = STps->drv_block = 0;
4208 STps->eof = ST_NOEOF;
4209 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4210 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4211 STps->drv_file = STps->drv_block = -1;
4213 STps->drv_file = STp->filemark_cnt;
4214 STps->drv_block = 0;
4217 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4218 STps->drv_file = STps->drv_block = (-1);
4219 STps->eof = ST_NOEOF;
4221 } else if (cmd_in == MTERASE) {
4223 } else if (SRpnt) { /* SCSI command was not completely successful. */
4224 if (SRpnt->sr_sense_buffer[2] & 0x40) {
4225 STps->eof = ST_EOM_OK;
4226 STps->drv_block = 0;
4229 STps->eof = ST_NOEOF;
4231 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
4234 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4235 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4239 return ioctl_result;
4243 /* Open the device */
4244 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4246 unsigned short flags;
4247 int i, b_size, new_session = FALSE, retval = 0;
4248 unsigned char cmd[MAX_COMMAND_SIZE];
4249 Scsi_Request * SRpnt = NULL;
4254 int dev = TAPE_NR(inode);
4255 int mode = TAPE_MODE(inode);
4257 write_lock(&os_scsi_tapes_lock);
4258 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4259 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4260 write_unlock(&os_scsi_tapes_lock);
4264 name = tape_name(STp);
4267 write_unlock(&os_scsi_tapes_lock);
4269 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4273 if (scsi_device_get(STp->device)) {
4274 write_unlock(&os_scsi_tapes_lock);
4276 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4280 filp->private_data = STp;
4282 write_unlock(&os_scsi_tapes_lock);
4283 STp->rew_at_close = TAPE_REWIND(inode);
4285 if( !scsi_block_when_processing_errors(STp->device) ) {
4289 if (mode != STp->current_mode) {
4292 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4293 name, STp->current_mode, mode);
4296 STp->current_mode = mode;
4298 STm = &(STp->modes[STp->current_mode]);
4300 flags = filp->f_flags;
4301 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4303 STp->raw = TAPE_IS_RAW(inode);
4307 /* Allocate data segments for this device's tape buffer */
4308 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4309 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4310 retval = (-EOVERFLOW);
4313 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4314 for (i = 0, b_size = 0;
4315 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4316 b_size += STp->buffer->sg[i++].length);
4317 STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
4319 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4320 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4321 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4322 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4325 STp->buffer->aux = NULL; /* this had better never happen! */
4326 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4330 STp->buffer->writing = 0;
4331 STp->buffer->syscall_result = 0;
4333 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4334 STps = &(STp->ps[i]);
4337 STp->ready = ST_READY;
4339 STp->nbr_waits = STp->nbr_finished = 0;
4342 memset (cmd, 0, MAX_COMMAND_SIZE);
4343 cmd[0] = TEST_UNIT_READY;
4345 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
4347 retval = (STp->buffer)->syscall_result;
4350 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4351 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4352 SRpnt->sr_sense_buffer[12] == 4 ) {
4354 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sr_sense_buffer[13]);
4356 if (filp->f_flags & O_NONBLOCK) {
4360 if (SRpnt->sr_sense_buffer[13] == 2) { /* initialize command required (LOAD) */
4361 memset (cmd, 0, MAX_COMMAND_SIZE);
4362 cmd[0] = START_STOP;
4365 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4366 STp->timeout, MAX_READY_RETRIES, TRUE);
4368 osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
4370 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4371 (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4373 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4377 for (i=0; i < 10; i++) {
4379 memset (cmd, 0, MAX_COMMAND_SIZE);
4380 cmd[0] = TEST_UNIT_READY;
4382 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4383 STp->timeout, MAX_READY_RETRIES, TRUE);
4384 if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4385 (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
4389 STp->pos_unknown = 0;
4390 STp->partition = STp->new_partition = 0;
4391 if (STp->can_partitions)
4392 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4393 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4394 STps = &(STp->ps[i]);
4395 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4396 STps->eof = ST_NOEOF;
4398 STps->last_block_valid = FALSE;
4399 STps->drv_block = 0;
4400 STps->drv_file = 0 ;
4403 STp->recover_count = 0;
4406 * if we have valid headers from before, and the drive/tape seem untouched,
4407 * open without reconfiguring and re-reading the headers
4409 if (!STp->buffer->syscall_result && STp->header_ok &&
4410 !SRpnt->sr_result && SRpnt->sr_sense_buffer[0] == 0) {
4412 memset(cmd, 0, MAX_COMMAND_SIZE);
4413 cmd[0] = MODE_SENSE;
4415 cmd[2] = VENDOR_IDENT_PAGE;
4416 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4418 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
4420 if (STp->buffer->syscall_result ||
4421 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4422 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4423 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4424 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4426 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4427 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4428 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4429 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4430 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4434 i = STp->first_frame_position;
4435 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4436 if (STp->door_locked == ST_UNLOCKED) {
4437 if (do_door_lock(STp, 1))
4438 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4440 STp->door_locked = ST_LOCKED_AUTO;
4442 if (!STp->frame_in_buffer) {
4443 STp->block_size = (STm->default_blksize > 0) ?
4444 STm->default_blksize : OS_DATA_SIZE;
4445 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4447 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4448 STp->fast_open = TRUE;
4449 scsi_release_request(SRpnt);
4453 if (i != STp->first_frame_position)
4454 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4455 name, i, STp->first_frame_position);
4459 STp->fast_open = FALSE;
4461 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4462 (SRpnt->sr_sense_buffer[2] != 2 || SRpnt->sr_sense_buffer[12] != 0x3A) ) {
4464 memset(cmd, 0, MAX_COMMAND_SIZE);
4465 cmd[0] = MODE_SELECT;
4467 cmd[4] = 4 + MODE_HEADER_LENGTH;
4469 (STp->buffer)->b_data[0] = cmd[4] - 1;
4470 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4471 (STp->buffer)->b_data[2] = 0; /* Reserved */
4472 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4473 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4474 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4475 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4476 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4479 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4481 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
4485 for (i=0; i < 10; i++) {
4487 memset (cmd, 0, MAX_COMMAND_SIZE);
4488 cmd[0] = TEST_UNIT_READY;
4490 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4491 STp->timeout, MAX_READY_RETRIES, TRUE);
4492 if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4493 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
4496 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {
4497 STp->pos_unknown = 0;
4498 STp->partition = STp->new_partition = 0;
4499 if (STp->can_partitions)
4500 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4501 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4502 STps = &(STp->ps[i]);
4504 STps->eof = ST_NOEOF;
4506 STps->last_block_valid = FALSE;
4507 STps->drv_block = 0;
4508 STps->drv_file = 0 ;
4515 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4516 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4518 if ((STp->buffer)->syscall_result != 0) {
4519 if ((STp->device)->scsi_level >= SCSI_2 &&
4520 (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4521 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4522 SRpnt->sr_sense_buffer[12] == 0x3a) { /* Check ASC */
4523 STp->ready = ST_NO_TAPE;
4525 STp->ready = ST_NOT_READY;
4526 scsi_release_request(SRpnt);
4528 STp->density = 0; /* Clear the erroneous "residue" */
4529 STp->write_prot = 0;
4530 STp->block_size = 0;
4531 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4532 STp->partition = STp->new_partition = 0;
4533 STp->door_locked = ST_UNLOCKED;
4537 osst_configure_onstream(STp, &SRpnt);
4539 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4540 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4541 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4542 STp->buffer->buffer_bytes =
4543 STp->buffer->read_pointer =
4544 STp->frame_in_buffer = 0;
4548 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4549 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4550 (STp->buffer)->buffer_blocks);
4553 if (STp->drv_write_prot) {
4554 STp->write_prot = 1;
4557 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4559 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4565 if (new_session) { /* Change the drive parameters for the new mode */
4568 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4570 STp->density_changed = STp->blksize_changed = FALSE;
4571 STp->compression_changed = FALSE;
4575 * properly position the tape and check the ADR headers
4577 if (STp->door_locked == ST_UNLOCKED) {
4578 if (do_door_lock(STp, 1))
4579 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4581 STp->door_locked = ST_LOCKED_AUTO;
4584 osst_analyze_headers(STp, &SRpnt);
4586 scsi_release_request(SRpnt);
4593 scsi_release_request(SRpnt);
4594 normalize_buffer(STp->buffer);
4597 scsi_device_put(STp->device);
4603 /* Flush the tape buffer before close */
4604 static int os_scsi_tape_flush(struct file * filp)
4606 int result = 0, result2;
4607 OS_Scsi_Tape * STp = filp->private_data;
4608 ST_mode * STm = &(STp->modes[STp->current_mode]);
4609 ST_partstat * STps = &(STp->ps[STp->partition]);
4610 Scsi_Request * SRpnt = NULL;
4611 char * name = tape_name(STp);
4613 if (file_count(filp) > 1)
4616 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4617 STp->write_type = OS_WRITE_DATA;
4618 result = osst_flush_write_buffer(STp, &SRpnt);
4619 if (result != 0 && result != (-ENOSPC))
4622 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4626 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4627 name, (long)(filp->f_pos));
4628 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4629 name, STp->nbr_waits, STp->nbr_finished);
4632 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4635 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4636 name, 1+STp->two_fm);
4639 else if (!STp->rew_at_close) {
4640 STps = &(STp->ps[STp->partition]);
4641 if (!STm->sysv || STps->rw != ST_READING) {
4643 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4644 else if (STps->eof == ST_FM_HIT) {
4645 result = cross_eof(STp, &SRpnt, FALSE);
4647 if (STps->drv_file >= 0)
4649 STps->drv_block = 0;
4653 STps->eof = ST_NOEOF;
4656 else if ((STps->eof == ST_NOEOF &&
4657 !(result = cross_eof(STp, &SRpnt, TRUE))) ||
4658 STps->eof == ST_FM_HIT) {
4659 if (STps->drv_file >= 0)
4661 STps->drv_block = 0;
4667 if (STp->rew_at_close) {
4668 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4669 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4670 if (result == 0 && result2 < 0)
4673 if (SRpnt) scsi_release_request(SRpnt);
4675 if (STp->recover_count) {
4676 printk(KERN_INFO "%s:I: %d recovered errors in", name, STp->recover_count);
4677 if (STp->write_count)
4678 printk(" %d frames written", STp->write_count);
4679 if (STp->read_count)
4680 printk(" %d frames read", STp->read_count);
4682 STp->recover_count = 0;
4684 STp->write_count = 0;
4685 STp->read_count = 0;
4691 /* Close the device and release it */
4692 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4695 OS_Scsi_Tape * STp = filp->private_data;
4696 Scsi_Request * SRpnt = NULL;
4698 if (SRpnt) scsi_release_request(SRpnt);
4700 if (STp->door_locked == ST_LOCKED_AUTO)
4701 do_door_lock(STp, 0);
4706 normalize_buffer(STp->buffer);
4707 write_lock(&os_scsi_tapes_lock);
4709 write_unlock(&os_scsi_tapes_lock);
4711 scsi_device_put(STp->device);
4717 /* The ioctl command */
4718 static int osst_ioctl(struct inode * inode,struct file * file,
4719 unsigned int cmd_in, unsigned long arg)
4721 int i, cmd_nr, cmd_type, retval = 0;
4725 Scsi_Request * SRpnt = NULL;
4726 OS_Scsi_Tape * STp = file->private_data;
4727 char * name = tape_name(STp);
4729 if (down_interruptible(&STp->lock))
4730 return -ERESTARTSYS;
4733 if (debugging && !STp->in_use) {
4734 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4739 STm = &(STp->modes[STp->current_mode]);
4740 STps = &(STp->ps[STp->partition]);
4743 * If we are in the middle of error recovery, don't let anyone
4744 * else try and use this device. Also, if error recovery fails, it
4745 * may try and take the device offline, in which case all further
4746 * access to the device is prohibited.
4748 if( !scsi_block_when_processing_errors(STp->device) ) {
4753 cmd_type = _IOC_TYPE(cmd_in);
4754 cmd_nr = _IOC_NR(cmd_in);
4756 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4757 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4759 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4763 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4768 i = copy_from_user((char *) &mtc, (char *)arg, sizeof(struct mtop));
4774 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4775 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4780 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4785 if (!STp->pos_unknown) {
4787 if (STps->eof == ST_FM_HIT) {
4788 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4790 if (STps->drv_file >= 0)
4791 STps->drv_file += 1;
4793 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4795 if (STps->drv_file >= 0)
4796 STps->drv_file += 1;
4800 if (mtc.mt_op == MTSEEK) {
4801 /* Old position must be restored if partition will be changed */
4802 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4805 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
4806 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
4807 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
4808 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
4809 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
4810 mtc.mt_op == MTCOMPRESSION;
4812 i = osst_flush_buffer(STp, &SRpnt, i);
4820 * If there was a bus reset, block further access
4821 * to this device. If the user wants to rewind the tape,
4822 * then reset the flag and allow access again.
4824 if(mtc.mt_op != MTREW &&
4825 mtc.mt_op != MTOFFL &&
4826 mtc.mt_op != MTRETEN &&
4827 mtc.mt_op != MTERASE &&
4828 mtc.mt_op != MTSEEK &&
4829 mtc.mt_op != MTEOM) {
4834 /* remove this when the midlevel properly clears was_reset */
4835 STp->device->was_reset = 0;
4838 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
4839 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
4840 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
4841 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
4842 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
4845 * The user tells us to move to another position on the tape.
4846 * If we were appending to the tape content, that would leave
4847 * the tape without proper end, in that case write EOD and
4848 * update the header to reflect its position.
4851 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
4852 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
4853 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
4854 STp->logical_blk_num, STps->drv_file, STps->drv_block );
4856 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
4857 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
4858 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4859 i = osst_write_trailer(STp, &SRpnt,
4860 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4862 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4863 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
4864 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
4874 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
4875 do_door_lock(STp, 0); /* Ignore result! */
4877 if (mtc.mt_op == MTSETDRVBUFFER &&
4878 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
4879 retval = osst_set_options(STp, mtc.mt_count);
4883 if (mtc.mt_op == MTSETPART) {
4884 if (mtc.mt_count >= STp->nbr_partitions)
4887 STp->new_partition = mtc.mt_count;
4893 if (mtc.mt_op == MTMKPART) {
4894 if (!STp->can_partitions) {
4898 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
4899 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
4903 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4904 STp->ps[i].rw = ST_IDLE;
4905 STp->ps[i].at_sm = 0;
4906 STp->ps[i].last_block_valid = FALSE;
4908 STp->partition = STp->new_partition = 0;
4909 STp->nbr_partitions = 1; /* Bad guess ?-) */
4910 STps->drv_block = STps->drv_file = 0;
4915 if (mtc.mt_op == MTSEEK) {
4917 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
4919 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
4920 if (!STp->can_partitions)
4921 STp->ps[0].rw = ST_IDLE;
4926 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
4927 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
4932 cross_eof(STp, &SRpnt, FALSE);
4934 if (mtc.mt_op == MTCOMPRESSION)
4935 retval = -EINVAL; /* OnStream drives don't have compression hardware */
4937 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
4938 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
4939 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
4943 if (!STm->defined) {
4948 if ((i = osst_flush_buffer(STp, &SRpnt, FALSE)) < 0) {
4953 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
4954 struct mtget mt_status;
4956 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
4961 mt_status.mt_type = MT_ISONSTREAM_SC;
4962 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
4963 mt_status.mt_dsreg =
4964 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
4965 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
4966 mt_status.mt_blkno = STps->drv_block;
4967 mt_status.mt_fileno = STps->drv_file;
4968 if (STp->block_size != 0) {
4969 if (STps->rw == ST_WRITING)
4970 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
4971 else if (STps->rw == ST_READING)
4972 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
4973 STp->block_size - 1) / STp->block_size;
4976 mt_status.mt_gstat = 0;
4977 if (STp->drv_write_prot)
4978 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
4979 if (mt_status.mt_blkno == 0) {
4980 if (mt_status.mt_fileno == 0)
4981 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
4983 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
4985 mt_status.mt_resid = STp->partition;
4986 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
4987 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
4988 else if (STps->eof >= ST_EOM_OK)
4989 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
4990 if (STp->density == 1)
4991 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
4992 else if (STp->density == 2)
4993 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
4994 else if (STp->density == 3)
4995 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
4996 if (STp->ready == ST_READY)
4997 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
4998 if (STp->ready == ST_NO_TAPE)
4999 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5001 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5002 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5003 STp->drv_buffer != 0)
5004 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5006 i = copy_to_user((char *)arg, (char *)&mt_status,
5007 sizeof(struct mtget));
5013 STp->recover_erreg = 0; /* Clear after read */
5016 } /* End of MTIOCGET */
5018 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5019 struct mtpos mt_pos;
5021 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5026 blk = osst_get_frame_position(STp, &SRpnt);
5028 blk = osst_get_sector(STp, &SRpnt);
5033 mt_pos.mt_blkno = blk;
5034 i = copy_to_user((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
5039 if (SRpnt) scsi_release_request(SRpnt);
5043 return scsi_ioctl(STp->device, cmd_in, (void *) arg);
5046 if (SRpnt) scsi_release_request(SRpnt);
5054 /* Memory handling routines */
5056 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5057 static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5062 if (from_initialization)
5063 priority = GFP_ATOMIC;
5065 priority = GFP_KERNEL;
5067 i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5068 tb = (OSST_buffer *)kmalloc(i, priority);
5070 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5074 tb->sg_segs = tb->orig_sg_segs = 0;
5075 tb->use_sg = max_sg;
5078 tb->buffer_size = 0;
5082 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5083 i, max_sg, need_dma);
5088 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5089 static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
5091 int segs, nbr, max_segs, b_size, priority, order, got;
5093 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5096 if (STbuffer->sg_segs) {
5097 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5098 normalize_buffer(STbuffer);
5100 /* See how many segments we can use -- need at least two */
5101 nbr = max_segs = STbuffer->use_sg;
5105 priority = GFP_KERNEL;
5107 priority |= GFP_DMA;
5109 priority |= __GFP_NOWARN;
5111 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5112 big enough to reach the goal (code assumes no segments in place) */
5113 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5114 STbuffer->sg[0].page = alloc_pages(priority, order);
5115 STbuffer->sg[0].offset = 0;
5116 if (STbuffer->sg[0].page != NULL) {
5117 STbuffer->sg[0].length = b_size;
5118 STbuffer->b_data = page_address(STbuffer->sg[0].page);
5122 if (STbuffer->sg[0].page == NULL) {
5123 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5126 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5127 for (segs=STbuffer->sg_segs=1, got=b_size;
5128 segs < max_segs && got < OS_FRAME_SIZE; ) {
5129 STbuffer->sg[segs].page =
5130 alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5131 STbuffer->sg[segs].offset = 0;
5132 if (STbuffer->sg[segs].page == NULL) {
5133 if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
5134 b_size /= 2; /* Large enough for the rest of the buffers */
5138 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5141 STbuffer->buffer_size = got;
5143 normalize_buffer(STbuffer);
5146 STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size;
5147 got += STbuffer->sg[segs].length;
5148 STbuffer->buffer_size = got;
5149 STbuffer->sg_segs = ++segs;
5154 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5155 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5157 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5158 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5159 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5167 /* Release the segments */
5168 static void normalize_buffer(OSST_buffer *STbuffer)
5170 int i, order, b_size;
5172 for (i=0; i < STbuffer->sg_segs; i++) {
5174 for (b_size = PAGE_SIZE, order = 0;
5175 b_size < STbuffer->sg[i].length;
5176 b_size *= 2, order++);
5178 __free_pages(STbuffer->sg[i].page, order);
5179 STbuffer->buffer_size -= STbuffer->sg[i].length;
5182 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5183 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5184 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5186 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5190 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5191 negative error code. */
5192 static int append_to_buffer(const char *ubp, OSST_buffer *st_bp, int do_count)
5194 int i, cnt, res, offset;
5196 for (i=0, offset=st_bp->buffer_bytes;
5197 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5198 offset -= st_bp->sg[i].length;
5199 if (i == st_bp->sg_segs) { /* Should never happen */
5200 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5203 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5204 cnt = st_bp->sg[i].length - offset < do_count ?
5205 st_bp->sg[i].length - offset : do_count;
5206 res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
5210 st_bp->buffer_bytes += cnt;
5214 if (do_count) { /* Should never happen */
5215 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5223 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5224 negative error code. */
5225 static int from_buffer(OSST_buffer *st_bp, char *ubp, int do_count)
5227 int i, cnt, res, offset;
5229 for (i=0, offset=st_bp->read_pointer;
5230 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5231 offset -= st_bp->sg[i].length;
5232 if (i == st_bp->sg_segs) { /* Should never happen */
5233 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5236 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5237 cnt = st_bp->sg[i].length - offset < do_count ?
5238 st_bp->sg[i].length - offset : do_count;
5239 res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
5243 st_bp->buffer_bytes -= cnt;
5244 st_bp->read_pointer += cnt;
5248 if (do_count) { /* Should never happen */
5249 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5255 /* Sets the tail of the buffer after fill point to zero.
5256 Returns zero (success) or negative error code. */
5257 static int osst_zero_buffer_tail(OSST_buffer *st_bp)
5259 int i, offset, do_count, cnt;
5261 for (i = 0, offset = st_bp->buffer_bytes;
5262 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5263 offset -= st_bp->sg[i].length;
5264 if (i == st_bp->sg_segs) { /* Should never happen */
5265 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5268 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5269 i < st_bp->sg_segs && do_count > 0; i++) {
5270 cnt = st_bp->sg[i].length - offset < do_count ?
5271 st_bp->sg[i].length - offset : do_count ;
5272 memset(page_address(st_bp->sg[i].page) + offset, 0, cnt);
5276 if (do_count) { /* Should never happen */
5277 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5283 /* Copy a osst 32K chunk of memory into the buffer.
5284 Returns zero (success) or negative error code. */
5285 static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5287 int i, cnt, do_count = OS_DATA_SIZE;
5289 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5290 cnt = st_bp->sg[i].length < do_count ?
5291 st_bp->sg[i].length : do_count ;
5292 memcpy(page_address(st_bp->sg[i].page), ptr, cnt);
5296 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5297 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5304 /* Copy a osst 32K chunk of memory from the buffer.
5305 Returns zero (success) or negative error code. */
5306 static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5308 int i, cnt, do_count = OS_DATA_SIZE;
5310 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5311 cnt = st_bp->sg[i].length < do_count ?
5312 st_bp->sg[i].length : do_count ;
5313 memcpy(ptr, page_address(st_bp->sg[i].page), cnt);
5317 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5318 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5326 /* Module housekeeping */
5328 static void validate_options (void)
5331 osst_max_dev = max_dev;
5332 if (write_threshold_kbs > 0)
5333 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5334 if (osst_write_threshold > osst_buffer_size)
5335 osst_write_threshold = osst_buffer_size;
5336 if (max_sg_segs >= OSST_FIRST_SG)
5337 osst_max_sg_segs = max_sg_segs;
5339 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5340 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5345 /* Set the boot options. Syntax: osst=xxx,yyy,...
5346 where xxx is write threshold in 1024 byte blocks,
5347 and yyy is number of s/g segments to use. */
5348 static int __init osst_setup (char *str)
5353 stp = get_options(str, ARRAY_SIZE(ints), ints);
5356 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5357 *parms[i].val = ints[i + 1];
5359 while (stp != NULL) {
5360 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5361 int len = strlen(parms[i].name);
5362 if (!strncmp(stp, parms[i].name, len) &&
5363 (*(stp + len) == ':' || *(stp + len) == '=')) {
5365 simple_strtoul(stp + len + 1, NULL, 0);
5369 if (i >= sizeof(parms) / sizeof(struct osst_dev_parm))
5370 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5372 stp = strchr(stp, ',');
5381 __setup("osst=", osst_setup);
5385 static struct file_operations osst_fops = {
5386 .owner = THIS_MODULE,
5388 .write = osst_write,
5389 .ioctl = osst_ioctl,
5390 .open = os_scsi_tape_open,
5391 .flush = os_scsi_tape_flush,
5392 .release = os_scsi_tape_close,
5395 static int osst_supports(Scsi_Device * SDp)
5397 struct osst_support_data {
5401 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5404 static struct osst_support_data support_list[] = {
5405 /* {"XXX", "Yy-", "", NULL}, example */
5409 struct osst_support_data *rp;
5411 /* We are willing to drive OnStream SC-x0 as well as the
5412 * * IDE, ParPort, FireWire, USB variants, if accessible by
5413 * * emulation layer (ide-scsi, usb-storage, ...) */
5415 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5416 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5417 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5418 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5424 * osst startup / cleanup code
5427 static int osst_probe(struct device *dev)
5429 Scsi_Device * SDp = to_scsi_device(dev);
5430 OS_Scsi_Tape * tpnt;
5433 OSST_buffer * buffer;
5434 struct gendisk * drive;
5435 int i, mode, dev_num;
5437 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5440 drive = alloc_disk(1);
5442 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5446 /* if this is the first attach, build the infrastructure */
5447 write_lock(&os_scsi_tapes_lock);
5448 if (os_scsi_tapes == NULL) {
5450 (OS_Scsi_Tape **)kmalloc(osst_max_dev * sizeof(OS_Scsi_Tape *),
5452 if (os_scsi_tapes == NULL) {
5453 write_unlock(&os_scsi_tapes_lock);
5454 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5457 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5460 if (osst_nr_dev >= osst_max_dev) {
5461 write_unlock(&os_scsi_tapes_lock);
5462 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5466 /* find a free minor number */
5467 for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++);
5468 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5471 /* allocate a OS_Scsi_Tape for this device */
5472 tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
5474 write_unlock(&os_scsi_tapes_lock);
5475 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5478 memset(tpnt, 0, sizeof(OS_Scsi_Tape));
5480 /* allocate a buffer for this device */
5481 i = SDp->host->sg_tablesize;
5482 if (osst_max_sg_segs < i)
5483 i = osst_max_sg_segs;
5484 buffer = new_tape_buffer(TRUE, SDp->host->unchecked_isa_dma, i);
5485 if (buffer == NULL) {
5486 write_unlock(&os_scsi_tapes_lock);
5487 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5491 os_scsi_tapes[dev_num] = tpnt;
5492 tpnt->buffer = buffer;
5494 drive->private_data = &tpnt->driver;
5495 sprintf(drive->disk_name, "osst%d", dev_num);
5496 tpnt->driver = &osst_template;
5497 tpnt->drive = drive;
5499 tpnt->capacity = 0xfffff;
5501 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
5502 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5504 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5505 tpnt->can_bsr = OSST_IN_FILE_POS;
5506 tpnt->can_partitions = 0;
5507 tpnt->two_fm = OSST_TWO_FM;
5508 tpnt->fast_mteom = OSST_FAST_MTEOM;
5509 tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5510 tpnt->write_threshold = osst_write_threshold;
5511 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5512 tpnt->partition = 0;
5513 tpnt->new_partition = 0;
5514 tpnt->nbr_partitions = 0;
5515 tpnt->min_block = 512;
5516 tpnt->max_block = OS_DATA_SIZE;
5517 tpnt->timeout = OSST_TIMEOUT;
5518 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5520 /* Recognize OnStream tapes */
5521 /* We don't need to test for OnStream, as this has been done in detect () */
5522 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5523 tpnt->omit_blklims = 1;
5525 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5526 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5527 tpnt->frame_in_buffer = 0;
5528 tpnt->header_ok = 0;
5529 tpnt->linux_media = 0;
5530 tpnt->header_cache = NULL;
5532 for (i=0; i < ST_NBR_MODES; i++) {
5533 STm = &(tpnt->modes[i]);
5534 STm->defined = FALSE;
5535 STm->sysv = OSST_SYSV;
5536 STm->defaults_for_writes = 0;
5537 STm->do_async_writes = OSST_ASYNC_WRITES;
5538 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5539 STm->do_read_ahead = OSST_READ_AHEAD;
5540 STm->default_compression = ST_DONT_TOUCH;
5541 STm->default_blksize = 512;
5542 STm->default_density = (-1); /* No forced density */
5545 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5546 STps = &(tpnt->ps[i]);
5548 STps->eof = ST_NOEOF;
5550 STps->last_block_valid = FALSE;
5551 STps->drv_block = (-1);
5552 STps->drv_file = (-1);
5555 tpnt->current_mode = 0;
5556 tpnt->modes[0].defined = TRUE;
5557 tpnt->modes[2].defined = TRUE;
5558 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = FALSE;
5560 init_MUTEX(&tpnt->lock);
5562 write_unlock(&os_scsi_tapes_lock);
5564 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5566 devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
5567 S_IFCHR | S_IRUGO | S_IWUGO,
5568 "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
5570 /* No-rewind entry */
5571 devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128),
5572 S_IFCHR | S_IRUGO | S_IWUGO,
5573 "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
5575 drive->number = devfs_register_tape(SDp->devfs_name);
5578 "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n",
5579 SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt));
5588 static int osst_remove(struct device *dev)
5590 Scsi_Device * SDp = to_scsi_device(dev);
5591 OS_Scsi_Tape * tpnt;
5594 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
5597 write_lock(&os_scsi_tapes_lock);
5598 for(i=0; i < osst_max_dev; i++) {
5599 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
5600 tpnt->device = NULL;
5601 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5602 devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
5603 devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
5605 devfs_unregister_tape(tpnt->drive->number);
5606 put_disk(tpnt->drive);
5607 os_scsi_tapes[i] = NULL;
5609 write_unlock(&os_scsi_tapes_lock);
5610 if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
5612 normalize_buffer(tpnt->buffer);
5613 kfree(tpnt->buffer);
5619 write_unlock(&os_scsi_tapes_lock);
5623 static int __init init_osst(void)
5625 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5629 if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
5630 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
5637 static void __exit exit_osst (void)
5642 scsi_unregister_driver(&osst_template.gendrv);
5643 unregister_chrdev(OSST_MAJOR, "osst");
5645 if (os_scsi_tapes) {
5646 for (i=0; i < osst_max_dev; ++i) {
5647 if (!(STp = os_scsi_tapes[i])) continue;
5648 /* This is defensive, supposed to happen during detach */
5649 if (STp->header_cache)
5650 vfree(STp->header_cache);
5652 normalize_buffer(STp->buffer);
5655 put_disk(STp->drive);
5658 kfree(os_scsi_tapes);
5660 printk(KERN_INFO "osst :I: Unloaded.\n");
5663 module_init(init_osst);
5664 module_exit(exit_osst);