ACPI: Enable bit 11 in _PDC to advertise hw coord
[linux-2.6/mini2440.git] / drivers / scsi / osst.c
blob0ea78d9a37db1a6b0da5b0a18f93fba2aa826a4e
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 <linux/smp_lock.h>
54 #include <asm/uaccess.h>
55 #include <asm/dma.h>
56 #include <asm/system.h>
58 /* The driver prints some debugging information on the console if DEBUG
59 is defined and non-zero. */
60 #define DEBUG 0
62 /* The message level for the debug messages is currently set to KERN_NOTICE
63 so that people can easily see the messages. Later when the debugging messages
64 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
65 #define OSST_DEB_MSG KERN_NOTICE
67 #include <scsi/scsi.h>
68 #include <scsi/scsi_dbg.h>
69 #include <scsi/scsi_device.h>
70 #include <scsi/scsi_driver.h>
71 #include <scsi/scsi_eh.h>
72 #include <scsi/scsi_host.h>
73 #include <scsi/scsi_ioctl.h>
75 #define ST_KILOBYTE 1024
77 #include "st.h"
78 #include "osst.h"
79 #include "osst_options.h"
80 #include "osst_detect.h"
82 static int max_dev = 0;
83 static int write_threshold_kbs = 0;
84 static int max_sg_segs = 0;
86 #ifdef MODULE
87 MODULE_AUTHOR("Willem Riede");
88 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
89 MODULE_LICENSE("GPL");
90 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
91 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
93 module_param(max_dev, int, 0444);
94 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
96 module_param(write_threshold_kbs, int, 0644);
97 MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
99 module_param(max_sg_segs, int, 0644);
100 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
101 #else
102 static struct osst_dev_parm {
103 char *name;
104 int *val;
105 } parms[] __initdata = {
106 { "max_dev", &max_dev },
107 { "write_threshold_kbs", &write_threshold_kbs },
108 { "max_sg_segs", &max_sg_segs }
110 #endif
112 /* Some default definitions have been moved to osst_options.h */
113 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
114 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116 /* The buffer size should fit into the 24 bits for length in the
117 6-byte SCSI read and write commands. */
118 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
119 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
120 #endif
122 #if DEBUG
123 static int debugging = 1;
124 /* uncomment define below to test error recovery */
125 // #define OSST_INJECT_ERRORS 1
126 #endif
128 /* Do not retry! The drive firmware already retries when appropriate,
129 and when it tries to tell us something, we had better listen... */
130 #define MAX_RETRIES 0
132 #define NO_TAPE NOT_READY
134 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
135 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
136 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
138 #define OSST_TIMEOUT (200 * HZ)
139 #define OSST_LONG_TIMEOUT (1800 * HZ)
141 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
142 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
143 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
144 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
146 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
147 24 bits) */
148 #define SET_DENS_AND_BLK 0x10001
150 static int osst_buffer_size = OSST_BUFFER_SIZE;
151 static int osst_write_threshold = OSST_WRITE_THRESHOLD;
152 static int osst_max_sg_segs = OSST_MAX_SG;
153 static int osst_max_dev = OSST_MAX_TAPES;
154 static int osst_nr_dev;
156 static struct osst_tape **os_scsi_tapes = NULL;
157 static DEFINE_RWLOCK(os_scsi_tapes_lock);
159 static int modes_defined = 0;
161 static struct osst_buffer *new_tape_buffer(int, int, int);
162 static int enlarge_buffer(struct osst_buffer *, int);
163 static void normalize_buffer(struct osst_buffer *);
164 static int append_to_buffer(const char __user *, struct osst_buffer *, int);
165 static int from_buffer(struct osst_buffer *, char __user *, int);
166 static int osst_zero_buffer_tail(struct osst_buffer *);
167 static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
168 static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
170 static int osst_probe(struct device *);
171 static int osst_remove(struct device *);
173 static struct scsi_driver osst_template = {
174 .owner = THIS_MODULE,
175 .gendrv = {
176 .name = "osst",
177 .probe = osst_probe,
178 .remove = osst_remove,
182 static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
183 unsigned int cmd_in, unsigned long arg);
185 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
187 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
189 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
191 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
193 static inline char *tape_name(struct osst_tape *tape)
195 return tape->drive->disk_name;
198 /* Routines that handle the interaction with mid-layer SCSI routines */
201 /* Normalize Sense */
202 static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
204 const u8 *ucp;
205 const u8 *sense = SRpnt->sense;
207 s->have_sense = scsi_normalize_sense(SRpnt->sense,
208 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
209 s->flags = 0;
211 if (s->have_sense) {
212 s->deferred = 0;
213 s->remainder_valid =
214 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
215 switch (sense[0] & 0x7f) {
216 case 0x71:
217 s->deferred = 1;
218 case 0x70:
219 s->fixed_format = 1;
220 s->flags = sense[2] & 0xe0;
221 break;
222 case 0x73:
223 s->deferred = 1;
224 case 0x72:
225 s->fixed_format = 0;
226 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
227 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
228 break;
233 /* Convert the result to success code */
234 static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
236 char *name = tape_name(STp);
237 int result = SRpnt->result;
238 u8 * sense = SRpnt->sense, scode;
239 #if DEBUG
240 const char *stp;
241 #endif
242 struct st_cmdstatus *cmdstatp;
244 if (!result)
245 return 0;
247 cmdstatp = &STp->buffer->cmdstat;
248 osst_analyze_sense(SRpnt, cmdstatp);
250 if (cmdstatp->have_sense)
251 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
252 else
253 scode = 0;
254 #if DEBUG
255 if (debugging) {
256 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
257 name, result,
258 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
259 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
260 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
261 name, scode, sense[12], sense[13]);
262 if (cmdstatp->have_sense)
263 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
265 else
266 #endif
267 if (cmdstatp->have_sense && (
268 scode != NO_SENSE &&
269 scode != RECOVERED_ERROR &&
270 /* scode != UNIT_ATTENTION && */
271 scode != BLANK_CHECK &&
272 scode != VOLUME_OVERFLOW &&
273 SRpnt->cmd[0] != MODE_SENSE &&
274 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
275 if (cmdstatp->have_sense) {
276 printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
277 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
279 else {
280 static int notyetprinted = 1;
282 printk(KERN_WARNING
283 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
284 name, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
285 host_byte(result));
286 if (notyetprinted) {
287 notyetprinted = 0;
288 printk(KERN_INFO
289 "%s:I: This warning may be caused by your scsi controller,\n", name);
290 printk(KERN_INFO
291 "%s:I: it has been reported with some Buslogic cards.\n", name);
295 STp->pos_unknown |= STp->device->was_reset;
297 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
298 STp->recover_count++;
299 STp->recover_erreg++;
300 #if DEBUG
301 if (debugging) {
302 if (SRpnt->cmd[0] == READ_6)
303 stp = "read";
304 else if (SRpnt->cmd[0] == WRITE_6)
305 stp = "write";
306 else
307 stp = "ioctl";
308 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
309 STp->recover_count);
311 #endif
312 if ((sense[2] & 0xe0) == 0)
313 return 0;
315 return (-EIO);
319 /* Wakeup from interrupt */
320 static void osst_sleep_done(void *data, char *sense, int result, int resid)
322 struct osst_request *SRpnt = data;
323 struct osst_tape *STp = SRpnt->stp;
325 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
326 STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
327 #if DEBUG
328 STp->write_pending = 0;
329 #endif
330 if (SRpnt->waiting)
331 complete(SRpnt->waiting);
334 /* osst_request memory management */
335 static struct osst_request *osst_allocate_request(void)
337 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
340 static void osst_release_request(struct osst_request *streq)
342 kfree(streq);
345 /* Do the scsi command. Waits until command performed if do_wait is true.
346 Otherwise osst_write_behind_check() is used to check that the command
347 has finished. */
348 static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
349 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
351 unsigned char *bp;
352 unsigned short use_sg;
353 #ifdef OSST_INJECT_ERRORS
354 static int inject = 0;
355 static int repeat = 0;
356 #endif
357 struct completion *waiting;
359 /* if async, make sure there's no command outstanding */
360 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
361 printk(KERN_ERR "%s: Async command already active.\n",
362 tape_name(STp));
363 if (signal_pending(current))
364 (STp->buffer)->syscall_result = (-EINTR);
365 else
366 (STp->buffer)->syscall_result = (-EBUSY);
367 return NULL;
370 if (SRpnt == NULL) {
371 SRpnt = osst_allocate_request();
372 if (SRpnt == NULL) {
373 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
374 tape_name(STp));
375 if (signal_pending(current))
376 (STp->buffer)->syscall_result = (-EINTR);
377 else
378 (STp->buffer)->syscall_result = (-EBUSY);
379 return NULL;
381 SRpnt->stp = STp;
384 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
385 which IO is outstanding. It's nulled out when the IO completes. */
386 if (!do_wait)
387 (STp->buffer)->last_SRpnt = SRpnt;
389 waiting = &STp->wait;
390 init_completion(waiting);
391 SRpnt->waiting = waiting;
393 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
394 if (use_sg) {
395 bp = (char *)&(STp->buffer->sg[0]);
396 if (STp->buffer->sg_segs < use_sg)
397 use_sg = STp->buffer->sg_segs;
399 else
400 bp = (STp->buffer)->b_data;
402 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
403 STp->buffer->cmdstat.have_sense = 0;
404 STp->buffer->syscall_result = 0;
406 if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
407 use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL))
408 /* could not allocate the buffer or request was too large */
409 (STp->buffer)->syscall_result = (-EBUSY);
410 else if (do_wait) {
411 wait_for_completion(waiting);
412 SRpnt->waiting = NULL;
413 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
414 #ifdef OSST_INJECT_ERRORS
415 if (STp->buffer->syscall_result == 0 &&
416 cmd[0] == READ_6 &&
417 cmd[4] &&
418 ( (++ inject % 83) == 29 ||
419 (STp->first_frame_position == 240
420 /* or STp->read_error_frame to fail again on the block calculated above */ &&
421 ++repeat < 3))) {
422 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
423 STp->buffer->last_result_fatal = 1;
425 #endif
427 return SRpnt;
431 /* Handle the write-behind checking (downs the semaphore) */
432 static void osst_write_behind_check(struct osst_tape *STp)
434 struct osst_buffer * STbuffer;
436 STbuffer = STp->buffer;
438 #if DEBUG
439 if (STp->write_pending)
440 STp->nbr_waits++;
441 else
442 STp->nbr_finished++;
443 #endif
444 wait_for_completion(&(STp->wait));
445 STp->buffer->last_SRpnt->waiting = NULL;
447 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
449 if (STp->buffer->syscall_result)
450 STp->buffer->syscall_result =
451 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
452 else
453 STp->first_frame_position++;
455 osst_release_request(STp->buffer->last_SRpnt);
457 if (STbuffer->writing < STbuffer->buffer_bytes)
458 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
460 STbuffer->last_SRpnt = NULL;
461 STbuffer->buffer_bytes -= STbuffer->writing;
462 STbuffer->writing = 0;
464 return;
469 /* Onstream specific Routines */
471 * Initialize the OnStream AUX
473 static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
474 int logical_blk_num, int blk_sz, int blk_cnt)
476 os_aux_t *aux = STp->buffer->aux;
477 os_partition_t *par = &aux->partition;
478 os_dat_t *dat = &aux->dat;
480 if (STp->raw) return;
482 memset(aux, 0, sizeof(*aux));
483 aux->format_id = htonl(0);
484 memcpy(aux->application_sig, "LIN4", 4);
485 aux->hdwr = htonl(0);
486 aux->frame_type = frame_type;
488 switch (frame_type) {
489 case OS_FRAME_TYPE_HEADER:
490 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
491 par->partition_num = OS_CONFIG_PARTITION;
492 par->par_desc_ver = OS_PARTITION_VERSION;
493 par->wrt_pass_cntr = htons(0xffff);
494 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
495 par->first_frame_ppos = htonl(0);
496 par->last_frame_ppos = htonl(0xbb7);
497 aux->frame_seq_num = htonl(0);
498 aux->logical_blk_num_high = htonl(0);
499 aux->logical_blk_num = htonl(0);
500 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
501 break;
502 case OS_FRAME_TYPE_DATA:
503 case OS_FRAME_TYPE_MARKER:
504 dat->dat_sz = 8;
505 dat->reserved1 = 0;
506 dat->entry_cnt = 1;
507 dat->reserved3 = 0;
508 dat->dat_list[0].blk_sz = htonl(blk_sz);
509 dat->dat_list[0].blk_cnt = htons(blk_cnt);
510 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
511 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
512 dat->dat_list[0].reserved = 0;
513 case OS_FRAME_TYPE_EOD:
514 aux->update_frame_cntr = htonl(0);
515 par->partition_num = OS_DATA_PARTITION;
516 par->par_desc_ver = OS_PARTITION_VERSION;
517 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
518 par->first_frame_ppos = htonl(STp->first_data_ppos);
519 par->last_frame_ppos = htonl(STp->capacity);
520 aux->frame_seq_num = htonl(frame_seq_number);
521 aux->logical_blk_num_high = htonl(0);
522 aux->logical_blk_num = htonl(logical_blk_num);
523 break;
524 default: ; /* probably FILL */
526 aux->filemark_cnt = htonl(STp->filemark_cnt);
527 aux->phys_fm = htonl(0xffffffff);
528 aux->last_mark_ppos = htonl(STp->last_mark_ppos);
529 aux->last_mark_lbn = htonl(STp->last_mark_lbn);
533 * Verify that we have the correct tape frame
535 static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
537 char * name = tape_name(STp);
538 os_aux_t * aux = STp->buffer->aux;
539 os_partition_t * par = &(aux->partition);
540 struct st_partstat * STps = &(STp->ps[STp->partition]);
541 int blk_cnt, blk_sz, i;
543 if (STp->raw) {
544 if (STp->buffer->syscall_result) {
545 for (i=0; i < STp->buffer->sg_segs; i++)
546 memset(page_address(sg_page(&STp->buffer->sg[i])),
547 0, STp->buffer->sg[i].length);
548 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
549 } else
550 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
551 return 1;
553 if (STp->buffer->syscall_result) {
554 #if DEBUG
555 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
556 #endif
557 return 0;
559 if (ntohl(aux->format_id) != 0) {
560 #if DEBUG
561 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
562 #endif
563 goto err_out;
565 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
566 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
567 #if DEBUG
568 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
569 #endif
570 goto err_out;
572 if (par->partition_num != OS_DATA_PARTITION) {
573 if (!STp->linux_media || STp->linux_media_version != 2) {
574 #if DEBUG
575 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
576 name, par->partition_num);
577 #endif
578 goto err_out;
581 if (par->par_desc_ver != OS_PARTITION_VERSION) {
582 #if DEBUG
583 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
584 #endif
585 goto err_out;
587 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
588 #if DEBUG
589 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
590 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
591 #endif
592 goto err_out;
594 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
595 aux->frame_type != OS_FRAME_TYPE_EOD &&
596 aux->frame_type != OS_FRAME_TYPE_MARKER) {
597 if (!quiet) {
598 #if DEBUG
599 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
600 #endif
602 goto err_out;
604 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
605 STp->first_frame_position < STp->eod_frame_ppos) {
606 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
607 STp->first_frame_position);
608 goto err_out;
610 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
611 if (!quiet) {
612 #if DEBUG
613 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
614 name, ntohl(aux->frame_seq_num), frame_seq_number);
615 #endif
617 goto err_out;
619 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
620 STps->eof = ST_FM_HIT;
622 i = ntohl(aux->filemark_cnt);
623 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
624 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
625 #if DEBUG
626 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
627 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
628 i, STp->first_frame_position - 1);
629 #endif
630 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
631 if (i >= STp->filemark_cnt)
632 STp->filemark_cnt = i+1;
635 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
636 STps->eof = ST_EOD_1;
637 STp->frame_in_buffer = 1;
639 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
640 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
641 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
642 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
643 STp->buffer->read_pointer = 0;
644 STp->frame_in_buffer = 1;
646 /* See what block size was used to write file */
647 if (STp->block_size != blk_sz && blk_sz > 0) {
648 printk(KERN_INFO
649 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
650 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
651 STp->block_size<1024?STp->block_size:STp->block_size/1024,
652 STp->block_size<1024?'b':'k');
653 STp->block_size = blk_sz;
654 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
656 STps->eof = ST_NOEOF;
658 STp->frame_seq_number = ntohl(aux->frame_seq_num);
659 STp->logical_blk_num = ntohl(aux->logical_blk_num);
660 return 1;
662 err_out:
663 if (STp->read_error_frame == 0)
664 STp->read_error_frame = STp->first_frame_position - 1;
665 return 0;
669 * Wait for the unit to become Ready
671 static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
672 unsigned timeout, int initial_delay)
674 unsigned char cmd[MAX_COMMAND_SIZE];
675 struct osst_request * SRpnt;
676 unsigned long startwait = jiffies;
677 #if DEBUG
678 int dbg = debugging;
679 char * name = tape_name(STp);
681 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
682 #endif
684 if (initial_delay > 0)
685 msleep(jiffies_to_msecs(initial_delay));
687 memset(cmd, 0, MAX_COMMAND_SIZE);
688 cmd[0] = TEST_UNIT_READY;
690 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
691 *aSRpnt = SRpnt;
692 if (!SRpnt) return (-EBUSY);
694 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
695 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
696 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
697 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
698 SRpnt->sense[13] == 0 ) )) {
699 #if DEBUG
700 if (debugging) {
701 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
702 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
703 debugging = 0;
705 #endif
706 msleep(100);
708 memset(cmd, 0, MAX_COMMAND_SIZE);
709 cmd[0] = TEST_UNIT_READY;
711 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
713 *aSRpnt = SRpnt;
714 #if DEBUG
715 debugging = dbg;
716 #endif
717 if ( STp->buffer->syscall_result &&
718 osst_write_error_recovery(STp, aSRpnt, 0) ) {
719 #if DEBUG
720 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
721 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
722 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
723 SRpnt->sense[12], SRpnt->sense[13]);
724 #endif
725 return (-EIO);
727 #if DEBUG
728 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
729 #endif
730 return 0;
734 * Wait for a tape to be inserted in the unit
736 static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
738 unsigned char cmd[MAX_COMMAND_SIZE];
739 struct osst_request * SRpnt;
740 unsigned long startwait = jiffies;
741 #if DEBUG
742 int dbg = debugging;
743 char * name = tape_name(STp);
745 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
746 #endif
748 memset(cmd, 0, MAX_COMMAND_SIZE);
749 cmd[0] = TEST_UNIT_READY;
751 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
752 *aSRpnt = SRpnt;
753 if (!SRpnt) return (-EBUSY);
755 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
756 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
757 #if DEBUG
758 if (debugging) {
759 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
760 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
761 debugging = 0;
763 #endif
764 msleep(100);
766 memset(cmd, 0, MAX_COMMAND_SIZE);
767 cmd[0] = TEST_UNIT_READY;
769 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
771 *aSRpnt = SRpnt;
772 #if DEBUG
773 debugging = dbg;
774 #endif
775 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
776 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
777 #if DEBUG
778 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
779 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
780 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
781 SRpnt->sense[12], SRpnt->sense[13]);
782 #endif
783 return 0;
785 #if DEBUG
786 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
787 #endif
788 return 1;
791 static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
793 int retval;
795 osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
796 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
797 if (retval) return (retval);
798 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
799 return (osst_get_frame_position(STp, aSRpnt));
803 * Wait for write(s) to complete
805 static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
807 unsigned char cmd[MAX_COMMAND_SIZE];
808 struct osst_request * SRpnt;
809 int result = 0;
810 int delay = OSST_WAIT_WRITE_COMPLETE;
811 #if DEBUG
812 char * name = tape_name(STp);
814 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
815 #endif
817 memset(cmd, 0, MAX_COMMAND_SIZE);
818 cmd[0] = WRITE_FILEMARKS;
819 cmd[1] = 1;
821 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
822 *aSRpnt = SRpnt;
823 if (!SRpnt) return (-EBUSY);
824 if (STp->buffer->syscall_result) {
825 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
826 if (SRpnt->sense[13] == 8) {
827 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
829 } else
830 result = osst_write_error_recovery(STp, aSRpnt, 0);
832 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
833 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
835 return (result);
838 #define OSST_POLL_PER_SEC 10
839 static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
841 unsigned long startwait = jiffies;
842 char * name = tape_name(STp);
843 #if DEBUG
844 char notyetprinted = 1;
845 #endif
846 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
847 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
849 while (time_before (jiffies, startwait + to*HZ))
851 int result;
852 result = osst_get_frame_position(STp, aSRpnt);
853 if (result == -EIO)
854 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
855 return 0; /* successful recovery leaves drive ready for frame */
856 if (result < 0) break;
857 if (STp->first_frame_position == curr &&
858 ((minlast < 0 &&
859 (signed)STp->last_frame_position > (signed)curr + minlast) ||
860 (minlast >= 0 && STp->cur_frames > minlast)
861 ) && result >= 0)
863 #if DEBUG
864 if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
865 printk (OSST_DEB_MSG
866 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
867 name, curr, curr+minlast, STp->first_frame_position,
868 STp->last_frame_position, STp->cur_frames,
869 result, (jiffies-startwait)/HZ,
870 (((jiffies-startwait)%HZ)*10)/HZ);
871 #endif
872 return 0;
874 #if DEBUG
875 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
877 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
878 name, curr, curr+minlast, STp->first_frame_position,
879 STp->last_frame_position, STp->cur_frames, result);
880 notyetprinted--;
882 #endif
883 msleep(1000 / OSST_POLL_PER_SEC);
885 #if DEBUG
886 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
887 name, curr, curr+minlast, STp->first_frame_position,
888 STp->last_frame_position, STp->cur_frames,
889 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
890 #endif
891 return -EBUSY;
894 static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
896 struct osst_request * SRpnt;
897 unsigned char cmd[MAX_COMMAND_SIZE];
898 unsigned long startwait = jiffies;
899 int retval = 1;
900 char * name = tape_name(STp);
902 if (writing) {
903 char mybuf[24];
904 char * olddata = STp->buffer->b_data;
905 int oldsize = STp->buffer->buffer_size;
907 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
909 memset(cmd, 0, MAX_COMMAND_SIZE);
910 cmd[0] = WRITE_FILEMARKS;
911 cmd[1] = 1;
912 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
913 MAX_RETRIES, 1);
915 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
917 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
919 /* some failure - not just not-ready */
920 retval = osst_write_error_recovery(STp, aSRpnt, 0);
921 break;
923 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
925 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
926 memset(cmd, 0, MAX_COMMAND_SIZE);
927 cmd[0] = READ_POSITION;
929 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
930 MAX_RETRIES, 1);
932 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
933 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
935 if (retval)
936 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
937 } else
938 /* TODO - figure out which error conditions can be handled */
939 if (STp->buffer->syscall_result)
940 printk(KERN_WARNING
941 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
942 (*aSRpnt)->sense[ 2] & 0x0f,
943 (*aSRpnt)->sense[12],
944 (*aSRpnt)->sense[13]);
946 return retval;
950 * Read the next OnStream tape frame at the current location
952 static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
954 unsigned char cmd[MAX_COMMAND_SIZE];
955 struct osst_request * SRpnt;
956 int retval = 0;
957 #if DEBUG
958 os_aux_t * aux = STp->buffer->aux;
959 char * name = tape_name(STp);
960 #endif
962 if (STp->poll)
963 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
964 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
966 memset(cmd, 0, MAX_COMMAND_SIZE);
967 cmd[0] = READ_6;
968 cmd[1] = 1;
969 cmd[4] = 1;
971 #if DEBUG
972 if (debugging)
973 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
974 #endif
975 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
976 STp->timeout, MAX_RETRIES, 1);
977 *aSRpnt = SRpnt;
978 if (!SRpnt)
979 return (-EBUSY);
981 if ((STp->buffer)->syscall_result) {
982 retval = 1;
983 if (STp->read_error_frame == 0) {
984 STp->read_error_frame = STp->first_frame_position;
985 #if DEBUG
986 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
987 #endif
989 #if DEBUG
990 if (debugging)
991 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
992 name,
993 SRpnt->sense[0], SRpnt->sense[1],
994 SRpnt->sense[2], SRpnt->sense[3],
995 SRpnt->sense[4], SRpnt->sense[5],
996 SRpnt->sense[6], SRpnt->sense[7]);
997 #endif
999 else
1000 STp->first_frame_position++;
1001 #if DEBUG
1002 if (debugging) {
1003 char sig[8]; int i;
1004 for (i=0;i<4;i++)
1005 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1006 sig[4] = '\0';
1007 printk(OSST_DEB_MSG
1008 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1009 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1010 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1011 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1012 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1013 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1014 if (aux->frame_type==2)
1015 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1016 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1017 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1019 #endif
1020 return (retval);
1023 static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1025 struct st_partstat * STps = &(STp->ps[STp->partition]);
1026 struct osst_request * SRpnt ;
1027 unsigned char cmd[MAX_COMMAND_SIZE];
1028 int retval = 0;
1029 char * name = tape_name(STp);
1031 if (STps->rw != ST_READING) { /* Initialize read operation */
1032 if (STps->rw == ST_WRITING || STp->dirty) {
1033 STp->write_type = OS_WRITE_DATA;
1034 osst_flush_write_buffer(STp, aSRpnt);
1035 osst_flush_drive_buffer(STp, aSRpnt);
1037 STps->rw = ST_READING;
1038 STp->frame_in_buffer = 0;
1041 * Issue a read 0 command to get the OnStream drive
1042 * read frames into its buffer.
1044 memset(cmd, 0, MAX_COMMAND_SIZE);
1045 cmd[0] = READ_6;
1046 cmd[1] = 1;
1048 #if DEBUG
1049 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1050 #endif
1051 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1052 *aSRpnt = SRpnt;
1053 if ((retval = STp->buffer->syscall_result))
1054 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1057 return retval;
1060 static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1061 int frame_seq_number, int quiet)
1063 struct st_partstat * STps = &(STp->ps[STp->partition]);
1064 char * name = tape_name(STp);
1065 int cnt = 0,
1066 bad = 0,
1067 past = 0,
1069 position;
1072 * If we want just any frame (-1) and there is a frame in the buffer, return it
1074 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1075 #if DEBUG
1076 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1077 #endif
1078 return (STps->eof);
1081 * Search and wait for the next logical tape frame
1083 while (1) {
1084 if (cnt++ > 400) {
1085 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1086 name, frame_seq_number);
1087 if (STp->read_error_frame) {
1088 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1089 #if DEBUG
1090 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1091 name, STp->read_error_frame);
1092 #endif
1093 STp->read_error_frame = 0;
1094 STp->abort_count++;
1096 return (-EIO);
1098 #if DEBUG
1099 if (debugging)
1100 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1101 name, frame_seq_number, cnt);
1102 #endif
1103 if ( osst_initiate_read(STp, aSRpnt)
1104 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1105 if (STp->raw)
1106 return (-EIO);
1107 position = osst_get_frame_position(STp, aSRpnt);
1108 if (position >= 0xbae && position < 0xbb8)
1109 position = 0xbb8;
1110 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1111 position = STp->read_error_frame - 1;
1112 bad = 0;
1114 else {
1115 position += 29;
1116 cnt += 19;
1118 #if DEBUG
1119 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1120 name, position);
1121 #endif
1122 osst_set_frame_position(STp, aSRpnt, position, 0);
1123 continue;
1125 if (osst_verify_frame(STp, frame_seq_number, quiet))
1126 break;
1127 if (osst_verify_frame(STp, -1, quiet)) {
1128 x = ntohl(STp->buffer->aux->frame_seq_num);
1129 if (STp->fast_open) {
1130 printk(KERN_WARNING
1131 "%s:W: Found logical frame %d instead of %d after fast open\n",
1132 name, x, frame_seq_number);
1133 STp->header_ok = 0;
1134 STp->read_error_frame = 0;
1135 return (-EIO);
1137 if (x > frame_seq_number) {
1138 if (++past > 3) {
1139 /* positioning backwards did not bring us to the desired frame */
1140 position = STp->read_error_frame - 1;
1142 else {
1143 position = osst_get_frame_position(STp, aSRpnt)
1144 + frame_seq_number - x - 1;
1146 if (STp->first_frame_position >= 3000 && position < 3000)
1147 position -= 10;
1149 #if DEBUG
1150 printk(OSST_DEB_MSG
1151 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1152 name, x, frame_seq_number,
1153 STp->first_frame_position - position);
1154 #endif
1155 osst_set_frame_position(STp, aSRpnt, position, 0);
1156 cnt += 10;
1158 else
1159 past = 0;
1161 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1162 #if DEBUG
1163 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1164 #endif
1165 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1166 cnt--;
1168 STp->frame_in_buffer = 0;
1170 if (cnt > 1) {
1171 STp->recover_count++;
1172 STp->recover_erreg++;
1173 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1174 name, STp->read_error_frame);
1176 STp->read_count++;
1178 #if DEBUG
1179 if (debugging || STps->eof)
1180 printk(OSST_DEB_MSG
1181 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1182 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1183 #endif
1184 STp->fast_open = 0;
1185 STp->read_error_frame = 0;
1186 return (STps->eof);
1189 static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1191 struct st_partstat * STps = &(STp->ps[STp->partition]);
1192 char * name = tape_name(STp);
1193 int retries = 0;
1194 int frame_seq_estimate, ppos_estimate, move;
1196 if (logical_blk_num < 0) logical_blk_num = 0;
1197 #if DEBUG
1198 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1199 name, logical_blk_num, STp->logical_blk_num,
1200 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1201 STp->block_size<1024?'b':'k');
1202 #endif
1203 /* Do we know where we are? */
1204 if (STps->drv_block >= 0) {
1205 move = logical_blk_num - STp->logical_blk_num;
1206 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1207 move /= (OS_DATA_SIZE / STp->block_size);
1208 frame_seq_estimate = STp->frame_seq_number + move;
1209 } else
1210 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1212 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1213 else ppos_estimate = frame_seq_estimate + 20;
1214 while (++retries < 10) {
1215 if (ppos_estimate > STp->eod_frame_ppos-2) {
1216 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1217 ppos_estimate = STp->eod_frame_ppos - 2;
1219 if (frame_seq_estimate < 0) {
1220 frame_seq_estimate = 0;
1221 ppos_estimate = 10;
1223 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1224 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1225 /* we've located the estimated frame, now does it have our block? */
1226 if (logical_blk_num < STp->logical_blk_num ||
1227 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1228 if (STps->eof == ST_FM_HIT)
1229 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1230 else {
1231 move = logical_blk_num - STp->logical_blk_num;
1232 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1233 move /= (OS_DATA_SIZE / STp->block_size);
1235 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1236 #if DEBUG
1237 printk(OSST_DEB_MSG
1238 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1239 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1240 STp->logical_blk_num, logical_blk_num, move);
1241 #endif
1242 frame_seq_estimate += move;
1243 ppos_estimate += move;
1244 continue;
1245 } else {
1246 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1247 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1248 STp->logical_blk_num = logical_blk_num;
1249 #if DEBUG
1250 printk(OSST_DEB_MSG
1251 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1252 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1253 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1254 STp->block_size);
1255 #endif
1256 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1257 if (STps->eof == ST_FM_HIT) {
1258 STps->drv_file++;
1259 STps->drv_block = 0;
1260 } else {
1261 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1262 STp->logical_blk_num -
1263 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1266 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1267 return 0;
1270 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1271 goto error;
1272 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1273 #if DEBUG
1274 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1275 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1276 STp->logical_blk_num, logical_blk_num);
1277 #endif
1278 if (frame_seq_estimate != STp->frame_seq_number)
1279 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1280 else
1281 break;
1283 error:
1284 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1285 name, logical_blk_num, STp->logical_blk_num, retries);
1286 return (-EIO);
1289 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1290 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1291 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1292 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1294 #define OSST_FRAME_SHIFT 6
1295 #define OSST_SECTOR_SHIFT 9
1296 #define OSST_SECTOR_MASK 0x03F
1298 static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1300 int sector;
1301 #if DEBUG
1302 char * name = tape_name(STp);
1304 printk(OSST_DEB_MSG
1305 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1306 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1307 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1308 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1309 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1310 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1311 #endif
1312 /* do we know where we are inside a file? */
1313 if (STp->ps[STp->partition].drv_block >= 0) {
1314 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1315 STp->first_frame_position) << OSST_FRAME_SHIFT;
1316 if (STp->ps[STp->partition].rw == ST_WRITING)
1317 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1318 else
1319 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1320 } else {
1321 sector = osst_get_frame_position(STp, aSRpnt);
1322 if (sector > 0)
1323 sector <<= OSST_FRAME_SHIFT;
1325 return sector;
1328 static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1330 struct st_partstat * STps = &(STp->ps[STp->partition]);
1331 int frame = sector >> OSST_FRAME_SHIFT,
1332 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1334 #if DEBUG
1335 char * name = tape_name(STp);
1337 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1338 name, sector, frame, offset);
1339 #endif
1340 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1342 if (frame <= STp->first_data_ppos) {
1343 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1344 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1346 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1347 if (r < 0) return r;
1349 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1350 if (r < 0) return r;
1352 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1354 if (offset) {
1355 STp->logical_blk_num += offset / STp->block_size;
1356 STp->buffer->read_pointer = offset;
1357 STp->buffer->buffer_bytes -= offset;
1358 } else {
1359 STp->frame_seq_number++;
1360 STp->frame_in_buffer = 0;
1361 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1362 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1364 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1365 if (STps->eof == ST_FM_HIT) {
1366 STps->drv_file++;
1367 STps->drv_block = 0;
1368 } else {
1369 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1370 STp->logical_blk_num -
1371 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1374 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1375 #if DEBUG
1376 printk(OSST_DEB_MSG
1377 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1378 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1379 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1380 #endif
1381 return 0;
1385 * Read back the drive's internal buffer contents, as a part
1386 * of the write error recovery mechanism for old OnStream
1387 * firmware revisions.
1388 * Precondition for this function to work: all frames in the
1389 * drive's buffer must be of one type (DATA, MARK or EOD)!
1391 static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1392 unsigned int frame, unsigned int skip, int pending)
1394 struct osst_request * SRpnt = * aSRpnt;
1395 unsigned char * buffer, * p;
1396 unsigned char cmd[MAX_COMMAND_SIZE];
1397 int flag, new_frame, i;
1398 int nframes = STp->cur_frames;
1399 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1400 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1401 - (nframes + pending - 1);
1402 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1403 - (nframes + pending - 1) * blks_per_frame;
1404 char * name = tape_name(STp);
1405 unsigned long startwait = jiffies;
1406 #if DEBUG
1407 int dbg = debugging;
1408 #endif
1410 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1411 return (-EIO);
1413 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1414 name, nframes, pending?" and one that was pending":"");
1416 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1417 #if DEBUG
1418 if (pending && debugging)
1419 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1420 name, frame_seq_number + nframes,
1421 logical_blk_num + nframes * blks_per_frame,
1422 p[0], p[1], p[2], p[3]);
1423 #endif
1424 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1426 memset(cmd, 0, MAX_COMMAND_SIZE);
1427 cmd[0] = 0x3C; /* Buffer Read */
1428 cmd[1] = 6; /* Retrieve Faulty Block */
1429 cmd[7] = 32768 >> 8;
1430 cmd[8] = 32768 & 0xff;
1432 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1433 STp->timeout, MAX_RETRIES, 1);
1435 if ((STp->buffer)->syscall_result || !SRpnt) {
1436 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1437 vfree(buffer);
1438 *aSRpnt = SRpnt;
1439 return (-EIO);
1441 osst_copy_from_buffer(STp->buffer, p);
1442 #if DEBUG
1443 if (debugging)
1444 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1445 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1446 #endif
1448 *aSRpnt = SRpnt;
1449 osst_get_frame_position(STp, aSRpnt);
1451 #if DEBUG
1452 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1453 #endif
1454 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1455 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1457 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1459 if (flag) {
1460 if (STp->write_type == OS_WRITE_HEADER) {
1461 i += skip;
1462 p += skip * OS_DATA_SIZE;
1464 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1465 new_frame = 3000-i;
1466 else
1467 new_frame += skip;
1468 #if DEBUG
1469 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1470 name, new_frame+i, frame_seq_number+i);
1471 #endif
1472 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1473 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1474 osst_get_frame_position(STp, aSRpnt);
1475 SRpnt = * aSRpnt;
1477 if (new_frame > frame + 1000) {
1478 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1479 vfree(buffer);
1480 return (-EIO);
1482 if ( i >= nframes + pending ) break;
1483 flag = 0;
1485 osst_copy_to_buffer(STp->buffer, p);
1487 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1489 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1490 logical_blk_num + i*blks_per_frame,
1491 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1492 memset(cmd, 0, MAX_COMMAND_SIZE);
1493 cmd[0] = WRITE_6;
1494 cmd[1] = 1;
1495 cmd[4] = 1;
1497 #if DEBUG
1498 if (debugging)
1499 printk(OSST_DEB_MSG
1500 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1501 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1502 p[0], p[1], p[2], p[3]);
1503 #endif
1504 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1505 STp->timeout, MAX_RETRIES, 1);
1507 if (STp->buffer->syscall_result)
1508 flag = 1;
1509 else {
1510 p += OS_DATA_SIZE; i++;
1512 /* if we just sent the last frame, wait till all successfully written */
1513 if ( i == nframes + pending ) {
1514 #if DEBUG
1515 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1516 #endif
1517 memset(cmd, 0, MAX_COMMAND_SIZE);
1518 cmd[0] = WRITE_FILEMARKS;
1519 cmd[1] = 1;
1520 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1521 STp->timeout, MAX_RETRIES, 1);
1522 #if DEBUG
1523 if (debugging) {
1524 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1525 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1526 debugging = 0;
1528 #endif
1529 flag = STp->buffer->syscall_result;
1530 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1532 memset(cmd, 0, MAX_COMMAND_SIZE);
1533 cmd[0] = TEST_UNIT_READY;
1535 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1536 MAX_RETRIES, 1);
1538 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1539 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1540 /* in the process of becoming ready */
1541 msleep(100);
1542 continue;
1544 if (STp->buffer->syscall_result)
1545 flag = 1;
1546 break;
1548 #if DEBUG
1549 debugging = dbg;
1550 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1551 #endif
1554 *aSRpnt = SRpnt;
1555 if (flag) {
1556 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1557 SRpnt->sense[12] == 0 &&
1558 SRpnt->sense[13] == 2) {
1559 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1560 vfree(buffer);
1561 return (-EIO); /* hit end of tape = fail */
1563 i = ((SRpnt->sense[3] << 24) |
1564 (SRpnt->sense[4] << 16) |
1565 (SRpnt->sense[5] << 8) |
1566 SRpnt->sense[6] ) - new_frame;
1567 p = &buffer[i * OS_DATA_SIZE];
1568 #if DEBUG
1569 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1570 #endif
1571 osst_get_frame_position(STp, aSRpnt);
1572 #if DEBUG
1573 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1574 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1575 #endif
1578 if (flag) {
1579 /* error recovery did not successfully complete */
1580 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1581 STp->write_type == OS_WRITE_HEADER?"header":"body");
1583 if (!pending)
1584 osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
1585 vfree(buffer);
1586 return 0;
1589 static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1590 unsigned int frame, unsigned int skip, int pending)
1592 unsigned char cmd[MAX_COMMAND_SIZE];
1593 struct osst_request * SRpnt;
1594 char * name = tape_name(STp);
1595 int expected = 0;
1596 int attempts = 1000 / skip;
1597 int flag = 1;
1598 unsigned long startwait = jiffies;
1599 #if DEBUG
1600 int dbg = debugging;
1601 #endif
1603 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1604 if (flag) {
1605 #if DEBUG
1606 debugging = dbg;
1607 #endif
1608 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1609 frame = 3000-skip;
1610 expected = frame+skip+STp->cur_frames+pending;
1611 #if DEBUG
1612 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1613 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1614 #endif
1615 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1616 flag = 0;
1617 attempts--;
1618 schedule_timeout_interruptible(msecs_to_jiffies(100));
1620 if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
1621 #if DEBUG
1622 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1623 name, STp->first_frame_position,
1624 STp->last_frame_position, STp->cur_frames);
1625 #endif
1626 frame = STp->last_frame_position;
1627 flag = 1;
1628 continue;
1630 if (pending && STp->cur_frames < 50) {
1632 memset(cmd, 0, MAX_COMMAND_SIZE);
1633 cmd[0] = WRITE_6;
1634 cmd[1] = 1;
1635 cmd[4] = 1;
1636 #if DEBUG
1637 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1638 name, STp->frame_seq_number-1, STp->first_frame_position);
1639 #endif
1640 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1641 STp->timeout, MAX_RETRIES, 1);
1642 *aSRpnt = SRpnt;
1644 if (STp->buffer->syscall_result) { /* additional write error */
1645 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1646 SRpnt->sense[12] == 0 &&
1647 SRpnt->sense[13] == 2) {
1648 printk(KERN_ERR
1649 "%s:E: Volume overflow in write error recovery\n",
1650 name);
1651 break; /* hit end of tape = fail */
1653 flag = 1;
1655 else
1656 pending = 0;
1658 continue;
1660 if (STp->cur_frames == 0) {
1661 #if DEBUG
1662 debugging = dbg;
1663 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1664 #endif
1665 if (STp->first_frame_position != expected) {
1666 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1667 name, STp->first_frame_position, expected);
1668 return (-EIO);
1670 return 0;
1672 #if DEBUG
1673 if (debugging) {
1674 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1675 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1676 debugging = 0;
1678 #endif
1679 schedule_timeout_interruptible(msecs_to_jiffies(100));
1681 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1682 #if DEBUG
1683 debugging = dbg;
1684 #endif
1685 return (-EIO);
1689 * Error recovery algorithm for the OnStream tape.
1692 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1694 struct osst_request * SRpnt = * aSRpnt;
1695 struct st_partstat * STps = & STp->ps[STp->partition];
1696 char * name = tape_name(STp);
1697 int retval = 0;
1698 int rw_state;
1699 unsigned int frame, skip;
1701 rw_state = STps->rw;
1703 if ((SRpnt->sense[ 2] & 0x0f) != 3
1704 || SRpnt->sense[12] != 12
1705 || SRpnt->sense[13] != 0) {
1706 #if DEBUG
1707 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1708 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1709 #endif
1710 return (-EIO);
1712 frame = (SRpnt->sense[3] << 24) |
1713 (SRpnt->sense[4] << 16) |
1714 (SRpnt->sense[5] << 8) |
1715 SRpnt->sense[6];
1716 skip = SRpnt->sense[9];
1718 #if DEBUG
1719 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1720 #endif
1721 osst_get_frame_position(STp, aSRpnt);
1722 #if DEBUG
1723 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1724 name, STp->first_frame_position, STp->last_frame_position);
1725 #endif
1726 switch (STp->write_type) {
1727 case OS_WRITE_DATA:
1728 case OS_WRITE_EOD:
1729 case OS_WRITE_NEW_MARK:
1730 printk(KERN_WARNING
1731 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1732 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1733 if (STp->os_fw_rev >= 10600)
1734 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1735 else
1736 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1737 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1738 retval?"E" :"I",
1739 retval?"" :"Don't worry, ",
1740 retval?" not ":" ");
1741 break;
1742 case OS_WRITE_LAST_MARK:
1743 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1744 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1745 retval = -EIO;
1746 break;
1747 case OS_WRITE_HEADER:
1748 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1749 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1750 break;
1751 default:
1752 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1753 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1755 osst_get_frame_position(STp, aSRpnt);
1756 #if DEBUG
1757 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1758 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1759 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1760 #endif
1761 if (retval == 0) {
1762 STp->recover_count++;
1763 STp->recover_erreg++;
1764 } else
1765 STp->abort_count++;
1767 STps->rw = rw_state;
1768 return retval;
1771 static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1772 int mt_op, int mt_count)
1774 char * name = tape_name(STp);
1775 int cnt;
1776 int last_mark_ppos = -1;
1778 #if DEBUG
1779 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1780 #endif
1781 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1782 #if DEBUG
1783 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1784 #endif
1785 return -EIO;
1787 if (STp->linux_media_version >= 4) {
1789 * direct lookup in header filemark list
1791 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1792 if (STp->header_ok &&
1793 STp->header_cache != NULL &&
1794 (cnt - mt_count) >= 0 &&
1795 (cnt - mt_count) < OS_FM_TAB_MAX &&
1796 (cnt - mt_count) < STp->filemark_cnt &&
1797 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1799 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1800 #if DEBUG
1801 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1802 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1803 STp->header_cache == NULL?"lack of header cache":"count out of range");
1804 else
1805 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1806 name, cnt,
1807 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1808 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1809 STp->buffer->aux->last_mark_ppos))?"match":"error",
1810 mt_count, last_mark_ppos);
1811 #endif
1812 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1813 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1814 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1815 #if DEBUG
1816 printk(OSST_DEB_MSG
1817 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1818 #endif
1819 return (-EIO);
1821 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1822 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1823 name, last_mark_ppos);
1824 return (-EIO);
1826 goto found;
1828 #if DEBUG
1829 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1830 #endif
1832 cnt = 0;
1833 while (cnt != mt_count) {
1834 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1835 if (last_mark_ppos == -1)
1836 return (-EIO);
1837 #if DEBUG
1838 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1839 #endif
1840 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1841 cnt++;
1842 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1843 #if DEBUG
1844 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1845 #endif
1846 return (-EIO);
1848 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1849 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1850 name, last_mark_ppos);
1851 return (-EIO);
1854 found:
1855 if (mt_op == MTBSFM) {
1856 STp->frame_seq_number++;
1857 STp->frame_in_buffer = 0;
1858 STp->buffer->buffer_bytes = 0;
1859 STp->buffer->read_pointer = 0;
1860 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1862 return 0;
1866 * ADRL 1.1 compatible "slow" space filemarks fwd version
1868 * Just scans for the filemark sequentially.
1870 static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1871 int mt_op, int mt_count)
1873 int cnt = 0;
1874 #if DEBUG
1875 char * name = tape_name(STp);
1877 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1878 #endif
1879 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1880 #if DEBUG
1881 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1882 #endif
1883 return (-EIO);
1885 while (1) {
1886 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1887 #if DEBUG
1888 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1889 #endif
1890 return (-EIO);
1892 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1893 cnt++;
1894 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1895 #if DEBUG
1896 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1897 #endif
1898 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1899 #if DEBUG
1900 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1901 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1902 #endif
1903 STp->eod_frame_ppos = STp->first_frame_position-1;
1905 return (-EIO);
1907 if (cnt == mt_count)
1908 break;
1909 STp->frame_in_buffer = 0;
1911 if (mt_op == MTFSF) {
1912 STp->frame_seq_number++;
1913 STp->frame_in_buffer = 0;
1914 STp->buffer->buffer_bytes = 0;
1915 STp->buffer->read_pointer = 0;
1916 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1918 return 0;
1922 * Fast linux specific version of OnStream FSF
1924 static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
1925 int mt_op, int mt_count)
1927 char * name = tape_name(STp);
1928 int cnt = 0,
1929 next_mark_ppos = -1;
1931 #if DEBUG
1932 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
1933 #endif
1934 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1935 #if DEBUG
1936 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1937 #endif
1938 return (-EIO);
1941 if (STp->linux_media_version >= 4) {
1943 * direct lookup in header filemark list
1945 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1946 if (STp->header_ok &&
1947 STp->header_cache != NULL &&
1948 (cnt + mt_count) < OS_FM_TAB_MAX &&
1949 (cnt + mt_count) < STp->filemark_cnt &&
1950 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1951 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1953 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1954 #if DEBUG
1955 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1956 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1957 STp->header_cache == NULL?"lack of header cache":"count out of range");
1958 else
1959 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1960 name, cnt,
1961 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1962 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1963 STp->buffer->aux->last_mark_ppos))?"match":"error",
1964 mt_count, next_mark_ppos);
1965 #endif
1966 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1967 #if DEBUG
1968 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1969 #endif
1970 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1971 } else {
1972 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1973 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1974 #if DEBUG
1975 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
1976 name);
1977 #endif
1978 return (-EIO);
1980 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1981 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1982 name, next_mark_ppos);
1983 return (-EIO);
1985 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1986 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
1987 name, cnt+mt_count, next_mark_ppos,
1988 ntohl(STp->buffer->aux->filemark_cnt));
1989 return (-EIO);
1992 } else {
1994 * Find nearest (usually previous) marker, then jump from marker to marker
1996 while (1) {
1997 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1998 break;
1999 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2000 #if DEBUG
2001 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2002 #endif
2003 return (-EIO);
2005 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2006 if (STp->first_mark_ppos == -1) {
2007 #if DEBUG
2008 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2009 #endif
2010 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2012 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2013 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2014 #if DEBUG
2015 printk(OSST_DEB_MSG
2016 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2017 name);
2018 #endif
2019 return (-EIO);
2021 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2022 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2023 name, STp->first_mark_ppos);
2024 return (-EIO);
2026 } else {
2027 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2028 return (-EIO);
2029 mt_count++;
2032 cnt++;
2033 while (cnt != mt_count) {
2034 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2035 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2036 #if DEBUG
2037 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2038 #endif
2039 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2041 #if DEBUG
2042 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2043 #endif
2044 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2045 cnt++;
2046 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2047 #if DEBUG
2048 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2049 name);
2050 #endif
2051 return (-EIO);
2053 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2054 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2055 name, next_mark_ppos);
2056 return (-EIO);
2060 if (mt_op == MTFSF) {
2061 STp->frame_seq_number++;
2062 STp->frame_in_buffer = 0;
2063 STp->buffer->buffer_bytes = 0;
2064 STp->buffer->read_pointer = 0;
2065 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2067 return 0;
2071 * In debug mode, we want to see as many errors as possible
2072 * to test the error recovery mechanism.
2074 #if DEBUG
2075 static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2077 unsigned char cmd[MAX_COMMAND_SIZE];
2078 struct osst_request * SRpnt = * aSRpnt;
2079 char * name = tape_name(STp);
2081 memset(cmd, 0, MAX_COMMAND_SIZE);
2082 cmd[0] = MODE_SELECT;
2083 cmd[1] = 0x10;
2084 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2086 (STp->buffer)->b_data[0] = cmd[4] - 1;
2087 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
2088 (STp->buffer)->b_data[2] = 0; /* Reserved */
2089 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
2090 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2091 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2092 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2093 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2095 if (debugging)
2096 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2098 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2099 *aSRpnt = SRpnt;
2101 if ((STp->buffer)->syscall_result)
2102 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2104 #endif
2107 static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2109 int result;
2110 int this_mark_ppos = STp->first_frame_position;
2111 int this_mark_lbn = STp->logical_blk_num;
2112 #if DEBUG
2113 char * name = tape_name(STp);
2114 #endif
2116 if (STp->raw) return 0;
2118 STp->write_type = OS_WRITE_NEW_MARK;
2119 #if DEBUG
2120 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2121 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2122 #endif
2123 STp->dirty = 1;
2124 result = osst_flush_write_buffer(STp, aSRpnt);
2125 result |= osst_flush_drive_buffer(STp, aSRpnt);
2126 STp->last_mark_ppos = this_mark_ppos;
2127 STp->last_mark_lbn = this_mark_lbn;
2128 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2129 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2130 if (STp->filemark_cnt++ == 0)
2131 STp->first_mark_ppos = this_mark_ppos;
2132 return result;
2135 static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2137 int result;
2138 #if DEBUG
2139 char * name = tape_name(STp);
2140 #endif
2142 if (STp->raw) return 0;
2144 STp->write_type = OS_WRITE_EOD;
2145 STp->eod_frame_ppos = STp->first_frame_position;
2146 #if DEBUG
2147 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2148 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2149 #endif
2150 STp->dirty = 1;
2152 result = osst_flush_write_buffer(STp, aSRpnt);
2153 result |= osst_flush_drive_buffer(STp, aSRpnt);
2154 STp->eod_frame_lfa = --(STp->frame_seq_number);
2155 return result;
2158 static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2160 char * name = tape_name(STp);
2162 #if DEBUG
2163 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2164 #endif
2165 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2166 osst_set_frame_position(STp, aSRpnt, where, 0);
2167 STp->write_type = OS_WRITE_FILLER;
2168 while (count--) {
2169 memcpy(STp->buffer->b_data, "Filler", 6);
2170 STp->buffer->buffer_bytes = 6;
2171 STp->dirty = 1;
2172 if (osst_flush_write_buffer(STp, aSRpnt)) {
2173 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2174 return (-EIO);
2177 #if DEBUG
2178 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2179 #endif
2180 return osst_flush_drive_buffer(STp, aSRpnt);
2183 static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2185 char * name = tape_name(STp);
2186 int result;
2188 #if DEBUG
2189 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2190 #endif
2191 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2192 osst_set_frame_position(STp, aSRpnt, where, 0);
2193 STp->write_type = OS_WRITE_HEADER;
2194 while (count--) {
2195 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2196 STp->buffer->buffer_bytes = sizeof(os_header_t);
2197 STp->dirty = 1;
2198 if (osst_flush_write_buffer(STp, aSRpnt)) {
2199 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2200 return (-EIO);
2203 result = osst_flush_drive_buffer(STp, aSRpnt);
2204 #if DEBUG
2205 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2206 #endif
2207 return result;
2210 static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2212 os_header_t * header;
2213 int result;
2214 char * name = tape_name(STp);
2216 #if DEBUG
2217 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2218 #endif
2219 if (STp->raw) return 0;
2221 if (STp->header_cache == NULL) {
2222 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2223 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2224 return (-ENOMEM);
2226 memset(STp->header_cache, 0, sizeof(os_header_t));
2227 #if DEBUG
2228 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2229 #endif
2231 if (STp->header_ok) STp->update_frame_cntr++;
2232 else STp->update_frame_cntr = 0;
2234 header = STp->header_cache;
2235 strcpy(header->ident_str, "ADR_SEQ");
2236 header->major_rev = 1;
2237 header->minor_rev = 4;
2238 header->ext_trk_tb_off = htons(17192);
2239 header->pt_par_num = 1;
2240 header->partition[0].partition_num = OS_DATA_PARTITION;
2241 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2242 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2243 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2244 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2245 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2246 header->cfg_col_width = htonl(20);
2247 header->dat_col_width = htonl(1500);
2248 header->qfa_col_width = htonl(0);
2249 header->ext_track_tb.nr_stream_part = 1;
2250 header->ext_track_tb.et_ent_sz = 32;
2251 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2252 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2253 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2254 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2255 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2256 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2257 header->dat_fm_tab.fm_part_num = 0;
2258 header->dat_fm_tab.fm_tab_ent_sz = 4;
2259 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2260 STp->filemark_cnt:OS_FM_TAB_MAX);
2262 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2263 if (STp->update_frame_cntr == 0)
2264 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2265 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2267 if (locate_eod) {
2268 #if DEBUG
2269 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2270 #endif
2271 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2273 if (result)
2274 printk(KERN_ERR "%s:E: Write header failed\n", name);
2275 else {
2276 memcpy(STp->application_sig, "LIN4", 4);
2277 STp->linux_media = 1;
2278 STp->linux_media_version = 4;
2279 STp->header_ok = 1;
2281 return result;
2284 static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2286 if (STp->header_cache != NULL)
2287 memset(STp->header_cache, 0, sizeof(os_header_t));
2289 STp->logical_blk_num = STp->frame_seq_number = 0;
2290 STp->frame_in_buffer = 0;
2291 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2292 STp->filemark_cnt = 0;
2293 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2294 return osst_write_header(STp, aSRpnt, 1);
2297 static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2299 char * name = tape_name(STp);
2300 os_header_t * header;
2301 os_aux_t * aux;
2302 char id_string[8];
2303 int linux_media_version,
2304 update_frame_cntr;
2306 if (STp->raw)
2307 return 1;
2309 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2310 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2311 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2312 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2313 if (osst_initiate_read (STp, aSRpnt)) {
2314 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2315 return 0;
2318 if (osst_read_frame(STp, aSRpnt, 180)) {
2319 #if DEBUG
2320 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2321 #endif
2322 return 0;
2324 header = (os_header_t *) STp->buffer->b_data; /* warning: only first segment addressable */
2325 aux = STp->buffer->aux;
2326 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2327 #if DEBUG
2328 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2329 #endif
2330 return 0;
2332 if (ntohl(aux->frame_seq_num) != 0 ||
2333 ntohl(aux->logical_blk_num) != 0 ||
2334 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2335 ntohl(aux->partition.first_frame_ppos) != 0 ||
2336 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2337 #if DEBUG
2338 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2339 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2340 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2341 ntohl(aux->partition.last_frame_ppos));
2342 #endif
2343 return 0;
2345 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2346 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2347 strlcpy(id_string, header->ident_str, 8);
2348 #if DEBUG
2349 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2350 #endif
2351 return 0;
2353 update_frame_cntr = ntohl(aux->update_frame_cntr);
2354 if (update_frame_cntr < STp->update_frame_cntr) {
2355 #if DEBUG
2356 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2357 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2358 #endif
2359 return 0;
2361 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2362 #if DEBUG
2363 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2364 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2365 header->minor_rev > 4 )? "Invalid" : "Warning:",
2366 header->major_rev, header->minor_rev);
2367 #endif
2368 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2369 return 0;
2371 #if DEBUG
2372 if (header->pt_par_num != 1)
2373 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2374 name, header->pt_par_num);
2375 #endif
2376 memcpy(id_string, aux->application_sig, 4);
2377 id_string[4] = 0;
2378 if (memcmp(id_string, "LIN", 3) == 0) {
2379 STp->linux_media = 1;
2380 linux_media_version = id_string[3] - '0';
2381 if (linux_media_version != 4)
2382 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2383 name, linux_media_version);
2384 } else {
2385 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2386 return 0;
2388 if (linux_media_version < STp->linux_media_version) {
2389 #if DEBUG
2390 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2391 name, ppos, linux_media_version);
2392 #endif
2393 return 0;
2395 if (linux_media_version > STp->linux_media_version) {
2396 #if DEBUG
2397 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2398 name, ppos, linux_media_version);
2399 #endif
2400 memcpy(STp->application_sig, id_string, 5);
2401 STp->linux_media_version = linux_media_version;
2402 STp->update_frame_cntr = -1;
2404 if (update_frame_cntr > STp->update_frame_cntr) {
2405 #if DEBUG
2406 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2407 name, ppos, update_frame_cntr);
2408 #endif
2409 if (STp->header_cache == NULL) {
2410 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2411 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2412 return 0;
2414 #if DEBUG
2415 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2416 #endif
2418 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2419 header = STp->header_cache; /* further accesses from cached (full) copy */
2421 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2422 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2423 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2424 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2425 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2426 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2427 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2428 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2429 STp->update_frame_cntr = update_frame_cntr;
2430 #if DEBUG
2431 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2432 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2433 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2434 STp->first_data_ppos,
2435 ntohl(header->partition[0].last_frame_ppos),
2436 ntohl(header->partition[0].eod_frame_ppos));
2437 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2438 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2439 #endif
2440 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2441 #if DEBUG
2442 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2443 #endif
2444 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2445 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2446 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2448 if (header->minor_rev == 4 &&
2449 (header->ext_trk_tb_off != htons(17192) ||
2450 header->partition[0].partition_num != OS_DATA_PARTITION ||
2451 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2452 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2453 header->cfg_col_width != htonl(20) ||
2454 header->dat_col_width != htonl(1500) ||
2455 header->qfa_col_width != htonl(0) ||
2456 header->ext_track_tb.nr_stream_part != 1 ||
2457 header->ext_track_tb.et_ent_sz != 32 ||
2458 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2459 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2460 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2461 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2462 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2463 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2464 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2465 header->dat_fm_tab.fm_tab_ent_cnt !=
2466 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2467 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2471 return 1;
2474 static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2476 int position, ppos;
2477 int first, last;
2478 int valid = 0;
2479 char * name = tape_name(STp);
2481 position = osst_get_frame_position(STp, aSRpnt);
2483 if (STp->raw) {
2484 STp->header_ok = STp->linux_media = 1;
2485 STp->linux_media_version = 0;
2486 return 1;
2488 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2489 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2490 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2491 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2492 #if DEBUG
2493 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2494 #endif
2496 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2497 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2499 first = position==10?0xbae: 5;
2500 last = position==10?0xbb3:10;
2502 for (ppos = first; ppos < last; ppos++)
2503 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2504 valid = 1;
2506 first = position==10? 5:0xbae;
2507 last = position==10?10:0xbb3;
2509 for (ppos = first; ppos < last; ppos++)
2510 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2511 valid = 1;
2513 if (!valid) {
2514 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2515 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2516 osst_set_frame_position(STp, aSRpnt, 10, 0);
2517 return 0;
2519 if (position <= STp->first_data_ppos) {
2520 position = STp->first_data_ppos;
2521 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2523 osst_set_frame_position(STp, aSRpnt, position, 0);
2524 STp->header_ok = 1;
2526 return 1;
2529 static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2531 int frame_position = STp->first_frame_position;
2532 int frame_seq_numbr = STp->frame_seq_number;
2533 int logical_blk_num = STp->logical_blk_num;
2534 int halfway_frame = STp->frame_in_buffer;
2535 int read_pointer = STp->buffer->read_pointer;
2536 int prev_mark_ppos = -1;
2537 int actual_mark_ppos, i, n;
2538 #if DEBUG
2539 char * name = tape_name(STp);
2541 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2542 #endif
2543 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2544 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2545 #if DEBUG
2546 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2547 #endif
2548 return (-EIO);
2550 if (STp->linux_media_version >= 4) {
2551 for (i=0; i<STp->filemark_cnt; i++)
2552 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2553 prev_mark_ppos = n;
2554 } else
2555 prev_mark_ppos = frame_position - 1; /* usually - we don't really know */
2556 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2557 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2558 if (frame_position != STp->first_frame_position ||
2559 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2560 prev_mark_ppos != actual_mark_ppos ) {
2561 #if DEBUG
2562 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2563 STp->first_frame_position, frame_position,
2564 STp->frame_seq_number + (halfway_frame?0:1),
2565 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2566 #endif
2567 return (-EIO);
2569 if (halfway_frame) {
2570 /* prepare buffer for append and rewrite on top of original */
2571 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2572 STp->buffer->buffer_bytes = read_pointer;
2573 STp->ps[STp->partition].rw = ST_WRITING;
2574 STp->dirty = 1;
2576 STp->frame_in_buffer = halfway_frame;
2577 STp->frame_seq_number = frame_seq_numbr;
2578 STp->logical_blk_num = logical_blk_num;
2579 return 0;
2582 /* Acc. to OnStream, the vers. numbering is the following:
2583 * X.XX for released versions (X=digit),
2584 * XXXY for unreleased versions (Y=letter)
2585 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2586 * This fn makes monoton numbers out of this scheme ...
2588 static unsigned int osst_parse_firmware_rev (const char * str)
2590 if (str[1] == '.') {
2591 return (str[0]-'0')*10000
2592 +(str[2]-'0')*1000
2593 +(str[3]-'0')*100;
2594 } else {
2595 return (str[0]-'0')*10000
2596 +(str[1]-'0')*1000
2597 +(str[2]-'0')*100 - 100
2598 +(str[3]-'@');
2603 * Configure the OnStream SCII tape drive for default operation
2605 static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2607 unsigned char cmd[MAX_COMMAND_SIZE];
2608 char * name = tape_name(STp);
2609 struct osst_request * SRpnt = * aSRpnt;
2610 osst_mode_parameter_header_t * header;
2611 osst_block_size_page_t * bs;
2612 osst_capabilities_page_t * cp;
2613 osst_tape_paramtr_page_t * prm;
2614 int drive_buffer_size;
2616 if (STp->ready != ST_READY) {
2617 #if DEBUG
2618 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2619 #endif
2620 return (-EIO);
2623 if (STp->os_fw_rev < 10600) {
2624 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2625 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2629 * Configure 32.5KB (data+aux) frame size.
2630 * Get the current frame size from the block size mode page
2632 memset(cmd, 0, MAX_COMMAND_SIZE);
2633 cmd[0] = MODE_SENSE;
2634 cmd[1] = 8;
2635 cmd[2] = BLOCK_SIZE_PAGE;
2636 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2638 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2639 if (SRpnt == NULL) {
2640 #if DEBUG
2641 printk(OSST_DEB_MSG "osst :D: Busy\n");
2642 #endif
2643 return (-EBUSY);
2645 *aSRpnt = SRpnt;
2646 if ((STp->buffer)->syscall_result != 0) {
2647 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2648 return (-EIO);
2651 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2652 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2654 #if DEBUG
2655 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2656 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2657 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2658 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2659 #endif
2662 * Configure default auto columns mode, 32.5KB transfer mode
2664 bs->one = 1;
2665 bs->play32 = 0;
2666 bs->play32_5 = 1;
2667 bs->record32 = 0;
2668 bs->record32_5 = 1;
2670 memset(cmd, 0, MAX_COMMAND_SIZE);
2671 cmd[0] = MODE_SELECT;
2672 cmd[1] = 0x10;
2673 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2675 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2676 *aSRpnt = SRpnt;
2677 if ((STp->buffer)->syscall_result != 0) {
2678 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2679 return (-EIO);
2682 #if DEBUG
2683 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2685 * In debug mode, we want to see as many errors as possible
2686 * to test the error recovery mechanism.
2688 osst_set_retries(STp, aSRpnt, 0);
2689 SRpnt = * aSRpnt;
2690 #endif
2693 * Set vendor name to 'LIN4' for "Linux support version 4".
2696 memset(cmd, 0, MAX_COMMAND_SIZE);
2697 cmd[0] = MODE_SELECT;
2698 cmd[1] = 0x10;
2699 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2701 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2702 header->medium_type = 0; /* Medium Type - ignoring */
2703 header->dsp = 0; /* Reserved */
2704 header->bdl = 0; /* Block Descriptor Length */
2706 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2707 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2708 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2709 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2710 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2711 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2712 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2713 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2715 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2716 *aSRpnt = SRpnt;
2718 if ((STp->buffer)->syscall_result != 0) {
2719 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2720 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2721 return (-EIO);
2724 memset(cmd, 0, MAX_COMMAND_SIZE);
2725 cmd[0] = MODE_SENSE;
2726 cmd[1] = 8;
2727 cmd[2] = CAPABILITIES_PAGE;
2728 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2730 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2731 *aSRpnt = SRpnt;
2733 if ((STp->buffer)->syscall_result != 0) {
2734 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2735 return (-EIO);
2738 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2739 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2740 sizeof(osst_mode_parameter_header_t) + header->bdl);
2742 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2744 memset(cmd, 0, MAX_COMMAND_SIZE);
2745 cmd[0] = MODE_SENSE;
2746 cmd[1] = 8;
2747 cmd[2] = TAPE_PARAMTR_PAGE;
2748 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2750 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2751 *aSRpnt = SRpnt;
2753 if ((STp->buffer)->syscall_result != 0) {
2754 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2755 return (-EIO);
2758 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2759 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2760 sizeof(osst_mode_parameter_header_t) + header->bdl);
2762 STp->density = prm->density;
2763 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2764 #if DEBUG
2765 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2766 name, STp->density, STp->capacity / 32, drive_buffer_size);
2767 #endif
2769 return 0;
2774 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2775 it messes up the block number). */
2776 static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2778 int result;
2779 char * name = tape_name(STp);
2781 #if DEBUG
2782 if (debugging)
2783 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2784 name, forward ? "forward" : "backward");
2785 #endif
2787 if (forward) {
2788 /* assumes that the filemark is already read by the drive, so this is low cost */
2789 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2791 else
2792 /* assumes this is only called if we just read the filemark! */
2793 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2795 if (result < 0)
2796 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2797 name, forward ? "forward" : "backward");
2799 return result;
2803 /* Get the tape position. */
2805 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2807 unsigned char scmd[MAX_COMMAND_SIZE];
2808 struct osst_request * SRpnt;
2809 int result = 0;
2810 char * name = tape_name(STp);
2812 /* KG: We want to be able to use it for checking Write Buffer availability
2813 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2814 char mybuf[24];
2815 char * olddata = STp->buffer->b_data;
2816 int oldsize = STp->buffer->buffer_size;
2818 if (STp->ready != ST_READY) return (-EIO);
2820 memset (scmd, 0, MAX_COMMAND_SIZE);
2821 scmd[0] = READ_POSITION;
2823 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2824 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2825 STp->timeout, MAX_RETRIES, 1);
2826 if (!SRpnt) {
2827 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2828 return (-EBUSY);
2830 *aSRpnt = SRpnt;
2832 if (STp->buffer->syscall_result)
2833 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
2835 if (result == -EINVAL)
2836 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2837 else {
2838 if (result == -EIO) { /* re-read position - this needs to preserve media errors */
2839 unsigned char mysense[16];
2840 memcpy (mysense, SRpnt->sense, 16);
2841 memset (scmd, 0, MAX_COMMAND_SIZE);
2842 scmd[0] = READ_POSITION;
2843 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2844 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2845 STp->timeout, MAX_RETRIES, 1);
2846 #if DEBUG
2847 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2848 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2849 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2850 #endif
2851 if (!STp->buffer->syscall_result)
2852 memcpy (SRpnt->sense, mysense, 16);
2853 else
2854 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2856 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2857 + ((STp->buffer)->b_data[5] << 16)
2858 + ((STp->buffer)->b_data[6] << 8)
2859 + (STp->buffer)->b_data[7];
2860 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2861 + ((STp->buffer)->b_data[ 9] << 16)
2862 + ((STp->buffer)->b_data[10] << 8)
2863 + (STp->buffer)->b_data[11];
2864 STp->cur_frames = (STp->buffer)->b_data[15];
2865 #if DEBUG
2866 if (debugging) {
2867 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2868 STp->first_frame_position, STp->last_frame_position,
2869 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2870 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2871 STp->cur_frames);
2873 #endif
2874 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2875 #if DEBUG
2876 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2877 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2878 #endif
2879 STp->first_frame_position = STp->last_frame_position;
2882 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2884 return (result == 0 ? STp->first_frame_position : result);
2888 /* Set the tape block */
2889 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2891 unsigned char scmd[MAX_COMMAND_SIZE];
2892 struct osst_request * SRpnt;
2893 struct st_partstat * STps;
2894 int result = 0;
2895 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2896 char * name = tape_name(STp);
2898 if (STp->ready != ST_READY) return (-EIO);
2900 STps = &(STp->ps[STp->partition]);
2902 if (ppos < 0 || ppos > STp->capacity) {
2903 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2904 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2905 result = (-EINVAL);
2908 do {
2909 #if DEBUG
2910 if (debugging)
2911 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2912 #endif
2913 memset (scmd, 0, MAX_COMMAND_SIZE);
2914 scmd[0] = SEEK_10;
2915 scmd[1] = 1;
2916 scmd[3] = (pp >> 24);
2917 scmd[4] = (pp >> 16);
2918 scmd[5] = (pp >> 8);
2919 scmd[6] = pp;
2920 if (skip)
2921 scmd[9] = 0x80;
2923 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
2924 MAX_RETRIES, 1);
2925 if (!SRpnt)
2926 return (-EBUSY);
2927 *aSRpnt = SRpnt;
2929 if ((STp->buffer)->syscall_result != 0) {
2930 #if DEBUG
2931 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
2932 name, STp->first_frame_position, pp);
2933 #endif
2934 result = (-EIO);
2936 if (pp != ppos)
2937 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
2938 } while ((pp != ppos) && (pp = ppos));
2939 STp->first_frame_position = STp->last_frame_position = ppos;
2940 STps->eof = ST_NOEOF;
2941 STps->at_sm = 0;
2942 STps->rw = ST_IDLE;
2943 STp->frame_in_buffer = 0;
2944 return result;
2947 static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
2949 struct st_partstat * STps = &(STp->ps[STp->partition]);
2950 int result = 0;
2952 if (STp->write_type != OS_WRITE_NEW_MARK) {
2953 /* true unless the user wrote the filemark for us */
2954 result = osst_flush_drive_buffer(STp, aSRpnt);
2955 if (result < 0) goto out;
2956 result = osst_write_filemark(STp, aSRpnt);
2957 if (result < 0) goto out;
2959 if (STps->drv_file >= 0)
2960 STps->drv_file++ ;
2961 STps->drv_block = 0;
2963 result = osst_write_eod(STp, aSRpnt);
2964 osst_write_header(STp, aSRpnt, leave_at_EOT);
2966 STps->eof = ST_FM;
2967 out:
2968 return result;
2971 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2973 /* Flush the write buffer (never need to write if variable blocksize). */
2974 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
2976 int offset, transfer, blks = 0;
2977 int result = 0;
2978 unsigned char cmd[MAX_COMMAND_SIZE];
2979 struct osst_request * SRpnt = *aSRpnt;
2980 struct st_partstat * STps;
2981 char * name = tape_name(STp);
2983 if ((STp->buffer)->writing) {
2984 if (SRpnt == (STp->buffer)->last_SRpnt)
2985 #if DEBUG
2986 { printk(OSST_DEB_MSG
2987 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
2988 #endif
2989 *aSRpnt = SRpnt = NULL;
2990 #if DEBUG
2991 } else if (SRpnt)
2992 printk(OSST_DEB_MSG
2993 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
2994 #endif
2995 osst_write_behind_check(STp);
2996 if ((STp->buffer)->syscall_result) {
2997 #if DEBUG
2998 if (debugging)
2999 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3000 name, (STp->buffer)->midlevel_result);
3001 #endif
3002 if ((STp->buffer)->midlevel_result == INT_MAX)
3003 return (-ENOSPC);
3004 return (-EIO);
3008 result = 0;
3009 if (STp->dirty == 1) {
3011 STp->write_count++;
3012 STps = &(STp->ps[STp->partition]);
3013 STps->rw = ST_WRITING;
3014 offset = STp->buffer->buffer_bytes;
3015 blks = (offset + STp->block_size - 1) / STp->block_size;
3016 transfer = OS_FRAME_SIZE;
3018 if (offset < OS_DATA_SIZE)
3019 osst_zero_buffer_tail(STp->buffer);
3021 if (STp->poll)
3022 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3023 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3025 memset(cmd, 0, MAX_COMMAND_SIZE);
3026 cmd[0] = WRITE_6;
3027 cmd[1] = 1;
3028 cmd[4] = 1;
3030 switch (STp->write_type) {
3031 case OS_WRITE_DATA:
3032 #if DEBUG
3033 if (debugging)
3034 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3035 name, blks, STp->frame_seq_number,
3036 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3037 #endif
3038 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3039 STp->logical_blk_num - blks, STp->block_size, blks);
3040 break;
3041 case OS_WRITE_EOD:
3042 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3043 STp->logical_blk_num, 0, 0);
3044 break;
3045 case OS_WRITE_NEW_MARK:
3046 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3047 STp->logical_blk_num++, 0, blks=1);
3048 break;
3049 case OS_WRITE_HEADER:
3050 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3051 break;
3052 default: /* probably FILLER */
3053 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3055 #if DEBUG
3056 if (debugging)
3057 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3058 name, offset, transfer, blks);
3059 #endif
3061 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3062 STp->timeout, MAX_RETRIES, 1);
3063 *aSRpnt = SRpnt;
3064 if (!SRpnt)
3065 return (-EBUSY);
3067 if ((STp->buffer)->syscall_result != 0) {
3068 #if DEBUG
3069 printk(OSST_DEB_MSG
3070 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3071 name, SRpnt->sense[0], SRpnt->sense[2],
3072 SRpnt->sense[12], SRpnt->sense[13]);
3073 #endif
3074 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3075 (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3076 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3077 STp->dirty = 0;
3078 (STp->buffer)->buffer_bytes = 0;
3079 result = (-ENOSPC);
3081 else {
3082 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3083 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3084 result = (-EIO);
3087 STps->drv_block = (-1); /* FIXME - even if write recovery succeeds? */
3089 else {
3090 STp->first_frame_position++;
3091 STp->dirty = 0;
3092 (STp->buffer)->buffer_bytes = 0;
3095 #if DEBUG
3096 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3097 #endif
3098 return result;
3102 /* Flush the tape buffer. The tape will be positioned correctly unless
3103 seek_next is true. */
3104 static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3106 struct st_partstat * STps;
3107 int backspace = 0, result = 0;
3108 #if DEBUG
3109 char * name = tape_name(STp);
3110 #endif
3113 * If there was a bus reset, block further access
3114 * to this device.
3116 if( STp->pos_unknown)
3117 return (-EIO);
3119 if (STp->ready != ST_READY)
3120 return 0;
3122 STps = &(STp->ps[STp->partition]);
3123 if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
3124 STp->write_type = OS_WRITE_DATA;
3125 return osst_flush_write_buffer(STp, aSRpnt);
3127 if (STp->block_size == 0)
3128 return 0;
3130 #if DEBUG
3131 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3132 #endif
3134 if (!STp->can_bsr) {
3135 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3136 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3137 (STp->buffer)->buffer_bytes = 0;
3138 (STp->buffer)->read_pointer = 0;
3139 STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */
3142 if (!seek_next) {
3143 if (STps->eof == ST_FM_HIT) {
3144 result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3145 if (!result)
3146 STps->eof = ST_NOEOF;
3147 else {
3148 if (STps->drv_file >= 0)
3149 STps->drv_file++;
3150 STps->drv_block = 0;
3153 if (!result && backspace > 0) /* TODO -- design and run a test case for this */
3154 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3156 else if (STps->eof == ST_FM_HIT) {
3157 if (STps->drv_file >= 0)
3158 STps->drv_file++;
3159 STps->drv_block = 0;
3160 STps->eof = ST_NOEOF;
3163 return result;
3166 static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3168 unsigned char cmd[MAX_COMMAND_SIZE];
3169 struct osst_request * SRpnt;
3170 int blks;
3171 #if DEBUG
3172 char * name = tape_name(STp);
3173 #endif
3175 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3176 #if DEBUG
3177 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3178 #endif
3179 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3180 return (-EIO);
3182 /* error recovery may have bumped us past the header partition */
3183 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3184 #if DEBUG
3185 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3186 #endif
3187 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3191 if (STp->poll)
3192 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3193 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3194 return (-EIO);
3196 // osst_build_stats(STp, &SRpnt);
3198 STp->ps[STp->partition].rw = ST_WRITING;
3199 STp->write_type = OS_WRITE_DATA;
3201 memset(cmd, 0, MAX_COMMAND_SIZE);
3202 cmd[0] = WRITE_6;
3203 cmd[1] = 1;
3204 cmd[4] = 1; /* one frame at a time... */
3205 blks = STp->buffer->buffer_bytes / STp->block_size;
3206 #if DEBUG
3207 if (debugging)
3208 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3209 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3210 #endif
3211 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3212 STp->logical_blk_num - blks, STp->block_size, blks);
3214 #if DEBUG
3215 if (!synchronous)
3216 STp->write_pending = 1;
3217 #endif
3218 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3219 MAX_RETRIES, synchronous);
3220 if (!SRpnt)
3221 return (-EBUSY);
3222 *aSRpnt = SRpnt;
3224 if (synchronous) {
3225 if (STp->buffer->syscall_result != 0) {
3226 #if DEBUG
3227 if (debugging)
3228 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3229 #endif
3230 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3231 (SRpnt->sense[2] & 0x40)) {
3232 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3233 return (-ENOSPC);
3235 else {
3236 if (osst_write_error_recovery(STp, aSRpnt, 1))
3237 return (-EIO);
3240 else
3241 STp->first_frame_position++;
3244 STp->write_count++;
3246 return 0;
3249 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3250 static int do_door_lock(struct osst_tape * STp, int do_lock)
3252 int retval, cmd;
3254 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3255 #if DEBUG
3256 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3257 #endif
3258 retval = scsi_ioctl(STp->device, cmd, NULL);
3259 if (!retval) {
3260 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3262 else {
3263 STp->door_locked = ST_LOCK_FAILS;
3265 return retval;
3268 /* Set the internal state after reset */
3269 static void reset_state(struct osst_tape *STp)
3271 int i;
3272 struct st_partstat *STps;
3274 STp->pos_unknown = 0;
3275 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3276 STps = &(STp->ps[i]);
3277 STps->rw = ST_IDLE;
3278 STps->eof = ST_NOEOF;
3279 STps->at_sm = 0;
3280 STps->last_block_valid = 0;
3281 STps->drv_block = -1;
3282 STps->drv_file = -1;
3287 /* Entry points to osst */
3289 /* Write command */
3290 static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3292 ssize_t total, retval = 0;
3293 ssize_t i, do_count, blks, transfer;
3294 int write_threshold;
3295 int doing_write = 0;
3296 const char __user * b_point;
3297 struct osst_request * SRpnt = NULL;
3298 struct st_modedef * STm;
3299 struct st_partstat * STps;
3300 struct osst_tape * STp = filp->private_data;
3301 char * name = tape_name(STp);
3304 if (mutex_lock_interruptible(&STp->lock))
3305 return (-ERESTARTSYS);
3308 * If we are in the middle of error recovery, don't let anyone
3309 * else try and use this device. Also, if error recovery fails, it
3310 * may try and take the device offline, in which case all further
3311 * access to the device is prohibited.
3313 if( !scsi_block_when_processing_errors(STp->device) ) {
3314 retval = (-ENXIO);
3315 goto out;
3318 if (STp->ready != ST_READY) {
3319 if (STp->ready == ST_NO_TAPE)
3320 retval = (-ENOMEDIUM);
3321 else
3322 retval = (-EIO);
3323 goto out;
3325 STm = &(STp->modes[STp->current_mode]);
3326 if (!STm->defined) {
3327 retval = (-ENXIO);
3328 goto out;
3330 if (count == 0)
3331 goto out;
3334 * If there was a bus reset, block further access
3335 * to this device.
3337 if (STp->pos_unknown) {
3338 retval = (-EIO);
3339 goto out;
3342 #if DEBUG
3343 if (!STp->in_use) {
3344 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3345 retval = (-EIO);
3346 goto out;
3348 #endif
3350 if (STp->write_prot) {
3351 retval = (-EACCES);
3352 goto out;
3355 /* Write must be integral number of blocks */
3356 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3357 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3358 name, count, STp->block_size<1024?
3359 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3360 retval = (-EINVAL);
3361 goto out;
3364 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3365 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3366 name, STp->first_frame_position);
3367 retval = (-ENOSPC);
3368 goto out;
3371 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3372 STp->door_locked = ST_LOCKED_AUTO;
3374 STps = &(STp->ps[STp->partition]);
3376 if (STps->rw == ST_READING) {
3377 #if DEBUG
3378 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3379 STps->drv_file, STps->drv_block);
3380 #endif
3381 retval = osst_flush_buffer(STp, &SRpnt, 0);
3382 if (retval)
3383 goto out;
3384 STps->rw = ST_IDLE;
3386 if (STps->rw != ST_WRITING) {
3387 /* Are we totally rewriting this tape? */
3388 if (!STp->header_ok ||
3389 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3390 (STps->drv_file == 0 && STps->drv_block == 0)) {
3391 STp->wrt_pass_cntr++;
3392 #if DEBUG
3393 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3394 name, STp->wrt_pass_cntr);
3395 #endif
3396 osst_reset_header(STp, &SRpnt);
3397 STps->drv_file = STps->drv_block = 0;
3399 /* Do we know where we'll be writing on the tape? */
3400 else {
3401 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3402 STps->drv_file < 0 || STps->drv_block < 0) {
3403 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3404 STps->drv_file = STp->filemark_cnt;
3405 STps->drv_block = 0;
3407 else {
3408 /* We have no idea where the tape is positioned - give up */
3409 #if DEBUG
3410 printk(OSST_DEB_MSG
3411 "%s:D: Cannot write at indeterminate position.\n", name);
3412 #endif
3413 retval = (-EIO);
3414 goto out;
3417 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3418 STp->filemark_cnt = STps->drv_file;
3419 STp->last_mark_ppos =
3420 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3421 printk(KERN_WARNING
3422 "%s:W: Overwriting file %d with old write pass counter %d\n",
3423 name, STps->drv_file, STp->wrt_pass_cntr);
3424 printk(KERN_WARNING
3425 "%s:W: may lead to stale data being accepted on reading back!\n",
3426 name);
3427 #if DEBUG
3428 printk(OSST_DEB_MSG
3429 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3430 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3431 #endif
3434 STp->fast_open = 0;
3436 if (!STp->header_ok) {
3437 #if DEBUG
3438 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3439 #endif
3440 retval = (-EIO);
3441 goto out;
3444 if ((STp->buffer)->writing) {
3445 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3446 osst_write_behind_check(STp);
3447 if ((STp->buffer)->syscall_result) {
3448 #if DEBUG
3449 if (debugging)
3450 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3451 (STp->buffer)->midlevel_result);
3452 #endif
3453 if ((STp->buffer)->midlevel_result == INT_MAX)
3454 STps->eof = ST_EOM_OK;
3455 else
3456 STps->eof = ST_EOM_ERROR;
3459 if (STps->eof == ST_EOM_OK) {
3460 retval = (-ENOSPC);
3461 goto out;
3463 else if (STps->eof == ST_EOM_ERROR) {
3464 retval = (-EIO);
3465 goto out;
3468 /* Check the buffer readability in cases where copy_user might catch
3469 the problems after some tape movement. */
3470 if ((copy_from_user(&i, buf, 1) != 0 ||
3471 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3472 retval = (-EFAULT);
3473 goto out;
3476 if (!STm->do_buffer_writes) {
3477 write_threshold = 1;
3479 else
3480 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3481 if (!STm->do_async_writes)
3482 write_threshold--;
3484 total = count;
3485 #if DEBUG
3486 if (debugging)
3487 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3488 name, (int) count, STps->drv_file, STps->drv_block,
3489 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3490 #endif
3491 b_point = buf;
3492 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3494 doing_write = 1;
3495 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3496 (STp->buffer)->buffer_bytes;
3497 if (do_count > count)
3498 do_count = count;
3500 i = append_to_buffer(b_point, STp->buffer, do_count);
3501 if (i) {
3502 retval = i;
3503 goto out;
3506 blks = do_count / STp->block_size;
3507 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3509 i = osst_write_frame(STp, &SRpnt, 1);
3511 if (i == (-ENOSPC)) {
3512 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3513 if (transfer <= do_count) {
3514 filp->f_pos += do_count - transfer;
3515 count -= do_count - transfer;
3516 if (STps->drv_block >= 0) {
3517 STps->drv_block += (do_count - transfer) / STp->block_size;
3519 STps->eof = ST_EOM_OK;
3520 retval = (-ENOSPC); /* EOM within current request */
3521 #if DEBUG
3522 if (debugging)
3523 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3524 name, (int) transfer);
3525 #endif
3527 else {
3528 STps->eof = ST_EOM_ERROR;
3529 STps->drv_block = (-1); /* Too cautious? */
3530 retval = (-EIO); /* EOM for old data */
3531 #if DEBUG
3532 if (debugging)
3533 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3534 #endif
3537 else
3538 retval = i;
3540 if (retval < 0) {
3541 if (SRpnt != NULL) {
3542 osst_release_request(SRpnt);
3543 SRpnt = NULL;
3545 STp->buffer->buffer_bytes = 0;
3546 STp->dirty = 0;
3547 if (count < total)
3548 retval = total - count;
3549 goto out;
3552 filp->f_pos += do_count;
3553 b_point += do_count;
3554 count -= do_count;
3555 if (STps->drv_block >= 0) {
3556 STps->drv_block += blks;
3558 STp->buffer->buffer_bytes = 0;
3559 STp->dirty = 0;
3560 } /* end while write threshold exceeded */
3562 if (count != 0) {
3563 STp->dirty = 1;
3564 i = append_to_buffer(b_point, STp->buffer, count);
3565 if (i) {
3566 retval = i;
3567 goto out;
3569 blks = count / STp->block_size;
3570 STp->logical_blk_num += blks;
3571 if (STps->drv_block >= 0) {
3572 STps->drv_block += blks;
3574 filp->f_pos += count;
3575 count = 0;
3578 if (doing_write && (STp->buffer)->syscall_result != 0) {
3579 retval = (STp->buffer)->syscall_result;
3580 goto out;
3583 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3584 /* Schedule an asynchronous write */
3585 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3586 STp->block_size) * STp->block_size;
3587 STp->dirty = !((STp->buffer)->writing ==
3588 (STp->buffer)->buffer_bytes);
3590 i = osst_write_frame(STp, &SRpnt, 0);
3591 if (i < 0) {
3592 retval = (-EIO);
3593 goto out;
3595 SRpnt = NULL; /* Prevent releasing this request! */
3597 STps->at_sm &= (total == 0);
3598 if (total > 0)
3599 STps->eof = ST_NOEOF;
3601 retval = total;
3603 out:
3604 if (SRpnt != NULL) osst_release_request(SRpnt);
3606 mutex_unlock(&STp->lock);
3608 return retval;
3612 /* Read command */
3613 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3615 ssize_t total, retval = 0;
3616 ssize_t i, transfer;
3617 int special;
3618 struct st_modedef * STm;
3619 struct st_partstat * STps;
3620 struct osst_request * SRpnt = NULL;
3621 struct osst_tape * STp = filp->private_data;
3622 char * name = tape_name(STp);
3625 if (mutex_lock_interruptible(&STp->lock))
3626 return (-ERESTARTSYS);
3629 * If we are in the middle of error recovery, don't let anyone
3630 * else try and use this device. Also, if error recovery fails, it
3631 * may try and take the device offline, in which case all further
3632 * access to the device is prohibited.
3634 if( !scsi_block_when_processing_errors(STp->device) ) {
3635 retval = (-ENXIO);
3636 goto out;
3639 if (STp->ready != ST_READY) {
3640 if (STp->ready == ST_NO_TAPE)
3641 retval = (-ENOMEDIUM);
3642 else
3643 retval = (-EIO);
3644 goto out;
3646 STm = &(STp->modes[STp->current_mode]);
3647 if (!STm->defined) {
3648 retval = (-ENXIO);
3649 goto out;
3651 #if DEBUG
3652 if (!STp->in_use) {
3653 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3654 retval = (-EIO);
3655 goto out;
3657 #endif
3658 /* Must have initialized medium */
3659 if (!STp->header_ok) {
3660 retval = (-EIO);
3661 goto out;
3664 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3665 STp->door_locked = ST_LOCKED_AUTO;
3667 STps = &(STp->ps[STp->partition]);
3668 if (STps->rw == ST_WRITING) {
3669 retval = osst_flush_buffer(STp, &SRpnt, 0);
3670 if (retval)
3671 goto out;
3672 STps->rw = ST_IDLE;
3673 /* FIXME -- this may leave the tape without EOD and up2date headers */
3676 if ((count % STp->block_size) != 0) {
3677 printk(KERN_WARNING
3678 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3679 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3682 #if DEBUG
3683 if (debugging && STps->eof != ST_NOEOF)
3684 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3685 STps->eof, (STp->buffer)->buffer_bytes);
3686 #endif
3687 if ((STp->buffer)->buffer_bytes == 0 &&
3688 STps->eof >= ST_EOD_1) {
3689 if (STps->eof < ST_EOD) {
3690 STps->eof += 1;
3691 retval = 0;
3692 goto out;
3694 retval = (-EIO); /* EOM or Blank Check */
3695 goto out;
3698 /* Check the buffer writability before any tape movement. Don't alter
3699 buffer data. */
3700 if (copy_from_user(&i, buf, 1) != 0 ||
3701 copy_to_user (buf, &i, 1) != 0 ||
3702 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3703 copy_to_user (buf + count - 1, &i, 1) != 0) {
3704 retval = (-EFAULT);
3705 goto out;
3708 /* Loop until enough data in buffer or a special condition found */
3709 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3711 /* Get new data if the buffer is empty */
3712 if ((STp->buffer)->buffer_bytes == 0) {
3713 if (STps->eof == ST_FM_HIT)
3714 break;
3715 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3716 if (special < 0) { /* No need to continue read */
3717 STp->frame_in_buffer = 0;
3718 retval = special;
3719 goto out;
3723 /* Move the data from driver buffer to user buffer */
3724 if ((STp->buffer)->buffer_bytes > 0) {
3725 #if DEBUG
3726 if (debugging && STps->eof != ST_NOEOF)
3727 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3728 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3729 #endif
3730 /* force multiple of block size, note block_size may have been adjusted */
3731 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3732 (STp->buffer)->buffer_bytes : count - total)/
3733 STp->block_size) * STp->block_size;
3735 if (transfer == 0) {
3736 printk(KERN_WARNING
3737 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3738 name, count, STp->block_size < 1024?
3739 STp->block_size:STp->block_size/1024,
3740 STp->block_size<1024?'b':'k');
3741 break;
3743 i = from_buffer(STp->buffer, buf, transfer);
3744 if (i) {
3745 retval = i;
3746 goto out;
3748 STp->logical_blk_num += transfer / STp->block_size;
3749 STps->drv_block += transfer / STp->block_size;
3750 filp->f_pos += transfer;
3751 buf += transfer;
3752 total += transfer;
3755 if ((STp->buffer)->buffer_bytes == 0) {
3756 #if DEBUG
3757 if (debugging)
3758 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3759 name, STp->frame_seq_number);
3760 #endif
3761 STp->frame_in_buffer = 0;
3762 STp->frame_seq_number++; /* frame to look for next time */
3764 } /* for (total = 0, special = 0; total < count && !special; ) */
3766 /* Change the eof state if no data from tape or buffer */
3767 if (total == 0) {
3768 if (STps->eof == ST_FM_HIT) {
3769 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3770 STps->drv_block = 0;
3771 if (STps->drv_file >= 0)
3772 STps->drv_file++;
3774 else if (STps->eof == ST_EOD_1) {
3775 STps->eof = ST_EOD_2;
3776 if (STps->drv_block > 0 && STps->drv_file >= 0)
3777 STps->drv_file++;
3778 STps->drv_block = 0;
3780 else if (STps->eof == ST_EOD_2)
3781 STps->eof = ST_EOD;
3783 else if (STps->eof == ST_FM)
3784 STps->eof = ST_NOEOF;
3786 retval = total;
3788 out:
3789 if (SRpnt != NULL) osst_release_request(SRpnt);
3791 mutex_unlock(&STp->lock);
3793 return retval;
3797 /* Set the driver options */
3798 static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3800 printk(KERN_INFO
3801 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3802 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3803 STm->do_read_ahead);
3804 printk(KERN_INFO
3805 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3806 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3807 printk(KERN_INFO
3808 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3809 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3810 STp->scsi2_logical);
3811 printk(KERN_INFO
3812 "%s:I: sysv: %d\n", name, STm->sysv);
3813 #if DEBUG
3814 printk(KERN_INFO
3815 "%s:D: debugging: %d\n",
3816 name, debugging);
3817 #endif
3821 static int osst_set_options(struct osst_tape *STp, long options)
3823 int value;
3824 long code;
3825 struct st_modedef * STm;
3826 char * name = tape_name(STp);
3828 STm = &(STp->modes[STp->current_mode]);
3829 if (!STm->defined) {
3830 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3831 modes_defined = 1;
3832 #if DEBUG
3833 if (debugging)
3834 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3835 name, STp->current_mode);
3836 #endif
3839 code = options & MT_ST_OPTIONS;
3840 if (code == MT_ST_BOOLEANS) {
3841 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3842 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3843 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3844 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3845 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3846 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3847 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3848 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3849 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3850 if ((STp->device)->scsi_level >= SCSI_2)
3851 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3852 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3853 STm->sysv = (options & MT_ST_SYSV) != 0;
3854 #if DEBUG
3855 debugging = (options & MT_ST_DEBUGGING) != 0;
3856 #endif
3857 osst_log_options(STp, STm, name);
3859 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3860 value = (code == MT_ST_SETBOOLEANS);
3861 if ((options & MT_ST_BUFFER_WRITES) != 0)
3862 STm->do_buffer_writes = value;
3863 if ((options & MT_ST_ASYNC_WRITES) != 0)
3864 STm->do_async_writes = value;
3865 if ((options & MT_ST_DEF_WRITES) != 0)
3866 STm->defaults_for_writes = value;
3867 if ((options & MT_ST_READ_AHEAD) != 0)
3868 STm->do_read_ahead = value;
3869 if ((options & MT_ST_TWO_FM) != 0)
3870 STp->two_fm = value;
3871 if ((options & MT_ST_FAST_MTEOM) != 0)
3872 STp->fast_mteom = value;
3873 if ((options & MT_ST_AUTO_LOCK) != 0)
3874 STp->do_auto_lock = value;
3875 if ((options & MT_ST_CAN_BSR) != 0)
3876 STp->can_bsr = value;
3877 if ((options & MT_ST_NO_BLKLIMS) != 0)
3878 STp->omit_blklims = value;
3879 if ((STp->device)->scsi_level >= SCSI_2 &&
3880 (options & MT_ST_CAN_PARTITIONS) != 0)
3881 STp->can_partitions = value;
3882 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3883 STp->scsi2_logical = value;
3884 if ((options & MT_ST_SYSV) != 0)
3885 STm->sysv = value;
3886 #if DEBUG
3887 if ((options & MT_ST_DEBUGGING) != 0)
3888 debugging = value;
3889 #endif
3890 osst_log_options(STp, STm, name);
3892 else if (code == MT_ST_WRITE_THRESHOLD) {
3893 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3894 if (value < 1 || value > osst_buffer_size) {
3895 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3896 name, value);
3897 return (-EIO);
3899 STp->write_threshold = value;
3900 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3901 name, value);
3903 else if (code == MT_ST_DEF_BLKSIZE) {
3904 value = (options & ~MT_ST_OPTIONS);
3905 if (value == ~MT_ST_OPTIONS) {
3906 STm->default_blksize = (-1);
3907 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3909 else {
3910 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3911 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3912 name, value);
3913 return (-EINVAL);
3915 STm->default_blksize = value;
3916 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3917 name, STm->default_blksize);
3920 else if (code == MT_ST_TIMEOUTS) {
3921 value = (options & ~MT_ST_OPTIONS);
3922 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3923 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3924 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3925 (value & ~MT_ST_SET_LONG_TIMEOUT));
3927 else {
3928 STp->timeout = value * HZ;
3929 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3932 else if (code == MT_ST_DEF_OPTIONS) {
3933 code = (options & ~MT_ST_CLEAR_DEFAULT);
3934 value = (options & MT_ST_CLEAR_DEFAULT);
3935 if (code == MT_ST_DEF_DENSITY) {
3936 if (value == MT_ST_CLEAR_DEFAULT) {
3937 STm->default_density = (-1);
3938 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3940 else {
3941 STm->default_density = value & 0xff;
3942 printk(KERN_INFO "%s:I: Density default set to %x\n",
3943 name, STm->default_density);
3946 else if (code == MT_ST_DEF_DRVBUFFER) {
3947 if (value == MT_ST_CLEAR_DEFAULT) {
3948 STp->default_drvbuffer = 0xff;
3949 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3951 else {
3952 STp->default_drvbuffer = value & 7;
3953 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3954 name, STp->default_drvbuffer);
3957 else if (code == MT_ST_DEF_COMPRESSION) {
3958 if (value == MT_ST_CLEAR_DEFAULT) {
3959 STm->default_compression = ST_DONT_TOUCH;
3960 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3962 else {
3963 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3964 printk(KERN_INFO "%s:I: Compression default set to %x\n",
3965 name, (value & 1));
3969 else
3970 return (-EIO);
3972 return 0;
3976 /* Internal ioctl function */
3977 static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
3978 unsigned int cmd_in, unsigned long arg)
3980 int timeout;
3981 long ltmp;
3982 int i, ioctl_result;
3983 int chg_eof = 1;
3984 unsigned char cmd[MAX_COMMAND_SIZE];
3985 struct osst_request * SRpnt = * aSRpnt;
3986 struct st_partstat * STps;
3987 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3988 int datalen = 0, direction = DMA_NONE;
3989 char * name = tape_name(STp);
3991 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3992 if (STp->ready == ST_NO_TAPE)
3993 return (-ENOMEDIUM);
3994 else
3995 return (-EIO);
3997 timeout = STp->long_timeout;
3998 STps = &(STp->ps[STp->partition]);
3999 fileno = STps->drv_file;
4000 blkno = STps->drv_block;
4001 at_sm = STps->at_sm;
4002 frame_seq_numbr = STp->frame_seq_number;
4003 logical_blk_num = STp->logical_blk_num;
4005 memset(cmd, 0, MAX_COMMAND_SIZE);
4006 switch (cmd_in) {
4007 case MTFSFM:
4008 chg_eof = 0; /* Changed from the FSF after this */
4009 case MTFSF:
4010 if (STp->raw)
4011 return (-EIO);
4012 if (STp->linux_media)
4013 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4014 else
4015 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4016 if (fileno >= 0)
4017 fileno += arg;
4018 blkno = 0;
4019 at_sm &= (arg == 0);
4020 goto os_bypass;
4022 case MTBSF:
4023 chg_eof = 0; /* Changed from the FSF after this */
4024 case MTBSFM:
4025 if (STp->raw)
4026 return (-EIO);
4027 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4028 if (fileno >= 0)
4029 fileno -= arg;
4030 blkno = (-1); /* We can't know the block number */
4031 at_sm &= (arg == 0);
4032 goto os_bypass;
4034 case MTFSR:
4035 case MTBSR:
4036 #if DEBUG
4037 if (debugging)
4038 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4039 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4040 #endif
4041 if (cmd_in == MTFSR) {
4042 logical_blk_num += arg;
4043 if (blkno >= 0) blkno += arg;
4045 else {
4046 logical_blk_num -= arg;
4047 if (blkno >= 0) blkno -= arg;
4049 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4050 fileno = STps->drv_file;
4051 blkno = STps->drv_block;
4052 at_sm &= (arg == 0);
4053 goto os_bypass;
4055 case MTFSS:
4056 cmd[0] = SPACE;
4057 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4058 cmd[2] = (arg >> 16);
4059 cmd[3] = (arg >> 8);
4060 cmd[4] = arg;
4061 #if DEBUG
4062 if (debugging)
4063 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4064 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4065 #endif
4066 if (arg != 0) {
4067 blkno = fileno = (-1);
4068 at_sm = 1;
4070 break;
4071 case MTBSS:
4072 cmd[0] = SPACE;
4073 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4074 ltmp = (-arg);
4075 cmd[2] = (ltmp >> 16);
4076 cmd[3] = (ltmp >> 8);
4077 cmd[4] = ltmp;
4078 #if DEBUG
4079 if (debugging) {
4080 if (cmd[2] & 0x80)
4081 ltmp = 0xff000000;
4082 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4083 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4084 name, (-ltmp));
4086 #endif
4087 if (arg != 0) {
4088 blkno = fileno = (-1);
4089 at_sm = 1;
4091 break;
4092 case MTWEOF:
4093 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4094 STp->write_type = OS_WRITE_DATA;
4095 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4096 } else
4097 ioctl_result = 0;
4098 #if DEBUG
4099 if (debugging)
4100 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4101 #endif
4102 for (i=0; i<arg; i++)
4103 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4104 if (fileno >= 0) fileno += arg;
4105 if (blkno >= 0) blkno = 0;
4106 goto os_bypass;
4108 case MTWSM:
4109 if (STp->write_prot)
4110 return (-EACCES);
4111 if (!STp->raw)
4112 return 0;
4113 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
4114 if (cmd_in == MTWSM)
4115 cmd[1] = 2;
4116 cmd[2] = (arg >> 16);
4117 cmd[3] = (arg >> 8);
4118 cmd[4] = arg;
4119 timeout = STp->timeout;
4120 #if DEBUG
4121 if (debugging)
4122 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4123 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4124 #endif
4125 if (fileno >= 0)
4126 fileno += arg;
4127 blkno = 0;
4128 at_sm = (cmd_in == MTWSM);
4129 break;
4130 case MTOFFL:
4131 case MTLOAD:
4132 case MTUNLOAD:
4133 case MTRETEN:
4134 cmd[0] = START_STOP;
4135 cmd[1] = 1; /* Don't wait for completion */
4136 if (cmd_in == MTLOAD) {
4137 if (STp->ready == ST_NO_TAPE)
4138 cmd[4] = 4; /* open tray */
4139 else
4140 cmd[4] = 1; /* load */
4142 if (cmd_in == MTRETEN)
4143 cmd[4] = 3; /* retension then mount */
4144 if (cmd_in == MTOFFL)
4145 cmd[4] = 4; /* rewind then eject */
4146 timeout = STp->timeout;
4147 #if DEBUG
4148 if (debugging) {
4149 switch (cmd_in) {
4150 case MTUNLOAD:
4151 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4152 break;
4153 case MTLOAD:
4154 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4155 break;
4156 case MTRETEN:
4157 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4158 break;
4159 case MTOFFL:
4160 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4161 break;
4164 #endif
4165 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4166 break;
4167 case MTNOP:
4168 #if DEBUG
4169 if (debugging)
4170 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4171 #endif
4172 return 0; /* Should do something ? */
4173 break;
4174 case MTEOM:
4175 #if DEBUG
4176 if (debugging)
4177 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4178 #endif
4179 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4180 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4181 ioctl_result = -EIO;
4182 goto os_bypass;
4184 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4185 #if DEBUG
4186 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4187 #endif
4188 ioctl_result = -EIO;
4189 goto os_bypass;
4191 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4192 fileno = STp->filemark_cnt;
4193 blkno = at_sm = 0;
4194 goto os_bypass;
4196 case MTERASE:
4197 if (STp->write_prot)
4198 return (-EACCES);
4199 ioctl_result = osst_reset_header(STp, &SRpnt);
4200 i = osst_write_eod(STp, &SRpnt);
4201 if (i < ioctl_result) ioctl_result = i;
4202 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4203 if (i < ioctl_result) ioctl_result = i;
4204 fileno = blkno = at_sm = 0 ;
4205 goto os_bypass;
4207 case MTREW:
4208 cmd[0] = REZERO_UNIT; /* rewind */
4209 cmd[1] = 1;
4210 #if DEBUG
4211 if (debugging)
4212 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4213 #endif
4214 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4215 break;
4217 case MTSETBLK: /* Set block length */
4218 if ((STps->drv_block == 0 ) &&
4219 !STp->dirty &&
4220 ((STp->buffer)->buffer_bytes == 0) &&
4221 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4222 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4223 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4225 * Only allowed to change the block size if you opened the
4226 * device at the beginning of a file before writing anything.
4227 * Note, that when reading, changing block_size is futile,
4228 * as the size used when writing overrides it.
4230 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4231 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4232 name, STp->block_size);
4233 return 0;
4235 case MTSETDENSITY: /* Set tape density */
4236 case MTSETDRVBUFFER: /* Set drive buffering */
4237 case SET_DENS_AND_BLK: /* Set density and block size */
4238 chg_eof = 0;
4239 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4240 return (-EIO); /* Not allowed if data in buffer */
4241 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4242 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4243 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4244 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4245 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4246 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4247 return (-EINVAL);
4249 return 0; /* FIXME silently ignore if block size didn't change */
4251 default:
4252 return (-ENOSYS);
4255 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4257 ioctl_result = (STp->buffer)->syscall_result;
4259 if (!SRpnt) {
4260 #if DEBUG
4261 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4262 #endif
4263 return ioctl_result;
4266 if (!ioctl_result) { /* SCSI command successful */
4267 STp->frame_seq_number = frame_seq_numbr;
4268 STp->logical_blk_num = logical_blk_num;
4271 os_bypass:
4272 #if DEBUG
4273 if (debugging)
4274 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4275 #endif
4277 if (!ioctl_result) { /* success */
4279 if (cmd_in == MTFSFM) {
4280 fileno--;
4281 blkno--;
4283 if (cmd_in == MTBSFM) {
4284 fileno++;
4285 blkno++;
4287 STps->drv_block = blkno;
4288 STps->drv_file = fileno;
4289 STps->at_sm = at_sm;
4291 if (cmd_in == MTEOM)
4292 STps->eof = ST_EOD;
4293 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4294 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4295 STps->drv_block++;
4296 STp->logical_blk_num++;
4297 STp->frame_seq_number++;
4298 STp->frame_in_buffer = 0;
4299 STp->buffer->read_pointer = 0;
4301 else if (cmd_in == MTFSF)
4302 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4303 else if (chg_eof)
4304 STps->eof = ST_NOEOF;
4306 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4307 STp->rew_at_close = 0;
4308 else if (cmd_in == MTLOAD) {
4309 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4310 STp->ps[i].rw = ST_IDLE;
4311 STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4313 STp->partition = 0;
4316 if (cmd_in == MTREW) {
4317 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4318 if (ioctl_result > 0)
4319 ioctl_result = 0;
4322 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4323 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4324 STps->drv_file = STps->drv_block = -1;
4325 else
4326 STps->drv_file = STps->drv_block = 0;
4327 STps->eof = ST_NOEOF;
4328 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4329 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4330 STps->drv_file = STps->drv_block = -1;
4331 else {
4332 STps->drv_file = STp->filemark_cnt;
4333 STps->drv_block = 0;
4335 STps->eof = ST_EOD;
4336 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4337 STps->drv_file = STps->drv_block = (-1);
4338 STps->eof = ST_NOEOF;
4339 STp->header_ok = 0;
4340 } else if (cmd_in == MTERASE) {
4341 STp->header_ok = 0;
4342 } else if (SRpnt) { /* SCSI command was not completely successful. */
4343 if (SRpnt->sense[2] & 0x40) {
4344 STps->eof = ST_EOM_OK;
4345 STps->drv_block = 0;
4347 if (chg_eof)
4348 STps->eof = ST_NOEOF;
4350 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4351 STps->eof = ST_EOD;
4353 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4354 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4356 *aSRpnt = SRpnt;
4358 return ioctl_result;
4362 /* Open the device */
4363 static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4365 unsigned short flags;
4366 int i, b_size, new_session = 0, retval = 0;
4367 unsigned char cmd[MAX_COMMAND_SIZE];
4368 struct osst_request * SRpnt = NULL;
4369 struct osst_tape * STp;
4370 struct st_modedef * STm;
4371 struct st_partstat * STps;
4372 char * name;
4373 int dev = TAPE_NR(inode);
4374 int mode = TAPE_MODE(inode);
4377 * We really want to do nonseekable_open(inode, filp); here, but some
4378 * versions of tar incorrectly call lseek on tapes and bail out if that
4379 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4381 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4383 write_lock(&os_scsi_tapes_lock);
4384 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4385 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4386 write_unlock(&os_scsi_tapes_lock);
4387 return (-ENXIO);
4390 name = tape_name(STp);
4392 if (STp->in_use) {
4393 write_unlock(&os_scsi_tapes_lock);
4394 #if DEBUG
4395 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4396 #endif
4397 return (-EBUSY);
4399 if (scsi_device_get(STp->device)) {
4400 write_unlock(&os_scsi_tapes_lock);
4401 #if DEBUG
4402 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4403 #endif
4404 return (-ENXIO);
4406 filp->private_data = STp;
4407 STp->in_use = 1;
4408 write_unlock(&os_scsi_tapes_lock);
4409 STp->rew_at_close = TAPE_REWIND(inode);
4411 if( !scsi_block_when_processing_errors(STp->device) ) {
4412 return -ENXIO;
4415 if (mode != STp->current_mode) {
4416 #if DEBUG
4417 if (debugging)
4418 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4419 name, STp->current_mode, mode);
4420 #endif
4421 new_session = 1;
4422 STp->current_mode = mode;
4424 STm = &(STp->modes[STp->current_mode]);
4426 flags = filp->f_flags;
4427 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4429 STp->raw = TAPE_IS_RAW(inode);
4430 if (STp->raw)
4431 STp->header_ok = 0;
4433 /* Allocate data segments for this device's tape buffer */
4434 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4435 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4436 retval = (-EOVERFLOW);
4437 goto err_out;
4439 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4440 for (i = 0, b_size = 0;
4441 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4442 b_size += STp->buffer->sg[i++].length);
4443 STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4444 #if DEBUG
4445 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4446 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4447 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4448 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4449 #endif
4450 } else {
4451 STp->buffer->aux = NULL; /* this had better never happen! */
4452 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4453 retval = (-EIO);
4454 goto err_out;
4456 STp->buffer->writing = 0;
4457 STp->buffer->syscall_result = 0;
4458 STp->dirty = 0;
4459 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4460 STps = &(STp->ps[i]);
4461 STps->rw = ST_IDLE;
4463 STp->ready = ST_READY;
4464 #if DEBUG
4465 STp->nbr_waits = STp->nbr_finished = 0;
4466 #endif
4468 memset (cmd, 0, MAX_COMMAND_SIZE);
4469 cmd[0] = TEST_UNIT_READY;
4471 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4472 if (!SRpnt) {
4473 retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
4474 goto err_out;
4476 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4477 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4478 SRpnt->sense[12] == 4 ) {
4479 #if DEBUG
4480 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4481 #endif
4482 if (filp->f_flags & O_NONBLOCK) {
4483 retval = -EAGAIN;
4484 goto err_out;
4486 if (SRpnt->sense[13] == 2) { /* initialize command required (LOAD) */
4487 memset (cmd, 0, MAX_COMMAND_SIZE);
4488 cmd[0] = START_STOP;
4489 cmd[1] = 1;
4490 cmd[4] = 1;
4491 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4492 STp->timeout, MAX_RETRIES, 1);
4494 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4496 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4497 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4498 #if DEBUG
4499 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4500 #endif
4501 STp->header_ok = 0;
4503 for (i=0; i < 10; i++) {
4505 memset (cmd, 0, MAX_COMMAND_SIZE);
4506 cmd[0] = TEST_UNIT_READY;
4508 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4509 STp->timeout, MAX_RETRIES, 1);
4510 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4511 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4512 break;
4515 STp->pos_unknown = 0;
4516 STp->partition = STp->new_partition = 0;
4517 if (STp->can_partitions)
4518 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4519 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4520 STps = &(STp->ps[i]);
4521 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4522 STps->eof = ST_NOEOF;
4523 STps->at_sm = 0;
4524 STps->last_block_valid = 0;
4525 STps->drv_block = 0;
4526 STps->drv_file = 0 ;
4528 new_session = 1;
4529 STp->recover_count = 0;
4530 STp->abort_count = 0;
4533 * if we have valid headers from before, and the drive/tape seem untouched,
4534 * open without reconfiguring and re-reading the headers
4536 if (!STp->buffer->syscall_result && STp->header_ok &&
4537 !SRpnt->result && SRpnt->sense[0] == 0) {
4539 memset(cmd, 0, MAX_COMMAND_SIZE);
4540 cmd[0] = MODE_SENSE;
4541 cmd[1] = 8;
4542 cmd[2] = VENDOR_IDENT_PAGE;
4543 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4545 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4547 if (STp->buffer->syscall_result ||
4548 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4549 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4550 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4551 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4552 #if DEBUG
4553 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4554 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4555 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4556 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4557 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4558 #endif
4559 STp->header_ok = 0;
4561 i = STp->first_frame_position;
4562 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4563 if (STp->door_locked == ST_UNLOCKED) {
4564 if (do_door_lock(STp, 1))
4565 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4566 else
4567 STp->door_locked = ST_LOCKED_AUTO;
4569 if (!STp->frame_in_buffer) {
4570 STp->block_size = (STm->default_blksize > 0) ?
4571 STm->default_blksize : OS_DATA_SIZE;
4572 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4574 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4575 STp->fast_open = 1;
4576 osst_release_request(SRpnt);
4577 return 0;
4579 #if DEBUG
4580 if (i != STp->first_frame_position)
4581 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4582 name, i, STp->first_frame_position);
4583 #endif
4584 STp->header_ok = 0;
4586 STp->fast_open = 0;
4588 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4589 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4591 memset(cmd, 0, MAX_COMMAND_SIZE);
4592 cmd[0] = MODE_SELECT;
4593 cmd[1] = 0x10;
4594 cmd[4] = 4 + MODE_HEADER_LENGTH;
4596 (STp->buffer)->b_data[0] = cmd[4] - 1;
4597 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4598 (STp->buffer)->b_data[2] = 0; /* Reserved */
4599 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4600 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4601 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4602 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4603 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4605 #if DEBUG
4606 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4607 #endif
4608 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4610 STp->header_ok = 0;
4612 for (i=0; i < 10; i++) {
4614 memset (cmd, 0, MAX_COMMAND_SIZE);
4615 cmd[0] = TEST_UNIT_READY;
4617 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4618 STp->timeout, MAX_RETRIES, 1);
4619 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4620 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4621 break;
4623 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4624 STp->pos_unknown = 0;
4625 STp->partition = STp->new_partition = 0;
4626 if (STp->can_partitions)
4627 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4628 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4629 STps = &(STp->ps[i]);
4630 STps->rw = ST_IDLE;
4631 STps->eof = ST_NOEOF;
4632 STps->at_sm = 0;
4633 STps->last_block_valid = 0;
4634 STps->drv_block = 0;
4635 STps->drv_file = 0 ;
4637 new_session = 1;
4642 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4643 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4645 if ((STp->buffer)->syscall_result != 0) {
4646 if ((STp->device)->scsi_level >= SCSI_2 &&
4647 (SRpnt->sense[0] & 0x70) == 0x70 &&
4648 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4649 SRpnt->sense[12] == 0x3a) { /* Check ASC */
4650 STp->ready = ST_NO_TAPE;
4651 } else
4652 STp->ready = ST_NOT_READY;
4653 osst_release_request(SRpnt);
4654 SRpnt = NULL;
4655 STp->density = 0; /* Clear the erroneous "residue" */
4656 STp->write_prot = 0;
4657 STp->block_size = 0;
4658 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4659 STp->partition = STp->new_partition = 0;
4660 STp->door_locked = ST_UNLOCKED;
4661 return 0;
4664 osst_configure_onstream(STp, &SRpnt);
4666 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4667 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4668 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4669 STp->buffer->buffer_bytes =
4670 STp->buffer->read_pointer =
4671 STp->frame_in_buffer = 0;
4673 #if DEBUG
4674 if (debugging)
4675 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4676 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4677 (STp->buffer)->buffer_blocks);
4678 #endif
4680 if (STp->drv_write_prot) {
4681 STp->write_prot = 1;
4682 #if DEBUG
4683 if (debugging)
4684 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4685 #endif
4686 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4687 retval = (-EROFS);
4688 goto err_out;
4692 if (new_session) { /* Change the drive parameters for the new mode */
4693 #if DEBUG
4694 if (debugging)
4695 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4696 #endif
4697 STp->density_changed = STp->blksize_changed = 0;
4698 STp->compression_changed = 0;
4702 * properly position the tape and check the ADR headers
4704 if (STp->door_locked == ST_UNLOCKED) {
4705 if (do_door_lock(STp, 1))
4706 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4707 else
4708 STp->door_locked = ST_LOCKED_AUTO;
4711 osst_analyze_headers(STp, &SRpnt);
4713 osst_release_request(SRpnt);
4714 SRpnt = NULL;
4716 return 0;
4718 err_out:
4719 if (SRpnt != NULL)
4720 osst_release_request(SRpnt);
4721 normalize_buffer(STp->buffer);
4722 STp->header_ok = 0;
4723 STp->in_use = 0;
4724 scsi_device_put(STp->device);
4726 return retval;
4729 /* BKL pushdown: spaghetti avoidance wrapper */
4730 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4732 int ret;
4734 lock_kernel();
4735 ret = __os_scsi_tape_open(inode, filp);
4736 unlock_kernel();
4737 return ret;
4742 /* Flush the tape buffer before close */
4743 static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4745 int result = 0, result2;
4746 struct osst_tape * STp = filp->private_data;
4747 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4748 struct st_partstat * STps = &(STp->ps[STp->partition]);
4749 struct osst_request * SRpnt = NULL;
4750 char * name = tape_name(STp);
4752 if (file_count(filp) > 1)
4753 return 0;
4755 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4756 STp->write_type = OS_WRITE_DATA;
4757 result = osst_flush_write_buffer(STp, &SRpnt);
4758 if (result != 0 && result != (-ENOSPC))
4759 goto out;
4761 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4763 #if DEBUG
4764 if (debugging) {
4765 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4766 name, (long)(filp->f_pos));
4767 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4768 name, STp->nbr_waits, STp->nbr_finished);
4770 #endif
4771 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4772 #if DEBUG
4773 if (debugging)
4774 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4775 name, 1+STp->two_fm);
4776 #endif
4778 else if (!STp->rew_at_close) {
4779 STps = &(STp->ps[STp->partition]);
4780 if (!STm->sysv || STps->rw != ST_READING) {
4781 if (STp->can_bsr)
4782 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4783 else if (STps->eof == ST_FM_HIT) {
4784 result = cross_eof(STp, &SRpnt, 0);
4785 if (result) {
4786 if (STps->drv_file >= 0)
4787 STps->drv_file++;
4788 STps->drv_block = 0;
4789 STps->eof = ST_FM;
4791 else
4792 STps->eof = ST_NOEOF;
4795 else if ((STps->eof == ST_NOEOF &&
4796 !(result = cross_eof(STp, &SRpnt, 1))) ||
4797 STps->eof == ST_FM_HIT) {
4798 if (STps->drv_file >= 0)
4799 STps->drv_file++;
4800 STps->drv_block = 0;
4801 STps->eof = ST_FM;
4805 out:
4806 if (STp->rew_at_close) {
4807 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4808 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4809 if (result == 0 && result2 < 0)
4810 result = result2;
4812 if (SRpnt) osst_release_request(SRpnt);
4814 if (STp->abort_count || STp->recover_count) {
4815 printk(KERN_INFO "%s:I:", name);
4816 if (STp->abort_count)
4817 printk(" %d unrecovered errors", STp->abort_count);
4818 if (STp->recover_count)
4819 printk(" %d recovered errors", STp->recover_count);
4820 if (STp->write_count)
4821 printk(" in %d frames written", STp->write_count);
4822 if (STp->read_count)
4823 printk(" in %d frames read", STp->read_count);
4824 printk("\n");
4825 STp->recover_count = 0;
4826 STp->abort_count = 0;
4828 STp->write_count = 0;
4829 STp->read_count = 0;
4831 return result;
4835 /* Close the device and release it */
4836 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4838 int result = 0;
4839 struct osst_tape * STp = filp->private_data;
4841 if (STp->door_locked == ST_LOCKED_AUTO)
4842 do_door_lock(STp, 0);
4844 if (STp->raw)
4845 STp->header_ok = 0;
4847 normalize_buffer(STp->buffer);
4848 write_lock(&os_scsi_tapes_lock);
4849 STp->in_use = 0;
4850 write_unlock(&os_scsi_tapes_lock);
4852 scsi_device_put(STp->device);
4854 return result;
4858 /* The ioctl command */
4859 static int osst_ioctl(struct inode * inode,struct file * file,
4860 unsigned int cmd_in, unsigned long arg)
4862 int i, cmd_nr, cmd_type, blk, retval = 0;
4863 struct st_modedef * STm;
4864 struct st_partstat * STps;
4865 struct osst_request * SRpnt = NULL;
4866 struct osst_tape * STp = file->private_data;
4867 char * name = tape_name(STp);
4868 void __user * p = (void __user *)arg;
4870 if (mutex_lock_interruptible(&STp->lock))
4871 return -ERESTARTSYS;
4873 #if DEBUG
4874 if (debugging && !STp->in_use) {
4875 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4876 retval = (-EIO);
4877 goto out;
4879 #endif
4880 STm = &(STp->modes[STp->current_mode]);
4881 STps = &(STp->ps[STp->partition]);
4884 * If we are in the middle of error recovery, don't let anyone
4885 * else try and use this device. Also, if error recovery fails, it
4886 * may try and take the device offline, in which case all further
4887 * access to the device is prohibited.
4889 if( !scsi_block_when_processing_errors(STp->device) ) {
4890 retval = (-ENXIO);
4891 goto out;
4894 cmd_type = _IOC_TYPE(cmd_in);
4895 cmd_nr = _IOC_NR(cmd_in);
4896 #if DEBUG
4897 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4898 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4899 #endif
4900 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4901 struct mtop mtc;
4902 int auto_weof = 0;
4904 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4905 retval = (-EINVAL);
4906 goto out;
4909 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4910 if (i) {
4911 retval = (-EFAULT);
4912 goto out;
4915 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4916 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4917 retval = (-EPERM);
4918 goto out;
4921 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4922 retval = (-ENXIO);
4923 goto out;
4926 if (!STp->pos_unknown) {
4928 if (STps->eof == ST_FM_HIT) {
4929 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4930 mtc.mt_count -= 1;
4931 if (STps->drv_file >= 0)
4932 STps->drv_file += 1;
4934 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4935 mtc.mt_count += 1;
4936 if (STps->drv_file >= 0)
4937 STps->drv_file += 1;
4941 if (mtc.mt_op == MTSEEK) {
4942 /* Old position must be restored if partition will be changed */
4943 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4945 else {
4946 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
4947 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
4948 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
4949 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
4950 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
4951 mtc.mt_op == MTCOMPRESSION;
4953 i = osst_flush_buffer(STp, &SRpnt, i);
4954 if (i < 0) {
4955 retval = i;
4956 goto out;
4959 else {
4961 * If there was a bus reset, block further access
4962 * to this device. If the user wants to rewind the tape,
4963 * then reset the flag and allow access again.
4965 if(mtc.mt_op != MTREW &&
4966 mtc.mt_op != MTOFFL &&
4967 mtc.mt_op != MTRETEN &&
4968 mtc.mt_op != MTERASE &&
4969 mtc.mt_op != MTSEEK &&
4970 mtc.mt_op != MTEOM) {
4971 retval = (-EIO);
4972 goto out;
4974 reset_state(STp);
4975 /* remove this when the midlevel properly clears was_reset */
4976 STp->device->was_reset = 0;
4979 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
4980 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
4981 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
4982 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
4983 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
4986 * The user tells us to move to another position on the tape.
4987 * If we were appending to the tape content, that would leave
4988 * the tape without proper end, in that case write EOD and
4989 * update the header to reflect its position.
4991 #if DEBUG
4992 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
4993 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
4994 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
4995 STp->logical_blk_num, STps->drv_file, STps->drv_block );
4996 #endif
4997 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
4998 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
4999 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5000 i = osst_write_trailer(STp, &SRpnt,
5001 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5002 #if DEBUG
5003 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5004 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5005 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5006 #endif
5007 if (i < 0) {
5008 retval = i;
5009 goto out;
5012 STps->rw = ST_IDLE;
5015 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5016 do_door_lock(STp, 0); /* Ignore result! */
5018 if (mtc.mt_op == MTSETDRVBUFFER &&
5019 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5020 retval = osst_set_options(STp, mtc.mt_count);
5021 goto out;
5024 if (mtc.mt_op == MTSETPART) {
5025 if (mtc.mt_count >= STp->nbr_partitions)
5026 retval = -EINVAL;
5027 else {
5028 STp->new_partition = mtc.mt_count;
5029 retval = 0;
5031 goto out;
5034 if (mtc.mt_op == MTMKPART) {
5035 if (!STp->can_partitions) {
5036 retval = (-EINVAL);
5037 goto out;
5039 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5040 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5041 retval = i;
5042 goto out;
5044 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5045 STp->ps[i].rw = ST_IDLE;
5046 STp->ps[i].at_sm = 0;
5047 STp->ps[i].last_block_valid = 0;
5049 STp->partition = STp->new_partition = 0;
5050 STp->nbr_partitions = 1; /* Bad guess ?-) */
5051 STps->drv_block = STps->drv_file = 0;
5052 retval = 0;
5053 goto out;
5056 if (mtc.mt_op == MTSEEK) {
5057 if (STp->raw)
5058 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5059 else
5060 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5061 if (!STp->can_partitions)
5062 STp->ps[0].rw = ST_IDLE;
5063 retval = i;
5064 goto out;
5067 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5068 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5069 goto out;
5072 if (auto_weof)
5073 cross_eof(STp, &SRpnt, 0);
5075 if (mtc.mt_op == MTCOMPRESSION)
5076 retval = -EINVAL; /* OnStream drives don't have compression hardware */
5077 else
5078 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5079 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5080 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5081 goto out;
5084 if (!STm->defined) {
5085 retval = (-ENXIO);
5086 goto out;
5089 if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5090 retval = i;
5091 goto out;
5094 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5095 struct mtget mt_status;
5097 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5098 retval = (-EINVAL);
5099 goto out;
5102 mt_status.mt_type = MT_ISONSTREAM_SC;
5103 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5104 mt_status.mt_dsreg =
5105 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5106 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5107 mt_status.mt_blkno = STps->drv_block;
5108 mt_status.mt_fileno = STps->drv_file;
5109 if (STp->block_size != 0) {
5110 if (STps->rw == ST_WRITING)
5111 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5112 else if (STps->rw == ST_READING)
5113 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5114 STp->block_size - 1) / STp->block_size;
5117 mt_status.mt_gstat = 0;
5118 if (STp->drv_write_prot)
5119 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5120 if (mt_status.mt_blkno == 0) {
5121 if (mt_status.mt_fileno == 0)
5122 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5123 else
5124 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5126 mt_status.mt_resid = STp->partition;
5127 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5128 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5129 else if (STps->eof >= ST_EOM_OK)
5130 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5131 if (STp->density == 1)
5132 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5133 else if (STp->density == 2)
5134 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5135 else if (STp->density == 3)
5136 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5137 if (STp->ready == ST_READY)
5138 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5139 if (STp->ready == ST_NO_TAPE)
5140 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5141 if (STps->at_sm)
5142 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5143 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5144 STp->drv_buffer != 0)
5145 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5147 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5148 if (i) {
5149 retval = (-EFAULT);
5150 goto out;
5153 STp->recover_erreg = 0; /* Clear after read */
5154 retval = 0;
5155 goto out;
5156 } /* End of MTIOCGET */
5158 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5159 struct mtpos mt_pos;
5161 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5162 retval = (-EINVAL);
5163 goto out;
5165 if (STp->raw)
5166 blk = osst_get_frame_position(STp, &SRpnt);
5167 else
5168 blk = osst_get_sector(STp, &SRpnt);
5169 if (blk < 0) {
5170 retval = blk;
5171 goto out;
5173 mt_pos.mt_blkno = blk;
5174 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5175 if (i)
5176 retval = -EFAULT;
5177 goto out;
5179 if (SRpnt) osst_release_request(SRpnt);
5181 mutex_unlock(&STp->lock);
5183 return scsi_ioctl(STp->device, cmd_in, p);
5185 out:
5186 if (SRpnt) osst_release_request(SRpnt);
5188 mutex_unlock(&STp->lock);
5190 return retval;
5193 #ifdef CONFIG_COMPAT
5194 static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5196 struct osst_tape *STp = file->private_data;
5197 struct scsi_device *sdev = STp->device;
5198 int ret = -ENOIOCTLCMD;
5199 if (sdev->host->hostt->compat_ioctl) {
5201 ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5204 return ret;
5206 #endif
5210 /* Memory handling routines */
5212 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5213 static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5215 int i;
5216 gfp_t priority;
5217 struct osst_buffer *tb;
5219 if (from_initialization)
5220 priority = GFP_ATOMIC;
5221 else
5222 priority = GFP_KERNEL;
5224 i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5225 tb = kzalloc(i, priority);
5226 if (!tb) {
5227 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5228 return NULL;
5231 tb->sg_segs = tb->orig_sg_segs = 0;
5232 tb->use_sg = max_sg;
5233 tb->in_use = 1;
5234 tb->dma = need_dma;
5235 tb->buffer_size = 0;
5236 #if DEBUG
5237 if (debugging)
5238 printk(OSST_DEB_MSG
5239 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5240 i, max_sg, need_dma);
5241 #endif
5242 return tb;
5245 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5246 static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5248 int segs, nbr, max_segs, b_size, order, got;
5249 gfp_t priority;
5251 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5252 return 1;
5254 if (STbuffer->sg_segs) {
5255 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5256 normalize_buffer(STbuffer);
5258 /* See how many segments we can use -- need at least two */
5259 nbr = max_segs = STbuffer->use_sg;
5260 if (nbr <= 2)
5261 return 0;
5263 priority = GFP_KERNEL /* | __GFP_NOWARN */;
5264 if (need_dma)
5265 priority |= GFP_DMA;
5267 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5268 big enough to reach the goal (code assumes no segments in place) */
5269 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5270 struct page *page = alloc_pages(priority, order);
5272 STbuffer->sg[0].offset = 0;
5273 if (page != NULL) {
5274 sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5275 STbuffer->b_data = page_address(page);
5276 break;
5279 if (sg_page(&STbuffer->sg[0]) == NULL) {
5280 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5281 return 0;
5283 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5284 for (segs=STbuffer->sg_segs=1, got=b_size;
5285 segs < max_segs && got < OS_FRAME_SIZE; ) {
5286 struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5287 STbuffer->sg[segs].offset = 0;
5288 if (page == NULL) {
5289 if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
5290 b_size /= 2; /* Large enough for the rest of the buffers */
5291 order--;
5292 continue;
5294 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5295 OS_FRAME_SIZE);
5296 #if DEBUG
5297 STbuffer->buffer_size = got;
5298 #endif
5299 normalize_buffer(STbuffer);
5300 return 0;
5302 sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5303 got += STbuffer->sg[segs].length;
5304 STbuffer->buffer_size = got;
5305 STbuffer->sg_segs = ++segs;
5307 #if DEBUG
5308 if (debugging) {
5309 printk(OSST_DEB_MSG
5310 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5311 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5312 printk(OSST_DEB_MSG
5313 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5314 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5315 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5317 #endif
5319 return 1;
5323 /* Release the segments */
5324 static void normalize_buffer(struct osst_buffer *STbuffer)
5326 int i, order, b_size;
5328 for (i=0; i < STbuffer->sg_segs; i++) {
5330 for (b_size = PAGE_SIZE, order = 0;
5331 b_size < STbuffer->sg[i].length;
5332 b_size *= 2, order++);
5334 __free_pages(sg_page(&STbuffer->sg[i]), order);
5335 STbuffer->buffer_size -= STbuffer->sg[i].length;
5337 #if DEBUG
5338 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5339 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5340 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5341 #endif
5342 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5346 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5347 negative error code. */
5348 static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5350 int i, cnt, res, offset;
5352 for (i=0, offset=st_bp->buffer_bytes;
5353 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5354 offset -= st_bp->sg[i].length;
5355 if (i == st_bp->sg_segs) { /* Should never happen */
5356 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5357 return (-EIO);
5359 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5360 cnt = st_bp->sg[i].length - offset < do_count ?
5361 st_bp->sg[i].length - offset : do_count;
5362 res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5363 if (res)
5364 return (-EFAULT);
5365 do_count -= cnt;
5366 st_bp->buffer_bytes += cnt;
5367 ubp += cnt;
5368 offset = 0;
5370 if (do_count) { /* Should never happen */
5371 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5372 do_count);
5373 return (-EIO);
5375 return 0;
5379 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5380 negative error code. */
5381 static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5383 int i, cnt, res, offset;
5385 for (i=0, offset=st_bp->read_pointer;
5386 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5387 offset -= st_bp->sg[i].length;
5388 if (i == st_bp->sg_segs) { /* Should never happen */
5389 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5390 return (-EIO);
5392 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5393 cnt = st_bp->sg[i].length - offset < do_count ?
5394 st_bp->sg[i].length - offset : do_count;
5395 res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5396 if (res)
5397 return (-EFAULT);
5398 do_count -= cnt;
5399 st_bp->buffer_bytes -= cnt;
5400 st_bp->read_pointer += cnt;
5401 ubp += cnt;
5402 offset = 0;
5404 if (do_count) { /* Should never happen */
5405 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5406 return (-EIO);
5408 return 0;
5411 /* Sets the tail of the buffer after fill point to zero.
5412 Returns zero (success) or negative error code. */
5413 static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5415 int i, offset, do_count, cnt;
5417 for (i = 0, offset = st_bp->buffer_bytes;
5418 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5419 offset -= st_bp->sg[i].length;
5420 if (i == st_bp->sg_segs) { /* Should never happen */
5421 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5422 return (-EIO);
5424 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5425 i < st_bp->sg_segs && do_count > 0; i++) {
5426 cnt = st_bp->sg[i].length - offset < do_count ?
5427 st_bp->sg[i].length - offset : do_count ;
5428 memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5429 do_count -= cnt;
5430 offset = 0;
5432 if (do_count) { /* Should never happen */
5433 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5434 return (-EIO);
5436 return 0;
5439 /* Copy a osst 32K chunk of memory into the buffer.
5440 Returns zero (success) or negative error code. */
5441 static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5443 int i, cnt, do_count = OS_DATA_SIZE;
5445 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5446 cnt = st_bp->sg[i].length < do_count ?
5447 st_bp->sg[i].length : do_count ;
5448 memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5449 do_count -= cnt;
5450 ptr += cnt;
5452 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5453 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5454 do_count, i);
5455 return (-EIO);
5457 return 0;
5460 /* Copy a osst 32K chunk of memory from the buffer.
5461 Returns zero (success) or negative error code. */
5462 static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5464 int i, cnt, do_count = OS_DATA_SIZE;
5466 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5467 cnt = st_bp->sg[i].length < do_count ?
5468 st_bp->sg[i].length : do_count ;
5469 memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5470 do_count -= cnt;
5471 ptr += cnt;
5473 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5474 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5475 do_count, i);
5476 return (-EIO);
5478 return 0;
5482 /* Module housekeeping */
5484 static void validate_options (void)
5486 if (max_dev > 0)
5487 osst_max_dev = max_dev;
5488 if (write_threshold_kbs > 0)
5489 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5490 if (osst_write_threshold > osst_buffer_size)
5491 osst_write_threshold = osst_buffer_size;
5492 if (max_sg_segs >= OSST_FIRST_SG)
5493 osst_max_sg_segs = max_sg_segs;
5494 #if DEBUG
5495 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5496 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5497 #endif
5500 #ifndef MODULE
5501 /* Set the boot options. Syntax: osst=xxx,yyy,...
5502 where xxx is write threshold in 1024 byte blocks,
5503 and yyy is number of s/g segments to use. */
5504 static int __init osst_setup (char *str)
5506 int i, ints[5];
5507 char *stp;
5509 stp = get_options(str, ARRAY_SIZE(ints), ints);
5511 if (ints[0] > 0) {
5512 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5513 *parms[i].val = ints[i + 1];
5514 } else {
5515 while (stp != NULL) {
5516 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5517 int len = strlen(parms[i].name);
5518 if (!strncmp(stp, parms[i].name, len) &&
5519 (*(stp + len) == ':' || *(stp + len) == '=')) {
5520 *parms[i].val =
5521 simple_strtoul(stp + len + 1, NULL, 0);
5522 break;
5525 if (i >= ARRAY_SIZE(parms))
5526 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5527 stp);
5528 stp = strchr(stp, ',');
5529 if (stp)
5530 stp++;
5534 return 1;
5537 __setup("osst=", osst_setup);
5539 #endif
5541 static const struct file_operations osst_fops = {
5542 .owner = THIS_MODULE,
5543 .read = osst_read,
5544 .write = osst_write,
5545 .ioctl = osst_ioctl,
5546 #ifdef CONFIG_COMPAT
5547 .compat_ioctl = osst_compat_ioctl,
5548 #endif
5549 .open = os_scsi_tape_open,
5550 .flush = os_scsi_tape_flush,
5551 .release = os_scsi_tape_close,
5554 static int osst_supports(struct scsi_device * SDp)
5556 struct osst_support_data {
5557 char *vendor;
5558 char *model;
5559 char *rev;
5560 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5563 static struct osst_support_data support_list[] = {
5564 /* {"XXX", "Yy-", "", NULL}, example */
5565 SIGS_FROM_OSST,
5566 {NULL, }};
5568 struct osst_support_data *rp;
5570 /* We are willing to drive OnStream SC-x0 as well as the
5571 * * IDE, ParPort, FireWire, USB variants, if accessible by
5572 * * emulation layer (ide-scsi, usb-storage, ...) */
5574 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5575 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5576 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5577 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5578 return 1;
5579 return 0;
5583 * sysfs support for osst driver parameter information
5586 static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5588 return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5591 static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5593 static int osst_create_sysfs_files(struct device_driver *sysfs)
5595 return driver_create_file(sysfs, &driver_attr_version);
5598 static void osst_remove_sysfs_files(struct device_driver *sysfs)
5600 driver_remove_file(sysfs, &driver_attr_version);
5604 * sysfs support for accessing ADR header information
5607 static ssize_t osst_adr_rev_show(struct device *dev,
5608 struct device_attribute *attr, char *buf)
5610 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5611 ssize_t l = 0;
5613 if (STp && STp->header_ok && STp->linux_media)
5614 l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5615 return l;
5618 DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5620 static ssize_t osst_linux_media_version_show(struct device *dev,
5621 struct device_attribute *attr,
5622 char *buf)
5624 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5625 ssize_t l = 0;
5627 if (STp && STp->header_ok && STp->linux_media)
5628 l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5629 return l;
5632 DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5634 static ssize_t osst_capacity_show(struct device *dev,
5635 struct device_attribute *attr, char *buf)
5637 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5638 ssize_t l = 0;
5640 if (STp && STp->header_ok && STp->linux_media)
5641 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5642 return l;
5645 DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5647 static ssize_t osst_first_data_ppos_show(struct device *dev,
5648 struct device_attribute *attr,
5649 char *buf)
5651 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5652 ssize_t l = 0;
5654 if (STp && STp->header_ok && STp->linux_media)
5655 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5656 return l;
5659 DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5661 static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5662 struct device_attribute *attr,
5663 char *buf)
5665 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5666 ssize_t l = 0;
5668 if (STp && STp->header_ok && STp->linux_media)
5669 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5670 return l;
5673 DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5675 static ssize_t osst_filemark_cnt_show(struct device *dev,
5676 struct device_attribute *attr, char *buf)
5678 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5679 ssize_t l = 0;
5681 if (STp && STp->header_ok && STp->linux_media)
5682 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5683 return l;
5686 DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5688 static struct class *osst_sysfs_class;
5690 static int osst_sysfs_init(void)
5692 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5693 if (IS_ERR(osst_sysfs_class)) {
5694 printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5695 return PTR_ERR(osst_sysfs_class);
5698 return 0;
5701 static void osst_sysfs_destroy(dev_t dev)
5703 device_destroy(osst_sysfs_class, dev);
5706 static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5708 struct device *osst_member;
5709 int err;
5711 osst_member = device_create(osst_sysfs_class, device, dev, STp,
5712 "%s", name);
5713 if (IS_ERR(osst_member)) {
5714 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5715 return PTR_ERR(osst_member);
5718 err = device_create_file(osst_member, &dev_attr_ADR_rev);
5719 if (err)
5720 goto err_out;
5721 err = device_create_file(osst_member, &dev_attr_media_version);
5722 if (err)
5723 goto err_out;
5724 err = device_create_file(osst_member, &dev_attr_capacity);
5725 if (err)
5726 goto err_out;
5727 err = device_create_file(osst_member, &dev_attr_BOT_frame);
5728 if (err)
5729 goto err_out;
5730 err = device_create_file(osst_member, &dev_attr_EOD_frame);
5731 if (err)
5732 goto err_out;
5733 err = device_create_file(osst_member, &dev_attr_file_count);
5734 if (err)
5735 goto err_out;
5737 return 0;
5739 err_out:
5740 osst_sysfs_destroy(dev);
5741 return err;
5744 static void osst_sysfs_cleanup(void)
5746 class_destroy(osst_sysfs_class);
5750 * osst startup / cleanup code
5753 static int osst_probe(struct device *dev)
5755 struct scsi_device * SDp = to_scsi_device(dev);
5756 struct osst_tape * tpnt;
5757 struct st_modedef * STm;
5758 struct st_partstat * STps;
5759 struct osst_buffer * buffer;
5760 struct gendisk * drive;
5761 int i, dev_num, err = -ENODEV;
5763 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5764 return -ENODEV;
5766 drive = alloc_disk(1);
5767 if (!drive) {
5768 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5769 return -ENODEV;
5772 /* if this is the first attach, build the infrastructure */
5773 write_lock(&os_scsi_tapes_lock);
5774 if (os_scsi_tapes == NULL) {
5775 os_scsi_tapes =
5776 (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
5777 GFP_ATOMIC);
5778 if (os_scsi_tapes == NULL) {
5779 write_unlock(&os_scsi_tapes_lock);
5780 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5781 goto out_put_disk;
5783 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5786 if (osst_nr_dev >= osst_max_dev) {
5787 write_unlock(&os_scsi_tapes_lock);
5788 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5789 goto out_put_disk;
5792 /* find a free minor number */
5793 for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++);
5794 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5795 dev_num = i;
5797 /* allocate a struct osst_tape for this device */
5798 tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5799 if (!tpnt) {
5800 write_unlock(&os_scsi_tapes_lock);
5801 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5802 goto out_put_disk;
5805 /* allocate a buffer for this device */
5806 i = SDp->host->sg_tablesize;
5807 if (osst_max_sg_segs < i)
5808 i = osst_max_sg_segs;
5809 buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5810 if (buffer == NULL) {
5811 write_unlock(&os_scsi_tapes_lock);
5812 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5813 kfree(tpnt);
5814 goto out_put_disk;
5816 os_scsi_tapes[dev_num] = tpnt;
5817 tpnt->buffer = buffer;
5818 tpnt->device = SDp;
5819 drive->private_data = &tpnt->driver;
5820 sprintf(drive->disk_name, "osst%d", dev_num);
5821 tpnt->driver = &osst_template;
5822 tpnt->drive = drive;
5823 tpnt->in_use = 0;
5824 tpnt->capacity = 0xfffff;
5825 tpnt->dirty = 0;
5826 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
5827 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5828 tpnt->density = 0;
5829 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5830 tpnt->can_bsr = OSST_IN_FILE_POS;
5831 tpnt->can_partitions = 0;
5832 tpnt->two_fm = OSST_TWO_FM;
5833 tpnt->fast_mteom = OSST_FAST_MTEOM;
5834 tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5835 tpnt->write_threshold = osst_write_threshold;
5836 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5837 tpnt->partition = 0;
5838 tpnt->new_partition = 0;
5839 tpnt->nbr_partitions = 0;
5840 tpnt->min_block = 512;
5841 tpnt->max_block = OS_DATA_SIZE;
5842 tpnt->timeout = OSST_TIMEOUT;
5843 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5845 /* Recognize OnStream tapes */
5846 /* We don't need to test for OnStream, as this has been done in detect () */
5847 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5848 tpnt->omit_blklims = 1;
5850 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5851 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5852 tpnt->frame_in_buffer = 0;
5853 tpnt->header_ok = 0;
5854 tpnt->linux_media = 0;
5855 tpnt->header_cache = NULL;
5857 for (i=0; i < ST_NBR_MODES; i++) {
5858 STm = &(tpnt->modes[i]);
5859 STm->defined = 0;
5860 STm->sysv = OSST_SYSV;
5861 STm->defaults_for_writes = 0;
5862 STm->do_async_writes = OSST_ASYNC_WRITES;
5863 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5864 STm->do_read_ahead = OSST_READ_AHEAD;
5865 STm->default_compression = ST_DONT_TOUCH;
5866 STm->default_blksize = 512;
5867 STm->default_density = (-1); /* No forced density */
5870 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5871 STps = &(tpnt->ps[i]);
5872 STps->rw = ST_IDLE;
5873 STps->eof = ST_NOEOF;
5874 STps->at_sm = 0;
5875 STps->last_block_valid = 0;
5876 STps->drv_block = (-1);
5877 STps->drv_file = (-1);
5880 tpnt->current_mode = 0;
5881 tpnt->modes[0].defined = 1;
5882 tpnt->modes[2].defined = 1;
5883 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5885 mutex_init(&tpnt->lock);
5886 osst_nr_dev++;
5887 write_unlock(&os_scsi_tapes_lock);
5890 char name[8];
5892 /* Rewind entry */
5893 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5894 if (err)
5895 goto out_free_buffer;
5897 /* No-rewind entry */
5898 snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5899 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5900 if (err)
5901 goto out_free_sysfs1;
5904 sdev_printk(KERN_INFO, SDp,
5905 "osst :I: Attached OnStream %.5s tape as %s\n",
5906 SDp->model, tape_name(tpnt));
5908 return 0;
5910 out_free_sysfs1:
5911 osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5912 out_free_buffer:
5913 kfree(buffer);
5914 out_put_disk:
5915 put_disk(drive);
5916 return err;
5919 static int osst_remove(struct device *dev)
5921 struct scsi_device * SDp = to_scsi_device(dev);
5922 struct osst_tape * tpnt;
5923 int i;
5925 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
5926 return 0;
5928 write_lock(&os_scsi_tapes_lock);
5929 for(i=0; i < osst_max_dev; i++) {
5930 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
5931 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
5932 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
5933 tpnt->device = NULL;
5934 put_disk(tpnt->drive);
5935 os_scsi_tapes[i] = NULL;
5936 osst_nr_dev--;
5937 write_unlock(&os_scsi_tapes_lock);
5938 vfree(tpnt->header_cache);
5939 if (tpnt->buffer) {
5940 normalize_buffer(tpnt->buffer);
5941 kfree(tpnt->buffer);
5943 kfree(tpnt);
5944 return 0;
5947 write_unlock(&os_scsi_tapes_lock);
5948 return 0;
5951 static int __init init_osst(void)
5953 int err;
5955 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5957 validate_options();
5959 err = osst_sysfs_init();
5960 if (err)
5961 return err;
5963 err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
5964 if (err < 0) {
5965 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
5966 goto err_out;
5969 err = scsi_register_driver(&osst_template.gendrv);
5970 if (err)
5971 goto err_out_chrdev;
5973 err = osst_create_sysfs_files(&osst_template.gendrv);
5974 if (err)
5975 goto err_out_scsidrv;
5977 return 0;
5979 err_out_scsidrv:
5980 scsi_unregister_driver(&osst_template.gendrv);
5981 err_out_chrdev:
5982 unregister_chrdev(OSST_MAJOR, "osst");
5983 err_out:
5984 osst_sysfs_cleanup();
5985 return err;
5988 static void __exit exit_osst (void)
5990 int i;
5991 struct osst_tape * STp;
5993 osst_remove_sysfs_files(&osst_template.gendrv);
5994 scsi_unregister_driver(&osst_template.gendrv);
5995 unregister_chrdev(OSST_MAJOR, "osst");
5996 osst_sysfs_cleanup();
5998 if (os_scsi_tapes) {
5999 for (i=0; i < osst_max_dev; ++i) {
6000 if (!(STp = os_scsi_tapes[i])) continue;
6001 /* This is defensive, supposed to happen during detach */
6002 vfree(STp->header_cache);
6003 if (STp->buffer) {
6004 normalize_buffer(STp->buffer);
6005 kfree(STp->buffer);
6007 put_disk(STp->drive);
6008 kfree(STp);
6010 kfree(os_scsi_tapes);
6012 printk(KERN_INFO "osst :I: Unloaded.\n");
6015 module_init(init_osst);
6016 module_exit(exit_osst);