[PATCH] drivers/video: Use ARRAY_SIZE macro
[linux-2.6/openmoko-kernel/knife-kernel.git] / drivers / scsi / osst.c
blob66ea47a9c53c74774e95f584f484761e0e2ff3f7
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 <asm/uaccess.h>
53 #include <asm/dma.h>
54 #include <asm/system.h>
56 /* The driver prints some debugging information on the console if DEBUG
57 is defined and non-zero. */
58 #define DEBUG 0
60 /* The message level for the debug messages is currently set to KERN_NOTICE
61 so that people can easily see the messages. Later when the debugging messages
62 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
63 #define OSST_DEB_MSG KERN_NOTICE
65 #include <scsi/scsi.h>
66 #include <scsi/scsi_dbg.h>
67 #include <scsi/scsi_device.h>
68 #include <scsi/scsi_driver.h>
69 #include <scsi/scsi_eh.h>
70 #include <scsi/scsi_host.h>
71 #include <scsi/scsi_ioctl.h>
73 #define ST_KILOBYTE 1024
75 #include "st.h"
76 #include "osst.h"
77 #include "osst_options.h"
78 #include "osst_detect.h"
80 static int max_dev = 0;
81 static int write_threshold_kbs = 0;
82 static int max_sg_segs = 0;
84 #ifdef MODULE
85 MODULE_AUTHOR("Willem Riede");
86 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
87 MODULE_LICENSE("GPL");
88 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
90 module_param(max_dev, int, 0444);
91 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
93 module_param(write_threshold_kbs, int, 0644);
94 MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
96 module_param(max_sg_segs, int, 0644);
97 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
98 #else
99 static struct osst_dev_parm {
100 char *name;
101 int *val;
102 } parms[] __initdata = {
103 { "max_dev", &max_dev },
104 { "write_threshold_kbs", &write_threshold_kbs },
105 { "max_sg_segs", &max_sg_segs }
107 #endif
109 /* Some default definitions have been moved to osst_options.h */
110 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
111 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
113 /* The buffer size should fit into the 24 bits for length in the
114 6-byte SCSI read and write commands. */
115 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
116 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
117 #endif
119 #if DEBUG
120 static int debugging = 1;
121 /* uncomment define below to test error recovery */
122 // #define OSST_INJECT_ERRORS 1
123 #endif
125 /* Do not retry! The drive firmware already retries when appropriate,
126 and when it tries to tell us something, we had better listen... */
127 #define MAX_RETRIES 0
129 #define NO_TAPE NOT_READY
131 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
132 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
133 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
135 #define OSST_TIMEOUT (200 * HZ)
136 #define OSST_LONG_TIMEOUT (1800 * HZ)
138 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
139 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
140 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
141 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
143 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
144 24 bits) */
145 #define SET_DENS_AND_BLK 0x10001
147 static int osst_buffer_size = OSST_BUFFER_SIZE;
148 static int osst_write_threshold = OSST_WRITE_THRESHOLD;
149 static int osst_max_sg_segs = OSST_MAX_SG;
150 static int osst_max_dev = OSST_MAX_TAPES;
151 static int osst_nr_dev;
153 static struct osst_tape **os_scsi_tapes = NULL;
154 static DEFINE_RWLOCK(os_scsi_tapes_lock);
156 static int modes_defined = 0;
158 static struct osst_buffer *new_tape_buffer(int, int, int);
159 static int enlarge_buffer(struct osst_buffer *, int);
160 static void normalize_buffer(struct osst_buffer *);
161 static int append_to_buffer(const char __user *, struct osst_buffer *, int);
162 static int from_buffer(struct osst_buffer *, char __user *, int);
163 static int osst_zero_buffer_tail(struct osst_buffer *);
164 static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
165 static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
167 static int osst_probe(struct device *);
168 static int osst_remove(struct device *);
170 static struct scsi_driver osst_template = {
171 .owner = THIS_MODULE,
172 .gendrv = {
173 .name = "osst",
174 .probe = osst_probe,
175 .remove = osst_remove,
179 static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
180 unsigned int cmd_in, unsigned long arg);
182 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
184 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
186 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
188 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
190 static inline char *tape_name(struct osst_tape *tape)
192 return tape->drive->disk_name;
195 /* Routines that handle the interaction with mid-layer SCSI routines */
198 /* Normalize Sense */
199 static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
201 const u8 *ucp;
202 const u8 *sense = SRpnt->sense;
204 s->have_sense = scsi_normalize_sense(SRpnt->sense,
205 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
206 s->flags = 0;
208 if (s->have_sense) {
209 s->deferred = 0;
210 s->remainder_valid =
211 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
212 switch (sense[0] & 0x7f) {
213 case 0x71:
214 s->deferred = 1;
215 case 0x70:
216 s->fixed_format = 1;
217 s->flags = sense[2] & 0xe0;
218 break;
219 case 0x73:
220 s->deferred = 1;
221 case 0x72:
222 s->fixed_format = 0;
223 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
224 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
225 break;
230 /* Convert the result to success code */
231 static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
233 char *name = tape_name(STp);
234 int result = SRpnt->result;
235 u8 * sense = SRpnt->sense, scode;
236 #if DEBUG
237 const char *stp;
238 #endif
239 struct st_cmdstatus *cmdstatp;
241 if (!result)
242 return 0;
244 cmdstatp = &STp->buffer->cmdstat;
245 osst_analyze_sense(SRpnt, cmdstatp);
247 if (cmdstatp->have_sense)
248 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
249 else
250 scode = 0;
251 #if DEBUG
252 if (debugging) {
253 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
254 name, result,
255 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
256 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
257 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
258 name, scode, sense[12], sense[13]);
259 if (cmdstatp->have_sense)
260 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
262 else
263 #endif
264 if (cmdstatp->have_sense && (
265 scode != NO_SENSE &&
266 scode != RECOVERED_ERROR &&
267 /* scode != UNIT_ATTENTION && */
268 scode != BLANK_CHECK &&
269 scode != VOLUME_OVERFLOW &&
270 SRpnt->cmd[0] != MODE_SENSE &&
271 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
272 if (cmdstatp->have_sense) {
273 printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
274 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
276 else {
277 static int notyetprinted = 1;
279 printk(KERN_WARNING
280 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
281 name, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
282 host_byte(result));
283 if (notyetprinted) {
284 notyetprinted = 0;
285 printk(KERN_INFO
286 "%s:I: This warning may be caused by your scsi controller,\n", name);
287 printk(KERN_INFO
288 "%s:I: it has been reported with some Buslogic cards.\n", name);
292 STp->pos_unknown |= STp->device->was_reset;
294 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
295 STp->recover_count++;
296 STp->recover_erreg++;
297 #if DEBUG
298 if (debugging) {
299 if (SRpnt->cmd[0] == READ_6)
300 stp = "read";
301 else if (SRpnt->cmd[0] == WRITE_6)
302 stp = "write";
303 else
304 stp = "ioctl";
305 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
306 STp->recover_count);
308 #endif
309 if ((sense[2] & 0xe0) == 0)
310 return 0;
312 return (-EIO);
316 /* Wakeup from interrupt */
317 static void osst_sleep_done(void *data, char *sense, int result, int resid)
319 struct osst_request *SRpnt = data;
320 struct osst_tape *STp = SRpnt->stp;
322 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
323 STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
324 #if DEBUG
325 STp->write_pending = 0;
326 #endif
327 if (SRpnt->waiting)
328 complete(SRpnt->waiting);
331 /* osst_request memory management */
332 static struct osst_request *osst_allocate_request(void)
334 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
337 static void osst_release_request(struct osst_request *streq)
339 kfree(streq);
342 /* Do the scsi command. Waits until command performed if do_wait is true.
343 Otherwise osst_write_behind_check() is used to check that the command
344 has finished. */
345 static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
346 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
348 unsigned char *bp;
349 unsigned short use_sg;
350 #ifdef OSST_INJECT_ERRORS
351 static int inject = 0;
352 static int repeat = 0;
353 #endif
354 struct completion *waiting;
356 /* if async, make sure there's no command outstanding */
357 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
358 printk(KERN_ERR "%s: Async command already active.\n",
359 tape_name(STp));
360 if (signal_pending(current))
361 (STp->buffer)->syscall_result = (-EINTR);
362 else
363 (STp->buffer)->syscall_result = (-EBUSY);
364 return NULL;
367 if (SRpnt == NULL) {
368 SRpnt = osst_allocate_request();
369 if (SRpnt == NULL) {
370 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
371 tape_name(STp));
372 if (signal_pending(current))
373 (STp->buffer)->syscall_result = (-EINTR);
374 else
375 (STp->buffer)->syscall_result = (-EBUSY);
376 return NULL;
378 SRpnt->stp = STp;
381 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
382 which IO is outstanding. It's nulled out when the IO completes. */
383 if (!do_wait)
384 (STp->buffer)->last_SRpnt = SRpnt;
386 waiting = &STp->wait;
387 init_completion(waiting);
388 SRpnt->waiting = waiting;
390 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
391 if (use_sg) {
392 bp = (char *)&(STp->buffer->sg[0]);
393 if (STp->buffer->sg_segs < use_sg)
394 use_sg = STp->buffer->sg_segs;
396 else
397 bp = (STp->buffer)->b_data;
399 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
400 STp->buffer->cmdstat.have_sense = 0;
401 STp->buffer->syscall_result = 0;
403 if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
404 use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL))
405 /* could not allocate the buffer or request was too large */
406 (STp->buffer)->syscall_result = (-EBUSY);
407 else if (do_wait) {
408 wait_for_completion(waiting);
409 SRpnt->waiting = NULL;
410 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
411 #ifdef OSST_INJECT_ERRORS
412 if (STp->buffer->syscall_result == 0 &&
413 cmd[0] == READ_6 &&
414 cmd[4] &&
415 ( (++ inject % 83) == 29 ||
416 (STp->first_frame_position == 240
417 /* or STp->read_error_frame to fail again on the block calculated above */ &&
418 ++repeat < 3))) {
419 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
420 STp->buffer->last_result_fatal = 1;
422 #endif
424 return SRpnt;
428 /* Handle the write-behind checking (downs the semaphore) */
429 static void osst_write_behind_check(struct osst_tape *STp)
431 struct osst_buffer * STbuffer;
433 STbuffer = STp->buffer;
435 #if DEBUG
436 if (STp->write_pending)
437 STp->nbr_waits++;
438 else
439 STp->nbr_finished++;
440 #endif
441 wait_for_completion(&(STp->wait));
442 STp->buffer->last_SRpnt->waiting = NULL;
444 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
446 if (STp->buffer->syscall_result)
447 STp->buffer->syscall_result =
448 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
449 else
450 STp->first_frame_position++;
452 osst_release_request(STp->buffer->last_SRpnt);
454 if (STbuffer->writing < STbuffer->buffer_bytes)
455 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
457 STbuffer->last_SRpnt = NULL;
458 STbuffer->buffer_bytes -= STbuffer->writing;
459 STbuffer->writing = 0;
461 return;
466 /* Onstream specific Routines */
468 * Initialize the OnStream AUX
470 static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
471 int logical_blk_num, int blk_sz, int blk_cnt)
473 os_aux_t *aux = STp->buffer->aux;
474 os_partition_t *par = &aux->partition;
475 os_dat_t *dat = &aux->dat;
477 if (STp->raw) return;
479 memset(aux, 0, sizeof(*aux));
480 aux->format_id = htonl(0);
481 memcpy(aux->application_sig, "LIN4", 4);
482 aux->hdwr = htonl(0);
483 aux->frame_type = frame_type;
485 switch (frame_type) {
486 case OS_FRAME_TYPE_HEADER:
487 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
488 par->partition_num = OS_CONFIG_PARTITION;
489 par->par_desc_ver = OS_PARTITION_VERSION;
490 par->wrt_pass_cntr = htons(0xffff);
491 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
492 par->first_frame_ppos = htonl(0);
493 par->last_frame_ppos = htonl(0xbb7);
494 aux->frame_seq_num = htonl(0);
495 aux->logical_blk_num_high = htonl(0);
496 aux->logical_blk_num = htonl(0);
497 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
498 break;
499 case OS_FRAME_TYPE_DATA:
500 case OS_FRAME_TYPE_MARKER:
501 dat->dat_sz = 8;
502 dat->reserved1 = 0;
503 dat->entry_cnt = 1;
504 dat->reserved3 = 0;
505 dat->dat_list[0].blk_sz = htonl(blk_sz);
506 dat->dat_list[0].blk_cnt = htons(blk_cnt);
507 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
508 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
509 dat->dat_list[0].reserved = 0;
510 case OS_FRAME_TYPE_EOD:
511 aux->update_frame_cntr = htonl(0);
512 par->partition_num = OS_DATA_PARTITION;
513 par->par_desc_ver = OS_PARTITION_VERSION;
514 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
515 par->first_frame_ppos = htonl(STp->first_data_ppos);
516 par->last_frame_ppos = htonl(STp->capacity);
517 aux->frame_seq_num = htonl(frame_seq_number);
518 aux->logical_blk_num_high = htonl(0);
519 aux->logical_blk_num = htonl(logical_blk_num);
520 break;
521 default: ; /* probably FILL */
523 aux->filemark_cnt = ntohl(STp->filemark_cnt);
524 aux->phys_fm = ntohl(0xffffffff);
525 aux->last_mark_ppos = ntohl(STp->last_mark_ppos);
526 aux->last_mark_lbn = ntohl(STp->last_mark_lbn);
530 * Verify that we have the correct tape frame
532 static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
534 char * name = tape_name(STp);
535 os_aux_t * aux = STp->buffer->aux;
536 os_partition_t * par = &(aux->partition);
537 struct st_partstat * STps = &(STp->ps[STp->partition]);
538 int blk_cnt, blk_sz, i;
540 if (STp->raw) {
541 if (STp->buffer->syscall_result) {
542 for (i=0; i < STp->buffer->sg_segs; i++)
543 memset(page_address(STp->buffer->sg[i].page),
544 0, STp->buffer->sg[i].length);
545 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
546 } else
547 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
548 return 1;
550 if (STp->buffer->syscall_result) {
551 #if DEBUG
552 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
553 #endif
554 return 0;
556 if (ntohl(aux->format_id) != 0) {
557 #if DEBUG
558 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
559 #endif
560 goto err_out;
562 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
563 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
564 #if DEBUG
565 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
566 #endif
567 goto err_out;
569 if (par->partition_num != OS_DATA_PARTITION) {
570 if (!STp->linux_media || STp->linux_media_version != 2) {
571 #if DEBUG
572 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
573 name, par->partition_num);
574 #endif
575 goto err_out;
578 if (par->par_desc_ver != OS_PARTITION_VERSION) {
579 #if DEBUG
580 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
581 #endif
582 goto err_out;
584 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
585 #if DEBUG
586 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
587 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
588 #endif
589 goto err_out;
591 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
592 aux->frame_type != OS_FRAME_TYPE_EOD &&
593 aux->frame_type != OS_FRAME_TYPE_MARKER) {
594 if (!quiet)
595 #if DEBUG
596 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
597 #endif
598 goto err_out;
600 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
601 STp->first_frame_position < STp->eod_frame_ppos) {
602 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
603 STp->first_frame_position);
604 goto err_out;
606 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
607 if (!quiet)
608 #if DEBUG
609 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
610 name, ntohl(aux->frame_seq_num), frame_seq_number);
611 #endif
612 goto err_out;
614 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
615 STps->eof = ST_FM_HIT;
617 i = ntohl(aux->filemark_cnt);
618 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
619 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
620 #if DEBUG
621 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
622 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
623 i, STp->first_frame_position - 1);
624 #endif
625 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
626 if (i >= STp->filemark_cnt)
627 STp->filemark_cnt = i+1;
630 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
631 STps->eof = ST_EOD_1;
632 STp->frame_in_buffer = 1;
634 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
635 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
636 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
637 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
638 STp->buffer->read_pointer = 0;
639 STp->frame_in_buffer = 1;
641 /* See what block size was used to write file */
642 if (STp->block_size != blk_sz && blk_sz > 0) {
643 printk(KERN_INFO
644 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
645 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
646 STp->block_size<1024?STp->block_size:STp->block_size/1024,
647 STp->block_size<1024?'b':'k');
648 STp->block_size = blk_sz;
649 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
651 STps->eof = ST_NOEOF;
653 STp->frame_seq_number = ntohl(aux->frame_seq_num);
654 STp->logical_blk_num = ntohl(aux->logical_blk_num);
655 return 1;
657 err_out:
658 if (STp->read_error_frame == 0)
659 STp->read_error_frame = STp->first_frame_position - 1;
660 return 0;
664 * Wait for the unit to become Ready
666 static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
667 unsigned timeout, int initial_delay)
669 unsigned char cmd[MAX_COMMAND_SIZE];
670 struct osst_request * SRpnt;
671 unsigned long startwait = jiffies;
672 #if DEBUG
673 int dbg = debugging;
674 char * name = tape_name(STp);
676 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
677 #endif
679 if (initial_delay > 0)
680 msleep(jiffies_to_msecs(initial_delay));
682 memset(cmd, 0, MAX_COMMAND_SIZE);
683 cmd[0] = TEST_UNIT_READY;
685 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
686 *aSRpnt = SRpnt;
687 if (!SRpnt) return (-EBUSY);
689 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
690 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
691 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
692 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
693 SRpnt->sense[13] == 0 ) )) {
694 #if DEBUG
695 if (debugging) {
696 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
697 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
698 debugging = 0;
700 #endif
701 msleep(100);
703 memset(cmd, 0, MAX_COMMAND_SIZE);
704 cmd[0] = TEST_UNIT_READY;
706 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
708 *aSRpnt = SRpnt;
709 #if DEBUG
710 debugging = dbg;
711 #endif
712 if ( STp->buffer->syscall_result &&
713 osst_write_error_recovery(STp, aSRpnt, 0) ) {
714 #if DEBUG
715 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
716 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
717 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
718 SRpnt->sense[12], SRpnt->sense[13]);
719 #endif
720 return (-EIO);
722 #if DEBUG
723 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
724 #endif
725 return 0;
729 * Wait for a tape to be inserted in the unit
731 static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
733 unsigned char cmd[MAX_COMMAND_SIZE];
734 struct osst_request * SRpnt;
735 unsigned long startwait = jiffies;
736 #if DEBUG
737 int dbg = debugging;
738 char * name = tape_name(STp);
740 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
741 #endif
743 memset(cmd, 0, MAX_COMMAND_SIZE);
744 cmd[0] = TEST_UNIT_READY;
746 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
747 *aSRpnt = SRpnt;
748 if (!SRpnt) return (-EBUSY);
750 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
751 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
752 #if DEBUG
753 if (debugging) {
754 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
755 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
756 debugging = 0;
758 #endif
759 msleep(100);
761 memset(cmd, 0, MAX_COMMAND_SIZE);
762 cmd[0] = TEST_UNIT_READY;
764 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
766 *aSRpnt = SRpnt;
767 #if DEBUG
768 debugging = dbg;
769 #endif
770 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
771 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
772 #if DEBUG
773 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
774 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
775 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
776 SRpnt->sense[12], SRpnt->sense[13]);
777 #endif
778 return 0;
780 #if DEBUG
781 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
782 #endif
783 return 1;
786 static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
788 int retval;
790 osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
791 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
792 if (retval) return (retval);
793 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
794 return (osst_get_frame_position(STp, aSRpnt));
798 * Wait for write(s) to complete
800 static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
802 unsigned char cmd[MAX_COMMAND_SIZE];
803 struct osst_request * SRpnt;
804 int result = 0;
805 int delay = OSST_WAIT_WRITE_COMPLETE;
806 #if DEBUG
807 char * name = tape_name(STp);
809 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
810 #endif
812 memset(cmd, 0, MAX_COMMAND_SIZE);
813 cmd[0] = WRITE_FILEMARKS;
814 cmd[1] = 1;
816 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
817 *aSRpnt = SRpnt;
818 if (!SRpnt) return (-EBUSY);
819 if (STp->buffer->syscall_result) {
820 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
821 if (SRpnt->sense[13] == 8) {
822 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
824 } else
825 result = osst_write_error_recovery(STp, aSRpnt, 0);
827 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
828 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
830 return (result);
833 #define OSST_POLL_PER_SEC 10
834 static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
836 unsigned long startwait = jiffies;
837 char * name = tape_name(STp);
838 #if DEBUG
839 char notyetprinted = 1;
840 #endif
841 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
842 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
844 while (time_before (jiffies, startwait + to*HZ))
846 int result;
847 result = osst_get_frame_position(STp, aSRpnt);
848 if (result == -EIO)
849 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
850 return 0; /* successful recovery leaves drive ready for frame */
851 if (result < 0) break;
852 if (STp->first_frame_position == curr &&
853 ((minlast < 0 &&
854 (signed)STp->last_frame_position > (signed)curr + minlast) ||
855 (minlast >= 0 && STp->cur_frames > minlast)
856 ) && result >= 0)
858 #if DEBUG
859 if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC)
860 printk (OSST_DEB_MSG
861 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
862 name, curr, curr+minlast, STp->first_frame_position,
863 STp->last_frame_position, STp->cur_frames,
864 result, (jiffies-startwait)/HZ,
865 (((jiffies-startwait)%HZ)*10)/HZ);
866 #endif
867 return 0;
869 #if DEBUG
870 if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted)
872 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
873 name, curr, curr+minlast, STp->first_frame_position,
874 STp->last_frame_position, STp->cur_frames, result);
875 notyetprinted--;
877 #endif
878 msleep(1000 / OSST_POLL_PER_SEC);
880 #if DEBUG
881 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
882 name, curr, curr+minlast, STp->first_frame_position,
883 STp->last_frame_position, STp->cur_frames,
884 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
885 #endif
886 return -EBUSY;
889 static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
891 struct osst_request * SRpnt;
892 unsigned char cmd[MAX_COMMAND_SIZE];
893 unsigned long startwait = jiffies;
894 int retval = 1;
895 char * name = tape_name(STp);
897 if (writing) {
898 char mybuf[24];
899 char * olddata = STp->buffer->b_data;
900 int oldsize = STp->buffer->buffer_size;
902 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
904 memset(cmd, 0, MAX_COMMAND_SIZE);
905 cmd[0] = WRITE_FILEMARKS;
906 cmd[1] = 1;
907 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
908 MAX_RETRIES, 1);
910 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
912 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
914 /* some failure - not just not-ready */
915 retval = osst_write_error_recovery(STp, aSRpnt, 0);
916 break;
918 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
920 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
921 memset(cmd, 0, MAX_COMMAND_SIZE);
922 cmd[0] = READ_POSITION;
924 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
925 MAX_RETRIES, 1);
927 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
928 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
930 if (retval)
931 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
932 } else
933 /* TODO - figure out which error conditions can be handled */
934 if (STp->buffer->syscall_result)
935 printk(KERN_WARNING
936 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
937 (*aSRpnt)->sense[ 2] & 0x0f,
938 (*aSRpnt)->sense[12],
939 (*aSRpnt)->sense[13]);
941 return retval;
945 * Read the next OnStream tape frame at the current location
947 static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
949 unsigned char cmd[MAX_COMMAND_SIZE];
950 struct osst_request * SRpnt;
951 int retval = 0;
952 #if DEBUG
953 os_aux_t * aux = STp->buffer->aux;
954 char * name = tape_name(STp);
955 #endif
957 if (STp->poll)
958 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
959 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
961 memset(cmd, 0, MAX_COMMAND_SIZE);
962 cmd[0] = READ_6;
963 cmd[1] = 1;
964 cmd[4] = 1;
966 #if DEBUG
967 if (debugging)
968 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
969 #endif
970 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
971 STp->timeout, MAX_RETRIES, 1);
972 *aSRpnt = SRpnt;
973 if (!SRpnt)
974 return (-EBUSY);
976 if ((STp->buffer)->syscall_result) {
977 retval = 1;
978 if (STp->read_error_frame == 0) {
979 STp->read_error_frame = STp->first_frame_position;
980 #if DEBUG
981 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
982 #endif
984 #if DEBUG
985 if (debugging)
986 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
987 name,
988 SRpnt->sense[0], SRpnt->sense[1],
989 SRpnt->sense[2], SRpnt->sense[3],
990 SRpnt->sense[4], SRpnt->sense[5],
991 SRpnt->sense[6], SRpnt->sense[7]);
992 #endif
994 else
995 STp->first_frame_position++;
996 #if DEBUG
997 if (debugging) {
998 char sig[8]; int i;
999 for (i=0;i<4;i++)
1000 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1001 sig[4] = '\0';
1002 printk(OSST_DEB_MSG
1003 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1004 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1005 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1006 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1007 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1008 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1009 if (aux->frame_type==2)
1010 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1011 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1012 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1014 #endif
1015 return (retval);
1018 static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1020 struct st_partstat * STps = &(STp->ps[STp->partition]);
1021 struct osst_request * SRpnt ;
1022 unsigned char cmd[MAX_COMMAND_SIZE];
1023 int retval = 0;
1024 char * name = tape_name(STp);
1026 if (STps->rw != ST_READING) { /* Initialize read operation */
1027 if (STps->rw == ST_WRITING || STp->dirty) {
1028 STp->write_type = OS_WRITE_DATA;
1029 osst_flush_write_buffer(STp, aSRpnt);
1030 osst_flush_drive_buffer(STp, aSRpnt);
1032 STps->rw = ST_READING;
1033 STp->frame_in_buffer = 0;
1036 * Issue a read 0 command to get the OnStream drive
1037 * read frames into its buffer.
1039 memset(cmd, 0, MAX_COMMAND_SIZE);
1040 cmd[0] = READ_6;
1041 cmd[1] = 1;
1043 #if DEBUG
1044 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1045 #endif
1046 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1047 *aSRpnt = SRpnt;
1048 if ((retval = STp->buffer->syscall_result))
1049 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1052 return retval;
1055 static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1056 int frame_seq_number, int quiet)
1058 struct st_partstat * STps = &(STp->ps[STp->partition]);
1059 char * name = tape_name(STp);
1060 int cnt = 0,
1061 bad = 0,
1062 past = 0,
1064 position;
1067 * If we want just any frame (-1) and there is a frame in the buffer, return it
1069 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1070 #if DEBUG
1071 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1072 #endif
1073 return (STps->eof);
1076 * Search and wait for the next logical tape frame
1078 while (1) {
1079 if (cnt++ > 400) {
1080 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1081 name, frame_seq_number);
1082 if (STp->read_error_frame) {
1083 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1084 #if DEBUG
1085 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1086 name, STp->read_error_frame);
1087 #endif
1088 STp->read_error_frame = 0;
1089 STp->abort_count++;
1091 return (-EIO);
1093 #if DEBUG
1094 if (debugging)
1095 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1096 name, frame_seq_number, cnt);
1097 #endif
1098 if ( osst_initiate_read(STp, aSRpnt)
1099 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1100 if (STp->raw)
1101 return (-EIO);
1102 position = osst_get_frame_position(STp, aSRpnt);
1103 if (position >= 0xbae && position < 0xbb8)
1104 position = 0xbb8;
1105 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1106 position = STp->read_error_frame - 1;
1107 bad = 0;
1109 else {
1110 position += 29;
1111 cnt += 19;
1113 #if DEBUG
1114 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1115 name, position);
1116 #endif
1117 osst_set_frame_position(STp, aSRpnt, position, 0);
1118 continue;
1120 if (osst_verify_frame(STp, frame_seq_number, quiet))
1121 break;
1122 if (osst_verify_frame(STp, -1, quiet)) {
1123 x = ntohl(STp->buffer->aux->frame_seq_num);
1124 if (STp->fast_open) {
1125 printk(KERN_WARNING
1126 "%s:W: Found logical frame %d instead of %d after fast open\n",
1127 name, x, frame_seq_number);
1128 STp->header_ok = 0;
1129 STp->read_error_frame = 0;
1130 return (-EIO);
1132 if (x > frame_seq_number) {
1133 if (++past > 3) {
1134 /* positioning backwards did not bring us to the desired frame */
1135 position = STp->read_error_frame - 1;
1137 else {
1138 position = osst_get_frame_position(STp, aSRpnt)
1139 + frame_seq_number - x - 1;
1141 if (STp->first_frame_position >= 3000 && position < 3000)
1142 position -= 10;
1144 #if DEBUG
1145 printk(OSST_DEB_MSG
1146 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1147 name, x, frame_seq_number,
1148 STp->first_frame_position - position);
1149 #endif
1150 osst_set_frame_position(STp, aSRpnt, position, 0);
1151 cnt += 10;
1153 else
1154 past = 0;
1156 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1157 #if DEBUG
1158 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1159 #endif
1160 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1161 cnt--;
1163 STp->frame_in_buffer = 0;
1165 if (cnt > 1) {
1166 STp->recover_count++;
1167 STp->recover_erreg++;
1168 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1169 name, STp->read_error_frame);
1171 STp->read_count++;
1173 #if DEBUG
1174 if (debugging || STps->eof)
1175 printk(OSST_DEB_MSG
1176 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1177 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1178 #endif
1179 STp->fast_open = 0;
1180 STp->read_error_frame = 0;
1181 return (STps->eof);
1184 static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1186 struct st_partstat * STps = &(STp->ps[STp->partition]);
1187 char * name = tape_name(STp);
1188 int retries = 0;
1189 int frame_seq_estimate, ppos_estimate, move;
1191 if (logical_blk_num < 0) logical_blk_num = 0;
1192 #if DEBUG
1193 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1194 name, logical_blk_num, STp->logical_blk_num,
1195 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1196 STp->block_size<1024?'b':'k');
1197 #endif
1198 /* Do we know where we are? */
1199 if (STps->drv_block >= 0) {
1200 move = logical_blk_num - STp->logical_blk_num;
1201 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1202 move /= (OS_DATA_SIZE / STp->block_size);
1203 frame_seq_estimate = STp->frame_seq_number + move;
1204 } else
1205 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1207 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1208 else ppos_estimate = frame_seq_estimate + 20;
1209 while (++retries < 10) {
1210 if (ppos_estimate > STp->eod_frame_ppos-2) {
1211 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1212 ppos_estimate = STp->eod_frame_ppos - 2;
1214 if (frame_seq_estimate < 0) {
1215 frame_seq_estimate = 0;
1216 ppos_estimate = 10;
1218 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1219 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1220 /* we've located the estimated frame, now does it have our block? */
1221 if (logical_blk_num < STp->logical_blk_num ||
1222 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1223 if (STps->eof == ST_FM_HIT)
1224 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1225 else {
1226 move = logical_blk_num - STp->logical_blk_num;
1227 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1228 move /= (OS_DATA_SIZE / STp->block_size);
1230 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1231 #if DEBUG
1232 printk(OSST_DEB_MSG
1233 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1234 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1235 STp->logical_blk_num, logical_blk_num, move);
1236 #endif
1237 frame_seq_estimate += move;
1238 ppos_estimate += move;
1239 continue;
1240 } else {
1241 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1242 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1243 STp->logical_blk_num = logical_blk_num;
1244 #if DEBUG
1245 printk(OSST_DEB_MSG
1246 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1247 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1248 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1249 STp->block_size);
1250 #endif
1251 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1252 if (STps->eof == ST_FM_HIT) {
1253 STps->drv_file++;
1254 STps->drv_block = 0;
1255 } else {
1256 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1257 STp->logical_blk_num -
1258 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1261 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1262 return 0;
1265 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1266 goto error;
1267 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1268 #if DEBUG
1269 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1270 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1271 STp->logical_blk_num, logical_blk_num);
1272 #endif
1273 if (frame_seq_estimate != STp->frame_seq_number)
1274 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1275 else
1276 break;
1278 error:
1279 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1280 name, logical_blk_num, STp->logical_blk_num, retries);
1281 return (-EIO);
1284 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1285 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1286 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1287 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1289 #define OSST_FRAME_SHIFT 6
1290 #define OSST_SECTOR_SHIFT 9
1291 #define OSST_SECTOR_MASK 0x03F
1293 static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1295 int sector;
1296 #if DEBUG
1297 char * name = tape_name(STp);
1299 printk(OSST_DEB_MSG
1300 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1301 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1302 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1303 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1304 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1305 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1306 #endif
1307 /* do we know where we are inside a file? */
1308 if (STp->ps[STp->partition].drv_block >= 0) {
1309 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1310 STp->first_frame_position) << OSST_FRAME_SHIFT;
1311 if (STp->ps[STp->partition].rw == ST_WRITING)
1312 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1313 else
1314 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1315 } else {
1316 sector = osst_get_frame_position(STp, aSRpnt);
1317 if (sector > 0)
1318 sector <<= OSST_FRAME_SHIFT;
1320 return sector;
1323 static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1325 struct st_partstat * STps = &(STp->ps[STp->partition]);
1326 int frame = sector >> OSST_FRAME_SHIFT,
1327 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1329 #if DEBUG
1330 char * name = tape_name(STp);
1332 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1333 name, sector, frame, offset);
1334 #endif
1335 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1337 if (frame <= STp->first_data_ppos) {
1338 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1339 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1341 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1342 if (r < 0) return r;
1344 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1345 if (r < 0) return r;
1347 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1349 if (offset) {
1350 STp->logical_blk_num += offset / STp->block_size;
1351 STp->buffer->read_pointer = offset;
1352 STp->buffer->buffer_bytes -= offset;
1353 } else {
1354 STp->frame_seq_number++;
1355 STp->frame_in_buffer = 0;
1356 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1357 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1359 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1360 if (STps->eof == ST_FM_HIT) {
1361 STps->drv_file++;
1362 STps->drv_block = 0;
1363 } else {
1364 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1365 STp->logical_blk_num -
1366 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1369 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1370 #if DEBUG
1371 printk(OSST_DEB_MSG
1372 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1373 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1374 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1375 #endif
1376 return 0;
1380 * Read back the drive's internal buffer contents, as a part
1381 * of the write error recovery mechanism for old OnStream
1382 * firmware revisions.
1383 * Precondition for this function to work: all frames in the
1384 * drive's buffer must be of one type (DATA, MARK or EOD)!
1386 static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1387 unsigned int frame, unsigned int skip, int pending)
1389 struct osst_request * SRpnt = * aSRpnt;
1390 unsigned char * buffer, * p;
1391 unsigned char cmd[MAX_COMMAND_SIZE];
1392 int flag, new_frame, i;
1393 int nframes = STp->cur_frames;
1394 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1395 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1396 - (nframes + pending - 1);
1397 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1398 - (nframes + pending - 1) * blks_per_frame;
1399 char * name = tape_name(STp);
1400 unsigned long startwait = jiffies;
1401 #if DEBUG
1402 int dbg = debugging;
1403 #endif
1405 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1406 return (-EIO);
1408 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1409 name, nframes, pending?" and one that was pending":"");
1411 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1412 #if DEBUG
1413 if (pending && debugging)
1414 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1415 name, frame_seq_number + nframes,
1416 logical_blk_num + nframes * blks_per_frame,
1417 p[0], p[1], p[2], p[3]);
1418 #endif
1419 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1421 memset(cmd, 0, MAX_COMMAND_SIZE);
1422 cmd[0] = 0x3C; /* Buffer Read */
1423 cmd[1] = 6; /* Retrieve Faulty Block */
1424 cmd[7] = 32768 >> 8;
1425 cmd[8] = 32768 & 0xff;
1427 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1428 STp->timeout, MAX_RETRIES, 1);
1430 if ((STp->buffer)->syscall_result || !SRpnt) {
1431 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1432 vfree(buffer);
1433 *aSRpnt = SRpnt;
1434 return (-EIO);
1436 osst_copy_from_buffer(STp->buffer, p);
1437 #if DEBUG
1438 if (debugging)
1439 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1440 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1441 #endif
1443 *aSRpnt = SRpnt;
1444 osst_get_frame_position(STp, aSRpnt);
1446 #if DEBUG
1447 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1448 #endif
1449 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1450 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1452 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1454 if (flag) {
1455 if (STp->write_type == OS_WRITE_HEADER) {
1456 i += skip;
1457 p += skip * OS_DATA_SIZE;
1459 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1460 new_frame = 3000-i;
1461 else
1462 new_frame += skip;
1463 #if DEBUG
1464 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1465 name, new_frame+i, frame_seq_number+i);
1466 #endif
1467 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1468 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1469 osst_get_frame_position(STp, aSRpnt);
1470 SRpnt = * aSRpnt;
1472 if (new_frame > frame + 1000) {
1473 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1474 vfree(buffer);
1475 return (-EIO);
1477 if ( i >= nframes + pending ) break;
1478 flag = 0;
1480 osst_copy_to_buffer(STp->buffer, p);
1482 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1484 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1485 logical_blk_num + i*blks_per_frame,
1486 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1487 memset(cmd, 0, MAX_COMMAND_SIZE);
1488 cmd[0] = WRITE_6;
1489 cmd[1] = 1;
1490 cmd[4] = 1;
1492 #if DEBUG
1493 if (debugging)
1494 printk(OSST_DEB_MSG
1495 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1496 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1497 p[0], p[1], p[2], p[3]);
1498 #endif
1499 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1500 STp->timeout, MAX_RETRIES, 1);
1502 if (STp->buffer->syscall_result)
1503 flag = 1;
1504 else {
1505 p += OS_DATA_SIZE; i++;
1507 /* if we just sent the last frame, wait till all successfully written */
1508 if ( i == nframes + pending ) {
1509 #if DEBUG
1510 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1511 #endif
1512 memset(cmd, 0, MAX_COMMAND_SIZE);
1513 cmd[0] = WRITE_FILEMARKS;
1514 cmd[1] = 1;
1515 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1516 STp->timeout, MAX_RETRIES, 1);
1517 #if DEBUG
1518 if (debugging) {
1519 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1520 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1521 debugging = 0;
1523 #endif
1524 flag = STp->buffer->syscall_result;
1525 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1527 memset(cmd, 0, MAX_COMMAND_SIZE);
1528 cmd[0] = TEST_UNIT_READY;
1530 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1531 MAX_RETRIES, 1);
1533 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1534 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1535 /* in the process of becoming ready */
1536 msleep(100);
1537 continue;
1539 if (STp->buffer->syscall_result)
1540 flag = 1;
1541 break;
1543 #if DEBUG
1544 debugging = dbg;
1545 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1546 #endif
1549 *aSRpnt = SRpnt;
1550 if (flag) {
1551 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1552 SRpnt->sense[12] == 0 &&
1553 SRpnt->sense[13] == 2) {
1554 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1555 vfree(buffer);
1556 return (-EIO); /* hit end of tape = fail */
1558 i = ((SRpnt->sense[3] << 24) |
1559 (SRpnt->sense[4] << 16) |
1560 (SRpnt->sense[5] << 8) |
1561 SRpnt->sense[6] ) - new_frame;
1562 p = &buffer[i * OS_DATA_SIZE];
1563 #if DEBUG
1564 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1565 #endif
1566 osst_get_frame_position(STp, aSRpnt);
1567 #if DEBUG
1568 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1569 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1570 #endif
1573 if (flag) {
1574 /* error recovery did not successfully complete */
1575 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1576 STp->write_type == OS_WRITE_HEADER?"header":"body");
1578 if (!pending)
1579 osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
1580 vfree(buffer);
1581 return 0;
1584 static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1585 unsigned int frame, unsigned int skip, int pending)
1587 unsigned char cmd[MAX_COMMAND_SIZE];
1588 struct osst_request * SRpnt;
1589 char * name = tape_name(STp);
1590 int expected = 0;
1591 int attempts = 1000 / skip;
1592 int flag = 1;
1593 unsigned long startwait = jiffies;
1594 #if DEBUG
1595 int dbg = debugging;
1596 #endif
1598 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1599 if (flag) {
1600 #if DEBUG
1601 debugging = dbg;
1602 #endif
1603 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1604 frame = 3000-skip;
1605 expected = frame+skip+STp->cur_frames+pending;
1606 #if DEBUG
1607 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1608 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1609 #endif
1610 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1611 flag = 0;
1612 attempts--;
1613 schedule_timeout_interruptible(msecs_to_jiffies(100));
1615 if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
1616 #if DEBUG
1617 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1618 name, STp->first_frame_position,
1619 STp->last_frame_position, STp->cur_frames);
1620 #endif
1621 frame = STp->last_frame_position;
1622 flag = 1;
1623 continue;
1625 if (pending && STp->cur_frames < 50) {
1627 memset(cmd, 0, MAX_COMMAND_SIZE);
1628 cmd[0] = WRITE_6;
1629 cmd[1] = 1;
1630 cmd[4] = 1;
1631 #if DEBUG
1632 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1633 name, STp->frame_seq_number-1, STp->first_frame_position);
1634 #endif
1635 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1636 STp->timeout, MAX_RETRIES, 1);
1637 *aSRpnt = SRpnt;
1639 if (STp->buffer->syscall_result) { /* additional write error */
1640 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1641 SRpnt->sense[12] == 0 &&
1642 SRpnt->sense[13] == 2) {
1643 printk(KERN_ERR
1644 "%s:E: Volume overflow in write error recovery\n",
1645 name);
1646 break; /* hit end of tape = fail */
1648 flag = 1;
1650 else
1651 pending = 0;
1653 continue;
1655 if (STp->cur_frames == 0) {
1656 #if DEBUG
1657 debugging = dbg;
1658 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1659 #endif
1660 if (STp->first_frame_position != expected) {
1661 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1662 name, STp->first_frame_position, expected);
1663 return (-EIO);
1665 return 0;
1667 #if DEBUG
1668 if (debugging) {
1669 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1670 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1671 debugging = 0;
1673 #endif
1674 schedule_timeout_interruptible(msecs_to_jiffies(100));
1676 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1677 #if DEBUG
1678 debugging = dbg;
1679 #endif
1680 return (-EIO);
1684 * Error recovery algorithm for the OnStream tape.
1687 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1689 struct osst_request * SRpnt = * aSRpnt;
1690 struct st_partstat * STps = & STp->ps[STp->partition];
1691 char * name = tape_name(STp);
1692 int retval = 0;
1693 int rw_state;
1694 unsigned int frame, skip;
1696 rw_state = STps->rw;
1698 if ((SRpnt->sense[ 2] & 0x0f) != 3
1699 || SRpnt->sense[12] != 12
1700 || SRpnt->sense[13] != 0) {
1701 #if DEBUG
1702 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1703 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1704 #endif
1705 return (-EIO);
1707 frame = (SRpnt->sense[3] << 24) |
1708 (SRpnt->sense[4] << 16) |
1709 (SRpnt->sense[5] << 8) |
1710 SRpnt->sense[6];
1711 skip = SRpnt->sense[9];
1713 #if DEBUG
1714 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1715 #endif
1716 osst_get_frame_position(STp, aSRpnt);
1717 #if DEBUG
1718 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1719 name, STp->first_frame_position, STp->last_frame_position);
1720 #endif
1721 switch (STp->write_type) {
1722 case OS_WRITE_DATA:
1723 case OS_WRITE_EOD:
1724 case OS_WRITE_NEW_MARK:
1725 printk(KERN_WARNING
1726 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1727 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1728 if (STp->os_fw_rev >= 10600)
1729 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1730 else
1731 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1732 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1733 retval?"E" :"I",
1734 retval?"" :"Don't worry, ",
1735 retval?" not ":" ");
1736 break;
1737 case OS_WRITE_LAST_MARK:
1738 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1739 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1740 retval = -EIO;
1741 break;
1742 case OS_WRITE_HEADER:
1743 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1744 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1745 break;
1746 default:
1747 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1748 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1750 osst_get_frame_position(STp, aSRpnt);
1751 #if DEBUG
1752 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1753 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1754 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1755 #endif
1756 if (retval == 0) {
1757 STp->recover_count++;
1758 STp->recover_erreg++;
1759 } else
1760 STp->abort_count++;
1762 STps->rw = rw_state;
1763 return retval;
1766 static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1767 int mt_op, int mt_count)
1769 char * name = tape_name(STp);
1770 int cnt;
1771 int last_mark_ppos = -1;
1773 #if DEBUG
1774 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1775 #endif
1776 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1777 #if DEBUG
1778 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1779 #endif
1780 return -EIO;
1782 if (STp->linux_media_version >= 4) {
1784 * direct lookup in header filemark list
1786 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1787 if (STp->header_ok &&
1788 STp->header_cache != NULL &&
1789 (cnt - mt_count) >= 0 &&
1790 (cnt - mt_count) < OS_FM_TAB_MAX &&
1791 (cnt - mt_count) < STp->filemark_cnt &&
1792 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1794 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1795 #if DEBUG
1796 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1797 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1798 STp->header_cache == NULL?"lack of header cache":"count out of range");
1799 else
1800 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1801 name, cnt,
1802 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1803 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1804 STp->buffer->aux->last_mark_ppos))?"match":"error",
1805 mt_count, last_mark_ppos);
1806 #endif
1807 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1808 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1809 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1810 #if DEBUG
1811 printk(OSST_DEB_MSG
1812 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1813 #endif
1814 return (-EIO);
1816 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1817 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1818 name, last_mark_ppos);
1819 return (-EIO);
1821 goto found;
1823 #if DEBUG
1824 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1825 #endif
1827 cnt = 0;
1828 while (cnt != mt_count) {
1829 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1830 if (last_mark_ppos == -1)
1831 return (-EIO);
1832 #if DEBUG
1833 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1834 #endif
1835 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1836 cnt++;
1837 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1838 #if DEBUG
1839 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1840 #endif
1841 return (-EIO);
1843 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1844 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1845 name, last_mark_ppos);
1846 return (-EIO);
1849 found:
1850 if (mt_op == MTBSFM) {
1851 STp->frame_seq_number++;
1852 STp->frame_in_buffer = 0;
1853 STp->buffer->buffer_bytes = 0;
1854 STp->buffer->read_pointer = 0;
1855 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1857 return 0;
1861 * ADRL 1.1 compatible "slow" space filemarks fwd version
1863 * Just scans for the filemark sequentially.
1865 static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1866 int mt_op, int mt_count)
1868 int cnt = 0;
1869 #if DEBUG
1870 char * name = tape_name(STp);
1872 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1873 #endif
1874 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1875 #if DEBUG
1876 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1877 #endif
1878 return (-EIO);
1880 while (1) {
1881 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1882 #if DEBUG
1883 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1884 #endif
1885 return (-EIO);
1887 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1888 cnt++;
1889 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1890 #if DEBUG
1891 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1892 #endif
1893 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1894 #if DEBUG
1895 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1896 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1897 #endif
1898 STp->eod_frame_ppos = STp->first_frame_position-1;
1900 return (-EIO);
1902 if (cnt == mt_count)
1903 break;
1904 STp->frame_in_buffer = 0;
1906 if (mt_op == MTFSF) {
1907 STp->frame_seq_number++;
1908 STp->frame_in_buffer = 0;
1909 STp->buffer->buffer_bytes = 0;
1910 STp->buffer->read_pointer = 0;
1911 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1913 return 0;
1917 * Fast linux specific version of OnStream FSF
1919 static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
1920 int mt_op, int mt_count)
1922 char * name = tape_name(STp);
1923 int cnt = 0,
1924 next_mark_ppos = -1;
1926 #if DEBUG
1927 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
1928 #endif
1929 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1930 #if DEBUG
1931 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1932 #endif
1933 return (-EIO);
1936 if (STp->linux_media_version >= 4) {
1938 * direct lookup in header filemark list
1940 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1941 if (STp->header_ok &&
1942 STp->header_cache != NULL &&
1943 (cnt + mt_count) < OS_FM_TAB_MAX &&
1944 (cnt + mt_count) < STp->filemark_cnt &&
1945 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1946 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1948 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1949 #if DEBUG
1950 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1951 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1952 STp->header_cache == NULL?"lack of header cache":"count out of range");
1953 else
1954 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1955 name, cnt,
1956 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1957 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1958 STp->buffer->aux->last_mark_ppos))?"match":"error",
1959 mt_count, next_mark_ppos);
1960 #endif
1961 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1962 #if DEBUG
1963 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1964 #endif
1965 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1966 } else {
1967 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1968 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1969 #if DEBUG
1970 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
1971 name);
1972 #endif
1973 return (-EIO);
1975 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1976 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1977 name, next_mark_ppos);
1978 return (-EIO);
1980 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1981 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
1982 name, cnt+mt_count, next_mark_ppos,
1983 ntohl(STp->buffer->aux->filemark_cnt));
1984 return (-EIO);
1987 } else {
1989 * Find nearest (usually previous) marker, then jump from marker to marker
1991 while (1) {
1992 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1993 break;
1994 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1995 #if DEBUG
1996 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1997 #endif
1998 return (-EIO);
2000 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2001 if (STp->first_mark_ppos == -1) {
2002 #if DEBUG
2003 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2004 #endif
2005 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2007 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2008 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2009 #if DEBUG
2010 printk(OSST_DEB_MSG
2011 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2012 name);
2013 #endif
2014 return (-EIO);
2016 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2017 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2018 name, STp->first_mark_ppos);
2019 return (-EIO);
2021 } else {
2022 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2023 return (-EIO);
2024 mt_count++;
2027 cnt++;
2028 while (cnt != mt_count) {
2029 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2030 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2031 #if DEBUG
2032 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2033 #endif
2034 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2036 #if DEBUG
2037 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2038 #endif
2039 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2040 cnt++;
2041 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2042 #if DEBUG
2043 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2044 name);
2045 #endif
2046 return (-EIO);
2048 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2049 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2050 name, next_mark_ppos);
2051 return (-EIO);
2055 if (mt_op == MTFSF) {
2056 STp->frame_seq_number++;
2057 STp->frame_in_buffer = 0;
2058 STp->buffer->buffer_bytes = 0;
2059 STp->buffer->read_pointer = 0;
2060 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2062 return 0;
2066 * In debug mode, we want to see as many errors as possible
2067 * to test the error recovery mechanism.
2069 #if DEBUG
2070 static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2072 unsigned char cmd[MAX_COMMAND_SIZE];
2073 struct osst_request * SRpnt = * aSRpnt;
2074 char * name = tape_name(STp);
2076 memset(cmd, 0, MAX_COMMAND_SIZE);
2077 cmd[0] = MODE_SELECT;
2078 cmd[1] = 0x10;
2079 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2081 (STp->buffer)->b_data[0] = cmd[4] - 1;
2082 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
2083 (STp->buffer)->b_data[2] = 0; /* Reserved */
2084 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
2085 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2086 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2087 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2088 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2090 if (debugging)
2091 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2093 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2094 *aSRpnt = SRpnt;
2096 if ((STp->buffer)->syscall_result)
2097 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2099 #endif
2102 static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2104 int result;
2105 int this_mark_ppos = STp->first_frame_position;
2106 int this_mark_lbn = STp->logical_blk_num;
2107 #if DEBUG
2108 char * name = tape_name(STp);
2109 #endif
2111 if (STp->raw) return 0;
2113 STp->write_type = OS_WRITE_NEW_MARK;
2114 #if DEBUG
2115 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2116 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2117 #endif
2118 STp->dirty = 1;
2119 result = osst_flush_write_buffer(STp, aSRpnt);
2120 result |= osst_flush_drive_buffer(STp, aSRpnt);
2121 STp->last_mark_ppos = this_mark_ppos;
2122 STp->last_mark_lbn = this_mark_lbn;
2123 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2124 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2125 if (STp->filemark_cnt++ == 0)
2126 STp->first_mark_ppos = this_mark_ppos;
2127 return result;
2130 static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2132 int result;
2133 #if DEBUG
2134 char * name = tape_name(STp);
2135 #endif
2137 if (STp->raw) return 0;
2139 STp->write_type = OS_WRITE_EOD;
2140 STp->eod_frame_ppos = STp->first_frame_position;
2141 #if DEBUG
2142 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2143 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2144 #endif
2145 STp->dirty = 1;
2147 result = osst_flush_write_buffer(STp, aSRpnt);
2148 result |= osst_flush_drive_buffer(STp, aSRpnt);
2149 STp->eod_frame_lfa = --(STp->frame_seq_number);
2150 return result;
2153 static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2155 char * name = tape_name(STp);
2157 #if DEBUG
2158 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2159 #endif
2160 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2161 osst_set_frame_position(STp, aSRpnt, where, 0);
2162 STp->write_type = OS_WRITE_FILLER;
2163 while (count--) {
2164 memcpy(STp->buffer->b_data, "Filler", 6);
2165 STp->buffer->buffer_bytes = 6;
2166 STp->dirty = 1;
2167 if (osst_flush_write_buffer(STp, aSRpnt)) {
2168 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2169 return (-EIO);
2172 #if DEBUG
2173 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2174 #endif
2175 return osst_flush_drive_buffer(STp, aSRpnt);
2178 static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2180 char * name = tape_name(STp);
2181 int result;
2183 #if DEBUG
2184 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2185 #endif
2186 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2187 osst_set_frame_position(STp, aSRpnt, where, 0);
2188 STp->write_type = OS_WRITE_HEADER;
2189 while (count--) {
2190 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2191 STp->buffer->buffer_bytes = sizeof(os_header_t);
2192 STp->dirty = 1;
2193 if (osst_flush_write_buffer(STp, aSRpnt)) {
2194 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2195 return (-EIO);
2198 result = osst_flush_drive_buffer(STp, aSRpnt);
2199 #if DEBUG
2200 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2201 #endif
2202 return result;
2205 static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2207 os_header_t * header;
2208 int result;
2209 char * name = tape_name(STp);
2211 #if DEBUG
2212 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2213 #endif
2214 if (STp->raw) return 0;
2216 if (STp->header_cache == NULL) {
2217 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2218 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2219 return (-ENOMEM);
2221 memset(STp->header_cache, 0, sizeof(os_header_t));
2222 #if DEBUG
2223 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2224 #endif
2226 if (STp->header_ok) STp->update_frame_cntr++;
2227 else STp->update_frame_cntr = 0;
2229 header = STp->header_cache;
2230 strcpy(header->ident_str, "ADR_SEQ");
2231 header->major_rev = 1;
2232 header->minor_rev = 4;
2233 header->ext_trk_tb_off = htons(17192);
2234 header->pt_par_num = 1;
2235 header->partition[0].partition_num = OS_DATA_PARTITION;
2236 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2237 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2238 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2239 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2240 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2241 header->cfg_col_width = htonl(20);
2242 header->dat_col_width = htonl(1500);
2243 header->qfa_col_width = htonl(0);
2244 header->ext_track_tb.nr_stream_part = 1;
2245 header->ext_track_tb.et_ent_sz = 32;
2246 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2247 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2248 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2249 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2250 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2251 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2252 header->dat_fm_tab.fm_part_num = 0;
2253 header->dat_fm_tab.fm_tab_ent_sz = 4;
2254 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2255 STp->filemark_cnt:OS_FM_TAB_MAX);
2257 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2258 if (STp->update_frame_cntr == 0)
2259 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2260 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2262 if (locate_eod) {
2263 #if DEBUG
2264 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2265 #endif
2266 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2268 if (result)
2269 printk(KERN_ERR "%s:E: Write header failed\n", name);
2270 else {
2271 memcpy(STp->application_sig, "LIN4", 4);
2272 STp->linux_media = 1;
2273 STp->linux_media_version = 4;
2274 STp->header_ok = 1;
2276 return result;
2279 static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2281 if (STp->header_cache != NULL)
2282 memset(STp->header_cache, 0, sizeof(os_header_t));
2284 STp->logical_blk_num = STp->frame_seq_number = 0;
2285 STp->frame_in_buffer = 0;
2286 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2287 STp->filemark_cnt = 0;
2288 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2289 return osst_write_header(STp, aSRpnt, 1);
2292 static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2294 char * name = tape_name(STp);
2295 os_header_t * header;
2296 os_aux_t * aux;
2297 char id_string[8];
2298 int linux_media_version,
2299 update_frame_cntr;
2301 if (STp->raw)
2302 return 1;
2304 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2305 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2306 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2307 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2308 if (osst_initiate_read (STp, aSRpnt)) {
2309 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2310 return 0;
2313 if (osst_read_frame(STp, aSRpnt, 180)) {
2314 #if DEBUG
2315 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2316 #endif
2317 return 0;
2319 header = (os_header_t *) STp->buffer->b_data; /* warning: only first segment addressable */
2320 aux = STp->buffer->aux;
2321 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2322 #if DEBUG
2323 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2324 #endif
2325 return 0;
2327 if (ntohl(aux->frame_seq_num) != 0 ||
2328 ntohl(aux->logical_blk_num) != 0 ||
2329 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2330 ntohl(aux->partition.first_frame_ppos) != 0 ||
2331 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2332 #if DEBUG
2333 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2334 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2335 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2336 ntohl(aux->partition.last_frame_ppos));
2337 #endif
2338 return 0;
2340 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2341 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2342 strlcpy(id_string, header->ident_str, 8);
2343 #if DEBUG
2344 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2345 #endif
2346 return 0;
2348 update_frame_cntr = ntohl(aux->update_frame_cntr);
2349 if (update_frame_cntr < STp->update_frame_cntr) {
2350 #if DEBUG
2351 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2352 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2353 #endif
2354 return 0;
2356 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2357 #if DEBUG
2358 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2359 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2360 header->minor_rev > 4 )? "Invalid" : "Warning:",
2361 header->major_rev, header->minor_rev);
2362 #endif
2363 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2364 return 0;
2366 #if DEBUG
2367 if (header->pt_par_num != 1)
2368 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2369 name, header->pt_par_num);
2370 #endif
2371 memcpy(id_string, aux->application_sig, 4);
2372 id_string[4] = 0;
2373 if (memcmp(id_string, "LIN", 3) == 0) {
2374 STp->linux_media = 1;
2375 linux_media_version = id_string[3] - '0';
2376 if (linux_media_version != 4)
2377 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2378 name, linux_media_version);
2379 } else {
2380 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2381 return 0;
2383 if (linux_media_version < STp->linux_media_version) {
2384 #if DEBUG
2385 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2386 name, ppos, linux_media_version);
2387 #endif
2388 return 0;
2390 if (linux_media_version > STp->linux_media_version) {
2391 #if DEBUG
2392 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2393 name, ppos, linux_media_version);
2394 #endif
2395 memcpy(STp->application_sig, id_string, 5);
2396 STp->linux_media_version = linux_media_version;
2397 STp->update_frame_cntr = -1;
2399 if (update_frame_cntr > STp->update_frame_cntr) {
2400 #if DEBUG
2401 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2402 name, ppos, update_frame_cntr);
2403 #endif
2404 if (STp->header_cache == NULL) {
2405 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2406 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2407 return 0;
2409 #if DEBUG
2410 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2411 #endif
2413 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2414 header = STp->header_cache; /* further accesses from cached (full) copy */
2416 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2417 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2418 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2419 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2420 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2421 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2422 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2423 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2424 STp->update_frame_cntr = update_frame_cntr;
2425 #if DEBUG
2426 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2427 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2428 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2429 STp->first_data_ppos,
2430 ntohl(header->partition[0].last_frame_ppos),
2431 ntohl(header->partition[0].eod_frame_ppos));
2432 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2433 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2434 #endif
2435 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2436 #if DEBUG
2437 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2438 #endif
2439 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2440 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2441 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2443 if (header->minor_rev == 4 &&
2444 (header->ext_trk_tb_off != htons(17192) ||
2445 header->partition[0].partition_num != OS_DATA_PARTITION ||
2446 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2447 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2448 header->cfg_col_width != htonl(20) ||
2449 header->dat_col_width != htonl(1500) ||
2450 header->qfa_col_width != htonl(0) ||
2451 header->ext_track_tb.nr_stream_part != 1 ||
2452 header->ext_track_tb.et_ent_sz != 32 ||
2453 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2454 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2455 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2456 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2457 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2458 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2459 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2460 header->dat_fm_tab.fm_tab_ent_cnt !=
2461 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2462 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2466 return 1;
2469 static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2471 int position, ppos;
2472 int first, last;
2473 int valid = 0;
2474 char * name = tape_name(STp);
2476 position = osst_get_frame_position(STp, aSRpnt);
2478 if (STp->raw) {
2479 STp->header_ok = STp->linux_media = 1;
2480 STp->linux_media_version = 0;
2481 return 1;
2483 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2484 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2485 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2486 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2487 #if DEBUG
2488 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2489 #endif
2491 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2492 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2494 first = position==10?0xbae: 5;
2495 last = position==10?0xbb3:10;
2497 for (ppos = first; ppos < last; ppos++)
2498 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2499 valid = 1;
2501 first = position==10? 5:0xbae;
2502 last = position==10?10:0xbb3;
2504 for (ppos = first; ppos < last; ppos++)
2505 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2506 valid = 1;
2508 if (!valid) {
2509 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2510 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2511 osst_set_frame_position(STp, aSRpnt, 10, 0);
2512 return 0;
2514 if (position <= STp->first_data_ppos) {
2515 position = STp->first_data_ppos;
2516 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2518 osst_set_frame_position(STp, aSRpnt, position, 0);
2519 STp->header_ok = 1;
2521 return 1;
2524 static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2526 int frame_position = STp->first_frame_position;
2527 int frame_seq_numbr = STp->frame_seq_number;
2528 int logical_blk_num = STp->logical_blk_num;
2529 int halfway_frame = STp->frame_in_buffer;
2530 int read_pointer = STp->buffer->read_pointer;
2531 int prev_mark_ppos = -1;
2532 int actual_mark_ppos, i, n;
2533 #if DEBUG
2534 char * name = tape_name(STp);
2536 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2537 #endif
2538 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2539 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2540 #if DEBUG
2541 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2542 #endif
2543 return (-EIO);
2545 if (STp->linux_media_version >= 4) {
2546 for (i=0; i<STp->filemark_cnt; i++)
2547 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2548 prev_mark_ppos = n;
2549 } else
2550 prev_mark_ppos = frame_position - 1; /* usually - we don't really know */
2551 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2552 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2553 if (frame_position != STp->first_frame_position ||
2554 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2555 prev_mark_ppos != actual_mark_ppos ) {
2556 #if DEBUG
2557 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2558 STp->first_frame_position, frame_position,
2559 STp->frame_seq_number + (halfway_frame?0:1),
2560 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2561 #endif
2562 return (-EIO);
2564 if (halfway_frame) {
2565 /* prepare buffer for append and rewrite on top of original */
2566 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2567 STp->buffer->buffer_bytes = read_pointer;
2568 STp->ps[STp->partition].rw = ST_WRITING;
2569 STp->dirty = 1;
2571 STp->frame_in_buffer = halfway_frame;
2572 STp->frame_seq_number = frame_seq_numbr;
2573 STp->logical_blk_num = logical_blk_num;
2574 return 0;
2577 /* Acc. to OnStream, the vers. numbering is the following:
2578 * X.XX for released versions (X=digit),
2579 * XXXY for unreleased versions (Y=letter)
2580 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2581 * This fn makes monoton numbers out of this scheme ...
2583 static unsigned int osst_parse_firmware_rev (const char * str)
2585 if (str[1] == '.') {
2586 return (str[0]-'0')*10000
2587 +(str[2]-'0')*1000
2588 +(str[3]-'0')*100;
2589 } else {
2590 return (str[0]-'0')*10000
2591 +(str[1]-'0')*1000
2592 +(str[2]-'0')*100 - 100
2593 +(str[3]-'@');
2598 * Configure the OnStream SCII tape drive for default operation
2600 static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2602 unsigned char cmd[MAX_COMMAND_SIZE];
2603 char * name = tape_name(STp);
2604 struct osst_request * SRpnt = * aSRpnt;
2605 osst_mode_parameter_header_t * header;
2606 osst_block_size_page_t * bs;
2607 osst_capabilities_page_t * cp;
2608 osst_tape_paramtr_page_t * prm;
2609 int drive_buffer_size;
2611 if (STp->ready != ST_READY) {
2612 #if DEBUG
2613 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2614 #endif
2615 return (-EIO);
2618 if (STp->os_fw_rev < 10600) {
2619 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2620 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2624 * Configure 32.5KB (data+aux) frame size.
2625 * Get the current frame size from the block size mode page
2627 memset(cmd, 0, MAX_COMMAND_SIZE);
2628 cmd[0] = MODE_SENSE;
2629 cmd[1] = 8;
2630 cmd[2] = BLOCK_SIZE_PAGE;
2631 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2633 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2634 if (SRpnt == NULL) {
2635 #if DEBUG
2636 printk(OSST_DEB_MSG "osst :D: Busy\n");
2637 #endif
2638 return (-EBUSY);
2640 *aSRpnt = SRpnt;
2641 if ((STp->buffer)->syscall_result != 0) {
2642 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2643 return (-EIO);
2646 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2647 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2649 #if DEBUG
2650 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2651 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2652 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2653 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2654 #endif
2657 * Configure default auto columns mode, 32.5KB transfer mode
2659 bs->one = 1;
2660 bs->play32 = 0;
2661 bs->play32_5 = 1;
2662 bs->record32 = 0;
2663 bs->record32_5 = 1;
2665 memset(cmd, 0, MAX_COMMAND_SIZE);
2666 cmd[0] = MODE_SELECT;
2667 cmd[1] = 0x10;
2668 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2670 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2671 *aSRpnt = SRpnt;
2672 if ((STp->buffer)->syscall_result != 0) {
2673 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2674 return (-EIO);
2677 #if DEBUG
2678 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2680 * In debug mode, we want to see as many errors as possible
2681 * to test the error recovery mechanism.
2683 osst_set_retries(STp, aSRpnt, 0);
2684 SRpnt = * aSRpnt;
2685 #endif
2688 * Set vendor name to 'LIN4' for "Linux support version 4".
2691 memset(cmd, 0, MAX_COMMAND_SIZE);
2692 cmd[0] = MODE_SELECT;
2693 cmd[1] = 0x10;
2694 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2696 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2697 header->medium_type = 0; /* Medium Type - ignoring */
2698 header->dsp = 0; /* Reserved */
2699 header->bdl = 0; /* Block Descriptor Length */
2701 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2702 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2703 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2704 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2705 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2706 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2707 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2708 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2710 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2711 *aSRpnt = SRpnt;
2713 if ((STp->buffer)->syscall_result != 0) {
2714 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2715 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2716 return (-EIO);
2719 memset(cmd, 0, MAX_COMMAND_SIZE);
2720 cmd[0] = MODE_SENSE;
2721 cmd[1] = 8;
2722 cmd[2] = CAPABILITIES_PAGE;
2723 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2725 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2726 *aSRpnt = SRpnt;
2728 if ((STp->buffer)->syscall_result != 0) {
2729 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2730 return (-EIO);
2733 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2734 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2735 sizeof(osst_mode_parameter_header_t) + header->bdl);
2737 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2739 memset(cmd, 0, MAX_COMMAND_SIZE);
2740 cmd[0] = MODE_SENSE;
2741 cmd[1] = 8;
2742 cmd[2] = TAPE_PARAMTR_PAGE;
2743 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2745 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2746 *aSRpnt = SRpnt;
2748 if ((STp->buffer)->syscall_result != 0) {
2749 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2750 return (-EIO);
2753 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2754 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2755 sizeof(osst_mode_parameter_header_t) + header->bdl);
2757 STp->density = prm->density;
2758 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2759 #if DEBUG
2760 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2761 name, STp->density, STp->capacity / 32, drive_buffer_size);
2762 #endif
2764 return 0;
2769 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2770 it messes up the block number). */
2771 static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2773 int result;
2774 char * name = tape_name(STp);
2776 #if DEBUG
2777 if (debugging)
2778 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2779 name, forward ? "forward" : "backward");
2780 #endif
2782 if (forward) {
2783 /* assumes that the filemark is already read by the drive, so this is low cost */
2784 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2786 else
2787 /* assumes this is only called if we just read the filemark! */
2788 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2790 if (result < 0)
2791 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2792 name, forward ? "forward" : "backward");
2794 return result;
2798 /* Get the tape position. */
2800 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2802 unsigned char scmd[MAX_COMMAND_SIZE];
2803 struct osst_request * SRpnt;
2804 int result = 0;
2805 char * name = tape_name(STp);
2807 /* KG: We want to be able to use it for checking Write Buffer availability
2808 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2809 char mybuf[24];
2810 char * olddata = STp->buffer->b_data;
2811 int oldsize = STp->buffer->buffer_size;
2813 if (STp->ready != ST_READY) return (-EIO);
2815 memset (scmd, 0, MAX_COMMAND_SIZE);
2816 scmd[0] = READ_POSITION;
2818 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2819 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2820 STp->timeout, MAX_RETRIES, 1);
2821 if (!SRpnt) {
2822 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2823 return (-EBUSY);
2825 *aSRpnt = SRpnt;
2827 if (STp->buffer->syscall_result)
2828 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
2830 if (result == -EINVAL)
2831 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2832 else {
2833 if (result == -EIO) { /* re-read position - this needs to preserve media errors */
2834 unsigned char mysense[16];
2835 memcpy (mysense, SRpnt->sense, 16);
2836 memset (scmd, 0, MAX_COMMAND_SIZE);
2837 scmd[0] = READ_POSITION;
2838 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2839 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2840 STp->timeout, MAX_RETRIES, 1);
2841 #if DEBUG
2842 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2843 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2844 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2845 #endif
2846 if (!STp->buffer->syscall_result)
2847 memcpy (SRpnt->sense, mysense, 16);
2848 else
2849 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2851 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2852 + ((STp->buffer)->b_data[5] << 16)
2853 + ((STp->buffer)->b_data[6] << 8)
2854 + (STp->buffer)->b_data[7];
2855 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2856 + ((STp->buffer)->b_data[ 9] << 16)
2857 + ((STp->buffer)->b_data[10] << 8)
2858 + (STp->buffer)->b_data[11];
2859 STp->cur_frames = (STp->buffer)->b_data[15];
2860 #if DEBUG
2861 if (debugging) {
2862 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2863 STp->first_frame_position, STp->last_frame_position,
2864 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2865 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2866 STp->cur_frames);
2868 #endif
2869 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2870 #if DEBUG
2871 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2872 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2873 #endif
2874 STp->first_frame_position = STp->last_frame_position;
2877 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2879 return (result == 0 ? STp->first_frame_position : result);
2883 /* Set the tape block */
2884 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2886 unsigned char scmd[MAX_COMMAND_SIZE];
2887 struct osst_request * SRpnt;
2888 struct st_partstat * STps;
2889 int result = 0;
2890 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2891 char * name = tape_name(STp);
2893 if (STp->ready != ST_READY) return (-EIO);
2895 STps = &(STp->ps[STp->partition]);
2897 if (ppos < 0 || ppos > STp->capacity) {
2898 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2899 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2900 result = (-EINVAL);
2903 do {
2904 #if DEBUG
2905 if (debugging)
2906 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2907 #endif
2908 memset (scmd, 0, MAX_COMMAND_SIZE);
2909 scmd[0] = SEEK_10;
2910 scmd[1] = 1;
2911 scmd[3] = (pp >> 24);
2912 scmd[4] = (pp >> 16);
2913 scmd[5] = (pp >> 8);
2914 scmd[6] = pp;
2915 if (skip)
2916 scmd[9] = 0x80;
2918 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
2919 MAX_RETRIES, 1);
2920 if (!SRpnt)
2921 return (-EBUSY);
2922 *aSRpnt = SRpnt;
2924 if ((STp->buffer)->syscall_result != 0) {
2925 #if DEBUG
2926 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
2927 name, STp->first_frame_position, pp);
2928 #endif
2929 result = (-EIO);
2931 if (pp != ppos)
2932 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
2933 } while ((pp != ppos) && (pp = ppos));
2934 STp->first_frame_position = STp->last_frame_position = ppos;
2935 STps->eof = ST_NOEOF;
2936 STps->at_sm = 0;
2937 STps->rw = ST_IDLE;
2938 STp->frame_in_buffer = 0;
2939 return result;
2942 static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
2944 struct st_partstat * STps = &(STp->ps[STp->partition]);
2945 int result = 0;
2947 if (STp->write_type != OS_WRITE_NEW_MARK) {
2948 /* true unless the user wrote the filemark for us */
2949 result = osst_flush_drive_buffer(STp, aSRpnt);
2950 if (result < 0) goto out;
2951 result = osst_write_filemark(STp, aSRpnt);
2952 if (result < 0) goto out;
2954 if (STps->drv_file >= 0)
2955 STps->drv_file++ ;
2956 STps->drv_block = 0;
2958 result = osst_write_eod(STp, aSRpnt);
2959 osst_write_header(STp, aSRpnt, leave_at_EOT);
2961 STps->eof = ST_FM;
2962 out:
2963 return result;
2966 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2968 /* Flush the write buffer (never need to write if variable blocksize). */
2969 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
2971 int offset, transfer, blks = 0;
2972 int result = 0;
2973 unsigned char cmd[MAX_COMMAND_SIZE];
2974 struct osst_request * SRpnt = *aSRpnt;
2975 struct st_partstat * STps;
2976 char * name = tape_name(STp);
2978 if ((STp->buffer)->writing) {
2979 if (SRpnt == (STp->buffer)->last_SRpnt)
2980 #if DEBUG
2981 { printk(OSST_DEB_MSG
2982 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
2983 #endif
2984 *aSRpnt = SRpnt = NULL;
2985 #if DEBUG
2986 } else if (SRpnt)
2987 printk(OSST_DEB_MSG
2988 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
2989 #endif
2990 osst_write_behind_check(STp);
2991 if ((STp->buffer)->syscall_result) {
2992 #if DEBUG
2993 if (debugging)
2994 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
2995 name, (STp->buffer)->midlevel_result);
2996 #endif
2997 if ((STp->buffer)->midlevel_result == INT_MAX)
2998 return (-ENOSPC);
2999 return (-EIO);
3003 result = 0;
3004 if (STp->dirty == 1) {
3006 STp->write_count++;
3007 STps = &(STp->ps[STp->partition]);
3008 STps->rw = ST_WRITING;
3009 offset = STp->buffer->buffer_bytes;
3010 blks = (offset + STp->block_size - 1) / STp->block_size;
3011 transfer = OS_FRAME_SIZE;
3013 if (offset < OS_DATA_SIZE)
3014 osst_zero_buffer_tail(STp->buffer);
3016 if (STp->poll)
3017 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3018 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3020 memset(cmd, 0, MAX_COMMAND_SIZE);
3021 cmd[0] = WRITE_6;
3022 cmd[1] = 1;
3023 cmd[4] = 1;
3025 switch (STp->write_type) {
3026 case OS_WRITE_DATA:
3027 #if DEBUG
3028 if (debugging)
3029 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3030 name, blks, STp->frame_seq_number,
3031 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3032 #endif
3033 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3034 STp->logical_blk_num - blks, STp->block_size, blks);
3035 break;
3036 case OS_WRITE_EOD:
3037 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3038 STp->logical_blk_num, 0, 0);
3039 break;
3040 case OS_WRITE_NEW_MARK:
3041 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3042 STp->logical_blk_num++, 0, blks=1);
3043 break;
3044 case OS_WRITE_HEADER:
3045 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3046 break;
3047 default: /* probably FILLER */
3048 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3050 #if DEBUG
3051 if (debugging)
3052 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3053 name, offset, transfer, blks);
3054 #endif
3056 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3057 STp->timeout, MAX_RETRIES, 1);
3058 *aSRpnt = SRpnt;
3059 if (!SRpnt)
3060 return (-EBUSY);
3062 if ((STp->buffer)->syscall_result != 0) {
3063 #if DEBUG
3064 printk(OSST_DEB_MSG
3065 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3066 name, SRpnt->sense[0], SRpnt->sense[2],
3067 SRpnt->sense[12], SRpnt->sense[13]);
3068 #endif
3069 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3070 (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3071 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3072 STp->dirty = 0;
3073 (STp->buffer)->buffer_bytes = 0;
3074 result = (-ENOSPC);
3076 else {
3077 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3078 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3079 result = (-EIO);
3082 STps->drv_block = (-1); /* FIXME - even if write recovery succeeds? */
3084 else {
3085 STp->first_frame_position++;
3086 STp->dirty = 0;
3087 (STp->buffer)->buffer_bytes = 0;
3090 #if DEBUG
3091 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3092 #endif
3093 return result;
3097 /* Flush the tape buffer. The tape will be positioned correctly unless
3098 seek_next is true. */
3099 static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3101 struct st_partstat * STps;
3102 int backspace = 0, result = 0;
3103 #if DEBUG
3104 char * name = tape_name(STp);
3105 #endif
3108 * If there was a bus reset, block further access
3109 * to this device.
3111 if( STp->pos_unknown)
3112 return (-EIO);
3114 if (STp->ready != ST_READY)
3115 return 0;
3117 STps = &(STp->ps[STp->partition]);
3118 if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
3119 STp->write_type = OS_WRITE_DATA;
3120 return osst_flush_write_buffer(STp, aSRpnt);
3122 if (STp->block_size == 0)
3123 return 0;
3125 #if DEBUG
3126 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3127 #endif
3129 if (!STp->can_bsr) {
3130 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3131 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3132 (STp->buffer)->buffer_bytes = 0;
3133 (STp->buffer)->read_pointer = 0;
3134 STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */
3137 if (!seek_next) {
3138 if (STps->eof == ST_FM_HIT) {
3139 result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3140 if (!result)
3141 STps->eof = ST_NOEOF;
3142 else {
3143 if (STps->drv_file >= 0)
3144 STps->drv_file++;
3145 STps->drv_block = 0;
3148 if (!result && backspace > 0) /* TODO -- design and run a test case for this */
3149 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3151 else if (STps->eof == ST_FM_HIT) {
3152 if (STps->drv_file >= 0)
3153 STps->drv_file++;
3154 STps->drv_block = 0;
3155 STps->eof = ST_NOEOF;
3158 return result;
3161 static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3163 unsigned char cmd[MAX_COMMAND_SIZE];
3164 struct osst_request * SRpnt;
3165 int blks;
3166 #if DEBUG
3167 char * name = tape_name(STp);
3168 #endif
3170 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3171 #if DEBUG
3172 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3173 #endif
3174 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3175 return (-EIO);
3177 /* error recovery may have bumped us past the header partition */
3178 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3179 #if DEBUG
3180 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3181 #endif
3182 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3186 if (STp->poll)
3187 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3188 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3189 return (-EIO);
3191 // osst_build_stats(STp, &SRpnt);
3193 STp->ps[STp->partition].rw = ST_WRITING;
3194 STp->write_type = OS_WRITE_DATA;
3196 memset(cmd, 0, MAX_COMMAND_SIZE);
3197 cmd[0] = WRITE_6;
3198 cmd[1] = 1;
3199 cmd[4] = 1; /* one frame at a time... */
3200 blks = STp->buffer->buffer_bytes / STp->block_size;
3201 #if DEBUG
3202 if (debugging)
3203 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3204 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3205 #endif
3206 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3207 STp->logical_blk_num - blks, STp->block_size, blks);
3209 #if DEBUG
3210 if (!synchronous)
3211 STp->write_pending = 1;
3212 #endif
3213 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3214 MAX_RETRIES, synchronous);
3215 if (!SRpnt)
3216 return (-EBUSY);
3217 *aSRpnt = SRpnt;
3219 if (synchronous) {
3220 if (STp->buffer->syscall_result != 0) {
3221 #if DEBUG
3222 if (debugging)
3223 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3224 #endif
3225 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3226 (SRpnt->sense[2] & 0x40)) {
3227 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3228 return (-ENOSPC);
3230 else {
3231 if (osst_write_error_recovery(STp, aSRpnt, 1))
3232 return (-EIO);
3235 else
3236 STp->first_frame_position++;
3239 STp->write_count++;
3241 return 0;
3244 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3245 static int do_door_lock(struct osst_tape * STp, int do_lock)
3247 int retval, cmd;
3249 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3250 #if DEBUG
3251 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3252 #endif
3253 retval = scsi_ioctl(STp->device, cmd, NULL);
3254 if (!retval) {
3255 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3257 else {
3258 STp->door_locked = ST_LOCK_FAILS;
3260 return retval;
3263 /* Set the internal state after reset */
3264 static void reset_state(struct osst_tape *STp)
3266 int i;
3267 struct st_partstat *STps;
3269 STp->pos_unknown = 0;
3270 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3271 STps = &(STp->ps[i]);
3272 STps->rw = ST_IDLE;
3273 STps->eof = ST_NOEOF;
3274 STps->at_sm = 0;
3275 STps->last_block_valid = 0;
3276 STps->drv_block = -1;
3277 STps->drv_file = -1;
3282 /* Entry points to osst */
3284 /* Write command */
3285 static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3287 ssize_t total, retval = 0;
3288 ssize_t i, do_count, blks, transfer;
3289 int write_threshold;
3290 int doing_write = 0;
3291 const char __user * b_point;
3292 struct osst_request * SRpnt = NULL;
3293 struct st_modedef * STm;
3294 struct st_partstat * STps;
3295 struct osst_tape * STp = filp->private_data;
3296 char * name = tape_name(STp);
3299 if (down_interruptible(&STp->lock))
3300 return (-ERESTARTSYS);
3303 * If we are in the middle of error recovery, don't let anyone
3304 * else try and use this device. Also, if error recovery fails, it
3305 * may try and take the device offline, in which case all further
3306 * access to the device is prohibited.
3308 if( !scsi_block_when_processing_errors(STp->device) ) {
3309 retval = (-ENXIO);
3310 goto out;
3313 if (STp->ready != ST_READY) {
3314 if (STp->ready == ST_NO_TAPE)
3315 retval = (-ENOMEDIUM);
3316 else
3317 retval = (-EIO);
3318 goto out;
3320 STm = &(STp->modes[STp->current_mode]);
3321 if (!STm->defined) {
3322 retval = (-ENXIO);
3323 goto out;
3325 if (count == 0)
3326 goto out;
3329 * If there was a bus reset, block further access
3330 * to this device.
3332 if (STp->pos_unknown) {
3333 retval = (-EIO);
3334 goto out;
3337 #if DEBUG
3338 if (!STp->in_use) {
3339 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3340 retval = (-EIO);
3341 goto out;
3343 #endif
3345 if (STp->write_prot) {
3346 retval = (-EACCES);
3347 goto out;
3350 /* Write must be integral number of blocks */
3351 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3352 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3353 name, count, STp->block_size<1024?
3354 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3355 retval = (-EINVAL);
3356 goto out;
3359 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3360 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3361 name, STp->first_frame_position);
3362 retval = (-ENOSPC);
3363 goto out;
3366 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3367 STp->door_locked = ST_LOCKED_AUTO;
3369 STps = &(STp->ps[STp->partition]);
3371 if (STps->rw == ST_READING) {
3372 #if DEBUG
3373 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3374 STps->drv_file, STps->drv_block);
3375 #endif
3376 retval = osst_flush_buffer(STp, &SRpnt, 0);
3377 if (retval)
3378 goto out;
3379 STps->rw = ST_IDLE;
3381 if (STps->rw != ST_WRITING) {
3382 /* Are we totally rewriting this tape? */
3383 if (!STp->header_ok ||
3384 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3385 (STps->drv_file == 0 && STps->drv_block == 0)) {
3386 STp->wrt_pass_cntr++;
3387 #if DEBUG
3388 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3389 name, STp->wrt_pass_cntr);
3390 #endif
3391 osst_reset_header(STp, &SRpnt);
3392 STps->drv_file = STps->drv_block = 0;
3394 /* Do we know where we'll be writing on the tape? */
3395 else {
3396 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3397 STps->drv_file < 0 || STps->drv_block < 0) {
3398 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3399 STps->drv_file = STp->filemark_cnt;
3400 STps->drv_block = 0;
3402 else {
3403 /* We have no idea where the tape is positioned - give up */
3404 #if DEBUG
3405 printk(OSST_DEB_MSG
3406 "%s:D: Cannot write at indeterminate position.\n", name);
3407 #endif
3408 retval = (-EIO);
3409 goto out;
3412 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3413 STp->filemark_cnt = STps->drv_file;
3414 STp->last_mark_ppos =
3415 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3416 printk(KERN_WARNING
3417 "%s:W: Overwriting file %d with old write pass counter %d\n",
3418 name, STps->drv_file, STp->wrt_pass_cntr);
3419 printk(KERN_WARNING
3420 "%s:W: may lead to stale data being accepted on reading back!\n",
3421 name);
3422 #if DEBUG
3423 printk(OSST_DEB_MSG
3424 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3425 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3426 #endif
3429 STp->fast_open = 0;
3431 if (!STp->header_ok) {
3432 #if DEBUG
3433 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3434 #endif
3435 retval = (-EIO);
3436 goto out;
3439 if ((STp->buffer)->writing) {
3440 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3441 osst_write_behind_check(STp);
3442 if ((STp->buffer)->syscall_result) {
3443 #if DEBUG
3444 if (debugging)
3445 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3446 (STp->buffer)->midlevel_result);
3447 #endif
3448 if ((STp->buffer)->midlevel_result == INT_MAX)
3449 STps->eof = ST_EOM_OK;
3450 else
3451 STps->eof = ST_EOM_ERROR;
3454 if (STps->eof == ST_EOM_OK) {
3455 retval = (-ENOSPC);
3456 goto out;
3458 else if (STps->eof == ST_EOM_ERROR) {
3459 retval = (-EIO);
3460 goto out;
3463 /* Check the buffer readability in cases where copy_user might catch
3464 the problems after some tape movement. */
3465 if ((copy_from_user(&i, buf, 1) != 0 ||
3466 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3467 retval = (-EFAULT);
3468 goto out;
3471 if (!STm->do_buffer_writes) {
3472 write_threshold = 1;
3474 else
3475 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3476 if (!STm->do_async_writes)
3477 write_threshold--;
3479 total = count;
3480 #if DEBUG
3481 if (debugging)
3482 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3483 name, (int) count, STps->drv_file, STps->drv_block,
3484 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3485 #endif
3486 b_point = buf;
3487 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3489 doing_write = 1;
3490 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3491 (STp->buffer)->buffer_bytes;
3492 if (do_count > count)
3493 do_count = count;
3495 i = append_to_buffer(b_point, STp->buffer, do_count);
3496 if (i) {
3497 retval = i;
3498 goto out;
3501 blks = do_count / STp->block_size;
3502 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3504 i = osst_write_frame(STp, &SRpnt, 1);
3506 if (i == (-ENOSPC)) {
3507 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3508 if (transfer <= do_count) {
3509 filp->f_pos += do_count - transfer;
3510 count -= do_count - transfer;
3511 if (STps->drv_block >= 0) {
3512 STps->drv_block += (do_count - transfer) / STp->block_size;
3514 STps->eof = ST_EOM_OK;
3515 retval = (-ENOSPC); /* EOM within current request */
3516 #if DEBUG
3517 if (debugging)
3518 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3519 name, (int) transfer);
3520 #endif
3522 else {
3523 STps->eof = ST_EOM_ERROR;
3524 STps->drv_block = (-1); /* Too cautious? */
3525 retval = (-EIO); /* EOM for old data */
3526 #if DEBUG
3527 if (debugging)
3528 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3529 #endif
3532 else
3533 retval = i;
3535 if (retval < 0) {
3536 if (SRpnt != NULL) {
3537 osst_release_request(SRpnt);
3538 SRpnt = NULL;
3540 STp->buffer->buffer_bytes = 0;
3541 STp->dirty = 0;
3542 if (count < total)
3543 retval = total - count;
3544 goto out;
3547 filp->f_pos += do_count;
3548 b_point += do_count;
3549 count -= do_count;
3550 if (STps->drv_block >= 0) {
3551 STps->drv_block += blks;
3553 STp->buffer->buffer_bytes = 0;
3554 STp->dirty = 0;
3555 } /* end while write threshold exceeded */
3557 if (count != 0) {
3558 STp->dirty = 1;
3559 i = append_to_buffer(b_point, STp->buffer, count);
3560 if (i) {
3561 retval = i;
3562 goto out;
3564 blks = count / STp->block_size;
3565 STp->logical_blk_num += blks;
3566 if (STps->drv_block >= 0) {
3567 STps->drv_block += blks;
3569 filp->f_pos += count;
3570 count = 0;
3573 if (doing_write && (STp->buffer)->syscall_result != 0) {
3574 retval = (STp->buffer)->syscall_result;
3575 goto out;
3578 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3579 /* Schedule an asynchronous write */
3580 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3581 STp->block_size) * STp->block_size;
3582 STp->dirty = !((STp->buffer)->writing ==
3583 (STp->buffer)->buffer_bytes);
3585 i = osst_write_frame(STp, &SRpnt, 0);
3586 if (i < 0) {
3587 retval = (-EIO);
3588 goto out;
3590 SRpnt = NULL; /* Prevent releasing this request! */
3592 STps->at_sm &= (total == 0);
3593 if (total > 0)
3594 STps->eof = ST_NOEOF;
3596 retval = total;
3598 out:
3599 if (SRpnt != NULL) osst_release_request(SRpnt);
3601 up(&STp->lock);
3603 return retval;
3607 /* Read command */
3608 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3610 ssize_t total, retval = 0;
3611 ssize_t i, transfer;
3612 int special;
3613 struct st_modedef * STm;
3614 struct st_partstat * STps;
3615 struct osst_request * SRpnt = NULL;
3616 struct osst_tape * STp = filp->private_data;
3617 char * name = tape_name(STp);
3620 if (down_interruptible(&STp->lock))
3621 return (-ERESTARTSYS);
3624 * If we are in the middle of error recovery, don't let anyone
3625 * else try and use this device. Also, if error recovery fails, it
3626 * may try and take the device offline, in which case all further
3627 * access to the device is prohibited.
3629 if( !scsi_block_when_processing_errors(STp->device) ) {
3630 retval = (-ENXIO);
3631 goto out;
3634 if (STp->ready != ST_READY) {
3635 if (STp->ready == ST_NO_TAPE)
3636 retval = (-ENOMEDIUM);
3637 else
3638 retval = (-EIO);
3639 goto out;
3641 STm = &(STp->modes[STp->current_mode]);
3642 if (!STm->defined) {
3643 retval = (-ENXIO);
3644 goto out;
3646 #if DEBUG
3647 if (!STp->in_use) {
3648 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3649 retval = (-EIO);
3650 goto out;
3652 #endif
3653 /* Must have initialized medium */
3654 if (!STp->header_ok) {
3655 retval = (-EIO);
3656 goto out;
3659 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3660 STp->door_locked = ST_LOCKED_AUTO;
3662 STps = &(STp->ps[STp->partition]);
3663 if (STps->rw == ST_WRITING) {
3664 retval = osst_flush_buffer(STp, &SRpnt, 0);
3665 if (retval)
3666 goto out;
3667 STps->rw = ST_IDLE;
3668 /* FIXME -- this may leave the tape without EOD and up2date headers */
3671 if ((count % STp->block_size) != 0) {
3672 printk(KERN_WARNING
3673 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3674 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3677 #if DEBUG
3678 if (debugging && STps->eof != ST_NOEOF)
3679 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3680 STps->eof, (STp->buffer)->buffer_bytes);
3681 #endif
3682 if ((STp->buffer)->buffer_bytes == 0 &&
3683 STps->eof >= ST_EOD_1) {
3684 if (STps->eof < ST_EOD) {
3685 STps->eof += 1;
3686 retval = 0;
3687 goto out;
3689 retval = (-EIO); /* EOM or Blank Check */
3690 goto out;
3693 /* Check the buffer writability before any tape movement. Don't alter
3694 buffer data. */
3695 if (copy_from_user(&i, buf, 1) != 0 ||
3696 copy_to_user (buf, &i, 1) != 0 ||
3697 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3698 copy_to_user (buf + count - 1, &i, 1) != 0) {
3699 retval = (-EFAULT);
3700 goto out;
3703 /* Loop until enough data in buffer or a special condition found */
3704 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3706 /* Get new data if the buffer is empty */
3707 if ((STp->buffer)->buffer_bytes == 0) {
3708 if (STps->eof == ST_FM_HIT)
3709 break;
3710 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3711 if (special < 0) { /* No need to continue read */
3712 STp->frame_in_buffer = 0;
3713 retval = special;
3714 goto out;
3718 /* Move the data from driver buffer to user buffer */
3719 if ((STp->buffer)->buffer_bytes > 0) {
3720 #if DEBUG
3721 if (debugging && STps->eof != ST_NOEOF)
3722 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3723 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3724 #endif
3725 /* force multiple of block size, note block_size may have been adjusted */
3726 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3727 (STp->buffer)->buffer_bytes : count - total)/
3728 STp->block_size) * STp->block_size;
3730 if (transfer == 0) {
3731 printk(KERN_WARNING
3732 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3733 name, count, STp->block_size < 1024?
3734 STp->block_size:STp->block_size/1024,
3735 STp->block_size<1024?'b':'k');
3736 break;
3738 i = from_buffer(STp->buffer, buf, transfer);
3739 if (i) {
3740 retval = i;
3741 goto out;
3743 STp->logical_blk_num += transfer / STp->block_size;
3744 STps->drv_block += transfer / STp->block_size;
3745 filp->f_pos += transfer;
3746 buf += transfer;
3747 total += transfer;
3750 if ((STp->buffer)->buffer_bytes == 0) {
3751 #if DEBUG
3752 if (debugging)
3753 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3754 name, STp->frame_seq_number);
3755 #endif
3756 STp->frame_in_buffer = 0;
3757 STp->frame_seq_number++; /* frame to look for next time */
3759 } /* for (total = 0, special = 0; total < count && !special; ) */
3761 /* Change the eof state if no data from tape or buffer */
3762 if (total == 0) {
3763 if (STps->eof == ST_FM_HIT) {
3764 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3765 STps->drv_block = 0;
3766 if (STps->drv_file >= 0)
3767 STps->drv_file++;
3769 else if (STps->eof == ST_EOD_1) {
3770 STps->eof = ST_EOD_2;
3771 if (STps->drv_block > 0 && STps->drv_file >= 0)
3772 STps->drv_file++;
3773 STps->drv_block = 0;
3775 else if (STps->eof == ST_EOD_2)
3776 STps->eof = ST_EOD;
3778 else if (STps->eof == ST_FM)
3779 STps->eof = ST_NOEOF;
3781 retval = total;
3783 out:
3784 if (SRpnt != NULL) osst_release_request(SRpnt);
3786 up(&STp->lock);
3788 return retval;
3792 /* Set the driver options */
3793 static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3795 printk(KERN_INFO
3796 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3797 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3798 STm->do_read_ahead);
3799 printk(KERN_INFO
3800 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3801 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3802 printk(KERN_INFO
3803 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3804 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3805 STp->scsi2_logical);
3806 printk(KERN_INFO
3807 "%s:I: sysv: %d\n", name, STm->sysv);
3808 #if DEBUG
3809 printk(KERN_INFO
3810 "%s:D: debugging: %d\n",
3811 name, debugging);
3812 #endif
3816 static int osst_set_options(struct osst_tape *STp, long options)
3818 int value;
3819 long code;
3820 struct st_modedef * STm;
3821 char * name = tape_name(STp);
3823 STm = &(STp->modes[STp->current_mode]);
3824 if (!STm->defined) {
3825 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3826 modes_defined = 1;
3827 #if DEBUG
3828 if (debugging)
3829 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3830 name, STp->current_mode);
3831 #endif
3834 code = options & MT_ST_OPTIONS;
3835 if (code == MT_ST_BOOLEANS) {
3836 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3837 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3838 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3839 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3840 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3841 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3842 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3843 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3844 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3845 if ((STp->device)->scsi_level >= SCSI_2)
3846 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3847 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3848 STm->sysv = (options & MT_ST_SYSV) != 0;
3849 #if DEBUG
3850 debugging = (options & MT_ST_DEBUGGING) != 0;
3851 #endif
3852 osst_log_options(STp, STm, name);
3854 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3855 value = (code == MT_ST_SETBOOLEANS);
3856 if ((options & MT_ST_BUFFER_WRITES) != 0)
3857 STm->do_buffer_writes = value;
3858 if ((options & MT_ST_ASYNC_WRITES) != 0)
3859 STm->do_async_writes = value;
3860 if ((options & MT_ST_DEF_WRITES) != 0)
3861 STm->defaults_for_writes = value;
3862 if ((options & MT_ST_READ_AHEAD) != 0)
3863 STm->do_read_ahead = value;
3864 if ((options & MT_ST_TWO_FM) != 0)
3865 STp->two_fm = value;
3866 if ((options & MT_ST_FAST_MTEOM) != 0)
3867 STp->fast_mteom = value;
3868 if ((options & MT_ST_AUTO_LOCK) != 0)
3869 STp->do_auto_lock = value;
3870 if ((options & MT_ST_CAN_BSR) != 0)
3871 STp->can_bsr = value;
3872 if ((options & MT_ST_NO_BLKLIMS) != 0)
3873 STp->omit_blklims = value;
3874 if ((STp->device)->scsi_level >= SCSI_2 &&
3875 (options & MT_ST_CAN_PARTITIONS) != 0)
3876 STp->can_partitions = value;
3877 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3878 STp->scsi2_logical = value;
3879 if ((options & MT_ST_SYSV) != 0)
3880 STm->sysv = value;
3881 #if DEBUG
3882 if ((options & MT_ST_DEBUGGING) != 0)
3883 debugging = value;
3884 #endif
3885 osst_log_options(STp, STm, name);
3887 else if (code == MT_ST_WRITE_THRESHOLD) {
3888 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3889 if (value < 1 || value > osst_buffer_size) {
3890 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3891 name, value);
3892 return (-EIO);
3894 STp->write_threshold = value;
3895 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3896 name, value);
3898 else if (code == MT_ST_DEF_BLKSIZE) {
3899 value = (options & ~MT_ST_OPTIONS);
3900 if (value == ~MT_ST_OPTIONS) {
3901 STm->default_blksize = (-1);
3902 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3904 else {
3905 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3906 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3907 name, value);
3908 return (-EINVAL);
3910 STm->default_blksize = value;
3911 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3912 name, STm->default_blksize);
3915 else if (code == MT_ST_TIMEOUTS) {
3916 value = (options & ~MT_ST_OPTIONS);
3917 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3918 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3919 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3920 (value & ~MT_ST_SET_LONG_TIMEOUT));
3922 else {
3923 STp->timeout = value * HZ;
3924 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3927 else if (code == MT_ST_DEF_OPTIONS) {
3928 code = (options & ~MT_ST_CLEAR_DEFAULT);
3929 value = (options & MT_ST_CLEAR_DEFAULT);
3930 if (code == MT_ST_DEF_DENSITY) {
3931 if (value == MT_ST_CLEAR_DEFAULT) {
3932 STm->default_density = (-1);
3933 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3935 else {
3936 STm->default_density = value & 0xff;
3937 printk(KERN_INFO "%s:I: Density default set to %x\n",
3938 name, STm->default_density);
3941 else if (code == MT_ST_DEF_DRVBUFFER) {
3942 if (value == MT_ST_CLEAR_DEFAULT) {
3943 STp->default_drvbuffer = 0xff;
3944 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3946 else {
3947 STp->default_drvbuffer = value & 7;
3948 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3949 name, STp->default_drvbuffer);
3952 else if (code == MT_ST_DEF_COMPRESSION) {
3953 if (value == MT_ST_CLEAR_DEFAULT) {
3954 STm->default_compression = ST_DONT_TOUCH;
3955 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3957 else {
3958 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3959 printk(KERN_INFO "%s:I: Compression default set to %x\n",
3960 name, (value & 1));
3964 else
3965 return (-EIO);
3967 return 0;
3971 /* Internal ioctl function */
3972 static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
3973 unsigned int cmd_in, unsigned long arg)
3975 int timeout;
3976 long ltmp;
3977 int i, ioctl_result;
3978 int chg_eof = 1;
3979 unsigned char cmd[MAX_COMMAND_SIZE];
3980 struct osst_request * SRpnt = * aSRpnt;
3981 struct st_partstat * STps;
3982 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3983 int datalen = 0, direction = DMA_NONE;
3984 char * name = tape_name(STp);
3986 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3987 if (STp->ready == ST_NO_TAPE)
3988 return (-ENOMEDIUM);
3989 else
3990 return (-EIO);
3992 timeout = STp->long_timeout;
3993 STps = &(STp->ps[STp->partition]);
3994 fileno = STps->drv_file;
3995 blkno = STps->drv_block;
3996 at_sm = STps->at_sm;
3997 frame_seq_numbr = STp->frame_seq_number;
3998 logical_blk_num = STp->logical_blk_num;
4000 memset(cmd, 0, MAX_COMMAND_SIZE);
4001 switch (cmd_in) {
4002 case MTFSFM:
4003 chg_eof = 0; /* Changed from the FSF after this */
4004 case MTFSF:
4005 if (STp->raw)
4006 return (-EIO);
4007 if (STp->linux_media)
4008 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4009 else
4010 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4011 if (fileno >= 0)
4012 fileno += arg;
4013 blkno = 0;
4014 at_sm &= (arg == 0);
4015 goto os_bypass;
4017 case MTBSF:
4018 chg_eof = 0; /* Changed from the FSF after this */
4019 case MTBSFM:
4020 if (STp->raw)
4021 return (-EIO);
4022 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4023 if (fileno >= 0)
4024 fileno -= arg;
4025 blkno = (-1); /* We can't know the block number */
4026 at_sm &= (arg == 0);
4027 goto os_bypass;
4029 case MTFSR:
4030 case MTBSR:
4031 #if DEBUG
4032 if (debugging)
4033 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4034 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4035 #endif
4036 if (cmd_in == MTFSR) {
4037 logical_blk_num += arg;
4038 if (blkno >= 0) blkno += arg;
4040 else {
4041 logical_blk_num -= arg;
4042 if (blkno >= 0) blkno -= arg;
4044 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4045 fileno = STps->drv_file;
4046 blkno = STps->drv_block;
4047 at_sm &= (arg == 0);
4048 goto os_bypass;
4050 case MTFSS:
4051 cmd[0] = SPACE;
4052 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4053 cmd[2] = (arg >> 16);
4054 cmd[3] = (arg >> 8);
4055 cmd[4] = arg;
4056 #if DEBUG
4057 if (debugging)
4058 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4059 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4060 #endif
4061 if (arg != 0) {
4062 blkno = fileno = (-1);
4063 at_sm = 1;
4065 break;
4066 case MTBSS:
4067 cmd[0] = SPACE;
4068 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4069 ltmp = (-arg);
4070 cmd[2] = (ltmp >> 16);
4071 cmd[3] = (ltmp >> 8);
4072 cmd[4] = ltmp;
4073 #if DEBUG
4074 if (debugging) {
4075 if (cmd[2] & 0x80)
4076 ltmp = 0xff000000;
4077 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4078 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4079 name, (-ltmp));
4081 #endif
4082 if (arg != 0) {
4083 blkno = fileno = (-1);
4084 at_sm = 1;
4086 break;
4087 case MTWEOF:
4088 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4089 STp->write_type = OS_WRITE_DATA;
4090 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4091 } else
4092 ioctl_result = 0;
4093 #if DEBUG
4094 if (debugging)
4095 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4096 #endif
4097 for (i=0; i<arg; i++)
4098 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4099 if (fileno >= 0) fileno += arg;
4100 if (blkno >= 0) blkno = 0;
4101 goto os_bypass;
4103 case MTWSM:
4104 if (STp->write_prot)
4105 return (-EACCES);
4106 if (!STp->raw)
4107 return 0;
4108 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
4109 if (cmd_in == MTWSM)
4110 cmd[1] = 2;
4111 cmd[2] = (arg >> 16);
4112 cmd[3] = (arg >> 8);
4113 cmd[4] = arg;
4114 timeout = STp->timeout;
4115 #if DEBUG
4116 if (debugging)
4117 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4118 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4119 #endif
4120 if (fileno >= 0)
4121 fileno += arg;
4122 blkno = 0;
4123 at_sm = (cmd_in == MTWSM);
4124 break;
4125 case MTOFFL:
4126 case MTLOAD:
4127 case MTUNLOAD:
4128 case MTRETEN:
4129 cmd[0] = START_STOP;
4130 cmd[1] = 1; /* Don't wait for completion */
4131 if (cmd_in == MTLOAD) {
4132 if (STp->ready == ST_NO_TAPE)
4133 cmd[4] = 4; /* open tray */
4134 else
4135 cmd[4] = 1; /* load */
4137 if (cmd_in == MTRETEN)
4138 cmd[4] = 3; /* retension then mount */
4139 if (cmd_in == MTOFFL)
4140 cmd[4] = 4; /* rewind then eject */
4141 timeout = STp->timeout;
4142 #if DEBUG
4143 if (debugging) {
4144 switch (cmd_in) {
4145 case MTUNLOAD:
4146 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4147 break;
4148 case MTLOAD:
4149 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4150 break;
4151 case MTRETEN:
4152 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4153 break;
4154 case MTOFFL:
4155 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4156 break;
4159 #endif
4160 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4161 break;
4162 case MTNOP:
4163 #if DEBUG
4164 if (debugging)
4165 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4166 #endif
4167 return 0; /* Should do something ? */
4168 break;
4169 case MTEOM:
4170 #if DEBUG
4171 if (debugging)
4172 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4173 #endif
4174 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4175 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4176 ioctl_result = -EIO;
4177 goto os_bypass;
4179 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4180 #if DEBUG
4181 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4182 #endif
4183 ioctl_result = -EIO;
4184 goto os_bypass;
4186 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4187 fileno = STp->filemark_cnt;
4188 blkno = at_sm = 0;
4189 goto os_bypass;
4191 case MTERASE:
4192 if (STp->write_prot)
4193 return (-EACCES);
4194 ioctl_result = osst_reset_header(STp, &SRpnt);
4195 i = osst_write_eod(STp, &SRpnt);
4196 if (i < ioctl_result) ioctl_result = i;
4197 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4198 if (i < ioctl_result) ioctl_result = i;
4199 fileno = blkno = at_sm = 0 ;
4200 goto os_bypass;
4202 case MTREW:
4203 cmd[0] = REZERO_UNIT; /* rewind */
4204 cmd[1] = 1;
4205 #if DEBUG
4206 if (debugging)
4207 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4208 #endif
4209 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4210 break;
4212 case MTSETBLK: /* Set block length */
4213 if ((STps->drv_block == 0 ) &&
4214 !STp->dirty &&
4215 ((STp->buffer)->buffer_bytes == 0) &&
4216 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4217 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4218 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4220 * Only allowed to change the block size if you opened the
4221 * device at the beginning of a file before writing anything.
4222 * Note, that when reading, changing block_size is futile,
4223 * as the size used when writing overrides it.
4225 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4226 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4227 name, STp->block_size);
4228 return 0;
4230 case MTSETDENSITY: /* Set tape density */
4231 case MTSETDRVBUFFER: /* Set drive buffering */
4232 case SET_DENS_AND_BLK: /* Set density and block size */
4233 chg_eof = 0;
4234 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4235 return (-EIO); /* Not allowed if data in buffer */
4236 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4237 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4238 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4239 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4240 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4241 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4242 return (-EINVAL);
4244 return 0; /* FIXME silently ignore if block size didn't change */
4246 default:
4247 return (-ENOSYS);
4250 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4252 ioctl_result = (STp->buffer)->syscall_result;
4254 if (!SRpnt) {
4255 #if DEBUG
4256 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4257 #endif
4258 return ioctl_result;
4261 if (!ioctl_result) { /* SCSI command successful */
4262 STp->frame_seq_number = frame_seq_numbr;
4263 STp->logical_blk_num = logical_blk_num;
4266 os_bypass:
4267 #if DEBUG
4268 if (debugging)
4269 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4270 #endif
4272 if (!ioctl_result) { /* success */
4274 if (cmd_in == MTFSFM) {
4275 fileno--;
4276 blkno--;
4278 if (cmd_in == MTBSFM) {
4279 fileno++;
4280 blkno++;
4282 STps->drv_block = blkno;
4283 STps->drv_file = fileno;
4284 STps->at_sm = at_sm;
4286 if (cmd_in == MTEOM)
4287 STps->eof = ST_EOD;
4288 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4289 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4290 STps->drv_block++;
4291 STp->logical_blk_num++;
4292 STp->frame_seq_number++;
4293 STp->frame_in_buffer = 0;
4294 STp->buffer->read_pointer = 0;
4296 else if (cmd_in == MTFSF)
4297 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4298 else if (chg_eof)
4299 STps->eof = ST_NOEOF;
4301 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4302 STp->rew_at_close = 0;
4303 else if (cmd_in == MTLOAD) {
4304 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4305 STp->ps[i].rw = ST_IDLE;
4306 STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4308 STp->partition = 0;
4311 if (cmd_in == MTREW) {
4312 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4313 if (ioctl_result > 0)
4314 ioctl_result = 0;
4317 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4318 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4319 STps->drv_file = STps->drv_block = -1;
4320 else
4321 STps->drv_file = STps->drv_block = 0;
4322 STps->eof = ST_NOEOF;
4323 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4324 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4325 STps->drv_file = STps->drv_block = -1;
4326 else {
4327 STps->drv_file = STp->filemark_cnt;
4328 STps->drv_block = 0;
4330 STps->eof = ST_EOD;
4331 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4332 STps->drv_file = STps->drv_block = (-1);
4333 STps->eof = ST_NOEOF;
4334 STp->header_ok = 0;
4335 } else if (cmd_in == MTERASE) {
4336 STp->header_ok = 0;
4337 } else if (SRpnt) { /* SCSI command was not completely successful. */
4338 if (SRpnt->sense[2] & 0x40) {
4339 STps->eof = ST_EOM_OK;
4340 STps->drv_block = 0;
4342 if (chg_eof)
4343 STps->eof = ST_NOEOF;
4345 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4346 STps->eof = ST_EOD;
4348 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4349 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4351 *aSRpnt = SRpnt;
4353 return ioctl_result;
4357 /* Open the device */
4358 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4360 unsigned short flags;
4361 int i, b_size, new_session = 0, retval = 0;
4362 unsigned char cmd[MAX_COMMAND_SIZE];
4363 struct osst_request * SRpnt = NULL;
4364 struct osst_tape * STp;
4365 struct st_modedef * STm;
4366 struct st_partstat * STps;
4367 char * name;
4368 int dev = TAPE_NR(inode);
4369 int mode = TAPE_MODE(inode);
4372 * We really want to do nonseekable_open(inode, filp); here, but some
4373 * versions of tar incorrectly call lseek on tapes and bail out if that
4374 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4376 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4378 write_lock(&os_scsi_tapes_lock);
4379 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4380 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4381 write_unlock(&os_scsi_tapes_lock);
4382 return (-ENXIO);
4385 name = tape_name(STp);
4387 if (STp->in_use) {
4388 write_unlock(&os_scsi_tapes_lock);
4389 #if DEBUG
4390 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4391 #endif
4392 return (-EBUSY);
4394 if (scsi_device_get(STp->device)) {
4395 write_unlock(&os_scsi_tapes_lock);
4396 #if DEBUG
4397 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4398 #endif
4399 return (-ENXIO);
4401 filp->private_data = STp;
4402 STp->in_use = 1;
4403 write_unlock(&os_scsi_tapes_lock);
4404 STp->rew_at_close = TAPE_REWIND(inode);
4406 if( !scsi_block_when_processing_errors(STp->device) ) {
4407 return -ENXIO;
4410 if (mode != STp->current_mode) {
4411 #if DEBUG
4412 if (debugging)
4413 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4414 name, STp->current_mode, mode);
4415 #endif
4416 new_session = 1;
4417 STp->current_mode = mode;
4419 STm = &(STp->modes[STp->current_mode]);
4421 flags = filp->f_flags;
4422 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4424 STp->raw = TAPE_IS_RAW(inode);
4425 if (STp->raw)
4426 STp->header_ok = 0;
4428 /* Allocate data segments for this device's tape buffer */
4429 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4430 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4431 retval = (-EOVERFLOW);
4432 goto err_out;
4434 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4435 for (i = 0, b_size = 0;
4436 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4437 b_size += STp->buffer->sg[i++].length);
4438 STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
4439 #if DEBUG
4440 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4441 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4442 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4443 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4444 #endif
4445 } else {
4446 STp->buffer->aux = NULL; /* this had better never happen! */
4447 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4448 retval = (-EIO);
4449 goto err_out;
4451 STp->buffer->writing = 0;
4452 STp->buffer->syscall_result = 0;
4453 STp->dirty = 0;
4454 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4455 STps = &(STp->ps[i]);
4456 STps->rw = ST_IDLE;
4458 STp->ready = ST_READY;
4459 #if DEBUG
4460 STp->nbr_waits = STp->nbr_finished = 0;
4461 #endif
4463 memset (cmd, 0, MAX_COMMAND_SIZE);
4464 cmd[0] = TEST_UNIT_READY;
4466 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4467 if (!SRpnt) {
4468 retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
4469 goto err_out;
4471 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4472 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4473 SRpnt->sense[12] == 4 ) {
4474 #if DEBUG
4475 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4476 #endif
4477 if (filp->f_flags & O_NONBLOCK) {
4478 retval = -EAGAIN;
4479 goto err_out;
4481 if (SRpnt->sense[13] == 2) { /* initialize command required (LOAD) */
4482 memset (cmd, 0, MAX_COMMAND_SIZE);
4483 cmd[0] = START_STOP;
4484 cmd[1] = 1;
4485 cmd[4] = 1;
4486 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4487 STp->timeout, MAX_RETRIES, 1);
4489 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4491 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4492 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4493 #if DEBUG
4494 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4495 #endif
4496 STp->header_ok = 0;
4498 for (i=0; i < 10; i++) {
4500 memset (cmd, 0, MAX_COMMAND_SIZE);
4501 cmd[0] = TEST_UNIT_READY;
4503 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4504 STp->timeout, MAX_RETRIES, 1);
4505 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4506 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4507 break;
4510 STp->pos_unknown = 0;
4511 STp->partition = STp->new_partition = 0;
4512 if (STp->can_partitions)
4513 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4514 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4515 STps = &(STp->ps[i]);
4516 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4517 STps->eof = ST_NOEOF;
4518 STps->at_sm = 0;
4519 STps->last_block_valid = 0;
4520 STps->drv_block = 0;
4521 STps->drv_file = 0 ;
4523 new_session = 1;
4524 STp->recover_count = 0;
4525 STp->abort_count = 0;
4528 * if we have valid headers from before, and the drive/tape seem untouched,
4529 * open without reconfiguring and re-reading the headers
4531 if (!STp->buffer->syscall_result && STp->header_ok &&
4532 !SRpnt->result && SRpnt->sense[0] == 0) {
4534 memset(cmd, 0, MAX_COMMAND_SIZE);
4535 cmd[0] = MODE_SENSE;
4536 cmd[1] = 8;
4537 cmd[2] = VENDOR_IDENT_PAGE;
4538 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4540 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4542 if (STp->buffer->syscall_result ||
4543 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4544 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4545 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4546 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4547 #if DEBUG
4548 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4549 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4550 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4551 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4552 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4553 #endif
4554 STp->header_ok = 0;
4556 i = STp->first_frame_position;
4557 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4558 if (STp->door_locked == ST_UNLOCKED) {
4559 if (do_door_lock(STp, 1))
4560 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4561 else
4562 STp->door_locked = ST_LOCKED_AUTO;
4564 if (!STp->frame_in_buffer) {
4565 STp->block_size = (STm->default_blksize > 0) ?
4566 STm->default_blksize : OS_DATA_SIZE;
4567 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4569 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4570 STp->fast_open = 1;
4571 osst_release_request(SRpnt);
4572 return 0;
4574 #if DEBUG
4575 if (i != STp->first_frame_position)
4576 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4577 name, i, STp->first_frame_position);
4578 #endif
4579 STp->header_ok = 0;
4581 STp->fast_open = 0;
4583 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4584 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4586 memset(cmd, 0, MAX_COMMAND_SIZE);
4587 cmd[0] = MODE_SELECT;
4588 cmd[1] = 0x10;
4589 cmd[4] = 4 + MODE_HEADER_LENGTH;
4591 (STp->buffer)->b_data[0] = cmd[4] - 1;
4592 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4593 (STp->buffer)->b_data[2] = 0; /* Reserved */
4594 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4595 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4596 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4597 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4598 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4600 #if DEBUG
4601 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4602 #endif
4603 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4605 STp->header_ok = 0;
4607 for (i=0; i < 10; i++) {
4609 memset (cmd, 0, MAX_COMMAND_SIZE);
4610 cmd[0] = TEST_UNIT_READY;
4612 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4613 STp->timeout, MAX_RETRIES, 1);
4614 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4615 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4616 break;
4618 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4619 STp->pos_unknown = 0;
4620 STp->partition = STp->new_partition = 0;
4621 if (STp->can_partitions)
4622 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4623 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4624 STps = &(STp->ps[i]);
4625 STps->rw = ST_IDLE;
4626 STps->eof = ST_NOEOF;
4627 STps->at_sm = 0;
4628 STps->last_block_valid = 0;
4629 STps->drv_block = 0;
4630 STps->drv_file = 0 ;
4632 new_session = 1;
4637 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4638 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4640 if ((STp->buffer)->syscall_result != 0) {
4641 if ((STp->device)->scsi_level >= SCSI_2 &&
4642 (SRpnt->sense[0] & 0x70) == 0x70 &&
4643 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4644 SRpnt->sense[12] == 0x3a) { /* Check ASC */
4645 STp->ready = ST_NO_TAPE;
4646 } else
4647 STp->ready = ST_NOT_READY;
4648 osst_release_request(SRpnt);
4649 SRpnt = NULL;
4650 STp->density = 0; /* Clear the erroneous "residue" */
4651 STp->write_prot = 0;
4652 STp->block_size = 0;
4653 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4654 STp->partition = STp->new_partition = 0;
4655 STp->door_locked = ST_UNLOCKED;
4656 return 0;
4659 osst_configure_onstream(STp, &SRpnt);
4661 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4662 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4663 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4664 STp->buffer->buffer_bytes =
4665 STp->buffer->read_pointer =
4666 STp->frame_in_buffer = 0;
4668 #if DEBUG
4669 if (debugging)
4670 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4671 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4672 (STp->buffer)->buffer_blocks);
4673 #endif
4675 if (STp->drv_write_prot) {
4676 STp->write_prot = 1;
4677 #if DEBUG
4678 if (debugging)
4679 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4680 #endif
4681 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4682 retval = (-EROFS);
4683 goto err_out;
4687 if (new_session) { /* Change the drive parameters for the new mode */
4688 #if DEBUG
4689 if (debugging)
4690 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4691 #endif
4692 STp->density_changed = STp->blksize_changed = 0;
4693 STp->compression_changed = 0;
4697 * properly position the tape and check the ADR headers
4699 if (STp->door_locked == ST_UNLOCKED) {
4700 if (do_door_lock(STp, 1))
4701 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4702 else
4703 STp->door_locked = ST_LOCKED_AUTO;
4706 osst_analyze_headers(STp, &SRpnt);
4708 osst_release_request(SRpnt);
4709 SRpnt = NULL;
4711 return 0;
4713 err_out:
4714 if (SRpnt != NULL)
4715 osst_release_request(SRpnt);
4716 normalize_buffer(STp->buffer);
4717 STp->header_ok = 0;
4718 STp->in_use = 0;
4719 scsi_device_put(STp->device);
4721 return retval;
4725 /* Flush the tape buffer before close */
4726 static int os_scsi_tape_flush(struct file * filp)
4728 int result = 0, result2;
4729 struct osst_tape * STp = filp->private_data;
4730 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4731 struct st_partstat * STps = &(STp->ps[STp->partition]);
4732 struct osst_request * SRpnt = NULL;
4733 char * name = tape_name(STp);
4735 if (file_count(filp) > 1)
4736 return 0;
4738 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4739 STp->write_type = OS_WRITE_DATA;
4740 result = osst_flush_write_buffer(STp, &SRpnt);
4741 if (result != 0 && result != (-ENOSPC))
4742 goto out;
4744 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4746 #if DEBUG
4747 if (debugging) {
4748 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4749 name, (long)(filp->f_pos));
4750 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4751 name, STp->nbr_waits, STp->nbr_finished);
4753 #endif
4754 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4755 #if DEBUG
4756 if (debugging)
4757 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4758 name, 1+STp->two_fm);
4759 #endif
4761 else if (!STp->rew_at_close) {
4762 STps = &(STp->ps[STp->partition]);
4763 if (!STm->sysv || STps->rw != ST_READING) {
4764 if (STp->can_bsr)
4765 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4766 else if (STps->eof == ST_FM_HIT) {
4767 result = cross_eof(STp, &SRpnt, 0);
4768 if (result) {
4769 if (STps->drv_file >= 0)
4770 STps->drv_file++;
4771 STps->drv_block = 0;
4772 STps->eof = ST_FM;
4774 else
4775 STps->eof = ST_NOEOF;
4778 else if ((STps->eof == ST_NOEOF &&
4779 !(result = cross_eof(STp, &SRpnt, 1))) ||
4780 STps->eof == ST_FM_HIT) {
4781 if (STps->drv_file >= 0)
4782 STps->drv_file++;
4783 STps->drv_block = 0;
4784 STps->eof = ST_FM;
4788 out:
4789 if (STp->rew_at_close) {
4790 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4791 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4792 if (result == 0 && result2 < 0)
4793 result = result2;
4795 if (SRpnt) osst_release_request(SRpnt);
4797 if (STp->abort_count || STp->recover_count) {
4798 printk(KERN_INFO "%s:I:", name);
4799 if (STp->abort_count)
4800 printk(" %d unrecovered errors", STp->abort_count);
4801 if (STp->recover_count)
4802 printk(" %d recovered errors", STp->recover_count);
4803 if (STp->write_count)
4804 printk(" in %d frames written", STp->write_count);
4805 if (STp->read_count)
4806 printk(" in %d frames read", STp->read_count);
4807 printk("\n");
4808 STp->recover_count = 0;
4809 STp->abort_count = 0;
4811 STp->write_count = 0;
4812 STp->read_count = 0;
4814 return result;
4818 /* Close the device and release it */
4819 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4821 int result = 0;
4822 struct osst_tape * STp = filp->private_data;
4824 if (STp->door_locked == ST_LOCKED_AUTO)
4825 do_door_lock(STp, 0);
4827 if (STp->raw)
4828 STp->header_ok = 0;
4830 normalize_buffer(STp->buffer);
4831 write_lock(&os_scsi_tapes_lock);
4832 STp->in_use = 0;
4833 write_unlock(&os_scsi_tapes_lock);
4835 scsi_device_put(STp->device);
4837 return result;
4841 /* The ioctl command */
4842 static int osst_ioctl(struct inode * inode,struct file * file,
4843 unsigned int cmd_in, unsigned long arg)
4845 int i, cmd_nr, cmd_type, retval = 0;
4846 unsigned int blk;
4847 struct st_modedef * STm;
4848 struct st_partstat * STps;
4849 struct osst_request * SRpnt = NULL;
4850 struct osst_tape * STp = file->private_data;
4851 char * name = tape_name(STp);
4852 void __user * p = (void __user *)arg;
4854 if (down_interruptible(&STp->lock))
4855 return -ERESTARTSYS;
4857 #if DEBUG
4858 if (debugging && !STp->in_use) {
4859 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4860 retval = (-EIO);
4861 goto out;
4863 #endif
4864 STm = &(STp->modes[STp->current_mode]);
4865 STps = &(STp->ps[STp->partition]);
4868 * If we are in the middle of error recovery, don't let anyone
4869 * else try and use this device. Also, if error recovery fails, it
4870 * may try and take the device offline, in which case all further
4871 * access to the device is prohibited.
4873 if( !scsi_block_when_processing_errors(STp->device) ) {
4874 retval = (-ENXIO);
4875 goto out;
4878 cmd_type = _IOC_TYPE(cmd_in);
4879 cmd_nr = _IOC_NR(cmd_in);
4880 #if DEBUG
4881 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4882 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4883 #endif
4884 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4885 struct mtop mtc;
4886 int auto_weof = 0;
4888 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4889 retval = (-EINVAL);
4890 goto out;
4893 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4894 if (i) {
4895 retval = (-EFAULT);
4896 goto out;
4899 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4900 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4901 retval = (-EPERM);
4902 goto out;
4905 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4906 retval = (-ENXIO);
4907 goto out;
4910 if (!STp->pos_unknown) {
4912 if (STps->eof == ST_FM_HIT) {
4913 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4914 mtc.mt_count -= 1;
4915 if (STps->drv_file >= 0)
4916 STps->drv_file += 1;
4918 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4919 mtc.mt_count += 1;
4920 if (STps->drv_file >= 0)
4921 STps->drv_file += 1;
4925 if (mtc.mt_op == MTSEEK) {
4926 /* Old position must be restored if partition will be changed */
4927 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4929 else {
4930 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
4931 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
4932 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
4933 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
4934 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
4935 mtc.mt_op == MTCOMPRESSION;
4937 i = osst_flush_buffer(STp, &SRpnt, i);
4938 if (i < 0) {
4939 retval = i;
4940 goto out;
4943 else {
4945 * If there was a bus reset, block further access
4946 * to this device. If the user wants to rewind the tape,
4947 * then reset the flag and allow access again.
4949 if(mtc.mt_op != MTREW &&
4950 mtc.mt_op != MTOFFL &&
4951 mtc.mt_op != MTRETEN &&
4952 mtc.mt_op != MTERASE &&
4953 mtc.mt_op != MTSEEK &&
4954 mtc.mt_op != MTEOM) {
4955 retval = (-EIO);
4956 goto out;
4958 reset_state(STp);
4959 /* remove this when the midlevel properly clears was_reset */
4960 STp->device->was_reset = 0;
4963 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
4964 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
4965 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
4966 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
4967 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
4970 * The user tells us to move to another position on the tape.
4971 * If we were appending to the tape content, that would leave
4972 * the tape without proper end, in that case write EOD and
4973 * update the header to reflect its position.
4975 #if DEBUG
4976 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
4977 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
4978 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
4979 STp->logical_blk_num, STps->drv_file, STps->drv_block );
4980 #endif
4981 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
4982 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
4983 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4984 i = osst_write_trailer(STp, &SRpnt,
4985 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4986 #if DEBUG
4987 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4988 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
4989 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
4990 #endif
4991 if (i < 0) {
4992 retval = i;
4993 goto out;
4996 STps->rw = ST_IDLE;
4999 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5000 do_door_lock(STp, 0); /* Ignore result! */
5002 if (mtc.mt_op == MTSETDRVBUFFER &&
5003 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5004 retval = osst_set_options(STp, mtc.mt_count);
5005 goto out;
5008 if (mtc.mt_op == MTSETPART) {
5009 if (mtc.mt_count >= STp->nbr_partitions)
5010 retval = -EINVAL;
5011 else {
5012 STp->new_partition = mtc.mt_count;
5013 retval = 0;
5015 goto out;
5018 if (mtc.mt_op == MTMKPART) {
5019 if (!STp->can_partitions) {
5020 retval = (-EINVAL);
5021 goto out;
5023 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5024 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5025 retval = i;
5026 goto out;
5028 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5029 STp->ps[i].rw = ST_IDLE;
5030 STp->ps[i].at_sm = 0;
5031 STp->ps[i].last_block_valid = 0;
5033 STp->partition = STp->new_partition = 0;
5034 STp->nbr_partitions = 1; /* Bad guess ?-) */
5035 STps->drv_block = STps->drv_file = 0;
5036 retval = 0;
5037 goto out;
5040 if (mtc.mt_op == MTSEEK) {
5041 if (STp->raw)
5042 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5043 else
5044 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5045 if (!STp->can_partitions)
5046 STp->ps[0].rw = ST_IDLE;
5047 retval = i;
5048 goto out;
5051 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5052 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5053 goto out;
5056 if (auto_weof)
5057 cross_eof(STp, &SRpnt, 0);
5059 if (mtc.mt_op == MTCOMPRESSION)
5060 retval = -EINVAL; /* OnStream drives don't have compression hardware */
5061 else
5062 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5063 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5064 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5065 goto out;
5068 if (!STm->defined) {
5069 retval = (-ENXIO);
5070 goto out;
5073 if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5074 retval = i;
5075 goto out;
5078 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5079 struct mtget mt_status;
5081 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5082 retval = (-EINVAL);
5083 goto out;
5086 mt_status.mt_type = MT_ISONSTREAM_SC;
5087 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5088 mt_status.mt_dsreg =
5089 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5090 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5091 mt_status.mt_blkno = STps->drv_block;
5092 mt_status.mt_fileno = STps->drv_file;
5093 if (STp->block_size != 0) {
5094 if (STps->rw == ST_WRITING)
5095 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5096 else if (STps->rw == ST_READING)
5097 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5098 STp->block_size - 1) / STp->block_size;
5101 mt_status.mt_gstat = 0;
5102 if (STp->drv_write_prot)
5103 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5104 if (mt_status.mt_blkno == 0) {
5105 if (mt_status.mt_fileno == 0)
5106 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5107 else
5108 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5110 mt_status.mt_resid = STp->partition;
5111 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5112 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5113 else if (STps->eof >= ST_EOM_OK)
5114 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5115 if (STp->density == 1)
5116 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5117 else if (STp->density == 2)
5118 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5119 else if (STp->density == 3)
5120 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5121 if (STp->ready == ST_READY)
5122 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5123 if (STp->ready == ST_NO_TAPE)
5124 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5125 if (STps->at_sm)
5126 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5127 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5128 STp->drv_buffer != 0)
5129 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5131 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5132 if (i) {
5133 retval = (-EFAULT);
5134 goto out;
5137 STp->recover_erreg = 0; /* Clear after read */
5138 retval = 0;
5139 goto out;
5140 } /* End of MTIOCGET */
5142 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5143 struct mtpos mt_pos;
5145 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5146 retval = (-EINVAL);
5147 goto out;
5149 if (STp->raw)
5150 blk = osst_get_frame_position(STp, &SRpnt);
5151 else
5152 blk = osst_get_sector(STp, &SRpnt);
5153 if (blk < 0) {
5154 retval = blk;
5155 goto out;
5157 mt_pos.mt_blkno = blk;
5158 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5159 if (i)
5160 retval = -EFAULT;
5161 goto out;
5163 if (SRpnt) osst_release_request(SRpnt);
5165 up(&STp->lock);
5167 return scsi_ioctl(STp->device, cmd_in, p);
5169 out:
5170 if (SRpnt) osst_release_request(SRpnt);
5172 up(&STp->lock);
5174 return retval;
5177 #ifdef CONFIG_COMPAT
5178 static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5180 struct osst_tape *STp = file->private_data;
5181 struct scsi_device *sdev = STp->device;
5182 int ret = -ENOIOCTLCMD;
5183 if (sdev->host->hostt->compat_ioctl) {
5185 ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5188 return ret;
5190 #endif
5194 /* Memory handling routines */
5196 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5197 static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5199 int i;
5200 gfp_t priority;
5201 struct osst_buffer *tb;
5203 if (from_initialization)
5204 priority = GFP_ATOMIC;
5205 else
5206 priority = GFP_KERNEL;
5208 i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5209 tb = (struct osst_buffer *)kmalloc(i, priority);
5210 if (!tb) {
5211 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5212 return NULL;
5214 memset(tb, 0, i);
5215 tb->sg_segs = tb->orig_sg_segs = 0;
5216 tb->use_sg = max_sg;
5217 tb->in_use = 1;
5218 tb->dma = need_dma;
5219 tb->buffer_size = 0;
5220 #if DEBUG
5221 if (debugging)
5222 printk(OSST_DEB_MSG
5223 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5224 i, max_sg, need_dma);
5225 #endif
5226 return tb;
5229 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5230 static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5232 int segs, nbr, max_segs, b_size, order, got;
5233 gfp_t priority;
5235 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5236 return 1;
5238 if (STbuffer->sg_segs) {
5239 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5240 normalize_buffer(STbuffer);
5242 /* See how many segments we can use -- need at least two */
5243 nbr = max_segs = STbuffer->use_sg;
5244 if (nbr <= 2)
5245 return 0;
5247 priority = GFP_KERNEL /* | __GFP_NOWARN */;
5248 if (need_dma)
5249 priority |= GFP_DMA;
5251 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5252 big enough to reach the goal (code assumes no segments in place) */
5253 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5254 STbuffer->sg[0].page = alloc_pages(priority, order);
5255 STbuffer->sg[0].offset = 0;
5256 if (STbuffer->sg[0].page != NULL) {
5257 STbuffer->sg[0].length = b_size;
5258 STbuffer->b_data = page_address(STbuffer->sg[0].page);
5259 break;
5262 if (STbuffer->sg[0].page == NULL) {
5263 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5264 return 0;
5266 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5267 for (segs=STbuffer->sg_segs=1, got=b_size;
5268 segs < max_segs && got < OS_FRAME_SIZE; ) {
5269 STbuffer->sg[segs].page =
5270 alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5271 STbuffer->sg[segs].offset = 0;
5272 if (STbuffer->sg[segs].page == NULL) {
5273 if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
5274 b_size /= 2; /* Large enough for the rest of the buffers */
5275 order--;
5276 continue;
5278 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5279 OS_FRAME_SIZE);
5280 #if DEBUG
5281 STbuffer->buffer_size = got;
5282 #endif
5283 normalize_buffer(STbuffer);
5284 return 0;
5286 STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size;
5287 got += STbuffer->sg[segs].length;
5288 STbuffer->buffer_size = got;
5289 STbuffer->sg_segs = ++segs;
5291 #if DEBUG
5292 if (debugging) {
5293 printk(OSST_DEB_MSG
5294 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5295 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5296 printk(OSST_DEB_MSG
5297 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5298 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5299 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5301 #endif
5303 return 1;
5307 /* Release the segments */
5308 static void normalize_buffer(struct osst_buffer *STbuffer)
5310 int i, order, b_size;
5312 for (i=0; i < STbuffer->sg_segs; i++) {
5314 for (b_size = PAGE_SIZE, order = 0;
5315 b_size < STbuffer->sg[i].length;
5316 b_size *= 2, order++);
5318 __free_pages(STbuffer->sg[i].page, order);
5319 STbuffer->buffer_size -= STbuffer->sg[i].length;
5321 #if DEBUG
5322 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5323 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5324 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5325 #endif
5326 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5330 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5331 negative error code. */
5332 static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5334 int i, cnt, res, offset;
5336 for (i=0, offset=st_bp->buffer_bytes;
5337 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5338 offset -= st_bp->sg[i].length;
5339 if (i == st_bp->sg_segs) { /* Should never happen */
5340 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5341 return (-EIO);
5343 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5344 cnt = st_bp->sg[i].length - offset < do_count ?
5345 st_bp->sg[i].length - offset : do_count;
5346 res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
5347 if (res)
5348 return (-EFAULT);
5349 do_count -= cnt;
5350 st_bp->buffer_bytes += cnt;
5351 ubp += cnt;
5352 offset = 0;
5354 if (do_count) { /* Should never happen */
5355 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5356 do_count);
5357 return (-EIO);
5359 return 0;
5363 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5364 negative error code. */
5365 static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5367 int i, cnt, res, offset;
5369 for (i=0, offset=st_bp->read_pointer;
5370 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5371 offset -= st_bp->sg[i].length;
5372 if (i == st_bp->sg_segs) { /* Should never happen */
5373 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5374 return (-EIO);
5376 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5377 cnt = st_bp->sg[i].length - offset < do_count ?
5378 st_bp->sg[i].length - offset : do_count;
5379 res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
5380 if (res)
5381 return (-EFAULT);
5382 do_count -= cnt;
5383 st_bp->buffer_bytes -= cnt;
5384 st_bp->read_pointer += cnt;
5385 ubp += cnt;
5386 offset = 0;
5388 if (do_count) { /* Should never happen */
5389 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5390 return (-EIO);
5392 return 0;
5395 /* Sets the tail of the buffer after fill point to zero.
5396 Returns zero (success) or negative error code. */
5397 static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5399 int i, offset, do_count, cnt;
5401 for (i = 0, offset = st_bp->buffer_bytes;
5402 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5403 offset -= st_bp->sg[i].length;
5404 if (i == st_bp->sg_segs) { /* Should never happen */
5405 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5406 return (-EIO);
5408 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5409 i < st_bp->sg_segs && do_count > 0; i++) {
5410 cnt = st_bp->sg[i].length - offset < do_count ?
5411 st_bp->sg[i].length - offset : do_count ;
5412 memset(page_address(st_bp->sg[i].page) + offset, 0, cnt);
5413 do_count -= cnt;
5414 offset = 0;
5416 if (do_count) { /* Should never happen */
5417 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5418 return (-EIO);
5420 return 0;
5423 /* Copy a osst 32K chunk of memory into the buffer.
5424 Returns zero (success) or negative error code. */
5425 static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5427 int i, cnt, do_count = OS_DATA_SIZE;
5429 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5430 cnt = st_bp->sg[i].length < do_count ?
5431 st_bp->sg[i].length : do_count ;
5432 memcpy(page_address(st_bp->sg[i].page), ptr, cnt);
5433 do_count -= cnt;
5434 ptr += cnt;
5436 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5437 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5438 do_count, i);
5439 return (-EIO);
5441 return 0;
5444 /* Copy a osst 32K chunk of memory from the buffer.
5445 Returns zero (success) or negative error code. */
5446 static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5448 int i, cnt, do_count = OS_DATA_SIZE;
5450 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5451 cnt = st_bp->sg[i].length < do_count ?
5452 st_bp->sg[i].length : do_count ;
5453 memcpy(ptr, page_address(st_bp->sg[i].page), cnt);
5454 do_count -= cnt;
5455 ptr += cnt;
5457 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5458 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5459 do_count, i);
5460 return (-EIO);
5462 return 0;
5466 /* Module housekeeping */
5468 static void validate_options (void)
5470 if (max_dev > 0)
5471 osst_max_dev = max_dev;
5472 if (write_threshold_kbs > 0)
5473 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5474 if (osst_write_threshold > osst_buffer_size)
5475 osst_write_threshold = osst_buffer_size;
5476 if (max_sg_segs >= OSST_FIRST_SG)
5477 osst_max_sg_segs = max_sg_segs;
5478 #if DEBUG
5479 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5480 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5481 #endif
5484 #ifndef MODULE
5485 /* Set the boot options. Syntax: osst=xxx,yyy,...
5486 where xxx is write threshold in 1024 byte blocks,
5487 and yyy is number of s/g segments to use. */
5488 static int __init osst_setup (char *str)
5490 int i, ints[5];
5491 char *stp;
5493 stp = get_options(str, ARRAY_SIZE(ints), ints);
5495 if (ints[0] > 0) {
5496 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5497 *parms[i].val = ints[i + 1];
5498 } else {
5499 while (stp != NULL) {
5500 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5501 int len = strlen(parms[i].name);
5502 if (!strncmp(stp, parms[i].name, len) &&
5503 (*(stp + len) == ':' || *(stp + len) == '=')) {
5504 *parms[i].val =
5505 simple_strtoul(stp + len + 1, NULL, 0);
5506 break;
5509 if (i >= sizeof(parms) / sizeof(struct osst_dev_parm))
5510 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5511 stp);
5512 stp = strchr(stp, ',');
5513 if (stp)
5514 stp++;
5518 return 1;
5521 __setup("osst=", osst_setup);
5523 #endif
5525 static struct file_operations osst_fops = {
5526 .owner = THIS_MODULE,
5527 .read = osst_read,
5528 .write = osst_write,
5529 .ioctl = osst_ioctl,
5530 #ifdef CONFIG_COMPAT
5531 .compat_ioctl = osst_compat_ioctl,
5532 #endif
5533 .open = os_scsi_tape_open,
5534 .flush = os_scsi_tape_flush,
5535 .release = os_scsi_tape_close,
5538 static int osst_supports(struct scsi_device * SDp)
5540 struct osst_support_data {
5541 char *vendor;
5542 char *model;
5543 char *rev;
5544 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5547 static struct osst_support_data support_list[] = {
5548 /* {"XXX", "Yy-", "", NULL}, example */
5549 SIGS_FROM_OSST,
5550 {NULL, }};
5552 struct osst_support_data *rp;
5554 /* We are willing to drive OnStream SC-x0 as well as the
5555 * * IDE, ParPort, FireWire, USB variants, if accessible by
5556 * * emulation layer (ide-scsi, usb-storage, ...) */
5558 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5559 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5560 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5561 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5562 return 1;
5563 return 0;
5567 * sysfs support for osst driver parameter information
5570 static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5572 return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5575 static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5577 static void osst_create_driverfs_files(struct device_driver *driverfs)
5579 driver_create_file(driverfs, &driver_attr_version);
5582 static void osst_remove_driverfs_files(struct device_driver *driverfs)
5584 driver_remove_file(driverfs, &driver_attr_version);
5588 * sysfs support for accessing ADR header information
5591 static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
5593 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5594 ssize_t l = 0;
5596 if (STp && STp->header_ok && STp->linux_media)
5597 l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5598 return l;
5601 CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5603 static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
5605 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5606 ssize_t l = 0;
5608 if (STp && STp->header_ok && STp->linux_media)
5609 l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5610 return l;
5613 CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5615 static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
5617 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5618 ssize_t l = 0;
5620 if (STp && STp->header_ok && STp->linux_media)
5621 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5622 return l;
5625 CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5627 static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
5629 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5630 ssize_t l = 0;
5632 if (STp && STp->header_ok && STp->linux_media)
5633 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5634 return l;
5637 CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5639 static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
5641 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5642 ssize_t l = 0;
5644 if (STp && STp->header_ok && STp->linux_media)
5645 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5646 return l;
5649 CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5651 static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
5653 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5654 ssize_t l = 0;
5656 if (STp && STp->header_ok && STp->linux_media)
5657 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5658 return l;
5661 CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5663 static struct class *osst_sysfs_class;
5665 static int osst_sysfs_valid = 0;
5667 static void osst_sysfs_init(void)
5669 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5670 if ( IS_ERR(osst_sysfs_class) )
5671 printk(KERN_WARNING "osst :W: Unable to register sysfs class\n");
5672 else
5673 osst_sysfs_valid = 1;
5676 static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5678 struct class_device *osst_class_member;
5680 if (!osst_sysfs_valid) return;
5682 osst_class_member = class_device_create(osst_sysfs_class, NULL, dev, device, "%s", name);
5683 if (IS_ERR(osst_class_member)) {
5684 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5685 return;
5687 class_set_devdata(osst_class_member, STp);
5688 class_device_create_file(osst_class_member, &class_device_attr_ADR_rev);
5689 class_device_create_file(osst_class_member, &class_device_attr_media_version);
5690 class_device_create_file(osst_class_member, &class_device_attr_capacity);
5691 class_device_create_file(osst_class_member, &class_device_attr_BOT_frame);
5692 class_device_create_file(osst_class_member, &class_device_attr_EOD_frame);
5693 class_device_create_file(osst_class_member, &class_device_attr_file_count);
5696 static void osst_sysfs_destroy(dev_t dev)
5698 if (!osst_sysfs_valid) return;
5700 class_device_destroy(osst_sysfs_class, dev);
5703 static void osst_sysfs_cleanup(void)
5705 if (osst_sysfs_valid) {
5706 class_destroy(osst_sysfs_class);
5707 osst_sysfs_valid = 0;
5712 * osst startup / cleanup code
5715 static int osst_probe(struct device *dev)
5717 struct scsi_device * SDp = to_scsi_device(dev);
5718 struct osst_tape * tpnt;
5719 struct st_modedef * STm;
5720 struct st_partstat * STps;
5721 struct osst_buffer * buffer;
5722 struct gendisk * drive;
5723 int i, dev_num;
5725 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5726 return -ENODEV;
5728 drive = alloc_disk(1);
5729 if (!drive) {
5730 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5731 return -ENODEV;
5734 /* if this is the first attach, build the infrastructure */
5735 write_lock(&os_scsi_tapes_lock);
5736 if (os_scsi_tapes == NULL) {
5737 os_scsi_tapes =
5738 (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
5739 GFP_ATOMIC);
5740 if (os_scsi_tapes == NULL) {
5741 write_unlock(&os_scsi_tapes_lock);
5742 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5743 goto out_put_disk;
5745 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5748 if (osst_nr_dev >= osst_max_dev) {
5749 write_unlock(&os_scsi_tapes_lock);
5750 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5751 goto out_put_disk;
5754 /* find a free minor number */
5755 for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++);
5756 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5757 dev_num = i;
5759 /* allocate a struct osst_tape for this device */
5760 tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5761 if (tpnt == NULL) {
5762 write_unlock(&os_scsi_tapes_lock);
5763 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5764 goto out_put_disk;
5766 memset(tpnt, 0, sizeof(struct osst_tape));
5768 /* allocate a buffer for this device */
5769 i = SDp->host->sg_tablesize;
5770 if (osst_max_sg_segs < i)
5771 i = osst_max_sg_segs;
5772 buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5773 if (buffer == NULL) {
5774 write_unlock(&os_scsi_tapes_lock);
5775 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5776 kfree(tpnt);
5777 goto out_put_disk;
5779 os_scsi_tapes[dev_num] = tpnt;
5780 tpnt->buffer = buffer;
5781 tpnt->device = SDp;
5782 drive->private_data = &tpnt->driver;
5783 sprintf(drive->disk_name, "osst%d", dev_num);
5784 tpnt->driver = &osst_template;
5785 tpnt->drive = drive;
5786 tpnt->in_use = 0;
5787 tpnt->capacity = 0xfffff;
5788 tpnt->dirty = 0;
5789 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
5790 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5791 tpnt->density = 0;
5792 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5793 tpnt->can_bsr = OSST_IN_FILE_POS;
5794 tpnt->can_partitions = 0;
5795 tpnt->two_fm = OSST_TWO_FM;
5796 tpnt->fast_mteom = OSST_FAST_MTEOM;
5797 tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5798 tpnt->write_threshold = osst_write_threshold;
5799 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5800 tpnt->partition = 0;
5801 tpnt->new_partition = 0;
5802 tpnt->nbr_partitions = 0;
5803 tpnt->min_block = 512;
5804 tpnt->max_block = OS_DATA_SIZE;
5805 tpnt->timeout = OSST_TIMEOUT;
5806 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5808 /* Recognize OnStream tapes */
5809 /* We don't need to test for OnStream, as this has been done in detect () */
5810 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5811 tpnt->omit_blklims = 1;
5813 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5814 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5815 tpnt->frame_in_buffer = 0;
5816 tpnt->header_ok = 0;
5817 tpnt->linux_media = 0;
5818 tpnt->header_cache = NULL;
5820 for (i=0; i < ST_NBR_MODES; i++) {
5821 STm = &(tpnt->modes[i]);
5822 STm->defined = 0;
5823 STm->sysv = OSST_SYSV;
5824 STm->defaults_for_writes = 0;
5825 STm->do_async_writes = OSST_ASYNC_WRITES;
5826 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5827 STm->do_read_ahead = OSST_READ_AHEAD;
5828 STm->default_compression = ST_DONT_TOUCH;
5829 STm->default_blksize = 512;
5830 STm->default_density = (-1); /* No forced density */
5833 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5834 STps = &(tpnt->ps[i]);
5835 STps->rw = ST_IDLE;
5836 STps->eof = ST_NOEOF;
5837 STps->at_sm = 0;
5838 STps->last_block_valid = 0;
5839 STps->drv_block = (-1);
5840 STps->drv_file = (-1);
5843 tpnt->current_mode = 0;
5844 tpnt->modes[0].defined = 1;
5845 tpnt->modes[2].defined = 1;
5846 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5848 init_MUTEX(&tpnt->lock);
5849 osst_nr_dev++;
5850 write_unlock(&os_scsi_tapes_lock);
5852 char name[8];
5853 /* Rewind entry */
5854 osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5855 /* No-rewind entry */
5856 snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5857 osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5860 sdev_printk(KERN_INFO, SDp,
5861 "osst :I: Attached OnStream %.5s tape as %s\n",
5862 SDp->model, tape_name(tpnt));
5864 return 0;
5866 out_put_disk:
5867 put_disk(drive);
5868 return -ENODEV;
5871 static int osst_remove(struct device *dev)
5873 struct scsi_device * SDp = to_scsi_device(dev);
5874 struct osst_tape * tpnt;
5875 int i;
5877 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
5878 return 0;
5880 write_lock(&os_scsi_tapes_lock);
5881 for(i=0; i < osst_max_dev; i++) {
5882 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
5883 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
5884 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
5885 tpnt->device = NULL;
5886 put_disk(tpnt->drive);
5887 os_scsi_tapes[i] = NULL;
5888 osst_nr_dev--;
5889 write_unlock(&os_scsi_tapes_lock);
5890 vfree(tpnt->header_cache);
5891 if (tpnt->buffer) {
5892 normalize_buffer(tpnt->buffer);
5893 kfree(tpnt->buffer);
5895 kfree(tpnt);
5896 return 0;
5899 write_unlock(&os_scsi_tapes_lock);
5900 return 0;
5903 static int __init init_osst(void)
5905 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5907 validate_options();
5908 osst_sysfs_init();
5910 if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
5911 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
5912 osst_sysfs_cleanup();
5913 return 1;
5915 osst_create_driverfs_files(&osst_template.gendrv);
5917 return 0;
5920 static void __exit exit_osst (void)
5922 int i;
5923 struct osst_tape * STp;
5925 osst_remove_driverfs_files(&osst_template.gendrv);
5926 scsi_unregister_driver(&osst_template.gendrv);
5927 unregister_chrdev(OSST_MAJOR, "osst");
5928 osst_sysfs_cleanup();
5930 if (os_scsi_tapes) {
5931 for (i=0; i < osst_max_dev; ++i) {
5932 if (!(STp = os_scsi_tapes[i])) continue;
5933 /* This is defensive, supposed to happen during detach */
5934 vfree(STp->header_cache);
5935 if (STp->buffer) {
5936 normalize_buffer(STp->buffer);
5937 kfree(STp->buffer);
5939 put_disk(STp->drive);
5940 kfree(STp);
5942 kfree(os_scsi_tapes);
5944 printk(KERN_INFO "osst :I: Unloaded.\n");
5947 module_init(init_osst);
5948 module_exit(exit_osst);