Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / drivers / scsi / osst.c
blobabef7048f25b32dffb1586cab131c7cac1817438
1 /*
2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
5 History:
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
17 email osst@riede.org
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27 static const char * osst_version = "0.99.4";
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>
36 #include <linux/fs.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
40 #include <linux/mm.h>
41 #include <linux/init.h>
42 #include <linux/string.h>
43 #include <linux/errno.h>
44 #include <linux/mtio.h>
45 #include <linux/ioctl.h>
46 #include <linux/fcntl.h>
47 #include <linux/spinlock.h>
48 #include <linux/vmalloc.h>
49 #include <linux/blkdev.h>
50 #include <linux/moduleparam.h>
51 #include <linux/delay.h>
52 #include <linux/jiffies.h>
53 #include <asm/uaccess.h>
54 #include <asm/dma.h>
55 #include <asm/system.h>
57 /* The driver prints some debugging information on the console if DEBUG
58 is defined and non-zero. */
59 #define DEBUG 0
61 /* The message level for the debug messages is currently set to KERN_NOTICE
62 so that people can easily see the messages. Later when the debugging messages
63 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
64 #define OSST_DEB_MSG KERN_NOTICE
66 #include <scsi/scsi.h>
67 #include <scsi/scsi_dbg.h>
68 #include <scsi/scsi_device.h>
69 #include <scsi/scsi_driver.h>
70 #include <scsi/scsi_eh.h>
71 #include <scsi/scsi_host.h>
72 #include <scsi/scsi_ioctl.h>
74 #define ST_KILOBYTE 1024
76 #include "st.h"
77 #include "osst.h"
78 #include "osst_options.h"
79 #include "osst_detect.h"
81 static int max_dev = 0;
82 static int write_threshold_kbs = 0;
83 static int max_sg_segs = 0;
85 #ifdef MODULE
86 MODULE_AUTHOR("Willem Riede");
87 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
88 MODULE_LICENSE("GPL");
89 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
90 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
92 module_param(max_dev, int, 0444);
93 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
95 module_param(write_threshold_kbs, int, 0644);
96 MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
98 module_param(max_sg_segs, int, 0644);
99 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
100 #else
101 static struct osst_dev_parm {
102 char *name;
103 int *val;
104 } parms[] __initdata = {
105 { "max_dev", &max_dev },
106 { "write_threshold_kbs", &write_threshold_kbs },
107 { "max_sg_segs", &max_sg_segs }
109 #endif
111 /* Some default definitions have been moved to osst_options.h */
112 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
113 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
115 /* The buffer size should fit into the 24 bits for length in the
116 6-byte SCSI read and write commands. */
117 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
118 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
119 #endif
121 #if DEBUG
122 static int debugging = 1;
123 /* uncomment define below to test error recovery */
124 // #define OSST_INJECT_ERRORS 1
125 #endif
127 /* Do not retry! The drive firmware already retries when appropriate,
128 and when it tries to tell us something, we had better listen... */
129 #define MAX_RETRIES 0
131 #define NO_TAPE NOT_READY
133 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
134 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
135 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
137 #define OSST_TIMEOUT (200 * HZ)
138 #define OSST_LONG_TIMEOUT (1800 * HZ)
140 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
141 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
142 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
143 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
145 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
146 24 bits) */
147 #define SET_DENS_AND_BLK 0x10001
149 static int osst_buffer_size = OSST_BUFFER_SIZE;
150 static int osst_write_threshold = OSST_WRITE_THRESHOLD;
151 static int osst_max_sg_segs = OSST_MAX_SG;
152 static int osst_max_dev = OSST_MAX_TAPES;
153 static int osst_nr_dev;
155 static struct osst_tape **os_scsi_tapes = NULL;
156 static DEFINE_RWLOCK(os_scsi_tapes_lock);
158 static int modes_defined = 0;
160 static struct osst_buffer *new_tape_buffer(int, int, int);
161 static int enlarge_buffer(struct osst_buffer *, int);
162 static void normalize_buffer(struct osst_buffer *);
163 static int append_to_buffer(const char __user *, struct osst_buffer *, int);
164 static int from_buffer(struct osst_buffer *, char __user *, int);
165 static int osst_zero_buffer_tail(struct osst_buffer *);
166 static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
167 static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
169 static int osst_probe(struct device *);
170 static int osst_remove(struct device *);
172 static struct scsi_driver osst_template = {
173 .owner = THIS_MODULE,
174 .gendrv = {
175 .name = "osst",
176 .probe = osst_probe,
177 .remove = osst_remove,
181 static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
182 unsigned int cmd_in, unsigned long arg);
184 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
186 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
188 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
190 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
192 static inline char *tape_name(struct osst_tape *tape)
194 return tape->drive->disk_name;
197 /* Routines that handle the interaction with mid-layer SCSI routines */
200 /* Normalize Sense */
201 static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
203 const u8 *ucp;
204 const u8 *sense = SRpnt->sense;
206 s->have_sense = scsi_normalize_sense(SRpnt->sense,
207 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
208 s->flags = 0;
210 if (s->have_sense) {
211 s->deferred = 0;
212 s->remainder_valid =
213 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
214 switch (sense[0] & 0x7f) {
215 case 0x71:
216 s->deferred = 1;
217 case 0x70:
218 s->fixed_format = 1;
219 s->flags = sense[2] & 0xe0;
220 break;
221 case 0x73:
222 s->deferred = 1;
223 case 0x72:
224 s->fixed_format = 0;
225 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
226 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
227 break;
232 /* Convert the result to success code */
233 static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
235 char *name = tape_name(STp);
236 int result = SRpnt->result;
237 u8 * sense = SRpnt->sense, scode;
238 #if DEBUG
239 const char *stp;
240 #endif
241 struct st_cmdstatus *cmdstatp;
243 if (!result)
244 return 0;
246 cmdstatp = &STp->buffer->cmdstat;
247 osst_analyze_sense(SRpnt, cmdstatp);
249 if (cmdstatp->have_sense)
250 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
251 else
252 scode = 0;
253 #if DEBUG
254 if (debugging) {
255 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
256 name, result,
257 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
258 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
259 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
260 name, scode, sense[12], sense[13]);
261 if (cmdstatp->have_sense)
262 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
264 else
265 #endif
266 if (cmdstatp->have_sense && (
267 scode != NO_SENSE &&
268 scode != RECOVERED_ERROR &&
269 /* scode != UNIT_ATTENTION && */
270 scode != BLANK_CHECK &&
271 scode != VOLUME_OVERFLOW &&
272 SRpnt->cmd[0] != MODE_SENSE &&
273 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
274 if (cmdstatp->have_sense) {
275 printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
276 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
278 else {
279 static int notyetprinted = 1;
281 printk(KERN_WARNING
282 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
283 name, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
284 host_byte(result));
285 if (notyetprinted) {
286 notyetprinted = 0;
287 printk(KERN_INFO
288 "%s:I: This warning may be caused by your scsi controller,\n", name);
289 printk(KERN_INFO
290 "%s:I: it has been reported with some Buslogic cards.\n", name);
294 STp->pos_unknown |= STp->device->was_reset;
296 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
297 STp->recover_count++;
298 STp->recover_erreg++;
299 #if DEBUG
300 if (debugging) {
301 if (SRpnt->cmd[0] == READ_6)
302 stp = "read";
303 else if (SRpnt->cmd[0] == WRITE_6)
304 stp = "write";
305 else
306 stp = "ioctl";
307 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
308 STp->recover_count);
310 #endif
311 if ((sense[2] & 0xe0) == 0)
312 return 0;
314 return (-EIO);
318 /* Wakeup from interrupt */
319 static void osst_sleep_done(void *data, char *sense, int result, int resid)
321 struct osst_request *SRpnt = data;
322 struct osst_tape *STp = SRpnt->stp;
324 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
325 STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
326 #if DEBUG
327 STp->write_pending = 0;
328 #endif
329 if (SRpnt->waiting)
330 complete(SRpnt->waiting);
333 /* osst_request memory management */
334 static struct osst_request *osst_allocate_request(void)
336 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
339 static void osst_release_request(struct osst_request *streq)
341 kfree(streq);
344 /* Do the scsi command. Waits until command performed if do_wait is true.
345 Otherwise osst_write_behind_check() is used to check that the command
346 has finished. */
347 static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
348 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
350 unsigned char *bp;
351 unsigned short use_sg;
352 #ifdef OSST_INJECT_ERRORS
353 static int inject = 0;
354 static int repeat = 0;
355 #endif
356 struct completion *waiting;
358 /* if async, make sure there's no command outstanding */
359 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
360 printk(KERN_ERR "%s: Async command already active.\n",
361 tape_name(STp));
362 if (signal_pending(current))
363 (STp->buffer)->syscall_result = (-EINTR);
364 else
365 (STp->buffer)->syscall_result = (-EBUSY);
366 return NULL;
369 if (SRpnt == NULL) {
370 SRpnt = osst_allocate_request();
371 if (SRpnt == NULL) {
372 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
373 tape_name(STp));
374 if (signal_pending(current))
375 (STp->buffer)->syscall_result = (-EINTR);
376 else
377 (STp->buffer)->syscall_result = (-EBUSY);
378 return NULL;
380 SRpnt->stp = STp;
383 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
384 which IO is outstanding. It's nulled out when the IO completes. */
385 if (!do_wait)
386 (STp->buffer)->last_SRpnt = SRpnt;
388 waiting = &STp->wait;
389 init_completion(waiting);
390 SRpnt->waiting = waiting;
392 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
393 if (use_sg) {
394 bp = (char *)&(STp->buffer->sg[0]);
395 if (STp->buffer->sg_segs < use_sg)
396 use_sg = STp->buffer->sg_segs;
398 else
399 bp = (STp->buffer)->b_data;
401 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
402 STp->buffer->cmdstat.have_sense = 0;
403 STp->buffer->syscall_result = 0;
405 if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
406 use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL))
407 /* could not allocate the buffer or request was too large */
408 (STp->buffer)->syscall_result = (-EBUSY);
409 else if (do_wait) {
410 wait_for_completion(waiting);
411 SRpnt->waiting = NULL;
412 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
413 #ifdef OSST_INJECT_ERRORS
414 if (STp->buffer->syscall_result == 0 &&
415 cmd[0] == READ_6 &&
416 cmd[4] &&
417 ( (++ inject % 83) == 29 ||
418 (STp->first_frame_position == 240
419 /* or STp->read_error_frame to fail again on the block calculated above */ &&
420 ++repeat < 3))) {
421 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
422 STp->buffer->last_result_fatal = 1;
424 #endif
426 return SRpnt;
430 /* Handle the write-behind checking (downs the semaphore) */
431 static void osst_write_behind_check(struct osst_tape *STp)
433 struct osst_buffer * STbuffer;
435 STbuffer = STp->buffer;
437 #if DEBUG
438 if (STp->write_pending)
439 STp->nbr_waits++;
440 else
441 STp->nbr_finished++;
442 #endif
443 wait_for_completion(&(STp->wait));
444 STp->buffer->last_SRpnt->waiting = NULL;
446 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
448 if (STp->buffer->syscall_result)
449 STp->buffer->syscall_result =
450 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
451 else
452 STp->first_frame_position++;
454 osst_release_request(STp->buffer->last_SRpnt);
456 if (STbuffer->writing < STbuffer->buffer_bytes)
457 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
459 STbuffer->last_SRpnt = NULL;
460 STbuffer->buffer_bytes -= STbuffer->writing;
461 STbuffer->writing = 0;
463 return;
468 /* Onstream specific Routines */
470 * Initialize the OnStream AUX
472 static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
473 int logical_blk_num, int blk_sz, int blk_cnt)
475 os_aux_t *aux = STp->buffer->aux;
476 os_partition_t *par = &aux->partition;
477 os_dat_t *dat = &aux->dat;
479 if (STp->raw) return;
481 memset(aux, 0, sizeof(*aux));
482 aux->format_id = htonl(0);
483 memcpy(aux->application_sig, "LIN4", 4);
484 aux->hdwr = htonl(0);
485 aux->frame_type = frame_type;
487 switch (frame_type) {
488 case OS_FRAME_TYPE_HEADER:
489 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
490 par->partition_num = OS_CONFIG_PARTITION;
491 par->par_desc_ver = OS_PARTITION_VERSION;
492 par->wrt_pass_cntr = htons(0xffff);
493 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
494 par->first_frame_ppos = htonl(0);
495 par->last_frame_ppos = htonl(0xbb7);
496 aux->frame_seq_num = htonl(0);
497 aux->logical_blk_num_high = htonl(0);
498 aux->logical_blk_num = htonl(0);
499 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
500 break;
501 case OS_FRAME_TYPE_DATA:
502 case OS_FRAME_TYPE_MARKER:
503 dat->dat_sz = 8;
504 dat->reserved1 = 0;
505 dat->entry_cnt = 1;
506 dat->reserved3 = 0;
507 dat->dat_list[0].blk_sz = htonl(blk_sz);
508 dat->dat_list[0].blk_cnt = htons(blk_cnt);
509 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
510 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
511 dat->dat_list[0].reserved = 0;
512 case OS_FRAME_TYPE_EOD:
513 aux->update_frame_cntr = htonl(0);
514 par->partition_num = OS_DATA_PARTITION;
515 par->par_desc_ver = OS_PARTITION_VERSION;
516 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
517 par->first_frame_ppos = htonl(STp->first_data_ppos);
518 par->last_frame_ppos = htonl(STp->capacity);
519 aux->frame_seq_num = htonl(frame_seq_number);
520 aux->logical_blk_num_high = htonl(0);
521 aux->logical_blk_num = htonl(logical_blk_num);
522 break;
523 default: ; /* probably FILL */
525 aux->filemark_cnt = htonl(STp->filemark_cnt);
526 aux->phys_fm = htonl(0xffffffff);
527 aux->last_mark_ppos = htonl(STp->last_mark_ppos);
528 aux->last_mark_lbn = htonl(STp->last_mark_lbn);
532 * Verify that we have the correct tape frame
534 static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
536 char * name = tape_name(STp);
537 os_aux_t * aux = STp->buffer->aux;
538 os_partition_t * par = &(aux->partition);
539 struct st_partstat * STps = &(STp->ps[STp->partition]);
540 int blk_cnt, blk_sz, i;
542 if (STp->raw) {
543 if (STp->buffer->syscall_result) {
544 for (i=0; i < STp->buffer->sg_segs; i++)
545 memset(page_address(sg_page(&STp->buffer->sg[i])),
546 0, STp->buffer->sg[i].length);
547 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
548 } else
549 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
550 return 1;
552 if (STp->buffer->syscall_result) {
553 #if DEBUG
554 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
555 #endif
556 return 0;
558 if (ntohl(aux->format_id) != 0) {
559 #if DEBUG
560 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
561 #endif
562 goto err_out;
564 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
565 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
566 #if DEBUG
567 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
568 #endif
569 goto err_out;
571 if (par->partition_num != OS_DATA_PARTITION) {
572 if (!STp->linux_media || STp->linux_media_version != 2) {
573 #if DEBUG
574 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
575 name, par->partition_num);
576 #endif
577 goto err_out;
580 if (par->par_desc_ver != OS_PARTITION_VERSION) {
581 #if DEBUG
582 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
583 #endif
584 goto err_out;
586 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
587 #if DEBUG
588 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
589 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
590 #endif
591 goto err_out;
593 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
594 aux->frame_type != OS_FRAME_TYPE_EOD &&
595 aux->frame_type != OS_FRAME_TYPE_MARKER) {
596 if (!quiet) {
597 #if DEBUG
598 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
599 #endif
601 goto err_out;
603 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
604 STp->first_frame_position < STp->eod_frame_ppos) {
605 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
606 STp->first_frame_position);
607 goto err_out;
609 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
610 if (!quiet) {
611 #if DEBUG
612 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
613 name, ntohl(aux->frame_seq_num), frame_seq_number);
614 #endif
616 goto err_out;
618 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
619 STps->eof = ST_FM_HIT;
621 i = ntohl(aux->filemark_cnt);
622 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
623 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
624 #if DEBUG
625 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
626 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
627 i, STp->first_frame_position - 1);
628 #endif
629 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
630 if (i >= STp->filemark_cnt)
631 STp->filemark_cnt = i+1;
634 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
635 STps->eof = ST_EOD_1;
636 STp->frame_in_buffer = 1;
638 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
639 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
640 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
641 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
642 STp->buffer->read_pointer = 0;
643 STp->frame_in_buffer = 1;
645 /* See what block size was used to write file */
646 if (STp->block_size != blk_sz && blk_sz > 0) {
647 printk(KERN_INFO
648 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
649 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
650 STp->block_size<1024?STp->block_size:STp->block_size/1024,
651 STp->block_size<1024?'b':'k');
652 STp->block_size = blk_sz;
653 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
655 STps->eof = ST_NOEOF;
657 STp->frame_seq_number = ntohl(aux->frame_seq_num);
658 STp->logical_blk_num = ntohl(aux->logical_blk_num);
659 return 1;
661 err_out:
662 if (STp->read_error_frame == 0)
663 STp->read_error_frame = STp->first_frame_position - 1;
664 return 0;
668 * Wait for the unit to become Ready
670 static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
671 unsigned timeout, int initial_delay)
673 unsigned char cmd[MAX_COMMAND_SIZE];
674 struct osst_request * SRpnt;
675 unsigned long startwait = jiffies;
676 #if DEBUG
677 int dbg = debugging;
678 char * name = tape_name(STp);
680 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
681 #endif
683 if (initial_delay > 0)
684 msleep(jiffies_to_msecs(initial_delay));
686 memset(cmd, 0, MAX_COMMAND_SIZE);
687 cmd[0] = TEST_UNIT_READY;
689 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
690 *aSRpnt = SRpnt;
691 if (!SRpnt) return (-EBUSY);
693 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
694 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
695 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
696 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
697 SRpnt->sense[13] == 0 ) )) {
698 #if DEBUG
699 if (debugging) {
700 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
701 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
702 debugging = 0;
704 #endif
705 msleep(100);
707 memset(cmd, 0, MAX_COMMAND_SIZE);
708 cmd[0] = TEST_UNIT_READY;
710 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
712 *aSRpnt = SRpnt;
713 #if DEBUG
714 debugging = dbg;
715 #endif
716 if ( STp->buffer->syscall_result &&
717 osst_write_error_recovery(STp, aSRpnt, 0) ) {
718 #if DEBUG
719 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
720 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
721 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
722 SRpnt->sense[12], SRpnt->sense[13]);
723 #endif
724 return (-EIO);
726 #if DEBUG
727 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
728 #endif
729 return 0;
733 * Wait for a tape to be inserted in the unit
735 static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
737 unsigned char cmd[MAX_COMMAND_SIZE];
738 struct osst_request * SRpnt;
739 unsigned long startwait = jiffies;
740 #if DEBUG
741 int dbg = debugging;
742 char * name = tape_name(STp);
744 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
745 #endif
747 memset(cmd, 0, MAX_COMMAND_SIZE);
748 cmd[0] = TEST_UNIT_READY;
750 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
751 *aSRpnt = SRpnt;
752 if (!SRpnt) return (-EBUSY);
754 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
755 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
756 #if DEBUG
757 if (debugging) {
758 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
759 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
760 debugging = 0;
762 #endif
763 msleep(100);
765 memset(cmd, 0, MAX_COMMAND_SIZE);
766 cmd[0] = TEST_UNIT_READY;
768 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
770 *aSRpnt = SRpnt;
771 #if DEBUG
772 debugging = dbg;
773 #endif
774 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
775 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
776 #if DEBUG
777 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
778 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
779 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
780 SRpnt->sense[12], SRpnt->sense[13]);
781 #endif
782 return 0;
784 #if DEBUG
785 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
786 #endif
787 return 1;
790 static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
792 int retval;
794 osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
795 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
796 if (retval) return (retval);
797 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
798 return (osst_get_frame_position(STp, aSRpnt));
802 * Wait for write(s) to complete
804 static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
806 unsigned char cmd[MAX_COMMAND_SIZE];
807 struct osst_request * SRpnt;
808 int result = 0;
809 int delay = OSST_WAIT_WRITE_COMPLETE;
810 #if DEBUG
811 char * name = tape_name(STp);
813 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
814 #endif
816 memset(cmd, 0, MAX_COMMAND_SIZE);
817 cmd[0] = WRITE_FILEMARKS;
818 cmd[1] = 1;
820 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
821 *aSRpnt = SRpnt;
822 if (!SRpnt) return (-EBUSY);
823 if (STp->buffer->syscall_result) {
824 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
825 if (SRpnt->sense[13] == 8) {
826 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
828 } else
829 result = osst_write_error_recovery(STp, aSRpnt, 0);
831 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
832 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
834 return (result);
837 #define OSST_POLL_PER_SEC 10
838 static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
840 unsigned long startwait = jiffies;
841 char * name = tape_name(STp);
842 #if DEBUG
843 char notyetprinted = 1;
844 #endif
845 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
846 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
848 while (time_before (jiffies, startwait + to*HZ))
850 int result;
851 result = osst_get_frame_position(STp, aSRpnt);
852 if (result == -EIO)
853 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
854 return 0; /* successful recovery leaves drive ready for frame */
855 if (result < 0) break;
856 if (STp->first_frame_position == curr &&
857 ((minlast < 0 &&
858 (signed)STp->last_frame_position > (signed)curr + minlast) ||
859 (minlast >= 0 && STp->cur_frames > minlast)
860 ) && result >= 0)
862 #if DEBUG
863 if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
864 printk (OSST_DEB_MSG
865 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
866 name, curr, curr+minlast, STp->first_frame_position,
867 STp->last_frame_position, STp->cur_frames,
868 result, (jiffies-startwait)/HZ,
869 (((jiffies-startwait)%HZ)*10)/HZ);
870 #endif
871 return 0;
873 #if DEBUG
874 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
876 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
877 name, curr, curr+minlast, STp->first_frame_position,
878 STp->last_frame_position, STp->cur_frames, result);
879 notyetprinted--;
881 #endif
882 msleep(1000 / OSST_POLL_PER_SEC);
884 #if DEBUG
885 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
886 name, curr, curr+minlast, STp->first_frame_position,
887 STp->last_frame_position, STp->cur_frames,
888 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
889 #endif
890 return -EBUSY;
893 static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
895 struct osst_request * SRpnt;
896 unsigned char cmd[MAX_COMMAND_SIZE];
897 unsigned long startwait = jiffies;
898 int retval = 1;
899 char * name = tape_name(STp);
901 if (writing) {
902 char mybuf[24];
903 char * olddata = STp->buffer->b_data;
904 int oldsize = STp->buffer->buffer_size;
906 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
908 memset(cmd, 0, MAX_COMMAND_SIZE);
909 cmd[0] = WRITE_FILEMARKS;
910 cmd[1] = 1;
911 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
912 MAX_RETRIES, 1);
914 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
916 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
918 /* some failure - not just not-ready */
919 retval = osst_write_error_recovery(STp, aSRpnt, 0);
920 break;
922 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
924 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
925 memset(cmd, 0, MAX_COMMAND_SIZE);
926 cmd[0] = READ_POSITION;
928 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
929 MAX_RETRIES, 1);
931 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
932 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
934 if (retval)
935 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
936 } else
937 /* TODO - figure out which error conditions can be handled */
938 if (STp->buffer->syscall_result)
939 printk(KERN_WARNING
940 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
941 (*aSRpnt)->sense[ 2] & 0x0f,
942 (*aSRpnt)->sense[12],
943 (*aSRpnt)->sense[13]);
945 return retval;
949 * Read the next OnStream tape frame at the current location
951 static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
953 unsigned char cmd[MAX_COMMAND_SIZE];
954 struct osst_request * SRpnt;
955 int retval = 0;
956 #if DEBUG
957 os_aux_t * aux = STp->buffer->aux;
958 char * name = tape_name(STp);
959 #endif
961 if (STp->poll)
962 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
963 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
965 memset(cmd, 0, MAX_COMMAND_SIZE);
966 cmd[0] = READ_6;
967 cmd[1] = 1;
968 cmd[4] = 1;
970 #if DEBUG
971 if (debugging)
972 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
973 #endif
974 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
975 STp->timeout, MAX_RETRIES, 1);
976 *aSRpnt = SRpnt;
977 if (!SRpnt)
978 return (-EBUSY);
980 if ((STp->buffer)->syscall_result) {
981 retval = 1;
982 if (STp->read_error_frame == 0) {
983 STp->read_error_frame = STp->first_frame_position;
984 #if DEBUG
985 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
986 #endif
988 #if DEBUG
989 if (debugging)
990 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
991 name,
992 SRpnt->sense[0], SRpnt->sense[1],
993 SRpnt->sense[2], SRpnt->sense[3],
994 SRpnt->sense[4], SRpnt->sense[5],
995 SRpnt->sense[6], SRpnt->sense[7]);
996 #endif
998 else
999 STp->first_frame_position++;
1000 #if DEBUG
1001 if (debugging) {
1002 char sig[8]; int i;
1003 for (i=0;i<4;i++)
1004 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1005 sig[4] = '\0';
1006 printk(OSST_DEB_MSG
1007 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1008 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1009 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1010 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1011 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1012 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1013 if (aux->frame_type==2)
1014 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1015 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1016 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1018 #endif
1019 return (retval);
1022 static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1024 struct st_partstat * STps = &(STp->ps[STp->partition]);
1025 struct osst_request * SRpnt ;
1026 unsigned char cmd[MAX_COMMAND_SIZE];
1027 int retval = 0;
1028 char * name = tape_name(STp);
1030 if (STps->rw != ST_READING) { /* Initialize read operation */
1031 if (STps->rw == ST_WRITING || STp->dirty) {
1032 STp->write_type = OS_WRITE_DATA;
1033 osst_flush_write_buffer(STp, aSRpnt);
1034 osst_flush_drive_buffer(STp, aSRpnt);
1036 STps->rw = ST_READING;
1037 STp->frame_in_buffer = 0;
1040 * Issue a read 0 command to get the OnStream drive
1041 * read frames into its buffer.
1043 memset(cmd, 0, MAX_COMMAND_SIZE);
1044 cmd[0] = READ_6;
1045 cmd[1] = 1;
1047 #if DEBUG
1048 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1049 #endif
1050 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1051 *aSRpnt = SRpnt;
1052 if ((retval = STp->buffer->syscall_result))
1053 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1056 return retval;
1059 static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1060 int frame_seq_number, int quiet)
1062 struct st_partstat * STps = &(STp->ps[STp->partition]);
1063 char * name = tape_name(STp);
1064 int cnt = 0,
1065 bad = 0,
1066 past = 0,
1068 position;
1071 * If we want just any frame (-1) and there is a frame in the buffer, return it
1073 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1074 #if DEBUG
1075 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1076 #endif
1077 return (STps->eof);
1080 * Search and wait for the next logical tape frame
1082 while (1) {
1083 if (cnt++ > 400) {
1084 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1085 name, frame_seq_number);
1086 if (STp->read_error_frame) {
1087 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1088 #if DEBUG
1089 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1090 name, STp->read_error_frame);
1091 #endif
1092 STp->read_error_frame = 0;
1093 STp->abort_count++;
1095 return (-EIO);
1097 #if DEBUG
1098 if (debugging)
1099 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1100 name, frame_seq_number, cnt);
1101 #endif
1102 if ( osst_initiate_read(STp, aSRpnt)
1103 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1104 if (STp->raw)
1105 return (-EIO);
1106 position = osst_get_frame_position(STp, aSRpnt);
1107 if (position >= 0xbae && position < 0xbb8)
1108 position = 0xbb8;
1109 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1110 position = STp->read_error_frame - 1;
1111 bad = 0;
1113 else {
1114 position += 29;
1115 cnt += 19;
1117 #if DEBUG
1118 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1119 name, position);
1120 #endif
1121 osst_set_frame_position(STp, aSRpnt, position, 0);
1122 continue;
1124 if (osst_verify_frame(STp, frame_seq_number, quiet))
1125 break;
1126 if (osst_verify_frame(STp, -1, quiet)) {
1127 x = ntohl(STp->buffer->aux->frame_seq_num);
1128 if (STp->fast_open) {
1129 printk(KERN_WARNING
1130 "%s:W: Found logical frame %d instead of %d after fast open\n",
1131 name, x, frame_seq_number);
1132 STp->header_ok = 0;
1133 STp->read_error_frame = 0;
1134 return (-EIO);
1136 if (x > frame_seq_number) {
1137 if (++past > 3) {
1138 /* positioning backwards did not bring us to the desired frame */
1139 position = STp->read_error_frame - 1;
1141 else {
1142 position = osst_get_frame_position(STp, aSRpnt)
1143 + frame_seq_number - x - 1;
1145 if (STp->first_frame_position >= 3000 && position < 3000)
1146 position -= 10;
1148 #if DEBUG
1149 printk(OSST_DEB_MSG
1150 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1151 name, x, frame_seq_number,
1152 STp->first_frame_position - position);
1153 #endif
1154 osst_set_frame_position(STp, aSRpnt, position, 0);
1155 cnt += 10;
1157 else
1158 past = 0;
1160 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1161 #if DEBUG
1162 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1163 #endif
1164 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1165 cnt--;
1167 STp->frame_in_buffer = 0;
1169 if (cnt > 1) {
1170 STp->recover_count++;
1171 STp->recover_erreg++;
1172 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1173 name, STp->read_error_frame);
1175 STp->read_count++;
1177 #if DEBUG
1178 if (debugging || STps->eof)
1179 printk(OSST_DEB_MSG
1180 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1181 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1182 #endif
1183 STp->fast_open = 0;
1184 STp->read_error_frame = 0;
1185 return (STps->eof);
1188 static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1190 struct st_partstat * STps = &(STp->ps[STp->partition]);
1191 char * name = tape_name(STp);
1192 int retries = 0;
1193 int frame_seq_estimate, ppos_estimate, move;
1195 if (logical_blk_num < 0) logical_blk_num = 0;
1196 #if DEBUG
1197 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1198 name, logical_blk_num, STp->logical_blk_num,
1199 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1200 STp->block_size<1024?'b':'k');
1201 #endif
1202 /* Do we know where we are? */
1203 if (STps->drv_block >= 0) {
1204 move = logical_blk_num - STp->logical_blk_num;
1205 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1206 move /= (OS_DATA_SIZE / STp->block_size);
1207 frame_seq_estimate = STp->frame_seq_number + move;
1208 } else
1209 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1211 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1212 else ppos_estimate = frame_seq_estimate + 20;
1213 while (++retries < 10) {
1214 if (ppos_estimate > STp->eod_frame_ppos-2) {
1215 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1216 ppos_estimate = STp->eod_frame_ppos - 2;
1218 if (frame_seq_estimate < 0) {
1219 frame_seq_estimate = 0;
1220 ppos_estimate = 10;
1222 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1223 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1224 /* we've located the estimated frame, now does it have our block? */
1225 if (logical_blk_num < STp->logical_blk_num ||
1226 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1227 if (STps->eof == ST_FM_HIT)
1228 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1229 else {
1230 move = logical_blk_num - STp->logical_blk_num;
1231 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1232 move /= (OS_DATA_SIZE / STp->block_size);
1234 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1235 #if DEBUG
1236 printk(OSST_DEB_MSG
1237 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1238 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1239 STp->logical_blk_num, logical_blk_num, move);
1240 #endif
1241 frame_seq_estimate += move;
1242 ppos_estimate += move;
1243 continue;
1244 } else {
1245 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1246 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1247 STp->logical_blk_num = logical_blk_num;
1248 #if DEBUG
1249 printk(OSST_DEB_MSG
1250 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1251 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1252 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1253 STp->block_size);
1254 #endif
1255 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1256 if (STps->eof == ST_FM_HIT) {
1257 STps->drv_file++;
1258 STps->drv_block = 0;
1259 } else {
1260 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1261 STp->logical_blk_num -
1262 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1265 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1266 return 0;
1269 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1270 goto error;
1271 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1272 #if DEBUG
1273 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1274 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1275 STp->logical_blk_num, logical_blk_num);
1276 #endif
1277 if (frame_seq_estimate != STp->frame_seq_number)
1278 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1279 else
1280 break;
1282 error:
1283 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1284 name, logical_blk_num, STp->logical_blk_num, retries);
1285 return (-EIO);
1288 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1289 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1290 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1291 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1293 #define OSST_FRAME_SHIFT 6
1294 #define OSST_SECTOR_SHIFT 9
1295 #define OSST_SECTOR_MASK 0x03F
1297 static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1299 int sector;
1300 #if DEBUG
1301 char * name = tape_name(STp);
1303 printk(OSST_DEB_MSG
1304 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1305 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1306 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1307 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1308 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1309 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1310 #endif
1311 /* do we know where we are inside a file? */
1312 if (STp->ps[STp->partition].drv_block >= 0) {
1313 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1314 STp->first_frame_position) << OSST_FRAME_SHIFT;
1315 if (STp->ps[STp->partition].rw == ST_WRITING)
1316 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1317 else
1318 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1319 } else {
1320 sector = osst_get_frame_position(STp, aSRpnt);
1321 if (sector > 0)
1322 sector <<= OSST_FRAME_SHIFT;
1324 return sector;
1327 static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1329 struct st_partstat * STps = &(STp->ps[STp->partition]);
1330 int frame = sector >> OSST_FRAME_SHIFT,
1331 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1333 #if DEBUG
1334 char * name = tape_name(STp);
1336 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1337 name, sector, frame, offset);
1338 #endif
1339 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1341 if (frame <= STp->first_data_ppos) {
1342 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1343 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1345 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1346 if (r < 0) return r;
1348 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1349 if (r < 0) return r;
1351 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1353 if (offset) {
1354 STp->logical_blk_num += offset / STp->block_size;
1355 STp->buffer->read_pointer = offset;
1356 STp->buffer->buffer_bytes -= offset;
1357 } else {
1358 STp->frame_seq_number++;
1359 STp->frame_in_buffer = 0;
1360 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1361 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1363 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1364 if (STps->eof == ST_FM_HIT) {
1365 STps->drv_file++;
1366 STps->drv_block = 0;
1367 } else {
1368 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1369 STp->logical_blk_num -
1370 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1373 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1374 #if DEBUG
1375 printk(OSST_DEB_MSG
1376 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1377 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1378 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1379 #endif
1380 return 0;
1384 * Read back the drive's internal buffer contents, as a part
1385 * of the write error recovery mechanism for old OnStream
1386 * firmware revisions.
1387 * Precondition for this function to work: all frames in the
1388 * drive's buffer must be of one type (DATA, MARK or EOD)!
1390 static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1391 unsigned int frame, unsigned int skip, int pending)
1393 struct osst_request * SRpnt = * aSRpnt;
1394 unsigned char * buffer, * p;
1395 unsigned char cmd[MAX_COMMAND_SIZE];
1396 int flag, new_frame, i;
1397 int nframes = STp->cur_frames;
1398 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1399 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1400 - (nframes + pending - 1);
1401 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1402 - (nframes + pending - 1) * blks_per_frame;
1403 char * name = tape_name(STp);
1404 unsigned long startwait = jiffies;
1405 #if DEBUG
1406 int dbg = debugging;
1407 #endif
1409 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1410 return (-EIO);
1412 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1413 name, nframes, pending?" and one that was pending":"");
1415 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1416 #if DEBUG
1417 if (pending && debugging)
1418 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1419 name, frame_seq_number + nframes,
1420 logical_blk_num + nframes * blks_per_frame,
1421 p[0], p[1], p[2], p[3]);
1422 #endif
1423 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1425 memset(cmd, 0, MAX_COMMAND_SIZE);
1426 cmd[0] = 0x3C; /* Buffer Read */
1427 cmd[1] = 6; /* Retrieve Faulty Block */
1428 cmd[7] = 32768 >> 8;
1429 cmd[8] = 32768 & 0xff;
1431 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1432 STp->timeout, MAX_RETRIES, 1);
1434 if ((STp->buffer)->syscall_result || !SRpnt) {
1435 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1436 vfree(buffer);
1437 *aSRpnt = SRpnt;
1438 return (-EIO);
1440 osst_copy_from_buffer(STp->buffer, p);
1441 #if DEBUG
1442 if (debugging)
1443 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1444 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1445 #endif
1447 *aSRpnt = SRpnt;
1448 osst_get_frame_position(STp, aSRpnt);
1450 #if DEBUG
1451 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1452 #endif
1453 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1454 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1456 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1458 if (flag) {
1459 if (STp->write_type == OS_WRITE_HEADER) {
1460 i += skip;
1461 p += skip * OS_DATA_SIZE;
1463 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1464 new_frame = 3000-i;
1465 else
1466 new_frame += skip;
1467 #if DEBUG
1468 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1469 name, new_frame+i, frame_seq_number+i);
1470 #endif
1471 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1472 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1473 osst_get_frame_position(STp, aSRpnt);
1474 SRpnt = * aSRpnt;
1476 if (new_frame > frame + 1000) {
1477 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1478 vfree(buffer);
1479 return (-EIO);
1481 if ( i >= nframes + pending ) break;
1482 flag = 0;
1484 osst_copy_to_buffer(STp->buffer, p);
1486 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1488 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1489 logical_blk_num + i*blks_per_frame,
1490 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1491 memset(cmd, 0, MAX_COMMAND_SIZE);
1492 cmd[0] = WRITE_6;
1493 cmd[1] = 1;
1494 cmd[4] = 1;
1496 #if DEBUG
1497 if (debugging)
1498 printk(OSST_DEB_MSG
1499 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1500 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1501 p[0], p[1], p[2], p[3]);
1502 #endif
1503 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1504 STp->timeout, MAX_RETRIES, 1);
1506 if (STp->buffer->syscall_result)
1507 flag = 1;
1508 else {
1509 p += OS_DATA_SIZE; i++;
1511 /* if we just sent the last frame, wait till all successfully written */
1512 if ( i == nframes + pending ) {
1513 #if DEBUG
1514 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1515 #endif
1516 memset(cmd, 0, MAX_COMMAND_SIZE);
1517 cmd[0] = WRITE_FILEMARKS;
1518 cmd[1] = 1;
1519 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1520 STp->timeout, MAX_RETRIES, 1);
1521 #if DEBUG
1522 if (debugging) {
1523 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1524 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1525 debugging = 0;
1527 #endif
1528 flag = STp->buffer->syscall_result;
1529 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1531 memset(cmd, 0, MAX_COMMAND_SIZE);
1532 cmd[0] = TEST_UNIT_READY;
1534 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1535 MAX_RETRIES, 1);
1537 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1538 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1539 /* in the process of becoming ready */
1540 msleep(100);
1541 continue;
1543 if (STp->buffer->syscall_result)
1544 flag = 1;
1545 break;
1547 #if DEBUG
1548 debugging = dbg;
1549 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1550 #endif
1553 *aSRpnt = SRpnt;
1554 if (flag) {
1555 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1556 SRpnt->sense[12] == 0 &&
1557 SRpnt->sense[13] == 2) {
1558 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1559 vfree(buffer);
1560 return (-EIO); /* hit end of tape = fail */
1562 i = ((SRpnt->sense[3] << 24) |
1563 (SRpnt->sense[4] << 16) |
1564 (SRpnt->sense[5] << 8) |
1565 SRpnt->sense[6] ) - new_frame;
1566 p = &buffer[i * OS_DATA_SIZE];
1567 #if DEBUG
1568 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1569 #endif
1570 osst_get_frame_position(STp, aSRpnt);
1571 #if DEBUG
1572 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1573 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1574 #endif
1577 if (flag) {
1578 /* error recovery did not successfully complete */
1579 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1580 STp->write_type == OS_WRITE_HEADER?"header":"body");
1582 if (!pending)
1583 osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
1584 vfree(buffer);
1585 return 0;
1588 static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1589 unsigned int frame, unsigned int skip, int pending)
1591 unsigned char cmd[MAX_COMMAND_SIZE];
1592 struct osst_request * SRpnt;
1593 char * name = tape_name(STp);
1594 int expected = 0;
1595 int attempts = 1000 / skip;
1596 int flag = 1;
1597 unsigned long startwait = jiffies;
1598 #if DEBUG
1599 int dbg = debugging;
1600 #endif
1602 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1603 if (flag) {
1604 #if DEBUG
1605 debugging = dbg;
1606 #endif
1607 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1608 frame = 3000-skip;
1609 expected = frame+skip+STp->cur_frames+pending;
1610 #if DEBUG
1611 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1612 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1613 #endif
1614 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1615 flag = 0;
1616 attempts--;
1617 schedule_timeout_interruptible(msecs_to_jiffies(100));
1619 if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
1620 #if DEBUG
1621 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1622 name, STp->first_frame_position,
1623 STp->last_frame_position, STp->cur_frames);
1624 #endif
1625 frame = STp->last_frame_position;
1626 flag = 1;
1627 continue;
1629 if (pending && STp->cur_frames < 50) {
1631 memset(cmd, 0, MAX_COMMAND_SIZE);
1632 cmd[0] = WRITE_6;
1633 cmd[1] = 1;
1634 cmd[4] = 1;
1635 #if DEBUG
1636 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1637 name, STp->frame_seq_number-1, STp->first_frame_position);
1638 #endif
1639 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1640 STp->timeout, MAX_RETRIES, 1);
1641 *aSRpnt = SRpnt;
1643 if (STp->buffer->syscall_result) { /* additional write error */
1644 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1645 SRpnt->sense[12] == 0 &&
1646 SRpnt->sense[13] == 2) {
1647 printk(KERN_ERR
1648 "%s:E: Volume overflow in write error recovery\n",
1649 name);
1650 break; /* hit end of tape = fail */
1652 flag = 1;
1654 else
1655 pending = 0;
1657 continue;
1659 if (STp->cur_frames == 0) {
1660 #if DEBUG
1661 debugging = dbg;
1662 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1663 #endif
1664 if (STp->first_frame_position != expected) {
1665 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1666 name, STp->first_frame_position, expected);
1667 return (-EIO);
1669 return 0;
1671 #if DEBUG
1672 if (debugging) {
1673 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1674 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1675 debugging = 0;
1677 #endif
1678 schedule_timeout_interruptible(msecs_to_jiffies(100));
1680 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1681 #if DEBUG
1682 debugging = dbg;
1683 #endif
1684 return (-EIO);
1688 * Error recovery algorithm for the OnStream tape.
1691 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1693 struct osst_request * SRpnt = * aSRpnt;
1694 struct st_partstat * STps = & STp->ps[STp->partition];
1695 char * name = tape_name(STp);
1696 int retval = 0;
1697 int rw_state;
1698 unsigned int frame, skip;
1700 rw_state = STps->rw;
1702 if ((SRpnt->sense[ 2] & 0x0f) != 3
1703 || SRpnt->sense[12] != 12
1704 || SRpnt->sense[13] != 0) {
1705 #if DEBUG
1706 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1707 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1708 #endif
1709 return (-EIO);
1711 frame = (SRpnt->sense[3] << 24) |
1712 (SRpnt->sense[4] << 16) |
1713 (SRpnt->sense[5] << 8) |
1714 SRpnt->sense[6];
1715 skip = SRpnt->sense[9];
1717 #if DEBUG
1718 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1719 #endif
1720 osst_get_frame_position(STp, aSRpnt);
1721 #if DEBUG
1722 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1723 name, STp->first_frame_position, STp->last_frame_position);
1724 #endif
1725 switch (STp->write_type) {
1726 case OS_WRITE_DATA:
1727 case OS_WRITE_EOD:
1728 case OS_WRITE_NEW_MARK:
1729 printk(KERN_WARNING
1730 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1731 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1732 if (STp->os_fw_rev >= 10600)
1733 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1734 else
1735 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1736 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1737 retval?"E" :"I",
1738 retval?"" :"Don't worry, ",
1739 retval?" not ":" ");
1740 break;
1741 case OS_WRITE_LAST_MARK:
1742 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1743 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1744 retval = -EIO;
1745 break;
1746 case OS_WRITE_HEADER:
1747 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1748 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1749 break;
1750 default:
1751 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1752 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1754 osst_get_frame_position(STp, aSRpnt);
1755 #if DEBUG
1756 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1757 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1758 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1759 #endif
1760 if (retval == 0) {
1761 STp->recover_count++;
1762 STp->recover_erreg++;
1763 } else
1764 STp->abort_count++;
1766 STps->rw = rw_state;
1767 return retval;
1770 static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1771 int mt_op, int mt_count)
1773 char * name = tape_name(STp);
1774 int cnt;
1775 int last_mark_ppos = -1;
1777 #if DEBUG
1778 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1779 #endif
1780 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1781 #if DEBUG
1782 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1783 #endif
1784 return -EIO;
1786 if (STp->linux_media_version >= 4) {
1788 * direct lookup in header filemark list
1790 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1791 if (STp->header_ok &&
1792 STp->header_cache != NULL &&
1793 (cnt - mt_count) >= 0 &&
1794 (cnt - mt_count) < OS_FM_TAB_MAX &&
1795 (cnt - mt_count) < STp->filemark_cnt &&
1796 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1798 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1799 #if DEBUG
1800 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1801 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1802 STp->header_cache == NULL?"lack of header cache":"count out of range");
1803 else
1804 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1805 name, cnt,
1806 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1807 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1808 STp->buffer->aux->last_mark_ppos))?"match":"error",
1809 mt_count, last_mark_ppos);
1810 #endif
1811 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1812 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1813 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1814 #if DEBUG
1815 printk(OSST_DEB_MSG
1816 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1817 #endif
1818 return (-EIO);
1820 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1821 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1822 name, last_mark_ppos);
1823 return (-EIO);
1825 goto found;
1827 #if DEBUG
1828 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1829 #endif
1831 cnt = 0;
1832 while (cnt != mt_count) {
1833 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1834 if (last_mark_ppos == -1)
1835 return (-EIO);
1836 #if DEBUG
1837 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1838 #endif
1839 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1840 cnt++;
1841 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1842 #if DEBUG
1843 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1844 #endif
1845 return (-EIO);
1847 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1848 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1849 name, last_mark_ppos);
1850 return (-EIO);
1853 found:
1854 if (mt_op == MTBSFM) {
1855 STp->frame_seq_number++;
1856 STp->frame_in_buffer = 0;
1857 STp->buffer->buffer_bytes = 0;
1858 STp->buffer->read_pointer = 0;
1859 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1861 return 0;
1865 * ADRL 1.1 compatible "slow" space filemarks fwd version
1867 * Just scans for the filemark sequentially.
1869 static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1870 int mt_op, int mt_count)
1872 int cnt = 0;
1873 #if DEBUG
1874 char * name = tape_name(STp);
1876 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1877 #endif
1878 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1879 #if DEBUG
1880 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1881 #endif
1882 return (-EIO);
1884 while (1) {
1885 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1886 #if DEBUG
1887 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1888 #endif
1889 return (-EIO);
1891 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1892 cnt++;
1893 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1894 #if DEBUG
1895 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1896 #endif
1897 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1898 #if DEBUG
1899 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1900 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1901 #endif
1902 STp->eod_frame_ppos = STp->first_frame_position-1;
1904 return (-EIO);
1906 if (cnt == mt_count)
1907 break;
1908 STp->frame_in_buffer = 0;
1910 if (mt_op == MTFSF) {
1911 STp->frame_seq_number++;
1912 STp->frame_in_buffer = 0;
1913 STp->buffer->buffer_bytes = 0;
1914 STp->buffer->read_pointer = 0;
1915 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1917 return 0;
1921 * Fast linux specific version of OnStream FSF
1923 static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
1924 int mt_op, int mt_count)
1926 char * name = tape_name(STp);
1927 int cnt = 0,
1928 next_mark_ppos = -1;
1930 #if DEBUG
1931 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
1932 #endif
1933 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1934 #if DEBUG
1935 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1936 #endif
1937 return (-EIO);
1940 if (STp->linux_media_version >= 4) {
1942 * direct lookup in header filemark list
1944 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1945 if (STp->header_ok &&
1946 STp->header_cache != NULL &&
1947 (cnt + mt_count) < OS_FM_TAB_MAX &&
1948 (cnt + mt_count) < STp->filemark_cnt &&
1949 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1950 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1952 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1953 #if DEBUG
1954 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1955 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1956 STp->header_cache == NULL?"lack of header cache":"count out of range");
1957 else
1958 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1959 name, cnt,
1960 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1961 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1962 STp->buffer->aux->last_mark_ppos))?"match":"error",
1963 mt_count, next_mark_ppos);
1964 #endif
1965 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1966 #if DEBUG
1967 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1968 #endif
1969 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1970 } else {
1971 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1972 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1973 #if DEBUG
1974 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
1975 name);
1976 #endif
1977 return (-EIO);
1979 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1980 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1981 name, next_mark_ppos);
1982 return (-EIO);
1984 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1985 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
1986 name, cnt+mt_count, next_mark_ppos,
1987 ntohl(STp->buffer->aux->filemark_cnt));
1988 return (-EIO);
1991 } else {
1993 * Find nearest (usually previous) marker, then jump from marker to marker
1995 while (1) {
1996 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1997 break;
1998 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1999 #if DEBUG
2000 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2001 #endif
2002 return (-EIO);
2004 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2005 if (STp->first_mark_ppos == -1) {
2006 #if DEBUG
2007 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2008 #endif
2009 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2011 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2012 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2013 #if DEBUG
2014 printk(OSST_DEB_MSG
2015 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2016 name);
2017 #endif
2018 return (-EIO);
2020 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2021 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2022 name, STp->first_mark_ppos);
2023 return (-EIO);
2025 } else {
2026 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2027 return (-EIO);
2028 mt_count++;
2031 cnt++;
2032 while (cnt != mt_count) {
2033 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2034 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2035 #if DEBUG
2036 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2037 #endif
2038 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2040 #if DEBUG
2041 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2042 #endif
2043 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2044 cnt++;
2045 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2046 #if DEBUG
2047 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2048 name);
2049 #endif
2050 return (-EIO);
2052 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2053 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2054 name, next_mark_ppos);
2055 return (-EIO);
2059 if (mt_op == MTFSF) {
2060 STp->frame_seq_number++;
2061 STp->frame_in_buffer = 0;
2062 STp->buffer->buffer_bytes = 0;
2063 STp->buffer->read_pointer = 0;
2064 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2066 return 0;
2070 * In debug mode, we want to see as many errors as possible
2071 * to test the error recovery mechanism.
2073 #if DEBUG
2074 static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2076 unsigned char cmd[MAX_COMMAND_SIZE];
2077 struct osst_request * SRpnt = * aSRpnt;
2078 char * name = tape_name(STp);
2080 memset(cmd, 0, MAX_COMMAND_SIZE);
2081 cmd[0] = MODE_SELECT;
2082 cmd[1] = 0x10;
2083 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2085 (STp->buffer)->b_data[0] = cmd[4] - 1;
2086 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
2087 (STp->buffer)->b_data[2] = 0; /* Reserved */
2088 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
2089 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2090 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2091 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2092 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2094 if (debugging)
2095 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2097 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2098 *aSRpnt = SRpnt;
2100 if ((STp->buffer)->syscall_result)
2101 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2103 #endif
2106 static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2108 int result;
2109 int this_mark_ppos = STp->first_frame_position;
2110 int this_mark_lbn = STp->logical_blk_num;
2111 #if DEBUG
2112 char * name = tape_name(STp);
2113 #endif
2115 if (STp->raw) return 0;
2117 STp->write_type = OS_WRITE_NEW_MARK;
2118 #if DEBUG
2119 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2120 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2121 #endif
2122 STp->dirty = 1;
2123 result = osst_flush_write_buffer(STp, aSRpnt);
2124 result |= osst_flush_drive_buffer(STp, aSRpnt);
2125 STp->last_mark_ppos = this_mark_ppos;
2126 STp->last_mark_lbn = this_mark_lbn;
2127 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2128 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2129 if (STp->filemark_cnt++ == 0)
2130 STp->first_mark_ppos = this_mark_ppos;
2131 return result;
2134 static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2136 int result;
2137 #if DEBUG
2138 char * name = tape_name(STp);
2139 #endif
2141 if (STp->raw) return 0;
2143 STp->write_type = OS_WRITE_EOD;
2144 STp->eod_frame_ppos = STp->first_frame_position;
2145 #if DEBUG
2146 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2147 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2148 #endif
2149 STp->dirty = 1;
2151 result = osst_flush_write_buffer(STp, aSRpnt);
2152 result |= osst_flush_drive_buffer(STp, aSRpnt);
2153 STp->eod_frame_lfa = --(STp->frame_seq_number);
2154 return result;
2157 static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2159 char * name = tape_name(STp);
2161 #if DEBUG
2162 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2163 #endif
2164 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2165 osst_set_frame_position(STp, aSRpnt, where, 0);
2166 STp->write_type = OS_WRITE_FILLER;
2167 while (count--) {
2168 memcpy(STp->buffer->b_data, "Filler", 6);
2169 STp->buffer->buffer_bytes = 6;
2170 STp->dirty = 1;
2171 if (osst_flush_write_buffer(STp, aSRpnt)) {
2172 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2173 return (-EIO);
2176 #if DEBUG
2177 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2178 #endif
2179 return osst_flush_drive_buffer(STp, aSRpnt);
2182 static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2184 char * name = tape_name(STp);
2185 int result;
2187 #if DEBUG
2188 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2189 #endif
2190 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2191 osst_set_frame_position(STp, aSRpnt, where, 0);
2192 STp->write_type = OS_WRITE_HEADER;
2193 while (count--) {
2194 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2195 STp->buffer->buffer_bytes = sizeof(os_header_t);
2196 STp->dirty = 1;
2197 if (osst_flush_write_buffer(STp, aSRpnt)) {
2198 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2199 return (-EIO);
2202 result = osst_flush_drive_buffer(STp, aSRpnt);
2203 #if DEBUG
2204 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2205 #endif
2206 return result;
2209 static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2211 os_header_t * header;
2212 int result;
2213 char * name = tape_name(STp);
2215 #if DEBUG
2216 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2217 #endif
2218 if (STp->raw) return 0;
2220 if (STp->header_cache == NULL) {
2221 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2222 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2223 return (-ENOMEM);
2225 memset(STp->header_cache, 0, sizeof(os_header_t));
2226 #if DEBUG
2227 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2228 #endif
2230 if (STp->header_ok) STp->update_frame_cntr++;
2231 else STp->update_frame_cntr = 0;
2233 header = STp->header_cache;
2234 strcpy(header->ident_str, "ADR_SEQ");
2235 header->major_rev = 1;
2236 header->minor_rev = 4;
2237 header->ext_trk_tb_off = htons(17192);
2238 header->pt_par_num = 1;
2239 header->partition[0].partition_num = OS_DATA_PARTITION;
2240 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2241 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2242 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2243 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2244 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2245 header->cfg_col_width = htonl(20);
2246 header->dat_col_width = htonl(1500);
2247 header->qfa_col_width = htonl(0);
2248 header->ext_track_tb.nr_stream_part = 1;
2249 header->ext_track_tb.et_ent_sz = 32;
2250 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2251 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2252 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2253 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2254 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2255 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2256 header->dat_fm_tab.fm_part_num = 0;
2257 header->dat_fm_tab.fm_tab_ent_sz = 4;
2258 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2259 STp->filemark_cnt:OS_FM_TAB_MAX);
2261 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2262 if (STp->update_frame_cntr == 0)
2263 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2264 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2266 if (locate_eod) {
2267 #if DEBUG
2268 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2269 #endif
2270 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2272 if (result)
2273 printk(KERN_ERR "%s:E: Write header failed\n", name);
2274 else {
2275 memcpy(STp->application_sig, "LIN4", 4);
2276 STp->linux_media = 1;
2277 STp->linux_media_version = 4;
2278 STp->header_ok = 1;
2280 return result;
2283 static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2285 if (STp->header_cache != NULL)
2286 memset(STp->header_cache, 0, sizeof(os_header_t));
2288 STp->logical_blk_num = STp->frame_seq_number = 0;
2289 STp->frame_in_buffer = 0;
2290 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2291 STp->filemark_cnt = 0;
2292 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2293 return osst_write_header(STp, aSRpnt, 1);
2296 static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2298 char * name = tape_name(STp);
2299 os_header_t * header;
2300 os_aux_t * aux;
2301 char id_string[8];
2302 int linux_media_version,
2303 update_frame_cntr;
2305 if (STp->raw)
2306 return 1;
2308 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2309 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2310 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2311 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2312 if (osst_initiate_read (STp, aSRpnt)) {
2313 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2314 return 0;
2317 if (osst_read_frame(STp, aSRpnt, 180)) {
2318 #if DEBUG
2319 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2320 #endif
2321 return 0;
2323 header = (os_header_t *) STp->buffer->b_data; /* warning: only first segment addressable */
2324 aux = STp->buffer->aux;
2325 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2326 #if DEBUG
2327 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2328 #endif
2329 return 0;
2331 if (ntohl(aux->frame_seq_num) != 0 ||
2332 ntohl(aux->logical_blk_num) != 0 ||
2333 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2334 ntohl(aux->partition.first_frame_ppos) != 0 ||
2335 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2336 #if DEBUG
2337 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2338 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2339 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2340 ntohl(aux->partition.last_frame_ppos));
2341 #endif
2342 return 0;
2344 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2345 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2346 strlcpy(id_string, header->ident_str, 8);
2347 #if DEBUG
2348 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2349 #endif
2350 return 0;
2352 update_frame_cntr = ntohl(aux->update_frame_cntr);
2353 if (update_frame_cntr < STp->update_frame_cntr) {
2354 #if DEBUG
2355 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2356 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2357 #endif
2358 return 0;
2360 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2361 #if DEBUG
2362 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2363 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2364 header->minor_rev > 4 )? "Invalid" : "Warning:",
2365 header->major_rev, header->minor_rev);
2366 #endif
2367 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2368 return 0;
2370 #if DEBUG
2371 if (header->pt_par_num != 1)
2372 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2373 name, header->pt_par_num);
2374 #endif
2375 memcpy(id_string, aux->application_sig, 4);
2376 id_string[4] = 0;
2377 if (memcmp(id_string, "LIN", 3) == 0) {
2378 STp->linux_media = 1;
2379 linux_media_version = id_string[3] - '0';
2380 if (linux_media_version != 4)
2381 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2382 name, linux_media_version);
2383 } else {
2384 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2385 return 0;
2387 if (linux_media_version < STp->linux_media_version) {
2388 #if DEBUG
2389 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2390 name, ppos, linux_media_version);
2391 #endif
2392 return 0;
2394 if (linux_media_version > STp->linux_media_version) {
2395 #if DEBUG
2396 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2397 name, ppos, linux_media_version);
2398 #endif
2399 memcpy(STp->application_sig, id_string, 5);
2400 STp->linux_media_version = linux_media_version;
2401 STp->update_frame_cntr = -1;
2403 if (update_frame_cntr > STp->update_frame_cntr) {
2404 #if DEBUG
2405 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2406 name, ppos, update_frame_cntr);
2407 #endif
2408 if (STp->header_cache == NULL) {
2409 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2410 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2411 return 0;
2413 #if DEBUG
2414 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2415 #endif
2417 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2418 header = STp->header_cache; /* further accesses from cached (full) copy */
2420 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2421 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2422 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2423 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2424 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2425 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2426 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2427 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2428 STp->update_frame_cntr = update_frame_cntr;
2429 #if DEBUG
2430 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2431 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2432 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2433 STp->first_data_ppos,
2434 ntohl(header->partition[0].last_frame_ppos),
2435 ntohl(header->partition[0].eod_frame_ppos));
2436 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2437 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2438 #endif
2439 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2440 #if DEBUG
2441 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2442 #endif
2443 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2444 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2445 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2447 if (header->minor_rev == 4 &&
2448 (header->ext_trk_tb_off != htons(17192) ||
2449 header->partition[0].partition_num != OS_DATA_PARTITION ||
2450 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2451 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2452 header->cfg_col_width != htonl(20) ||
2453 header->dat_col_width != htonl(1500) ||
2454 header->qfa_col_width != htonl(0) ||
2455 header->ext_track_tb.nr_stream_part != 1 ||
2456 header->ext_track_tb.et_ent_sz != 32 ||
2457 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2458 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2459 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2460 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2461 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2462 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2463 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2464 header->dat_fm_tab.fm_tab_ent_cnt !=
2465 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2466 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2470 return 1;
2473 static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2475 int position, ppos;
2476 int first, last;
2477 int valid = 0;
2478 char * name = tape_name(STp);
2480 position = osst_get_frame_position(STp, aSRpnt);
2482 if (STp->raw) {
2483 STp->header_ok = STp->linux_media = 1;
2484 STp->linux_media_version = 0;
2485 return 1;
2487 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2488 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2489 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2490 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2491 #if DEBUG
2492 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2493 #endif
2495 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2496 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2498 first = position==10?0xbae: 5;
2499 last = position==10?0xbb3:10;
2501 for (ppos = first; ppos < last; ppos++)
2502 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2503 valid = 1;
2505 first = position==10? 5:0xbae;
2506 last = position==10?10:0xbb3;
2508 for (ppos = first; ppos < last; ppos++)
2509 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2510 valid = 1;
2512 if (!valid) {
2513 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2514 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2515 osst_set_frame_position(STp, aSRpnt, 10, 0);
2516 return 0;
2518 if (position <= STp->first_data_ppos) {
2519 position = STp->first_data_ppos;
2520 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2522 osst_set_frame_position(STp, aSRpnt, position, 0);
2523 STp->header_ok = 1;
2525 return 1;
2528 static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2530 int frame_position = STp->first_frame_position;
2531 int frame_seq_numbr = STp->frame_seq_number;
2532 int logical_blk_num = STp->logical_blk_num;
2533 int halfway_frame = STp->frame_in_buffer;
2534 int read_pointer = STp->buffer->read_pointer;
2535 int prev_mark_ppos = -1;
2536 int actual_mark_ppos, i, n;
2537 #if DEBUG
2538 char * name = tape_name(STp);
2540 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2541 #endif
2542 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2543 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2544 #if DEBUG
2545 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2546 #endif
2547 return (-EIO);
2549 if (STp->linux_media_version >= 4) {
2550 for (i=0; i<STp->filemark_cnt; i++)
2551 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2552 prev_mark_ppos = n;
2553 } else
2554 prev_mark_ppos = frame_position - 1; /* usually - we don't really know */
2555 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2556 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2557 if (frame_position != STp->first_frame_position ||
2558 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2559 prev_mark_ppos != actual_mark_ppos ) {
2560 #if DEBUG
2561 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2562 STp->first_frame_position, frame_position,
2563 STp->frame_seq_number + (halfway_frame?0:1),
2564 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2565 #endif
2566 return (-EIO);
2568 if (halfway_frame) {
2569 /* prepare buffer for append and rewrite on top of original */
2570 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2571 STp->buffer->buffer_bytes = read_pointer;
2572 STp->ps[STp->partition].rw = ST_WRITING;
2573 STp->dirty = 1;
2575 STp->frame_in_buffer = halfway_frame;
2576 STp->frame_seq_number = frame_seq_numbr;
2577 STp->logical_blk_num = logical_blk_num;
2578 return 0;
2581 /* Acc. to OnStream, the vers. numbering is the following:
2582 * X.XX for released versions (X=digit),
2583 * XXXY for unreleased versions (Y=letter)
2584 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2585 * This fn makes monoton numbers out of this scheme ...
2587 static unsigned int osst_parse_firmware_rev (const char * str)
2589 if (str[1] == '.') {
2590 return (str[0]-'0')*10000
2591 +(str[2]-'0')*1000
2592 +(str[3]-'0')*100;
2593 } else {
2594 return (str[0]-'0')*10000
2595 +(str[1]-'0')*1000
2596 +(str[2]-'0')*100 - 100
2597 +(str[3]-'@');
2602 * Configure the OnStream SCII tape drive for default operation
2604 static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2606 unsigned char cmd[MAX_COMMAND_SIZE];
2607 char * name = tape_name(STp);
2608 struct osst_request * SRpnt = * aSRpnt;
2609 osst_mode_parameter_header_t * header;
2610 osst_block_size_page_t * bs;
2611 osst_capabilities_page_t * cp;
2612 osst_tape_paramtr_page_t * prm;
2613 int drive_buffer_size;
2615 if (STp->ready != ST_READY) {
2616 #if DEBUG
2617 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2618 #endif
2619 return (-EIO);
2622 if (STp->os_fw_rev < 10600) {
2623 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2624 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2628 * Configure 32.5KB (data+aux) frame size.
2629 * Get the current frame size from the block size mode page
2631 memset(cmd, 0, MAX_COMMAND_SIZE);
2632 cmd[0] = MODE_SENSE;
2633 cmd[1] = 8;
2634 cmd[2] = BLOCK_SIZE_PAGE;
2635 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2637 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2638 if (SRpnt == NULL) {
2639 #if DEBUG
2640 printk(OSST_DEB_MSG "osst :D: Busy\n");
2641 #endif
2642 return (-EBUSY);
2644 *aSRpnt = SRpnt;
2645 if ((STp->buffer)->syscall_result != 0) {
2646 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2647 return (-EIO);
2650 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2651 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2653 #if DEBUG
2654 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2655 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2656 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2657 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2658 #endif
2661 * Configure default auto columns mode, 32.5KB transfer mode
2663 bs->one = 1;
2664 bs->play32 = 0;
2665 bs->play32_5 = 1;
2666 bs->record32 = 0;
2667 bs->record32_5 = 1;
2669 memset(cmd, 0, MAX_COMMAND_SIZE);
2670 cmd[0] = MODE_SELECT;
2671 cmd[1] = 0x10;
2672 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2674 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2675 *aSRpnt = SRpnt;
2676 if ((STp->buffer)->syscall_result != 0) {
2677 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2678 return (-EIO);
2681 #if DEBUG
2682 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2684 * In debug mode, we want to see as many errors as possible
2685 * to test the error recovery mechanism.
2687 osst_set_retries(STp, aSRpnt, 0);
2688 SRpnt = * aSRpnt;
2689 #endif
2692 * Set vendor name to 'LIN4' for "Linux support version 4".
2695 memset(cmd, 0, MAX_COMMAND_SIZE);
2696 cmd[0] = MODE_SELECT;
2697 cmd[1] = 0x10;
2698 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2700 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2701 header->medium_type = 0; /* Medium Type - ignoring */
2702 header->dsp = 0; /* Reserved */
2703 header->bdl = 0; /* Block Descriptor Length */
2705 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2706 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2707 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2708 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2709 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2710 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2711 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2712 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2714 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2715 *aSRpnt = SRpnt;
2717 if ((STp->buffer)->syscall_result != 0) {
2718 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2719 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2720 return (-EIO);
2723 memset(cmd, 0, MAX_COMMAND_SIZE);
2724 cmd[0] = MODE_SENSE;
2725 cmd[1] = 8;
2726 cmd[2] = CAPABILITIES_PAGE;
2727 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2729 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2730 *aSRpnt = SRpnt;
2732 if ((STp->buffer)->syscall_result != 0) {
2733 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2734 return (-EIO);
2737 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2738 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2739 sizeof(osst_mode_parameter_header_t) + header->bdl);
2741 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2743 memset(cmd, 0, MAX_COMMAND_SIZE);
2744 cmd[0] = MODE_SENSE;
2745 cmd[1] = 8;
2746 cmd[2] = TAPE_PARAMTR_PAGE;
2747 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2749 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2750 *aSRpnt = SRpnt;
2752 if ((STp->buffer)->syscall_result != 0) {
2753 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2754 return (-EIO);
2757 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2758 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2759 sizeof(osst_mode_parameter_header_t) + header->bdl);
2761 STp->density = prm->density;
2762 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2763 #if DEBUG
2764 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2765 name, STp->density, STp->capacity / 32, drive_buffer_size);
2766 #endif
2768 return 0;
2773 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2774 it messes up the block number). */
2775 static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2777 int result;
2778 char * name = tape_name(STp);
2780 #if DEBUG
2781 if (debugging)
2782 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2783 name, forward ? "forward" : "backward");
2784 #endif
2786 if (forward) {
2787 /* assumes that the filemark is already read by the drive, so this is low cost */
2788 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2790 else
2791 /* assumes this is only called if we just read the filemark! */
2792 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2794 if (result < 0)
2795 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2796 name, forward ? "forward" : "backward");
2798 return result;
2802 /* Get the tape position. */
2804 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2806 unsigned char scmd[MAX_COMMAND_SIZE];
2807 struct osst_request * SRpnt;
2808 int result = 0;
2809 char * name = tape_name(STp);
2811 /* KG: We want to be able to use it for checking Write Buffer availability
2812 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2813 char mybuf[24];
2814 char * olddata = STp->buffer->b_data;
2815 int oldsize = STp->buffer->buffer_size;
2817 if (STp->ready != ST_READY) return (-EIO);
2819 memset (scmd, 0, MAX_COMMAND_SIZE);
2820 scmd[0] = READ_POSITION;
2822 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2823 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2824 STp->timeout, MAX_RETRIES, 1);
2825 if (!SRpnt) {
2826 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2827 return (-EBUSY);
2829 *aSRpnt = SRpnt;
2831 if (STp->buffer->syscall_result)
2832 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
2834 if (result == -EINVAL)
2835 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2836 else {
2837 if (result == -EIO) { /* re-read position - this needs to preserve media errors */
2838 unsigned char mysense[16];
2839 memcpy (mysense, SRpnt->sense, 16);
2840 memset (scmd, 0, MAX_COMMAND_SIZE);
2841 scmd[0] = READ_POSITION;
2842 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2843 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2844 STp->timeout, MAX_RETRIES, 1);
2845 #if DEBUG
2846 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2847 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2848 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2849 #endif
2850 if (!STp->buffer->syscall_result)
2851 memcpy (SRpnt->sense, mysense, 16);
2852 else
2853 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2855 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2856 + ((STp->buffer)->b_data[5] << 16)
2857 + ((STp->buffer)->b_data[6] << 8)
2858 + (STp->buffer)->b_data[7];
2859 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2860 + ((STp->buffer)->b_data[ 9] << 16)
2861 + ((STp->buffer)->b_data[10] << 8)
2862 + (STp->buffer)->b_data[11];
2863 STp->cur_frames = (STp->buffer)->b_data[15];
2864 #if DEBUG
2865 if (debugging) {
2866 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2867 STp->first_frame_position, STp->last_frame_position,
2868 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2869 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2870 STp->cur_frames);
2872 #endif
2873 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2874 #if DEBUG
2875 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2876 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2877 #endif
2878 STp->first_frame_position = STp->last_frame_position;
2881 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2883 return (result == 0 ? STp->first_frame_position : result);
2887 /* Set the tape block */
2888 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2890 unsigned char scmd[MAX_COMMAND_SIZE];
2891 struct osst_request * SRpnt;
2892 struct st_partstat * STps;
2893 int result = 0;
2894 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2895 char * name = tape_name(STp);
2897 if (STp->ready != ST_READY) return (-EIO);
2899 STps = &(STp->ps[STp->partition]);
2901 if (ppos < 0 || ppos > STp->capacity) {
2902 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2903 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2904 result = (-EINVAL);
2907 do {
2908 #if DEBUG
2909 if (debugging)
2910 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2911 #endif
2912 memset (scmd, 0, MAX_COMMAND_SIZE);
2913 scmd[0] = SEEK_10;
2914 scmd[1] = 1;
2915 scmd[3] = (pp >> 24);
2916 scmd[4] = (pp >> 16);
2917 scmd[5] = (pp >> 8);
2918 scmd[6] = pp;
2919 if (skip)
2920 scmd[9] = 0x80;
2922 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
2923 MAX_RETRIES, 1);
2924 if (!SRpnt)
2925 return (-EBUSY);
2926 *aSRpnt = SRpnt;
2928 if ((STp->buffer)->syscall_result != 0) {
2929 #if DEBUG
2930 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
2931 name, STp->first_frame_position, pp);
2932 #endif
2933 result = (-EIO);
2935 if (pp != ppos)
2936 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
2937 } while ((pp != ppos) && (pp = ppos));
2938 STp->first_frame_position = STp->last_frame_position = ppos;
2939 STps->eof = ST_NOEOF;
2940 STps->at_sm = 0;
2941 STps->rw = ST_IDLE;
2942 STp->frame_in_buffer = 0;
2943 return result;
2946 static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
2948 struct st_partstat * STps = &(STp->ps[STp->partition]);
2949 int result = 0;
2951 if (STp->write_type != OS_WRITE_NEW_MARK) {
2952 /* true unless the user wrote the filemark for us */
2953 result = osst_flush_drive_buffer(STp, aSRpnt);
2954 if (result < 0) goto out;
2955 result = osst_write_filemark(STp, aSRpnt);
2956 if (result < 0) goto out;
2958 if (STps->drv_file >= 0)
2959 STps->drv_file++ ;
2960 STps->drv_block = 0;
2962 result = osst_write_eod(STp, aSRpnt);
2963 osst_write_header(STp, aSRpnt, leave_at_EOT);
2965 STps->eof = ST_FM;
2966 out:
2967 return result;
2970 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2972 /* Flush the write buffer (never need to write if variable blocksize). */
2973 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
2975 int offset, transfer, blks = 0;
2976 int result = 0;
2977 unsigned char cmd[MAX_COMMAND_SIZE];
2978 struct osst_request * SRpnt = *aSRpnt;
2979 struct st_partstat * STps;
2980 char * name = tape_name(STp);
2982 if ((STp->buffer)->writing) {
2983 if (SRpnt == (STp->buffer)->last_SRpnt)
2984 #if DEBUG
2985 { printk(OSST_DEB_MSG
2986 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
2987 #endif
2988 *aSRpnt = SRpnt = NULL;
2989 #if DEBUG
2990 } else if (SRpnt)
2991 printk(OSST_DEB_MSG
2992 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
2993 #endif
2994 osst_write_behind_check(STp);
2995 if ((STp->buffer)->syscall_result) {
2996 #if DEBUG
2997 if (debugging)
2998 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
2999 name, (STp->buffer)->midlevel_result);
3000 #endif
3001 if ((STp->buffer)->midlevel_result == INT_MAX)
3002 return (-ENOSPC);
3003 return (-EIO);
3007 result = 0;
3008 if (STp->dirty == 1) {
3010 STp->write_count++;
3011 STps = &(STp->ps[STp->partition]);
3012 STps->rw = ST_WRITING;
3013 offset = STp->buffer->buffer_bytes;
3014 blks = (offset + STp->block_size - 1) / STp->block_size;
3015 transfer = OS_FRAME_SIZE;
3017 if (offset < OS_DATA_SIZE)
3018 osst_zero_buffer_tail(STp->buffer);
3020 if (STp->poll)
3021 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3022 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3024 memset(cmd, 0, MAX_COMMAND_SIZE);
3025 cmd[0] = WRITE_6;
3026 cmd[1] = 1;
3027 cmd[4] = 1;
3029 switch (STp->write_type) {
3030 case OS_WRITE_DATA:
3031 #if DEBUG
3032 if (debugging)
3033 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3034 name, blks, STp->frame_seq_number,
3035 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3036 #endif
3037 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3038 STp->logical_blk_num - blks, STp->block_size, blks);
3039 break;
3040 case OS_WRITE_EOD:
3041 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3042 STp->logical_blk_num, 0, 0);
3043 break;
3044 case OS_WRITE_NEW_MARK:
3045 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3046 STp->logical_blk_num++, 0, blks=1);
3047 break;
3048 case OS_WRITE_HEADER:
3049 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3050 break;
3051 default: /* probably FILLER */
3052 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3054 #if DEBUG
3055 if (debugging)
3056 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3057 name, offset, transfer, blks);
3058 #endif
3060 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3061 STp->timeout, MAX_RETRIES, 1);
3062 *aSRpnt = SRpnt;
3063 if (!SRpnt)
3064 return (-EBUSY);
3066 if ((STp->buffer)->syscall_result != 0) {
3067 #if DEBUG
3068 printk(OSST_DEB_MSG
3069 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3070 name, SRpnt->sense[0], SRpnt->sense[2],
3071 SRpnt->sense[12], SRpnt->sense[13]);
3072 #endif
3073 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3074 (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3075 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3076 STp->dirty = 0;
3077 (STp->buffer)->buffer_bytes = 0;
3078 result = (-ENOSPC);
3080 else {
3081 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3082 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3083 result = (-EIO);
3086 STps->drv_block = (-1); /* FIXME - even if write recovery succeeds? */
3088 else {
3089 STp->first_frame_position++;
3090 STp->dirty = 0;
3091 (STp->buffer)->buffer_bytes = 0;
3094 #if DEBUG
3095 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3096 #endif
3097 return result;
3101 /* Flush the tape buffer. The tape will be positioned correctly unless
3102 seek_next is true. */
3103 static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3105 struct st_partstat * STps;
3106 int backspace = 0, result = 0;
3107 #if DEBUG
3108 char * name = tape_name(STp);
3109 #endif
3112 * If there was a bus reset, block further access
3113 * to this device.
3115 if( STp->pos_unknown)
3116 return (-EIO);
3118 if (STp->ready != ST_READY)
3119 return 0;
3121 STps = &(STp->ps[STp->partition]);
3122 if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
3123 STp->write_type = OS_WRITE_DATA;
3124 return osst_flush_write_buffer(STp, aSRpnt);
3126 if (STp->block_size == 0)
3127 return 0;
3129 #if DEBUG
3130 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3131 #endif
3133 if (!STp->can_bsr) {
3134 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3135 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3136 (STp->buffer)->buffer_bytes = 0;
3137 (STp->buffer)->read_pointer = 0;
3138 STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */
3141 if (!seek_next) {
3142 if (STps->eof == ST_FM_HIT) {
3143 result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3144 if (!result)
3145 STps->eof = ST_NOEOF;
3146 else {
3147 if (STps->drv_file >= 0)
3148 STps->drv_file++;
3149 STps->drv_block = 0;
3152 if (!result && backspace > 0) /* TODO -- design and run a test case for this */
3153 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3155 else if (STps->eof == ST_FM_HIT) {
3156 if (STps->drv_file >= 0)
3157 STps->drv_file++;
3158 STps->drv_block = 0;
3159 STps->eof = ST_NOEOF;
3162 return result;
3165 static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3167 unsigned char cmd[MAX_COMMAND_SIZE];
3168 struct osst_request * SRpnt;
3169 int blks;
3170 #if DEBUG
3171 char * name = tape_name(STp);
3172 #endif
3174 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3175 #if DEBUG
3176 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3177 #endif
3178 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3179 return (-EIO);
3181 /* error recovery may have bumped us past the header partition */
3182 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3183 #if DEBUG
3184 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3185 #endif
3186 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3190 if (STp->poll)
3191 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3192 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3193 return (-EIO);
3195 // osst_build_stats(STp, &SRpnt);
3197 STp->ps[STp->partition].rw = ST_WRITING;
3198 STp->write_type = OS_WRITE_DATA;
3200 memset(cmd, 0, MAX_COMMAND_SIZE);
3201 cmd[0] = WRITE_6;
3202 cmd[1] = 1;
3203 cmd[4] = 1; /* one frame at a time... */
3204 blks = STp->buffer->buffer_bytes / STp->block_size;
3205 #if DEBUG
3206 if (debugging)
3207 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3208 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3209 #endif
3210 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3211 STp->logical_blk_num - blks, STp->block_size, blks);
3213 #if DEBUG
3214 if (!synchronous)
3215 STp->write_pending = 1;
3216 #endif
3217 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3218 MAX_RETRIES, synchronous);
3219 if (!SRpnt)
3220 return (-EBUSY);
3221 *aSRpnt = SRpnt;
3223 if (synchronous) {
3224 if (STp->buffer->syscall_result != 0) {
3225 #if DEBUG
3226 if (debugging)
3227 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3228 #endif
3229 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3230 (SRpnt->sense[2] & 0x40)) {
3231 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3232 return (-ENOSPC);
3234 else {
3235 if (osst_write_error_recovery(STp, aSRpnt, 1))
3236 return (-EIO);
3239 else
3240 STp->first_frame_position++;
3243 STp->write_count++;
3245 return 0;
3248 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3249 static int do_door_lock(struct osst_tape * STp, int do_lock)
3251 int retval, cmd;
3253 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3254 #if DEBUG
3255 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3256 #endif
3257 retval = scsi_ioctl(STp->device, cmd, NULL);
3258 if (!retval) {
3259 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3261 else {
3262 STp->door_locked = ST_LOCK_FAILS;
3264 return retval;
3267 /* Set the internal state after reset */
3268 static void reset_state(struct osst_tape *STp)
3270 int i;
3271 struct st_partstat *STps;
3273 STp->pos_unknown = 0;
3274 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3275 STps = &(STp->ps[i]);
3276 STps->rw = ST_IDLE;
3277 STps->eof = ST_NOEOF;
3278 STps->at_sm = 0;
3279 STps->last_block_valid = 0;
3280 STps->drv_block = -1;
3281 STps->drv_file = -1;
3286 /* Entry points to osst */
3288 /* Write command */
3289 static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3291 ssize_t total, retval = 0;
3292 ssize_t i, do_count, blks, transfer;
3293 int write_threshold;
3294 int doing_write = 0;
3295 const char __user * b_point;
3296 struct osst_request * SRpnt = NULL;
3297 struct st_modedef * STm;
3298 struct st_partstat * STps;
3299 struct osst_tape * STp = filp->private_data;
3300 char * name = tape_name(STp);
3303 if (mutex_lock_interruptible(&STp->lock))
3304 return (-ERESTARTSYS);
3307 * If we are in the middle of error recovery, don't let anyone
3308 * else try and use this device. Also, if error recovery fails, it
3309 * may try and take the device offline, in which case all further
3310 * access to the device is prohibited.
3312 if( !scsi_block_when_processing_errors(STp->device) ) {
3313 retval = (-ENXIO);
3314 goto out;
3317 if (STp->ready != ST_READY) {
3318 if (STp->ready == ST_NO_TAPE)
3319 retval = (-ENOMEDIUM);
3320 else
3321 retval = (-EIO);
3322 goto out;
3324 STm = &(STp->modes[STp->current_mode]);
3325 if (!STm->defined) {
3326 retval = (-ENXIO);
3327 goto out;
3329 if (count == 0)
3330 goto out;
3333 * If there was a bus reset, block further access
3334 * to this device.
3336 if (STp->pos_unknown) {
3337 retval = (-EIO);
3338 goto out;
3341 #if DEBUG
3342 if (!STp->in_use) {
3343 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3344 retval = (-EIO);
3345 goto out;
3347 #endif
3349 if (STp->write_prot) {
3350 retval = (-EACCES);
3351 goto out;
3354 /* Write must be integral number of blocks */
3355 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3356 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3357 name, count, STp->block_size<1024?
3358 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3359 retval = (-EINVAL);
3360 goto out;
3363 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3364 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3365 name, STp->first_frame_position);
3366 retval = (-ENOSPC);
3367 goto out;
3370 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3371 STp->door_locked = ST_LOCKED_AUTO;
3373 STps = &(STp->ps[STp->partition]);
3375 if (STps->rw == ST_READING) {
3376 #if DEBUG
3377 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3378 STps->drv_file, STps->drv_block);
3379 #endif
3380 retval = osst_flush_buffer(STp, &SRpnt, 0);
3381 if (retval)
3382 goto out;
3383 STps->rw = ST_IDLE;
3385 if (STps->rw != ST_WRITING) {
3386 /* Are we totally rewriting this tape? */
3387 if (!STp->header_ok ||
3388 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3389 (STps->drv_file == 0 && STps->drv_block == 0)) {
3390 STp->wrt_pass_cntr++;
3391 #if DEBUG
3392 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3393 name, STp->wrt_pass_cntr);
3394 #endif
3395 osst_reset_header(STp, &SRpnt);
3396 STps->drv_file = STps->drv_block = 0;
3398 /* Do we know where we'll be writing on the tape? */
3399 else {
3400 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3401 STps->drv_file < 0 || STps->drv_block < 0) {
3402 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3403 STps->drv_file = STp->filemark_cnt;
3404 STps->drv_block = 0;
3406 else {
3407 /* We have no idea where the tape is positioned - give up */
3408 #if DEBUG
3409 printk(OSST_DEB_MSG
3410 "%s:D: Cannot write at indeterminate position.\n", name);
3411 #endif
3412 retval = (-EIO);
3413 goto out;
3416 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3417 STp->filemark_cnt = STps->drv_file;
3418 STp->last_mark_ppos =
3419 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3420 printk(KERN_WARNING
3421 "%s:W: Overwriting file %d with old write pass counter %d\n",
3422 name, STps->drv_file, STp->wrt_pass_cntr);
3423 printk(KERN_WARNING
3424 "%s:W: may lead to stale data being accepted on reading back!\n",
3425 name);
3426 #if DEBUG
3427 printk(OSST_DEB_MSG
3428 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3429 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3430 #endif
3433 STp->fast_open = 0;
3435 if (!STp->header_ok) {
3436 #if DEBUG
3437 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3438 #endif
3439 retval = (-EIO);
3440 goto out;
3443 if ((STp->buffer)->writing) {
3444 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3445 osst_write_behind_check(STp);
3446 if ((STp->buffer)->syscall_result) {
3447 #if DEBUG
3448 if (debugging)
3449 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3450 (STp->buffer)->midlevel_result);
3451 #endif
3452 if ((STp->buffer)->midlevel_result == INT_MAX)
3453 STps->eof = ST_EOM_OK;
3454 else
3455 STps->eof = ST_EOM_ERROR;
3458 if (STps->eof == ST_EOM_OK) {
3459 retval = (-ENOSPC);
3460 goto out;
3462 else if (STps->eof == ST_EOM_ERROR) {
3463 retval = (-EIO);
3464 goto out;
3467 /* Check the buffer readability in cases where copy_user might catch
3468 the problems after some tape movement. */
3469 if ((copy_from_user(&i, buf, 1) != 0 ||
3470 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3471 retval = (-EFAULT);
3472 goto out;
3475 if (!STm->do_buffer_writes) {
3476 write_threshold = 1;
3478 else
3479 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3480 if (!STm->do_async_writes)
3481 write_threshold--;
3483 total = count;
3484 #if DEBUG
3485 if (debugging)
3486 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3487 name, (int) count, STps->drv_file, STps->drv_block,
3488 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3489 #endif
3490 b_point = buf;
3491 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3493 doing_write = 1;
3494 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3495 (STp->buffer)->buffer_bytes;
3496 if (do_count > count)
3497 do_count = count;
3499 i = append_to_buffer(b_point, STp->buffer, do_count);
3500 if (i) {
3501 retval = i;
3502 goto out;
3505 blks = do_count / STp->block_size;
3506 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3508 i = osst_write_frame(STp, &SRpnt, 1);
3510 if (i == (-ENOSPC)) {
3511 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3512 if (transfer <= do_count) {
3513 filp->f_pos += do_count - transfer;
3514 count -= do_count - transfer;
3515 if (STps->drv_block >= 0) {
3516 STps->drv_block += (do_count - transfer) / STp->block_size;
3518 STps->eof = ST_EOM_OK;
3519 retval = (-ENOSPC); /* EOM within current request */
3520 #if DEBUG
3521 if (debugging)
3522 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3523 name, (int) transfer);
3524 #endif
3526 else {
3527 STps->eof = ST_EOM_ERROR;
3528 STps->drv_block = (-1); /* Too cautious? */
3529 retval = (-EIO); /* EOM for old data */
3530 #if DEBUG
3531 if (debugging)
3532 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3533 #endif
3536 else
3537 retval = i;
3539 if (retval < 0) {
3540 if (SRpnt != NULL) {
3541 osst_release_request(SRpnt);
3542 SRpnt = NULL;
3544 STp->buffer->buffer_bytes = 0;
3545 STp->dirty = 0;
3546 if (count < total)
3547 retval = total - count;
3548 goto out;
3551 filp->f_pos += do_count;
3552 b_point += do_count;
3553 count -= do_count;
3554 if (STps->drv_block >= 0) {
3555 STps->drv_block += blks;
3557 STp->buffer->buffer_bytes = 0;
3558 STp->dirty = 0;
3559 } /* end while write threshold exceeded */
3561 if (count != 0) {
3562 STp->dirty = 1;
3563 i = append_to_buffer(b_point, STp->buffer, count);
3564 if (i) {
3565 retval = i;
3566 goto out;
3568 blks = count / STp->block_size;
3569 STp->logical_blk_num += blks;
3570 if (STps->drv_block >= 0) {
3571 STps->drv_block += blks;
3573 filp->f_pos += count;
3574 count = 0;
3577 if (doing_write && (STp->buffer)->syscall_result != 0) {
3578 retval = (STp->buffer)->syscall_result;
3579 goto out;
3582 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3583 /* Schedule an asynchronous write */
3584 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3585 STp->block_size) * STp->block_size;
3586 STp->dirty = !((STp->buffer)->writing ==
3587 (STp->buffer)->buffer_bytes);
3589 i = osst_write_frame(STp, &SRpnt, 0);
3590 if (i < 0) {
3591 retval = (-EIO);
3592 goto out;
3594 SRpnt = NULL; /* Prevent releasing this request! */
3596 STps->at_sm &= (total == 0);
3597 if (total > 0)
3598 STps->eof = ST_NOEOF;
3600 retval = total;
3602 out:
3603 if (SRpnt != NULL) osst_release_request(SRpnt);
3605 mutex_unlock(&STp->lock);
3607 return retval;
3611 /* Read command */
3612 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3614 ssize_t total, retval = 0;
3615 ssize_t i, transfer;
3616 int special;
3617 struct st_modedef * STm;
3618 struct st_partstat * STps;
3619 struct osst_request * SRpnt = NULL;
3620 struct osst_tape * STp = filp->private_data;
3621 char * name = tape_name(STp);
3624 if (mutex_lock_interruptible(&STp->lock))
3625 return (-ERESTARTSYS);
3628 * If we are in the middle of error recovery, don't let anyone
3629 * else try and use this device. Also, if error recovery fails, it
3630 * may try and take the device offline, in which case all further
3631 * access to the device is prohibited.
3633 if( !scsi_block_when_processing_errors(STp->device) ) {
3634 retval = (-ENXIO);
3635 goto out;
3638 if (STp->ready != ST_READY) {
3639 if (STp->ready == ST_NO_TAPE)
3640 retval = (-ENOMEDIUM);
3641 else
3642 retval = (-EIO);
3643 goto out;
3645 STm = &(STp->modes[STp->current_mode]);
3646 if (!STm->defined) {
3647 retval = (-ENXIO);
3648 goto out;
3650 #if DEBUG
3651 if (!STp->in_use) {
3652 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3653 retval = (-EIO);
3654 goto out;
3656 #endif
3657 /* Must have initialized medium */
3658 if (!STp->header_ok) {
3659 retval = (-EIO);
3660 goto out;
3663 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3664 STp->door_locked = ST_LOCKED_AUTO;
3666 STps = &(STp->ps[STp->partition]);
3667 if (STps->rw == ST_WRITING) {
3668 retval = osst_flush_buffer(STp, &SRpnt, 0);
3669 if (retval)
3670 goto out;
3671 STps->rw = ST_IDLE;
3672 /* FIXME -- this may leave the tape without EOD and up2date headers */
3675 if ((count % STp->block_size) != 0) {
3676 printk(KERN_WARNING
3677 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3678 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3681 #if DEBUG
3682 if (debugging && STps->eof != ST_NOEOF)
3683 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3684 STps->eof, (STp->buffer)->buffer_bytes);
3685 #endif
3686 if ((STp->buffer)->buffer_bytes == 0 &&
3687 STps->eof >= ST_EOD_1) {
3688 if (STps->eof < ST_EOD) {
3689 STps->eof += 1;
3690 retval = 0;
3691 goto out;
3693 retval = (-EIO); /* EOM or Blank Check */
3694 goto out;
3697 /* Check the buffer writability before any tape movement. Don't alter
3698 buffer data. */
3699 if (copy_from_user(&i, buf, 1) != 0 ||
3700 copy_to_user (buf, &i, 1) != 0 ||
3701 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3702 copy_to_user (buf + count - 1, &i, 1) != 0) {
3703 retval = (-EFAULT);
3704 goto out;
3707 /* Loop until enough data in buffer or a special condition found */
3708 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3710 /* Get new data if the buffer is empty */
3711 if ((STp->buffer)->buffer_bytes == 0) {
3712 if (STps->eof == ST_FM_HIT)
3713 break;
3714 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3715 if (special < 0) { /* No need to continue read */
3716 STp->frame_in_buffer = 0;
3717 retval = special;
3718 goto out;
3722 /* Move the data from driver buffer to user buffer */
3723 if ((STp->buffer)->buffer_bytes > 0) {
3724 #if DEBUG
3725 if (debugging && STps->eof != ST_NOEOF)
3726 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3727 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3728 #endif
3729 /* force multiple of block size, note block_size may have been adjusted */
3730 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3731 (STp->buffer)->buffer_bytes : count - total)/
3732 STp->block_size) * STp->block_size;
3734 if (transfer == 0) {
3735 printk(KERN_WARNING
3736 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3737 name, count, STp->block_size < 1024?
3738 STp->block_size:STp->block_size/1024,
3739 STp->block_size<1024?'b':'k');
3740 break;
3742 i = from_buffer(STp->buffer, buf, transfer);
3743 if (i) {
3744 retval = i;
3745 goto out;
3747 STp->logical_blk_num += transfer / STp->block_size;
3748 STps->drv_block += transfer / STp->block_size;
3749 filp->f_pos += transfer;
3750 buf += transfer;
3751 total += transfer;
3754 if ((STp->buffer)->buffer_bytes == 0) {
3755 #if DEBUG
3756 if (debugging)
3757 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3758 name, STp->frame_seq_number);
3759 #endif
3760 STp->frame_in_buffer = 0;
3761 STp->frame_seq_number++; /* frame to look for next time */
3763 } /* for (total = 0, special = 0; total < count && !special; ) */
3765 /* Change the eof state if no data from tape or buffer */
3766 if (total == 0) {
3767 if (STps->eof == ST_FM_HIT) {
3768 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3769 STps->drv_block = 0;
3770 if (STps->drv_file >= 0)
3771 STps->drv_file++;
3773 else if (STps->eof == ST_EOD_1) {
3774 STps->eof = ST_EOD_2;
3775 if (STps->drv_block > 0 && STps->drv_file >= 0)
3776 STps->drv_file++;
3777 STps->drv_block = 0;
3779 else if (STps->eof == ST_EOD_2)
3780 STps->eof = ST_EOD;
3782 else if (STps->eof == ST_FM)
3783 STps->eof = ST_NOEOF;
3785 retval = total;
3787 out:
3788 if (SRpnt != NULL) osst_release_request(SRpnt);
3790 mutex_unlock(&STp->lock);
3792 return retval;
3796 /* Set the driver options */
3797 static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3799 printk(KERN_INFO
3800 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3801 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3802 STm->do_read_ahead);
3803 printk(KERN_INFO
3804 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3805 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3806 printk(KERN_INFO
3807 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3808 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3809 STp->scsi2_logical);
3810 printk(KERN_INFO
3811 "%s:I: sysv: %d\n", name, STm->sysv);
3812 #if DEBUG
3813 printk(KERN_INFO
3814 "%s:D: debugging: %d\n",
3815 name, debugging);
3816 #endif
3820 static int osst_set_options(struct osst_tape *STp, long options)
3822 int value;
3823 long code;
3824 struct st_modedef * STm;
3825 char * name = tape_name(STp);
3827 STm = &(STp->modes[STp->current_mode]);
3828 if (!STm->defined) {
3829 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3830 modes_defined = 1;
3831 #if DEBUG
3832 if (debugging)
3833 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3834 name, STp->current_mode);
3835 #endif
3838 code = options & MT_ST_OPTIONS;
3839 if (code == MT_ST_BOOLEANS) {
3840 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3841 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3842 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3843 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3844 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3845 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3846 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3847 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3848 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3849 if ((STp->device)->scsi_level >= SCSI_2)
3850 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3851 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3852 STm->sysv = (options & MT_ST_SYSV) != 0;
3853 #if DEBUG
3854 debugging = (options & MT_ST_DEBUGGING) != 0;
3855 #endif
3856 osst_log_options(STp, STm, name);
3858 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3859 value = (code == MT_ST_SETBOOLEANS);
3860 if ((options & MT_ST_BUFFER_WRITES) != 0)
3861 STm->do_buffer_writes = value;
3862 if ((options & MT_ST_ASYNC_WRITES) != 0)
3863 STm->do_async_writes = value;
3864 if ((options & MT_ST_DEF_WRITES) != 0)
3865 STm->defaults_for_writes = value;
3866 if ((options & MT_ST_READ_AHEAD) != 0)
3867 STm->do_read_ahead = value;
3868 if ((options & MT_ST_TWO_FM) != 0)
3869 STp->two_fm = value;
3870 if ((options & MT_ST_FAST_MTEOM) != 0)
3871 STp->fast_mteom = value;
3872 if ((options & MT_ST_AUTO_LOCK) != 0)
3873 STp->do_auto_lock = value;
3874 if ((options & MT_ST_CAN_BSR) != 0)
3875 STp->can_bsr = value;
3876 if ((options & MT_ST_NO_BLKLIMS) != 0)
3877 STp->omit_blklims = value;
3878 if ((STp->device)->scsi_level >= SCSI_2 &&
3879 (options & MT_ST_CAN_PARTITIONS) != 0)
3880 STp->can_partitions = value;
3881 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3882 STp->scsi2_logical = value;
3883 if ((options & MT_ST_SYSV) != 0)
3884 STm->sysv = value;
3885 #if DEBUG
3886 if ((options & MT_ST_DEBUGGING) != 0)
3887 debugging = value;
3888 #endif
3889 osst_log_options(STp, STm, name);
3891 else if (code == MT_ST_WRITE_THRESHOLD) {
3892 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3893 if (value < 1 || value > osst_buffer_size) {
3894 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3895 name, value);
3896 return (-EIO);
3898 STp->write_threshold = value;
3899 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3900 name, value);
3902 else if (code == MT_ST_DEF_BLKSIZE) {
3903 value = (options & ~MT_ST_OPTIONS);
3904 if (value == ~MT_ST_OPTIONS) {
3905 STm->default_blksize = (-1);
3906 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3908 else {
3909 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3910 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3911 name, value);
3912 return (-EINVAL);
3914 STm->default_blksize = value;
3915 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3916 name, STm->default_blksize);
3919 else if (code == MT_ST_TIMEOUTS) {
3920 value = (options & ~MT_ST_OPTIONS);
3921 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3922 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3923 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3924 (value & ~MT_ST_SET_LONG_TIMEOUT));
3926 else {
3927 STp->timeout = value * HZ;
3928 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3931 else if (code == MT_ST_DEF_OPTIONS) {
3932 code = (options & ~MT_ST_CLEAR_DEFAULT);
3933 value = (options & MT_ST_CLEAR_DEFAULT);
3934 if (code == MT_ST_DEF_DENSITY) {
3935 if (value == MT_ST_CLEAR_DEFAULT) {
3936 STm->default_density = (-1);
3937 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3939 else {
3940 STm->default_density = value & 0xff;
3941 printk(KERN_INFO "%s:I: Density default set to %x\n",
3942 name, STm->default_density);
3945 else if (code == MT_ST_DEF_DRVBUFFER) {
3946 if (value == MT_ST_CLEAR_DEFAULT) {
3947 STp->default_drvbuffer = 0xff;
3948 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3950 else {
3951 STp->default_drvbuffer = value & 7;
3952 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3953 name, STp->default_drvbuffer);
3956 else if (code == MT_ST_DEF_COMPRESSION) {
3957 if (value == MT_ST_CLEAR_DEFAULT) {
3958 STm->default_compression = ST_DONT_TOUCH;
3959 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3961 else {
3962 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3963 printk(KERN_INFO "%s:I: Compression default set to %x\n",
3964 name, (value & 1));
3968 else
3969 return (-EIO);
3971 return 0;
3975 /* Internal ioctl function */
3976 static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
3977 unsigned int cmd_in, unsigned long arg)
3979 int timeout;
3980 long ltmp;
3981 int i, ioctl_result;
3982 int chg_eof = 1;
3983 unsigned char cmd[MAX_COMMAND_SIZE];
3984 struct osst_request * SRpnt = * aSRpnt;
3985 struct st_partstat * STps;
3986 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3987 int datalen = 0, direction = DMA_NONE;
3988 char * name = tape_name(STp);
3990 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3991 if (STp->ready == ST_NO_TAPE)
3992 return (-ENOMEDIUM);
3993 else
3994 return (-EIO);
3996 timeout = STp->long_timeout;
3997 STps = &(STp->ps[STp->partition]);
3998 fileno = STps->drv_file;
3999 blkno = STps->drv_block;
4000 at_sm = STps->at_sm;
4001 frame_seq_numbr = STp->frame_seq_number;
4002 logical_blk_num = STp->logical_blk_num;
4004 memset(cmd, 0, MAX_COMMAND_SIZE);
4005 switch (cmd_in) {
4006 case MTFSFM:
4007 chg_eof = 0; /* Changed from the FSF after this */
4008 case MTFSF:
4009 if (STp->raw)
4010 return (-EIO);
4011 if (STp->linux_media)
4012 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4013 else
4014 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4015 if (fileno >= 0)
4016 fileno += arg;
4017 blkno = 0;
4018 at_sm &= (arg == 0);
4019 goto os_bypass;
4021 case MTBSF:
4022 chg_eof = 0; /* Changed from the FSF after this */
4023 case MTBSFM:
4024 if (STp->raw)
4025 return (-EIO);
4026 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4027 if (fileno >= 0)
4028 fileno -= arg;
4029 blkno = (-1); /* We can't know the block number */
4030 at_sm &= (arg == 0);
4031 goto os_bypass;
4033 case MTFSR:
4034 case MTBSR:
4035 #if DEBUG
4036 if (debugging)
4037 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4038 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4039 #endif
4040 if (cmd_in == MTFSR) {
4041 logical_blk_num += arg;
4042 if (blkno >= 0) blkno += arg;
4044 else {
4045 logical_blk_num -= arg;
4046 if (blkno >= 0) blkno -= arg;
4048 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4049 fileno = STps->drv_file;
4050 blkno = STps->drv_block;
4051 at_sm &= (arg == 0);
4052 goto os_bypass;
4054 case MTFSS:
4055 cmd[0] = SPACE;
4056 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4057 cmd[2] = (arg >> 16);
4058 cmd[3] = (arg >> 8);
4059 cmd[4] = arg;
4060 #if DEBUG
4061 if (debugging)
4062 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4063 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4064 #endif
4065 if (arg != 0) {
4066 blkno = fileno = (-1);
4067 at_sm = 1;
4069 break;
4070 case MTBSS:
4071 cmd[0] = SPACE;
4072 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4073 ltmp = (-arg);
4074 cmd[2] = (ltmp >> 16);
4075 cmd[3] = (ltmp >> 8);
4076 cmd[4] = ltmp;
4077 #if DEBUG
4078 if (debugging) {
4079 if (cmd[2] & 0x80)
4080 ltmp = 0xff000000;
4081 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4082 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4083 name, (-ltmp));
4085 #endif
4086 if (arg != 0) {
4087 blkno = fileno = (-1);
4088 at_sm = 1;
4090 break;
4091 case MTWEOF:
4092 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4093 STp->write_type = OS_WRITE_DATA;
4094 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4095 } else
4096 ioctl_result = 0;
4097 #if DEBUG
4098 if (debugging)
4099 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4100 #endif
4101 for (i=0; i<arg; i++)
4102 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4103 if (fileno >= 0) fileno += arg;
4104 if (blkno >= 0) blkno = 0;
4105 goto os_bypass;
4107 case MTWSM:
4108 if (STp->write_prot)
4109 return (-EACCES);
4110 if (!STp->raw)
4111 return 0;
4112 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
4113 if (cmd_in == MTWSM)
4114 cmd[1] = 2;
4115 cmd[2] = (arg >> 16);
4116 cmd[3] = (arg >> 8);
4117 cmd[4] = arg;
4118 timeout = STp->timeout;
4119 #if DEBUG
4120 if (debugging)
4121 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4122 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4123 #endif
4124 if (fileno >= 0)
4125 fileno += arg;
4126 blkno = 0;
4127 at_sm = (cmd_in == MTWSM);
4128 break;
4129 case MTOFFL:
4130 case MTLOAD:
4131 case MTUNLOAD:
4132 case MTRETEN:
4133 cmd[0] = START_STOP;
4134 cmd[1] = 1; /* Don't wait for completion */
4135 if (cmd_in == MTLOAD) {
4136 if (STp->ready == ST_NO_TAPE)
4137 cmd[4] = 4; /* open tray */
4138 else
4139 cmd[4] = 1; /* load */
4141 if (cmd_in == MTRETEN)
4142 cmd[4] = 3; /* retension then mount */
4143 if (cmd_in == MTOFFL)
4144 cmd[4] = 4; /* rewind then eject */
4145 timeout = STp->timeout;
4146 #if DEBUG
4147 if (debugging) {
4148 switch (cmd_in) {
4149 case MTUNLOAD:
4150 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4151 break;
4152 case MTLOAD:
4153 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4154 break;
4155 case MTRETEN:
4156 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4157 break;
4158 case MTOFFL:
4159 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4160 break;
4163 #endif
4164 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4165 break;
4166 case MTNOP:
4167 #if DEBUG
4168 if (debugging)
4169 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4170 #endif
4171 return 0; /* Should do something ? */
4172 break;
4173 case MTEOM:
4174 #if DEBUG
4175 if (debugging)
4176 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4177 #endif
4178 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4179 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4180 ioctl_result = -EIO;
4181 goto os_bypass;
4183 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4184 #if DEBUG
4185 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4186 #endif
4187 ioctl_result = -EIO;
4188 goto os_bypass;
4190 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4191 fileno = STp->filemark_cnt;
4192 blkno = at_sm = 0;
4193 goto os_bypass;
4195 case MTERASE:
4196 if (STp->write_prot)
4197 return (-EACCES);
4198 ioctl_result = osst_reset_header(STp, &SRpnt);
4199 i = osst_write_eod(STp, &SRpnt);
4200 if (i < ioctl_result) ioctl_result = i;
4201 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4202 if (i < ioctl_result) ioctl_result = i;
4203 fileno = blkno = at_sm = 0 ;
4204 goto os_bypass;
4206 case MTREW:
4207 cmd[0] = REZERO_UNIT; /* rewind */
4208 cmd[1] = 1;
4209 #if DEBUG
4210 if (debugging)
4211 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4212 #endif
4213 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4214 break;
4216 case MTSETBLK: /* Set block length */
4217 if ((STps->drv_block == 0 ) &&
4218 !STp->dirty &&
4219 ((STp->buffer)->buffer_bytes == 0) &&
4220 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4221 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4222 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4224 * Only allowed to change the block size if you opened the
4225 * device at the beginning of a file before writing anything.
4226 * Note, that when reading, changing block_size is futile,
4227 * as the size used when writing overrides it.
4229 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4230 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4231 name, STp->block_size);
4232 return 0;
4234 case MTSETDENSITY: /* Set tape density */
4235 case MTSETDRVBUFFER: /* Set drive buffering */
4236 case SET_DENS_AND_BLK: /* Set density and block size */
4237 chg_eof = 0;
4238 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4239 return (-EIO); /* Not allowed if data in buffer */
4240 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4241 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4242 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4243 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4244 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4245 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4246 return (-EINVAL);
4248 return 0; /* FIXME silently ignore if block size didn't change */
4250 default:
4251 return (-ENOSYS);
4254 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4256 ioctl_result = (STp->buffer)->syscall_result;
4258 if (!SRpnt) {
4259 #if DEBUG
4260 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4261 #endif
4262 return ioctl_result;
4265 if (!ioctl_result) { /* SCSI command successful */
4266 STp->frame_seq_number = frame_seq_numbr;
4267 STp->logical_blk_num = logical_blk_num;
4270 os_bypass:
4271 #if DEBUG
4272 if (debugging)
4273 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4274 #endif
4276 if (!ioctl_result) { /* success */
4278 if (cmd_in == MTFSFM) {
4279 fileno--;
4280 blkno--;
4282 if (cmd_in == MTBSFM) {
4283 fileno++;
4284 blkno++;
4286 STps->drv_block = blkno;
4287 STps->drv_file = fileno;
4288 STps->at_sm = at_sm;
4290 if (cmd_in == MTEOM)
4291 STps->eof = ST_EOD;
4292 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4293 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4294 STps->drv_block++;
4295 STp->logical_blk_num++;
4296 STp->frame_seq_number++;
4297 STp->frame_in_buffer = 0;
4298 STp->buffer->read_pointer = 0;
4300 else if (cmd_in == MTFSF)
4301 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4302 else if (chg_eof)
4303 STps->eof = ST_NOEOF;
4305 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4306 STp->rew_at_close = 0;
4307 else if (cmd_in == MTLOAD) {
4308 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4309 STp->ps[i].rw = ST_IDLE;
4310 STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4312 STp->partition = 0;
4315 if (cmd_in == MTREW) {
4316 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4317 if (ioctl_result > 0)
4318 ioctl_result = 0;
4321 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4322 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4323 STps->drv_file = STps->drv_block = -1;
4324 else
4325 STps->drv_file = STps->drv_block = 0;
4326 STps->eof = ST_NOEOF;
4327 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4328 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4329 STps->drv_file = STps->drv_block = -1;
4330 else {
4331 STps->drv_file = STp->filemark_cnt;
4332 STps->drv_block = 0;
4334 STps->eof = ST_EOD;
4335 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4336 STps->drv_file = STps->drv_block = (-1);
4337 STps->eof = ST_NOEOF;
4338 STp->header_ok = 0;
4339 } else if (cmd_in == MTERASE) {
4340 STp->header_ok = 0;
4341 } else if (SRpnt) { /* SCSI command was not completely successful. */
4342 if (SRpnt->sense[2] & 0x40) {
4343 STps->eof = ST_EOM_OK;
4344 STps->drv_block = 0;
4346 if (chg_eof)
4347 STps->eof = ST_NOEOF;
4349 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4350 STps->eof = ST_EOD;
4352 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4353 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4355 *aSRpnt = SRpnt;
4357 return ioctl_result;
4361 /* Open the device */
4362 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4364 unsigned short flags;
4365 int i, b_size, new_session = 0, retval = 0;
4366 unsigned char cmd[MAX_COMMAND_SIZE];
4367 struct osst_request * SRpnt = NULL;
4368 struct osst_tape * STp;
4369 struct st_modedef * STm;
4370 struct st_partstat * STps;
4371 char * name;
4372 int dev = TAPE_NR(inode);
4373 int mode = TAPE_MODE(inode);
4376 * We really want to do nonseekable_open(inode, filp); here, but some
4377 * versions of tar incorrectly call lseek on tapes and bail out if that
4378 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4380 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4382 write_lock(&os_scsi_tapes_lock);
4383 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4384 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4385 write_unlock(&os_scsi_tapes_lock);
4386 return (-ENXIO);
4389 name = tape_name(STp);
4391 if (STp->in_use) {
4392 write_unlock(&os_scsi_tapes_lock);
4393 #if DEBUG
4394 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4395 #endif
4396 return (-EBUSY);
4398 if (scsi_device_get(STp->device)) {
4399 write_unlock(&os_scsi_tapes_lock);
4400 #if DEBUG
4401 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4402 #endif
4403 return (-ENXIO);
4405 filp->private_data = STp;
4406 STp->in_use = 1;
4407 write_unlock(&os_scsi_tapes_lock);
4408 STp->rew_at_close = TAPE_REWIND(inode);
4410 if( !scsi_block_when_processing_errors(STp->device) ) {
4411 return -ENXIO;
4414 if (mode != STp->current_mode) {
4415 #if DEBUG
4416 if (debugging)
4417 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4418 name, STp->current_mode, mode);
4419 #endif
4420 new_session = 1;
4421 STp->current_mode = mode;
4423 STm = &(STp->modes[STp->current_mode]);
4425 flags = filp->f_flags;
4426 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4428 STp->raw = TAPE_IS_RAW(inode);
4429 if (STp->raw)
4430 STp->header_ok = 0;
4432 /* Allocate data segments for this device's tape buffer */
4433 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4434 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4435 retval = (-EOVERFLOW);
4436 goto err_out;
4438 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4439 for (i = 0, b_size = 0;
4440 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4441 b_size += STp->buffer->sg[i++].length);
4442 STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4443 #if DEBUG
4444 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4445 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4446 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4447 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4448 #endif
4449 } else {
4450 STp->buffer->aux = NULL; /* this had better never happen! */
4451 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4452 retval = (-EIO);
4453 goto err_out;
4455 STp->buffer->writing = 0;
4456 STp->buffer->syscall_result = 0;
4457 STp->dirty = 0;
4458 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4459 STps = &(STp->ps[i]);
4460 STps->rw = ST_IDLE;
4462 STp->ready = ST_READY;
4463 #if DEBUG
4464 STp->nbr_waits = STp->nbr_finished = 0;
4465 #endif
4467 memset (cmd, 0, MAX_COMMAND_SIZE);
4468 cmd[0] = TEST_UNIT_READY;
4470 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4471 if (!SRpnt) {
4472 retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
4473 goto err_out;
4475 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4476 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4477 SRpnt->sense[12] == 4 ) {
4478 #if DEBUG
4479 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4480 #endif
4481 if (filp->f_flags & O_NONBLOCK) {
4482 retval = -EAGAIN;
4483 goto err_out;
4485 if (SRpnt->sense[13] == 2) { /* initialize command required (LOAD) */
4486 memset (cmd, 0, MAX_COMMAND_SIZE);
4487 cmd[0] = START_STOP;
4488 cmd[1] = 1;
4489 cmd[4] = 1;
4490 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4491 STp->timeout, MAX_RETRIES, 1);
4493 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4495 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4496 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4497 #if DEBUG
4498 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4499 #endif
4500 STp->header_ok = 0;
4502 for (i=0; i < 10; i++) {
4504 memset (cmd, 0, MAX_COMMAND_SIZE);
4505 cmd[0] = TEST_UNIT_READY;
4507 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4508 STp->timeout, MAX_RETRIES, 1);
4509 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4510 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4511 break;
4514 STp->pos_unknown = 0;
4515 STp->partition = STp->new_partition = 0;
4516 if (STp->can_partitions)
4517 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4518 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4519 STps = &(STp->ps[i]);
4520 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4521 STps->eof = ST_NOEOF;
4522 STps->at_sm = 0;
4523 STps->last_block_valid = 0;
4524 STps->drv_block = 0;
4525 STps->drv_file = 0 ;
4527 new_session = 1;
4528 STp->recover_count = 0;
4529 STp->abort_count = 0;
4532 * if we have valid headers from before, and the drive/tape seem untouched,
4533 * open without reconfiguring and re-reading the headers
4535 if (!STp->buffer->syscall_result && STp->header_ok &&
4536 !SRpnt->result && SRpnt->sense[0] == 0) {
4538 memset(cmd, 0, MAX_COMMAND_SIZE);
4539 cmd[0] = MODE_SENSE;
4540 cmd[1] = 8;
4541 cmd[2] = VENDOR_IDENT_PAGE;
4542 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4544 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4546 if (STp->buffer->syscall_result ||
4547 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4548 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4549 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4550 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4551 #if DEBUG
4552 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4553 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4554 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4555 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4556 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4557 #endif
4558 STp->header_ok = 0;
4560 i = STp->first_frame_position;
4561 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4562 if (STp->door_locked == ST_UNLOCKED) {
4563 if (do_door_lock(STp, 1))
4564 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4565 else
4566 STp->door_locked = ST_LOCKED_AUTO;
4568 if (!STp->frame_in_buffer) {
4569 STp->block_size = (STm->default_blksize > 0) ?
4570 STm->default_blksize : OS_DATA_SIZE;
4571 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4573 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4574 STp->fast_open = 1;
4575 osst_release_request(SRpnt);
4576 return 0;
4578 #if DEBUG
4579 if (i != STp->first_frame_position)
4580 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4581 name, i, STp->first_frame_position);
4582 #endif
4583 STp->header_ok = 0;
4585 STp->fast_open = 0;
4587 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4588 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4590 memset(cmd, 0, MAX_COMMAND_SIZE);
4591 cmd[0] = MODE_SELECT;
4592 cmd[1] = 0x10;
4593 cmd[4] = 4 + MODE_HEADER_LENGTH;
4595 (STp->buffer)->b_data[0] = cmd[4] - 1;
4596 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4597 (STp->buffer)->b_data[2] = 0; /* Reserved */
4598 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4599 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4600 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4601 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4602 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4604 #if DEBUG
4605 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4606 #endif
4607 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4609 STp->header_ok = 0;
4611 for (i=0; i < 10; i++) {
4613 memset (cmd, 0, MAX_COMMAND_SIZE);
4614 cmd[0] = TEST_UNIT_READY;
4616 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4617 STp->timeout, MAX_RETRIES, 1);
4618 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4619 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4620 break;
4622 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4623 STp->pos_unknown = 0;
4624 STp->partition = STp->new_partition = 0;
4625 if (STp->can_partitions)
4626 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4627 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4628 STps = &(STp->ps[i]);
4629 STps->rw = ST_IDLE;
4630 STps->eof = ST_NOEOF;
4631 STps->at_sm = 0;
4632 STps->last_block_valid = 0;
4633 STps->drv_block = 0;
4634 STps->drv_file = 0 ;
4636 new_session = 1;
4641 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4642 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4644 if ((STp->buffer)->syscall_result != 0) {
4645 if ((STp->device)->scsi_level >= SCSI_2 &&
4646 (SRpnt->sense[0] & 0x70) == 0x70 &&
4647 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4648 SRpnt->sense[12] == 0x3a) { /* Check ASC */
4649 STp->ready = ST_NO_TAPE;
4650 } else
4651 STp->ready = ST_NOT_READY;
4652 osst_release_request(SRpnt);
4653 SRpnt = NULL;
4654 STp->density = 0; /* Clear the erroneous "residue" */
4655 STp->write_prot = 0;
4656 STp->block_size = 0;
4657 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4658 STp->partition = STp->new_partition = 0;
4659 STp->door_locked = ST_UNLOCKED;
4660 return 0;
4663 osst_configure_onstream(STp, &SRpnt);
4665 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4666 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4667 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4668 STp->buffer->buffer_bytes =
4669 STp->buffer->read_pointer =
4670 STp->frame_in_buffer = 0;
4672 #if DEBUG
4673 if (debugging)
4674 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4675 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4676 (STp->buffer)->buffer_blocks);
4677 #endif
4679 if (STp->drv_write_prot) {
4680 STp->write_prot = 1;
4681 #if DEBUG
4682 if (debugging)
4683 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4684 #endif
4685 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4686 retval = (-EROFS);
4687 goto err_out;
4691 if (new_session) { /* Change the drive parameters for the new mode */
4692 #if DEBUG
4693 if (debugging)
4694 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4695 #endif
4696 STp->density_changed = STp->blksize_changed = 0;
4697 STp->compression_changed = 0;
4701 * properly position the tape and check the ADR headers
4703 if (STp->door_locked == ST_UNLOCKED) {
4704 if (do_door_lock(STp, 1))
4705 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4706 else
4707 STp->door_locked = ST_LOCKED_AUTO;
4710 osst_analyze_headers(STp, &SRpnt);
4712 osst_release_request(SRpnt);
4713 SRpnt = NULL;
4715 return 0;
4717 err_out:
4718 if (SRpnt != NULL)
4719 osst_release_request(SRpnt);
4720 normalize_buffer(STp->buffer);
4721 STp->header_ok = 0;
4722 STp->in_use = 0;
4723 scsi_device_put(STp->device);
4725 return retval;
4729 /* Flush the tape buffer before close */
4730 static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4732 int result = 0, result2;
4733 struct osst_tape * STp = filp->private_data;
4734 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4735 struct st_partstat * STps = &(STp->ps[STp->partition]);
4736 struct osst_request * SRpnt = NULL;
4737 char * name = tape_name(STp);
4739 if (file_count(filp) > 1)
4740 return 0;
4742 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4743 STp->write_type = OS_WRITE_DATA;
4744 result = osst_flush_write_buffer(STp, &SRpnt);
4745 if (result != 0 && result != (-ENOSPC))
4746 goto out;
4748 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4750 #if DEBUG
4751 if (debugging) {
4752 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4753 name, (long)(filp->f_pos));
4754 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4755 name, STp->nbr_waits, STp->nbr_finished);
4757 #endif
4758 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4759 #if DEBUG
4760 if (debugging)
4761 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4762 name, 1+STp->two_fm);
4763 #endif
4765 else if (!STp->rew_at_close) {
4766 STps = &(STp->ps[STp->partition]);
4767 if (!STm->sysv || STps->rw != ST_READING) {
4768 if (STp->can_bsr)
4769 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4770 else if (STps->eof == ST_FM_HIT) {
4771 result = cross_eof(STp, &SRpnt, 0);
4772 if (result) {
4773 if (STps->drv_file >= 0)
4774 STps->drv_file++;
4775 STps->drv_block = 0;
4776 STps->eof = ST_FM;
4778 else
4779 STps->eof = ST_NOEOF;
4782 else if ((STps->eof == ST_NOEOF &&
4783 !(result = cross_eof(STp, &SRpnt, 1))) ||
4784 STps->eof == ST_FM_HIT) {
4785 if (STps->drv_file >= 0)
4786 STps->drv_file++;
4787 STps->drv_block = 0;
4788 STps->eof = ST_FM;
4792 out:
4793 if (STp->rew_at_close) {
4794 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4795 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4796 if (result == 0 && result2 < 0)
4797 result = result2;
4799 if (SRpnt) osst_release_request(SRpnt);
4801 if (STp->abort_count || STp->recover_count) {
4802 printk(KERN_INFO "%s:I:", name);
4803 if (STp->abort_count)
4804 printk(" %d unrecovered errors", STp->abort_count);
4805 if (STp->recover_count)
4806 printk(" %d recovered errors", STp->recover_count);
4807 if (STp->write_count)
4808 printk(" in %d frames written", STp->write_count);
4809 if (STp->read_count)
4810 printk(" in %d frames read", STp->read_count);
4811 printk("\n");
4812 STp->recover_count = 0;
4813 STp->abort_count = 0;
4815 STp->write_count = 0;
4816 STp->read_count = 0;
4818 return result;
4822 /* Close the device and release it */
4823 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4825 int result = 0;
4826 struct osst_tape * STp = filp->private_data;
4828 if (STp->door_locked == ST_LOCKED_AUTO)
4829 do_door_lock(STp, 0);
4831 if (STp->raw)
4832 STp->header_ok = 0;
4834 normalize_buffer(STp->buffer);
4835 write_lock(&os_scsi_tapes_lock);
4836 STp->in_use = 0;
4837 write_unlock(&os_scsi_tapes_lock);
4839 scsi_device_put(STp->device);
4841 return result;
4845 /* The ioctl command */
4846 static int osst_ioctl(struct inode * inode,struct file * file,
4847 unsigned int cmd_in, unsigned long arg)
4849 int i, cmd_nr, cmd_type, blk, retval = 0;
4850 struct st_modedef * STm;
4851 struct st_partstat * STps;
4852 struct osst_request * SRpnt = NULL;
4853 struct osst_tape * STp = file->private_data;
4854 char * name = tape_name(STp);
4855 void __user * p = (void __user *)arg;
4857 if (mutex_lock_interruptible(&STp->lock))
4858 return -ERESTARTSYS;
4860 #if DEBUG
4861 if (debugging && !STp->in_use) {
4862 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4863 retval = (-EIO);
4864 goto out;
4866 #endif
4867 STm = &(STp->modes[STp->current_mode]);
4868 STps = &(STp->ps[STp->partition]);
4871 * If we are in the middle of error recovery, don't let anyone
4872 * else try and use this device. Also, if error recovery fails, it
4873 * may try and take the device offline, in which case all further
4874 * access to the device is prohibited.
4876 if( !scsi_block_when_processing_errors(STp->device) ) {
4877 retval = (-ENXIO);
4878 goto out;
4881 cmd_type = _IOC_TYPE(cmd_in);
4882 cmd_nr = _IOC_NR(cmd_in);
4883 #if DEBUG
4884 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4885 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4886 #endif
4887 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4888 struct mtop mtc;
4889 int auto_weof = 0;
4891 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4892 retval = (-EINVAL);
4893 goto out;
4896 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4897 if (i) {
4898 retval = (-EFAULT);
4899 goto out;
4902 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4903 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4904 retval = (-EPERM);
4905 goto out;
4908 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4909 retval = (-ENXIO);
4910 goto out;
4913 if (!STp->pos_unknown) {
4915 if (STps->eof == ST_FM_HIT) {
4916 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4917 mtc.mt_count -= 1;
4918 if (STps->drv_file >= 0)
4919 STps->drv_file += 1;
4921 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4922 mtc.mt_count += 1;
4923 if (STps->drv_file >= 0)
4924 STps->drv_file += 1;
4928 if (mtc.mt_op == MTSEEK) {
4929 /* Old position must be restored if partition will be changed */
4930 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4932 else {
4933 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
4934 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
4935 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
4936 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
4937 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
4938 mtc.mt_op == MTCOMPRESSION;
4940 i = osst_flush_buffer(STp, &SRpnt, i);
4941 if (i < 0) {
4942 retval = i;
4943 goto out;
4946 else {
4948 * If there was a bus reset, block further access
4949 * to this device. If the user wants to rewind the tape,
4950 * then reset the flag and allow access again.
4952 if(mtc.mt_op != MTREW &&
4953 mtc.mt_op != MTOFFL &&
4954 mtc.mt_op != MTRETEN &&
4955 mtc.mt_op != MTERASE &&
4956 mtc.mt_op != MTSEEK &&
4957 mtc.mt_op != MTEOM) {
4958 retval = (-EIO);
4959 goto out;
4961 reset_state(STp);
4962 /* remove this when the midlevel properly clears was_reset */
4963 STp->device->was_reset = 0;
4966 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
4967 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
4968 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
4969 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
4970 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
4973 * The user tells us to move to another position on the tape.
4974 * If we were appending to the tape content, that would leave
4975 * the tape without proper end, in that case write EOD and
4976 * update the header to reflect its position.
4978 #if DEBUG
4979 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
4980 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
4981 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
4982 STp->logical_blk_num, STps->drv_file, STps->drv_block );
4983 #endif
4984 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
4985 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
4986 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4987 i = osst_write_trailer(STp, &SRpnt,
4988 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4989 #if DEBUG
4990 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4991 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
4992 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
4993 #endif
4994 if (i < 0) {
4995 retval = i;
4996 goto out;
4999 STps->rw = ST_IDLE;
5002 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5003 do_door_lock(STp, 0); /* Ignore result! */
5005 if (mtc.mt_op == MTSETDRVBUFFER &&
5006 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5007 retval = osst_set_options(STp, mtc.mt_count);
5008 goto out;
5011 if (mtc.mt_op == MTSETPART) {
5012 if (mtc.mt_count >= STp->nbr_partitions)
5013 retval = -EINVAL;
5014 else {
5015 STp->new_partition = mtc.mt_count;
5016 retval = 0;
5018 goto out;
5021 if (mtc.mt_op == MTMKPART) {
5022 if (!STp->can_partitions) {
5023 retval = (-EINVAL);
5024 goto out;
5026 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5027 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5028 retval = i;
5029 goto out;
5031 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5032 STp->ps[i].rw = ST_IDLE;
5033 STp->ps[i].at_sm = 0;
5034 STp->ps[i].last_block_valid = 0;
5036 STp->partition = STp->new_partition = 0;
5037 STp->nbr_partitions = 1; /* Bad guess ?-) */
5038 STps->drv_block = STps->drv_file = 0;
5039 retval = 0;
5040 goto out;
5043 if (mtc.mt_op == MTSEEK) {
5044 if (STp->raw)
5045 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5046 else
5047 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5048 if (!STp->can_partitions)
5049 STp->ps[0].rw = ST_IDLE;
5050 retval = i;
5051 goto out;
5054 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5055 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5056 goto out;
5059 if (auto_weof)
5060 cross_eof(STp, &SRpnt, 0);
5062 if (mtc.mt_op == MTCOMPRESSION)
5063 retval = -EINVAL; /* OnStream drives don't have compression hardware */
5064 else
5065 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5066 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5067 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5068 goto out;
5071 if (!STm->defined) {
5072 retval = (-ENXIO);
5073 goto out;
5076 if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5077 retval = i;
5078 goto out;
5081 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5082 struct mtget mt_status;
5084 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5085 retval = (-EINVAL);
5086 goto out;
5089 mt_status.mt_type = MT_ISONSTREAM_SC;
5090 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5091 mt_status.mt_dsreg =
5092 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5093 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5094 mt_status.mt_blkno = STps->drv_block;
5095 mt_status.mt_fileno = STps->drv_file;
5096 if (STp->block_size != 0) {
5097 if (STps->rw == ST_WRITING)
5098 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5099 else if (STps->rw == ST_READING)
5100 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5101 STp->block_size - 1) / STp->block_size;
5104 mt_status.mt_gstat = 0;
5105 if (STp->drv_write_prot)
5106 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5107 if (mt_status.mt_blkno == 0) {
5108 if (mt_status.mt_fileno == 0)
5109 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5110 else
5111 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5113 mt_status.mt_resid = STp->partition;
5114 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5115 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5116 else if (STps->eof >= ST_EOM_OK)
5117 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5118 if (STp->density == 1)
5119 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5120 else if (STp->density == 2)
5121 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5122 else if (STp->density == 3)
5123 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5124 if (STp->ready == ST_READY)
5125 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5126 if (STp->ready == ST_NO_TAPE)
5127 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5128 if (STps->at_sm)
5129 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5130 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5131 STp->drv_buffer != 0)
5132 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5134 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5135 if (i) {
5136 retval = (-EFAULT);
5137 goto out;
5140 STp->recover_erreg = 0; /* Clear after read */
5141 retval = 0;
5142 goto out;
5143 } /* End of MTIOCGET */
5145 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5146 struct mtpos mt_pos;
5148 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5149 retval = (-EINVAL);
5150 goto out;
5152 if (STp->raw)
5153 blk = osst_get_frame_position(STp, &SRpnt);
5154 else
5155 blk = osst_get_sector(STp, &SRpnt);
5156 if (blk < 0) {
5157 retval = blk;
5158 goto out;
5160 mt_pos.mt_blkno = blk;
5161 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5162 if (i)
5163 retval = -EFAULT;
5164 goto out;
5166 if (SRpnt) osst_release_request(SRpnt);
5168 mutex_unlock(&STp->lock);
5170 return scsi_ioctl(STp->device, cmd_in, p);
5172 out:
5173 if (SRpnt) osst_release_request(SRpnt);
5175 mutex_unlock(&STp->lock);
5177 return retval;
5180 #ifdef CONFIG_COMPAT
5181 static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5183 struct osst_tape *STp = file->private_data;
5184 struct scsi_device *sdev = STp->device;
5185 int ret = -ENOIOCTLCMD;
5186 if (sdev->host->hostt->compat_ioctl) {
5188 ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5191 return ret;
5193 #endif
5197 /* Memory handling routines */
5199 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5200 static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5202 int i;
5203 gfp_t priority;
5204 struct osst_buffer *tb;
5206 if (from_initialization)
5207 priority = GFP_ATOMIC;
5208 else
5209 priority = GFP_KERNEL;
5211 i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5212 tb = kzalloc(i, priority);
5213 if (!tb) {
5214 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5215 return NULL;
5218 tb->sg_segs = tb->orig_sg_segs = 0;
5219 tb->use_sg = max_sg;
5220 tb->in_use = 1;
5221 tb->dma = need_dma;
5222 tb->buffer_size = 0;
5223 #if DEBUG
5224 if (debugging)
5225 printk(OSST_DEB_MSG
5226 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5227 i, max_sg, need_dma);
5228 #endif
5229 return tb;
5232 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5233 static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5235 int segs, nbr, max_segs, b_size, order, got;
5236 gfp_t priority;
5238 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5239 return 1;
5241 if (STbuffer->sg_segs) {
5242 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5243 normalize_buffer(STbuffer);
5245 /* See how many segments we can use -- need at least two */
5246 nbr = max_segs = STbuffer->use_sg;
5247 if (nbr <= 2)
5248 return 0;
5250 priority = GFP_KERNEL /* | __GFP_NOWARN */;
5251 if (need_dma)
5252 priority |= GFP_DMA;
5254 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5255 big enough to reach the goal (code assumes no segments in place) */
5256 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5257 struct page *page = alloc_pages(priority, order);
5259 STbuffer->sg[0].offset = 0;
5260 if (page != NULL) {
5261 sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5262 STbuffer->b_data = page_address(page);
5263 break;
5266 if (sg_page(&STbuffer->sg[0]) == NULL) {
5267 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5268 return 0;
5270 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5271 for (segs=STbuffer->sg_segs=1, got=b_size;
5272 segs < max_segs && got < OS_FRAME_SIZE; ) {
5273 struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5274 STbuffer->sg[segs].offset = 0;
5275 if (page == NULL) {
5276 if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
5277 b_size /= 2; /* Large enough for the rest of the buffers */
5278 order--;
5279 continue;
5281 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5282 OS_FRAME_SIZE);
5283 #if DEBUG
5284 STbuffer->buffer_size = got;
5285 #endif
5286 normalize_buffer(STbuffer);
5287 return 0;
5289 sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5290 got += STbuffer->sg[segs].length;
5291 STbuffer->buffer_size = got;
5292 STbuffer->sg_segs = ++segs;
5294 #if DEBUG
5295 if (debugging) {
5296 printk(OSST_DEB_MSG
5297 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5298 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5299 printk(OSST_DEB_MSG
5300 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5301 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5302 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5304 #endif
5306 return 1;
5310 /* Release the segments */
5311 static void normalize_buffer(struct osst_buffer *STbuffer)
5313 int i, order, b_size;
5315 for (i=0; i < STbuffer->sg_segs; i++) {
5317 for (b_size = PAGE_SIZE, order = 0;
5318 b_size < STbuffer->sg[i].length;
5319 b_size *= 2, order++);
5321 __free_pages(sg_page(&STbuffer->sg[i]), order);
5322 STbuffer->buffer_size -= STbuffer->sg[i].length;
5324 #if DEBUG
5325 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5326 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5327 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5328 #endif
5329 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5333 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5334 negative error code. */
5335 static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5337 int i, cnt, res, offset;
5339 for (i=0, offset=st_bp->buffer_bytes;
5340 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5341 offset -= st_bp->sg[i].length;
5342 if (i == st_bp->sg_segs) { /* Should never happen */
5343 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5344 return (-EIO);
5346 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5347 cnt = st_bp->sg[i].length - offset < do_count ?
5348 st_bp->sg[i].length - offset : do_count;
5349 res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5350 if (res)
5351 return (-EFAULT);
5352 do_count -= cnt;
5353 st_bp->buffer_bytes += cnt;
5354 ubp += cnt;
5355 offset = 0;
5357 if (do_count) { /* Should never happen */
5358 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5359 do_count);
5360 return (-EIO);
5362 return 0;
5366 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5367 negative error code. */
5368 static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5370 int i, cnt, res, offset;
5372 for (i=0, offset=st_bp->read_pointer;
5373 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5374 offset -= st_bp->sg[i].length;
5375 if (i == st_bp->sg_segs) { /* Should never happen */
5376 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5377 return (-EIO);
5379 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5380 cnt = st_bp->sg[i].length - offset < do_count ?
5381 st_bp->sg[i].length - offset : do_count;
5382 res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5383 if (res)
5384 return (-EFAULT);
5385 do_count -= cnt;
5386 st_bp->buffer_bytes -= cnt;
5387 st_bp->read_pointer += cnt;
5388 ubp += cnt;
5389 offset = 0;
5391 if (do_count) { /* Should never happen */
5392 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5393 return (-EIO);
5395 return 0;
5398 /* Sets the tail of the buffer after fill point to zero.
5399 Returns zero (success) or negative error code. */
5400 static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5402 int i, offset, do_count, cnt;
5404 for (i = 0, offset = st_bp->buffer_bytes;
5405 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5406 offset -= st_bp->sg[i].length;
5407 if (i == st_bp->sg_segs) { /* Should never happen */
5408 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5409 return (-EIO);
5411 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5412 i < st_bp->sg_segs && do_count > 0; i++) {
5413 cnt = st_bp->sg[i].length - offset < do_count ?
5414 st_bp->sg[i].length - offset : do_count ;
5415 memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5416 do_count -= cnt;
5417 offset = 0;
5419 if (do_count) { /* Should never happen */
5420 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5421 return (-EIO);
5423 return 0;
5426 /* Copy a osst 32K chunk of memory into the buffer.
5427 Returns zero (success) or negative error code. */
5428 static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5430 int i, cnt, do_count = OS_DATA_SIZE;
5432 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5433 cnt = st_bp->sg[i].length < do_count ?
5434 st_bp->sg[i].length : do_count ;
5435 memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5436 do_count -= cnt;
5437 ptr += cnt;
5439 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5440 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5441 do_count, i);
5442 return (-EIO);
5444 return 0;
5447 /* Copy a osst 32K chunk of memory from the buffer.
5448 Returns zero (success) or negative error code. */
5449 static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5451 int i, cnt, do_count = OS_DATA_SIZE;
5453 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5454 cnt = st_bp->sg[i].length < do_count ?
5455 st_bp->sg[i].length : do_count ;
5456 memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5457 do_count -= cnt;
5458 ptr += cnt;
5460 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5461 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5462 do_count, i);
5463 return (-EIO);
5465 return 0;
5469 /* Module housekeeping */
5471 static void validate_options (void)
5473 if (max_dev > 0)
5474 osst_max_dev = max_dev;
5475 if (write_threshold_kbs > 0)
5476 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5477 if (osst_write_threshold > osst_buffer_size)
5478 osst_write_threshold = osst_buffer_size;
5479 if (max_sg_segs >= OSST_FIRST_SG)
5480 osst_max_sg_segs = max_sg_segs;
5481 #if DEBUG
5482 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5483 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5484 #endif
5487 #ifndef MODULE
5488 /* Set the boot options. Syntax: osst=xxx,yyy,...
5489 where xxx is write threshold in 1024 byte blocks,
5490 and yyy is number of s/g segments to use. */
5491 static int __init osst_setup (char *str)
5493 int i, ints[5];
5494 char *stp;
5496 stp = get_options(str, ARRAY_SIZE(ints), ints);
5498 if (ints[0] > 0) {
5499 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5500 *parms[i].val = ints[i + 1];
5501 } else {
5502 while (stp != NULL) {
5503 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5504 int len = strlen(parms[i].name);
5505 if (!strncmp(stp, parms[i].name, len) &&
5506 (*(stp + len) == ':' || *(stp + len) == '=')) {
5507 *parms[i].val =
5508 simple_strtoul(stp + len + 1, NULL, 0);
5509 break;
5512 if (i >= ARRAY_SIZE(parms))
5513 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5514 stp);
5515 stp = strchr(stp, ',');
5516 if (stp)
5517 stp++;
5521 return 1;
5524 __setup("osst=", osst_setup);
5526 #endif
5528 static const struct file_operations osst_fops = {
5529 .owner = THIS_MODULE,
5530 .read = osst_read,
5531 .write = osst_write,
5532 .ioctl = osst_ioctl,
5533 #ifdef CONFIG_COMPAT
5534 .compat_ioctl = osst_compat_ioctl,
5535 #endif
5536 .open = os_scsi_tape_open,
5537 .flush = os_scsi_tape_flush,
5538 .release = os_scsi_tape_close,
5541 static int osst_supports(struct scsi_device * SDp)
5543 struct osst_support_data {
5544 char *vendor;
5545 char *model;
5546 char *rev;
5547 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5550 static struct osst_support_data support_list[] = {
5551 /* {"XXX", "Yy-", "", NULL}, example */
5552 SIGS_FROM_OSST,
5553 {NULL, }};
5555 struct osst_support_data *rp;
5557 /* We are willing to drive OnStream SC-x0 as well as the
5558 * * IDE, ParPort, FireWire, USB variants, if accessible by
5559 * * emulation layer (ide-scsi, usb-storage, ...) */
5561 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5562 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5563 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5564 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5565 return 1;
5566 return 0;
5570 * sysfs support for osst driver parameter information
5573 static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5575 return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5578 static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5580 static int osst_create_sysfs_files(struct device_driver *sysfs)
5582 return driver_create_file(sysfs, &driver_attr_version);
5585 static void osst_remove_sysfs_files(struct device_driver *sysfs)
5587 driver_remove_file(sysfs, &driver_attr_version);
5591 * sysfs support for accessing ADR header information
5594 static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
5596 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5597 ssize_t l = 0;
5599 if (STp && STp->header_ok && STp->linux_media)
5600 l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5601 return l;
5604 CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5606 static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
5608 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5609 ssize_t l = 0;
5611 if (STp && STp->header_ok && STp->linux_media)
5612 l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5613 return l;
5616 CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5618 static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
5620 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5621 ssize_t l = 0;
5623 if (STp && STp->header_ok && STp->linux_media)
5624 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5625 return l;
5628 CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5630 static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
5632 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5633 ssize_t l = 0;
5635 if (STp && STp->header_ok && STp->linux_media)
5636 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5637 return l;
5640 CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5642 static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
5644 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5645 ssize_t l = 0;
5647 if (STp && STp->header_ok && STp->linux_media)
5648 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5649 return l;
5652 CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5654 static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
5656 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5657 ssize_t l = 0;
5659 if (STp && STp->header_ok && STp->linux_media)
5660 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5661 return l;
5664 CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5666 static struct class *osst_sysfs_class;
5668 static int osst_sysfs_init(void)
5670 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5671 if (IS_ERR(osst_sysfs_class)) {
5672 printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5673 return PTR_ERR(osst_sysfs_class);
5676 return 0;
5679 static void osst_sysfs_destroy(dev_t dev)
5681 class_device_destroy(osst_sysfs_class, dev);
5684 static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5686 struct class_device *osst_class_member;
5687 int err;
5689 osst_class_member = class_device_create(osst_sysfs_class, NULL, dev,
5690 device, "%s", name);
5691 if (IS_ERR(osst_class_member)) {
5692 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5693 return PTR_ERR(osst_class_member);
5696 class_set_devdata(osst_class_member, STp);
5697 err = class_device_create_file(osst_class_member,
5698 &class_device_attr_ADR_rev);
5699 if (err)
5700 goto err_out;
5701 err = class_device_create_file(osst_class_member,
5702 &class_device_attr_media_version);
5703 if (err)
5704 goto err_out;
5705 err = class_device_create_file(osst_class_member,
5706 &class_device_attr_capacity);
5707 if (err)
5708 goto err_out;
5709 err = class_device_create_file(osst_class_member,
5710 &class_device_attr_BOT_frame);
5711 if (err)
5712 goto err_out;
5713 err = class_device_create_file(osst_class_member,
5714 &class_device_attr_EOD_frame);
5715 if (err)
5716 goto err_out;
5717 err = class_device_create_file(osst_class_member,
5718 &class_device_attr_file_count);
5719 if (err)
5720 goto err_out;
5722 return 0;
5724 err_out:
5725 osst_sysfs_destroy(dev);
5726 return err;
5729 static void osst_sysfs_cleanup(void)
5731 class_destroy(osst_sysfs_class);
5735 * osst startup / cleanup code
5738 static int osst_probe(struct device *dev)
5740 struct scsi_device * SDp = to_scsi_device(dev);
5741 struct osst_tape * tpnt;
5742 struct st_modedef * STm;
5743 struct st_partstat * STps;
5744 struct osst_buffer * buffer;
5745 struct gendisk * drive;
5746 int i, dev_num, err = -ENODEV;
5748 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5749 return -ENODEV;
5751 drive = alloc_disk(1);
5752 if (!drive) {
5753 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5754 return -ENODEV;
5757 /* if this is the first attach, build the infrastructure */
5758 write_lock(&os_scsi_tapes_lock);
5759 if (os_scsi_tapes == NULL) {
5760 os_scsi_tapes =
5761 (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
5762 GFP_ATOMIC);
5763 if (os_scsi_tapes == NULL) {
5764 write_unlock(&os_scsi_tapes_lock);
5765 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5766 goto out_put_disk;
5768 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5771 if (osst_nr_dev >= osst_max_dev) {
5772 write_unlock(&os_scsi_tapes_lock);
5773 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5774 goto out_put_disk;
5777 /* find a free minor number */
5778 for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++);
5779 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5780 dev_num = i;
5782 /* allocate a struct osst_tape for this device */
5783 tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5784 if (!tpnt) {
5785 write_unlock(&os_scsi_tapes_lock);
5786 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5787 goto out_put_disk;
5790 /* allocate a buffer for this device */
5791 i = SDp->host->sg_tablesize;
5792 if (osst_max_sg_segs < i)
5793 i = osst_max_sg_segs;
5794 buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5795 if (buffer == NULL) {
5796 write_unlock(&os_scsi_tapes_lock);
5797 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5798 kfree(tpnt);
5799 goto out_put_disk;
5801 os_scsi_tapes[dev_num] = tpnt;
5802 tpnt->buffer = buffer;
5803 tpnt->device = SDp;
5804 drive->private_data = &tpnt->driver;
5805 sprintf(drive->disk_name, "osst%d", dev_num);
5806 tpnt->driver = &osst_template;
5807 tpnt->drive = drive;
5808 tpnt->in_use = 0;
5809 tpnt->capacity = 0xfffff;
5810 tpnt->dirty = 0;
5811 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
5812 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5813 tpnt->density = 0;
5814 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5815 tpnt->can_bsr = OSST_IN_FILE_POS;
5816 tpnt->can_partitions = 0;
5817 tpnt->two_fm = OSST_TWO_FM;
5818 tpnt->fast_mteom = OSST_FAST_MTEOM;
5819 tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5820 tpnt->write_threshold = osst_write_threshold;
5821 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5822 tpnt->partition = 0;
5823 tpnt->new_partition = 0;
5824 tpnt->nbr_partitions = 0;
5825 tpnt->min_block = 512;
5826 tpnt->max_block = OS_DATA_SIZE;
5827 tpnt->timeout = OSST_TIMEOUT;
5828 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5830 /* Recognize OnStream tapes */
5831 /* We don't need to test for OnStream, as this has been done in detect () */
5832 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5833 tpnt->omit_blklims = 1;
5835 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5836 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5837 tpnt->frame_in_buffer = 0;
5838 tpnt->header_ok = 0;
5839 tpnt->linux_media = 0;
5840 tpnt->header_cache = NULL;
5842 for (i=0; i < ST_NBR_MODES; i++) {
5843 STm = &(tpnt->modes[i]);
5844 STm->defined = 0;
5845 STm->sysv = OSST_SYSV;
5846 STm->defaults_for_writes = 0;
5847 STm->do_async_writes = OSST_ASYNC_WRITES;
5848 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5849 STm->do_read_ahead = OSST_READ_AHEAD;
5850 STm->default_compression = ST_DONT_TOUCH;
5851 STm->default_blksize = 512;
5852 STm->default_density = (-1); /* No forced density */
5855 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5856 STps = &(tpnt->ps[i]);
5857 STps->rw = ST_IDLE;
5858 STps->eof = ST_NOEOF;
5859 STps->at_sm = 0;
5860 STps->last_block_valid = 0;
5861 STps->drv_block = (-1);
5862 STps->drv_file = (-1);
5865 tpnt->current_mode = 0;
5866 tpnt->modes[0].defined = 1;
5867 tpnt->modes[2].defined = 1;
5868 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5870 mutex_init(&tpnt->lock);
5871 osst_nr_dev++;
5872 write_unlock(&os_scsi_tapes_lock);
5875 char name[8];
5877 /* Rewind entry */
5878 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5879 if (err)
5880 goto out_free_buffer;
5882 /* No-rewind entry */
5883 snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5884 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5885 if (err)
5886 goto out_free_sysfs1;
5889 sdev_printk(KERN_INFO, SDp,
5890 "osst :I: Attached OnStream %.5s tape as %s\n",
5891 SDp->model, tape_name(tpnt));
5893 return 0;
5895 out_free_sysfs1:
5896 osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5897 out_free_buffer:
5898 kfree(buffer);
5899 out_put_disk:
5900 put_disk(drive);
5901 return err;
5904 static int osst_remove(struct device *dev)
5906 struct scsi_device * SDp = to_scsi_device(dev);
5907 struct osst_tape * tpnt;
5908 int i;
5910 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
5911 return 0;
5913 write_lock(&os_scsi_tapes_lock);
5914 for(i=0; i < osst_max_dev; i++) {
5915 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
5916 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
5917 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
5918 tpnt->device = NULL;
5919 put_disk(tpnt->drive);
5920 os_scsi_tapes[i] = NULL;
5921 osst_nr_dev--;
5922 write_unlock(&os_scsi_tapes_lock);
5923 vfree(tpnt->header_cache);
5924 if (tpnt->buffer) {
5925 normalize_buffer(tpnt->buffer);
5926 kfree(tpnt->buffer);
5928 kfree(tpnt);
5929 return 0;
5932 write_unlock(&os_scsi_tapes_lock);
5933 return 0;
5936 static int __init init_osst(void)
5938 int err;
5940 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5942 validate_options();
5944 err = osst_sysfs_init();
5945 if (err)
5946 return err;
5948 err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
5949 if (err < 0) {
5950 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
5951 goto err_out;
5954 err = scsi_register_driver(&osst_template.gendrv);
5955 if (err)
5956 goto err_out_chrdev;
5958 err = osst_create_sysfs_files(&osst_template.gendrv);
5959 if (err)
5960 goto err_out_scsidrv;
5962 return 0;
5964 err_out_scsidrv:
5965 scsi_unregister_driver(&osst_template.gendrv);
5966 err_out_chrdev:
5967 unregister_chrdev(OSST_MAJOR, "osst");
5968 err_out:
5969 osst_sysfs_cleanup();
5970 return err;
5973 static void __exit exit_osst (void)
5975 int i;
5976 struct osst_tape * STp;
5978 osst_remove_sysfs_files(&osst_template.gendrv);
5979 scsi_unregister_driver(&osst_template.gendrv);
5980 unregister_chrdev(OSST_MAJOR, "osst");
5981 osst_sysfs_cleanup();
5983 if (os_scsi_tapes) {
5984 for (i=0; i < osst_max_dev; ++i) {
5985 if (!(STp = os_scsi_tapes[i])) continue;
5986 /* This is defensive, supposed to happen during detach */
5987 vfree(STp->header_cache);
5988 if (STp->buffer) {
5989 normalize_buffer(STp->buffer);
5990 kfree(STp->buffer);
5992 put_disk(STp->drive);
5993 kfree(STp);
5995 kfree(os_scsi_tapes);
5997 printk(KERN_INFO "osst :I: Unloaded.\n");
6000 module_init(init_osst);
6001 module_exit(exit_osst);