sync hh.org
[hh.org.git] / drivers / scsi / osst.c
blob824fe080d1dc2b9d0b2e1a35b2e1a64464e615b9
1 /*
2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
5 History:
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
17 email osst@riede.org
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27 static const char * osst_version = "0.99.4";
29 /* The "failure to reconnect" firmware bug */
30 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31 #define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
34 #include <linux/module.h>
36 #include <linux/fs.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
40 #include <linux/mm.h>
41 #include <linux/init.h>
42 #include <linux/string.h>
43 #include <linux/errno.h>
44 #include <linux/mtio.h>
45 #include <linux/ioctl.h>
46 #include <linux/fcntl.h>
47 #include <linux/spinlock.h>
48 #include <linux/vmalloc.h>
49 #include <linux/blkdev.h>
50 #include <linux/moduleparam.h>
51 #include <linux/delay.h>
52 #include <linux/jiffies.h>
53 #include <asm/uaccess.h>
54 #include <asm/dma.h>
55 #include <asm/system.h>
57 /* The driver prints some debugging information on the console if DEBUG
58 is defined and non-zero. */
59 #define DEBUG 0
61 /* The message level for the debug messages is currently set to KERN_NOTICE
62 so that people can easily see the messages. Later when the debugging messages
63 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
64 #define OSST_DEB_MSG KERN_NOTICE
66 #include <scsi/scsi.h>
67 #include <scsi/scsi_dbg.h>
68 #include <scsi/scsi_device.h>
69 #include <scsi/scsi_driver.h>
70 #include <scsi/scsi_eh.h>
71 #include <scsi/scsi_host.h>
72 #include <scsi/scsi_ioctl.h>
74 #define ST_KILOBYTE 1024
76 #include "st.h"
77 #include "osst.h"
78 #include "osst_options.h"
79 #include "osst_detect.h"
81 static int max_dev = 0;
82 static int write_threshold_kbs = 0;
83 static int max_sg_segs = 0;
85 #ifdef MODULE
86 MODULE_AUTHOR("Willem Riede");
87 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
88 MODULE_LICENSE("GPL");
89 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
91 module_param(max_dev, int, 0444);
92 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
94 module_param(write_threshold_kbs, int, 0644);
95 MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
97 module_param(max_sg_segs, int, 0644);
98 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
99 #else
100 static struct osst_dev_parm {
101 char *name;
102 int *val;
103 } parms[] __initdata = {
104 { "max_dev", &max_dev },
105 { "write_threshold_kbs", &write_threshold_kbs },
106 { "max_sg_segs", &max_sg_segs }
108 #endif
110 /* Some default definitions have been moved to osst_options.h */
111 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
112 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
114 /* The buffer size should fit into the 24 bits for length in the
115 6-byte SCSI read and write commands. */
116 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
117 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
118 #endif
120 #if DEBUG
121 static int debugging = 1;
122 /* uncomment define below to test error recovery */
123 // #define OSST_INJECT_ERRORS 1
124 #endif
126 /* Do not retry! The drive firmware already retries when appropriate,
127 and when it tries to tell us something, we had better listen... */
128 #define MAX_RETRIES 0
130 #define NO_TAPE NOT_READY
132 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
133 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
134 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
136 #define OSST_TIMEOUT (200 * HZ)
137 #define OSST_LONG_TIMEOUT (1800 * HZ)
139 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
140 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
141 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
142 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
144 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
145 24 bits) */
146 #define SET_DENS_AND_BLK 0x10001
148 static int osst_buffer_size = OSST_BUFFER_SIZE;
149 static int osst_write_threshold = OSST_WRITE_THRESHOLD;
150 static int osst_max_sg_segs = OSST_MAX_SG;
151 static int osst_max_dev = OSST_MAX_TAPES;
152 static int osst_nr_dev;
154 static struct osst_tape **os_scsi_tapes = NULL;
155 static DEFINE_RWLOCK(os_scsi_tapes_lock);
157 static int modes_defined = 0;
159 static struct osst_buffer *new_tape_buffer(int, int, int);
160 static int enlarge_buffer(struct osst_buffer *, int);
161 static void normalize_buffer(struct osst_buffer *);
162 static int append_to_buffer(const char __user *, struct osst_buffer *, int);
163 static int from_buffer(struct osst_buffer *, char __user *, int);
164 static int osst_zero_buffer_tail(struct osst_buffer *);
165 static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
166 static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
168 static int osst_probe(struct device *);
169 static int osst_remove(struct device *);
171 static struct scsi_driver osst_template = {
172 .owner = THIS_MODULE,
173 .gendrv = {
174 .name = "osst",
175 .probe = osst_probe,
176 .remove = osst_remove,
180 static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
181 unsigned int cmd_in, unsigned long arg);
183 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
185 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
187 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
189 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
191 static inline char *tape_name(struct osst_tape *tape)
193 return tape->drive->disk_name;
196 /* Routines that handle the interaction with mid-layer SCSI routines */
199 /* Normalize Sense */
200 static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
202 const u8 *ucp;
203 const u8 *sense = SRpnt->sense;
205 s->have_sense = scsi_normalize_sense(SRpnt->sense,
206 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
207 s->flags = 0;
209 if (s->have_sense) {
210 s->deferred = 0;
211 s->remainder_valid =
212 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
213 switch (sense[0] & 0x7f) {
214 case 0x71:
215 s->deferred = 1;
216 case 0x70:
217 s->fixed_format = 1;
218 s->flags = sense[2] & 0xe0;
219 break;
220 case 0x73:
221 s->deferred = 1;
222 case 0x72:
223 s->fixed_format = 0;
224 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
225 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
226 break;
231 /* Convert the result to success code */
232 static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
234 char *name = tape_name(STp);
235 int result = SRpnt->result;
236 u8 * sense = SRpnt->sense, scode;
237 #if DEBUG
238 const char *stp;
239 #endif
240 struct st_cmdstatus *cmdstatp;
242 if (!result)
243 return 0;
245 cmdstatp = &STp->buffer->cmdstat;
246 osst_analyze_sense(SRpnt, cmdstatp);
248 if (cmdstatp->have_sense)
249 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
250 else
251 scode = 0;
252 #if DEBUG
253 if (debugging) {
254 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
255 name, result,
256 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
257 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
258 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
259 name, scode, sense[12], sense[13]);
260 if (cmdstatp->have_sense)
261 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
263 else
264 #endif
265 if (cmdstatp->have_sense && (
266 scode != NO_SENSE &&
267 scode != RECOVERED_ERROR &&
268 /* scode != UNIT_ATTENTION && */
269 scode != BLANK_CHECK &&
270 scode != VOLUME_OVERFLOW &&
271 SRpnt->cmd[0] != MODE_SENSE &&
272 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
273 if (cmdstatp->have_sense) {
274 printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
275 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
277 else {
278 static int notyetprinted = 1;
280 printk(KERN_WARNING
281 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
282 name, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
283 host_byte(result));
284 if (notyetprinted) {
285 notyetprinted = 0;
286 printk(KERN_INFO
287 "%s:I: This warning may be caused by your scsi controller,\n", name);
288 printk(KERN_INFO
289 "%s:I: it has been reported with some Buslogic cards.\n", name);
293 STp->pos_unknown |= STp->device->was_reset;
295 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
296 STp->recover_count++;
297 STp->recover_erreg++;
298 #if DEBUG
299 if (debugging) {
300 if (SRpnt->cmd[0] == READ_6)
301 stp = "read";
302 else if (SRpnt->cmd[0] == WRITE_6)
303 stp = "write";
304 else
305 stp = "ioctl";
306 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
307 STp->recover_count);
309 #endif
310 if ((sense[2] & 0xe0) == 0)
311 return 0;
313 return (-EIO);
317 /* Wakeup from interrupt */
318 static void osst_sleep_done(void *data, char *sense, int result, int resid)
320 struct osst_request *SRpnt = data;
321 struct osst_tape *STp = SRpnt->stp;
323 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
324 STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
325 #if DEBUG
326 STp->write_pending = 0;
327 #endif
328 if (SRpnt->waiting)
329 complete(SRpnt->waiting);
332 /* osst_request memory management */
333 static struct osst_request *osst_allocate_request(void)
335 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
338 static void osst_release_request(struct osst_request *streq)
340 kfree(streq);
343 /* Do the scsi command. Waits until command performed if do_wait is true.
344 Otherwise osst_write_behind_check() is used to check that the command
345 has finished. */
346 static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
347 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
349 unsigned char *bp;
350 unsigned short use_sg;
351 #ifdef OSST_INJECT_ERRORS
352 static int inject = 0;
353 static int repeat = 0;
354 #endif
355 struct completion *waiting;
357 /* if async, make sure there's no command outstanding */
358 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
359 printk(KERN_ERR "%s: Async command already active.\n",
360 tape_name(STp));
361 if (signal_pending(current))
362 (STp->buffer)->syscall_result = (-EINTR);
363 else
364 (STp->buffer)->syscall_result = (-EBUSY);
365 return NULL;
368 if (SRpnt == NULL) {
369 SRpnt = osst_allocate_request();
370 if (SRpnt == NULL) {
371 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
372 tape_name(STp));
373 if (signal_pending(current))
374 (STp->buffer)->syscall_result = (-EINTR);
375 else
376 (STp->buffer)->syscall_result = (-EBUSY);
377 return NULL;
379 SRpnt->stp = STp;
382 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
383 which IO is outstanding. It's nulled out when the IO completes. */
384 if (!do_wait)
385 (STp->buffer)->last_SRpnt = SRpnt;
387 waiting = &STp->wait;
388 init_completion(waiting);
389 SRpnt->waiting = waiting;
391 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
392 if (use_sg) {
393 bp = (char *)&(STp->buffer->sg[0]);
394 if (STp->buffer->sg_segs < use_sg)
395 use_sg = STp->buffer->sg_segs;
397 else
398 bp = (STp->buffer)->b_data;
400 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
401 STp->buffer->cmdstat.have_sense = 0;
402 STp->buffer->syscall_result = 0;
404 if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
405 use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL))
406 /* could not allocate the buffer or request was too large */
407 (STp->buffer)->syscall_result = (-EBUSY);
408 else if (do_wait) {
409 wait_for_completion(waiting);
410 SRpnt->waiting = NULL;
411 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
412 #ifdef OSST_INJECT_ERRORS
413 if (STp->buffer->syscall_result == 0 &&
414 cmd[0] == READ_6 &&
415 cmd[4] &&
416 ( (++ inject % 83) == 29 ||
417 (STp->first_frame_position == 240
418 /* or STp->read_error_frame to fail again on the block calculated above */ &&
419 ++repeat < 3))) {
420 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
421 STp->buffer->last_result_fatal = 1;
423 #endif
425 return SRpnt;
429 /* Handle the write-behind checking (downs the semaphore) */
430 static void osst_write_behind_check(struct osst_tape *STp)
432 struct osst_buffer * STbuffer;
434 STbuffer = STp->buffer;
436 #if DEBUG
437 if (STp->write_pending)
438 STp->nbr_waits++;
439 else
440 STp->nbr_finished++;
441 #endif
442 wait_for_completion(&(STp->wait));
443 STp->buffer->last_SRpnt->waiting = NULL;
445 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
447 if (STp->buffer->syscall_result)
448 STp->buffer->syscall_result =
449 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
450 else
451 STp->first_frame_position++;
453 osst_release_request(STp->buffer->last_SRpnt);
455 if (STbuffer->writing < STbuffer->buffer_bytes)
456 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
458 STbuffer->last_SRpnt = NULL;
459 STbuffer->buffer_bytes -= STbuffer->writing;
460 STbuffer->writing = 0;
462 return;
467 /* Onstream specific Routines */
469 * Initialize the OnStream AUX
471 static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
472 int logical_blk_num, int blk_sz, int blk_cnt)
474 os_aux_t *aux = STp->buffer->aux;
475 os_partition_t *par = &aux->partition;
476 os_dat_t *dat = &aux->dat;
478 if (STp->raw) return;
480 memset(aux, 0, sizeof(*aux));
481 aux->format_id = htonl(0);
482 memcpy(aux->application_sig, "LIN4", 4);
483 aux->hdwr = htonl(0);
484 aux->frame_type = frame_type;
486 switch (frame_type) {
487 case OS_FRAME_TYPE_HEADER:
488 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
489 par->partition_num = OS_CONFIG_PARTITION;
490 par->par_desc_ver = OS_PARTITION_VERSION;
491 par->wrt_pass_cntr = htons(0xffff);
492 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
493 par->first_frame_ppos = htonl(0);
494 par->last_frame_ppos = htonl(0xbb7);
495 aux->frame_seq_num = htonl(0);
496 aux->logical_blk_num_high = htonl(0);
497 aux->logical_blk_num = htonl(0);
498 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
499 break;
500 case OS_FRAME_TYPE_DATA:
501 case OS_FRAME_TYPE_MARKER:
502 dat->dat_sz = 8;
503 dat->reserved1 = 0;
504 dat->entry_cnt = 1;
505 dat->reserved3 = 0;
506 dat->dat_list[0].blk_sz = htonl(blk_sz);
507 dat->dat_list[0].blk_cnt = htons(blk_cnt);
508 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
509 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
510 dat->dat_list[0].reserved = 0;
511 case OS_FRAME_TYPE_EOD:
512 aux->update_frame_cntr = htonl(0);
513 par->partition_num = OS_DATA_PARTITION;
514 par->par_desc_ver = OS_PARTITION_VERSION;
515 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
516 par->first_frame_ppos = htonl(STp->first_data_ppos);
517 par->last_frame_ppos = htonl(STp->capacity);
518 aux->frame_seq_num = htonl(frame_seq_number);
519 aux->logical_blk_num_high = htonl(0);
520 aux->logical_blk_num = htonl(logical_blk_num);
521 break;
522 default: ; /* probably FILL */
524 aux->filemark_cnt = ntohl(STp->filemark_cnt);
525 aux->phys_fm = ntohl(0xffffffff);
526 aux->last_mark_ppos = ntohl(STp->last_mark_ppos);
527 aux->last_mark_lbn = ntohl(STp->last_mark_lbn);
531 * Verify that we have the correct tape frame
533 static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
535 char * name = tape_name(STp);
536 os_aux_t * aux = STp->buffer->aux;
537 os_partition_t * par = &(aux->partition);
538 struct st_partstat * STps = &(STp->ps[STp->partition]);
539 int blk_cnt, blk_sz, i;
541 if (STp->raw) {
542 if (STp->buffer->syscall_result) {
543 for (i=0; i < STp->buffer->sg_segs; i++)
544 memset(page_address(STp->buffer->sg[i].page),
545 0, STp->buffer->sg[i].length);
546 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
547 } else
548 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
549 return 1;
551 if (STp->buffer->syscall_result) {
552 #if DEBUG
553 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
554 #endif
555 return 0;
557 if (ntohl(aux->format_id) != 0) {
558 #if DEBUG
559 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
560 #endif
561 goto err_out;
563 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
564 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
565 #if DEBUG
566 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
567 #endif
568 goto err_out;
570 if (par->partition_num != OS_DATA_PARTITION) {
571 if (!STp->linux_media || STp->linux_media_version != 2) {
572 #if DEBUG
573 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
574 name, par->partition_num);
575 #endif
576 goto err_out;
579 if (par->par_desc_ver != OS_PARTITION_VERSION) {
580 #if DEBUG
581 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
582 #endif
583 goto err_out;
585 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
586 #if DEBUG
587 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
588 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
589 #endif
590 goto err_out;
592 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
593 aux->frame_type != OS_FRAME_TYPE_EOD &&
594 aux->frame_type != OS_FRAME_TYPE_MARKER) {
595 if (!quiet)
596 #if DEBUG
597 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
598 #endif
599 goto err_out;
601 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
602 STp->first_frame_position < STp->eod_frame_ppos) {
603 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
604 STp->first_frame_position);
605 goto err_out;
607 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
608 if (!quiet)
609 #if DEBUG
610 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
611 name, ntohl(aux->frame_seq_num), frame_seq_number);
612 #endif
613 goto err_out;
615 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
616 STps->eof = ST_FM_HIT;
618 i = ntohl(aux->filemark_cnt);
619 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
620 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
621 #if DEBUG
622 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
623 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
624 i, STp->first_frame_position - 1);
625 #endif
626 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
627 if (i >= STp->filemark_cnt)
628 STp->filemark_cnt = i+1;
631 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
632 STps->eof = ST_EOD_1;
633 STp->frame_in_buffer = 1;
635 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
636 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
637 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
638 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
639 STp->buffer->read_pointer = 0;
640 STp->frame_in_buffer = 1;
642 /* See what block size was used to write file */
643 if (STp->block_size != blk_sz && blk_sz > 0) {
644 printk(KERN_INFO
645 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
646 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
647 STp->block_size<1024?STp->block_size:STp->block_size/1024,
648 STp->block_size<1024?'b':'k');
649 STp->block_size = blk_sz;
650 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
652 STps->eof = ST_NOEOF;
654 STp->frame_seq_number = ntohl(aux->frame_seq_num);
655 STp->logical_blk_num = ntohl(aux->logical_blk_num);
656 return 1;
658 err_out:
659 if (STp->read_error_frame == 0)
660 STp->read_error_frame = STp->first_frame_position - 1;
661 return 0;
665 * Wait for the unit to become Ready
667 static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
668 unsigned timeout, int initial_delay)
670 unsigned char cmd[MAX_COMMAND_SIZE];
671 struct osst_request * SRpnt;
672 unsigned long startwait = jiffies;
673 #if DEBUG
674 int dbg = debugging;
675 char * name = tape_name(STp);
677 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
678 #endif
680 if (initial_delay > 0)
681 msleep(jiffies_to_msecs(initial_delay));
683 memset(cmd, 0, MAX_COMMAND_SIZE);
684 cmd[0] = TEST_UNIT_READY;
686 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
687 *aSRpnt = SRpnt;
688 if (!SRpnt) return (-EBUSY);
690 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
691 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
692 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
693 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
694 SRpnt->sense[13] == 0 ) )) {
695 #if DEBUG
696 if (debugging) {
697 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
698 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
699 debugging = 0;
701 #endif
702 msleep(100);
704 memset(cmd, 0, MAX_COMMAND_SIZE);
705 cmd[0] = TEST_UNIT_READY;
707 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
709 *aSRpnt = SRpnt;
710 #if DEBUG
711 debugging = dbg;
712 #endif
713 if ( STp->buffer->syscall_result &&
714 osst_write_error_recovery(STp, aSRpnt, 0) ) {
715 #if DEBUG
716 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
717 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
718 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
719 SRpnt->sense[12], SRpnt->sense[13]);
720 #endif
721 return (-EIO);
723 #if DEBUG
724 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
725 #endif
726 return 0;
730 * Wait for a tape to be inserted in the unit
732 static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
734 unsigned char cmd[MAX_COMMAND_SIZE];
735 struct osst_request * SRpnt;
736 unsigned long startwait = jiffies;
737 #if DEBUG
738 int dbg = debugging;
739 char * name = tape_name(STp);
741 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
742 #endif
744 memset(cmd, 0, MAX_COMMAND_SIZE);
745 cmd[0] = TEST_UNIT_READY;
747 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
748 *aSRpnt = SRpnt;
749 if (!SRpnt) return (-EBUSY);
751 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
752 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
753 #if DEBUG
754 if (debugging) {
755 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
756 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
757 debugging = 0;
759 #endif
760 msleep(100);
762 memset(cmd, 0, MAX_COMMAND_SIZE);
763 cmd[0] = TEST_UNIT_READY;
765 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
767 *aSRpnt = SRpnt;
768 #if DEBUG
769 debugging = dbg;
770 #endif
771 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
772 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
773 #if DEBUG
774 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
775 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
776 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
777 SRpnt->sense[12], SRpnt->sense[13]);
778 #endif
779 return 0;
781 #if DEBUG
782 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
783 #endif
784 return 1;
787 static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
789 int retval;
791 osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
792 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
793 if (retval) return (retval);
794 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
795 return (osst_get_frame_position(STp, aSRpnt));
799 * Wait for write(s) to complete
801 static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
803 unsigned char cmd[MAX_COMMAND_SIZE];
804 struct osst_request * SRpnt;
805 int result = 0;
806 int delay = OSST_WAIT_WRITE_COMPLETE;
807 #if DEBUG
808 char * name = tape_name(STp);
810 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
811 #endif
813 memset(cmd, 0, MAX_COMMAND_SIZE);
814 cmd[0] = WRITE_FILEMARKS;
815 cmd[1] = 1;
817 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
818 *aSRpnt = SRpnt;
819 if (!SRpnt) return (-EBUSY);
820 if (STp->buffer->syscall_result) {
821 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
822 if (SRpnt->sense[13] == 8) {
823 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
825 } else
826 result = osst_write_error_recovery(STp, aSRpnt, 0);
828 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
829 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
831 return (result);
834 #define OSST_POLL_PER_SEC 10
835 static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
837 unsigned long startwait = jiffies;
838 char * name = tape_name(STp);
839 #if DEBUG
840 char notyetprinted = 1;
841 #endif
842 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
843 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
845 while (time_before (jiffies, startwait + to*HZ))
847 int result;
848 result = osst_get_frame_position(STp, aSRpnt);
849 if (result == -EIO)
850 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
851 return 0; /* successful recovery leaves drive ready for frame */
852 if (result < 0) break;
853 if (STp->first_frame_position == curr &&
854 ((minlast < 0 &&
855 (signed)STp->last_frame_position > (signed)curr + minlast) ||
856 (minlast >= 0 && STp->cur_frames > minlast)
857 ) && result >= 0)
859 #if DEBUG
860 if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
861 printk (OSST_DEB_MSG
862 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
863 name, curr, curr+minlast, STp->first_frame_position,
864 STp->last_frame_position, STp->cur_frames,
865 result, (jiffies-startwait)/HZ,
866 (((jiffies-startwait)%HZ)*10)/HZ);
867 #endif
868 return 0;
870 #if DEBUG
871 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
873 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
874 name, curr, curr+minlast, STp->first_frame_position,
875 STp->last_frame_position, STp->cur_frames, result);
876 notyetprinted--;
878 #endif
879 msleep(1000 / OSST_POLL_PER_SEC);
881 #if DEBUG
882 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
883 name, curr, curr+minlast, STp->first_frame_position,
884 STp->last_frame_position, STp->cur_frames,
885 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
886 #endif
887 return -EBUSY;
890 static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
892 struct osst_request * SRpnt;
893 unsigned char cmd[MAX_COMMAND_SIZE];
894 unsigned long startwait = jiffies;
895 int retval = 1;
896 char * name = tape_name(STp);
898 if (writing) {
899 char mybuf[24];
900 char * olddata = STp->buffer->b_data;
901 int oldsize = STp->buffer->buffer_size;
903 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
905 memset(cmd, 0, MAX_COMMAND_SIZE);
906 cmd[0] = WRITE_FILEMARKS;
907 cmd[1] = 1;
908 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
909 MAX_RETRIES, 1);
911 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
913 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
915 /* some failure - not just not-ready */
916 retval = osst_write_error_recovery(STp, aSRpnt, 0);
917 break;
919 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
921 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
922 memset(cmd, 0, MAX_COMMAND_SIZE);
923 cmd[0] = READ_POSITION;
925 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
926 MAX_RETRIES, 1);
928 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
929 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
931 if (retval)
932 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
933 } else
934 /* TODO - figure out which error conditions can be handled */
935 if (STp->buffer->syscall_result)
936 printk(KERN_WARNING
937 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
938 (*aSRpnt)->sense[ 2] & 0x0f,
939 (*aSRpnt)->sense[12],
940 (*aSRpnt)->sense[13]);
942 return retval;
946 * Read the next OnStream tape frame at the current location
948 static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
950 unsigned char cmd[MAX_COMMAND_SIZE];
951 struct osst_request * SRpnt;
952 int retval = 0;
953 #if DEBUG
954 os_aux_t * aux = STp->buffer->aux;
955 char * name = tape_name(STp);
956 #endif
958 if (STp->poll)
959 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
960 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
962 memset(cmd, 0, MAX_COMMAND_SIZE);
963 cmd[0] = READ_6;
964 cmd[1] = 1;
965 cmd[4] = 1;
967 #if DEBUG
968 if (debugging)
969 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
970 #endif
971 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
972 STp->timeout, MAX_RETRIES, 1);
973 *aSRpnt = SRpnt;
974 if (!SRpnt)
975 return (-EBUSY);
977 if ((STp->buffer)->syscall_result) {
978 retval = 1;
979 if (STp->read_error_frame == 0) {
980 STp->read_error_frame = STp->first_frame_position;
981 #if DEBUG
982 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
983 #endif
985 #if DEBUG
986 if (debugging)
987 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
988 name,
989 SRpnt->sense[0], SRpnt->sense[1],
990 SRpnt->sense[2], SRpnt->sense[3],
991 SRpnt->sense[4], SRpnt->sense[5],
992 SRpnt->sense[6], SRpnt->sense[7]);
993 #endif
995 else
996 STp->first_frame_position++;
997 #if DEBUG
998 if (debugging) {
999 char sig[8]; int i;
1000 for (i=0;i<4;i++)
1001 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1002 sig[4] = '\0';
1003 printk(OSST_DEB_MSG
1004 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1005 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1006 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1007 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1008 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1009 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1010 if (aux->frame_type==2)
1011 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1012 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1013 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1015 #endif
1016 return (retval);
1019 static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1021 struct st_partstat * STps = &(STp->ps[STp->partition]);
1022 struct osst_request * SRpnt ;
1023 unsigned char cmd[MAX_COMMAND_SIZE];
1024 int retval = 0;
1025 char * name = tape_name(STp);
1027 if (STps->rw != ST_READING) { /* Initialize read operation */
1028 if (STps->rw == ST_WRITING || STp->dirty) {
1029 STp->write_type = OS_WRITE_DATA;
1030 osst_flush_write_buffer(STp, aSRpnt);
1031 osst_flush_drive_buffer(STp, aSRpnt);
1033 STps->rw = ST_READING;
1034 STp->frame_in_buffer = 0;
1037 * Issue a read 0 command to get the OnStream drive
1038 * read frames into its buffer.
1040 memset(cmd, 0, MAX_COMMAND_SIZE);
1041 cmd[0] = READ_6;
1042 cmd[1] = 1;
1044 #if DEBUG
1045 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1046 #endif
1047 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1048 *aSRpnt = SRpnt;
1049 if ((retval = STp->buffer->syscall_result))
1050 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1053 return retval;
1056 static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1057 int frame_seq_number, int quiet)
1059 struct st_partstat * STps = &(STp->ps[STp->partition]);
1060 char * name = tape_name(STp);
1061 int cnt = 0,
1062 bad = 0,
1063 past = 0,
1065 position;
1068 * If we want just any frame (-1) and there is a frame in the buffer, return it
1070 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1071 #if DEBUG
1072 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1073 #endif
1074 return (STps->eof);
1077 * Search and wait for the next logical tape frame
1079 while (1) {
1080 if (cnt++ > 400) {
1081 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1082 name, frame_seq_number);
1083 if (STp->read_error_frame) {
1084 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1085 #if DEBUG
1086 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1087 name, STp->read_error_frame);
1088 #endif
1089 STp->read_error_frame = 0;
1090 STp->abort_count++;
1092 return (-EIO);
1094 #if DEBUG
1095 if (debugging)
1096 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1097 name, frame_seq_number, cnt);
1098 #endif
1099 if ( osst_initiate_read(STp, aSRpnt)
1100 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1101 if (STp->raw)
1102 return (-EIO);
1103 position = osst_get_frame_position(STp, aSRpnt);
1104 if (position >= 0xbae && position < 0xbb8)
1105 position = 0xbb8;
1106 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1107 position = STp->read_error_frame - 1;
1108 bad = 0;
1110 else {
1111 position += 29;
1112 cnt += 19;
1114 #if DEBUG
1115 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1116 name, position);
1117 #endif
1118 osst_set_frame_position(STp, aSRpnt, position, 0);
1119 continue;
1121 if (osst_verify_frame(STp, frame_seq_number, quiet))
1122 break;
1123 if (osst_verify_frame(STp, -1, quiet)) {
1124 x = ntohl(STp->buffer->aux->frame_seq_num);
1125 if (STp->fast_open) {
1126 printk(KERN_WARNING
1127 "%s:W: Found logical frame %d instead of %d after fast open\n",
1128 name, x, frame_seq_number);
1129 STp->header_ok = 0;
1130 STp->read_error_frame = 0;
1131 return (-EIO);
1133 if (x > frame_seq_number) {
1134 if (++past > 3) {
1135 /* positioning backwards did not bring us to the desired frame */
1136 position = STp->read_error_frame - 1;
1138 else {
1139 position = osst_get_frame_position(STp, aSRpnt)
1140 + frame_seq_number - x - 1;
1142 if (STp->first_frame_position >= 3000 && position < 3000)
1143 position -= 10;
1145 #if DEBUG
1146 printk(OSST_DEB_MSG
1147 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1148 name, x, frame_seq_number,
1149 STp->first_frame_position - position);
1150 #endif
1151 osst_set_frame_position(STp, aSRpnt, position, 0);
1152 cnt += 10;
1154 else
1155 past = 0;
1157 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1158 #if DEBUG
1159 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1160 #endif
1161 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1162 cnt--;
1164 STp->frame_in_buffer = 0;
1166 if (cnt > 1) {
1167 STp->recover_count++;
1168 STp->recover_erreg++;
1169 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1170 name, STp->read_error_frame);
1172 STp->read_count++;
1174 #if DEBUG
1175 if (debugging || STps->eof)
1176 printk(OSST_DEB_MSG
1177 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1178 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1179 #endif
1180 STp->fast_open = 0;
1181 STp->read_error_frame = 0;
1182 return (STps->eof);
1185 static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1187 struct st_partstat * STps = &(STp->ps[STp->partition]);
1188 char * name = tape_name(STp);
1189 int retries = 0;
1190 int frame_seq_estimate, ppos_estimate, move;
1192 if (logical_blk_num < 0) logical_blk_num = 0;
1193 #if DEBUG
1194 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1195 name, logical_blk_num, STp->logical_blk_num,
1196 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1197 STp->block_size<1024?'b':'k');
1198 #endif
1199 /* Do we know where we are? */
1200 if (STps->drv_block >= 0) {
1201 move = logical_blk_num - STp->logical_blk_num;
1202 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1203 move /= (OS_DATA_SIZE / STp->block_size);
1204 frame_seq_estimate = STp->frame_seq_number + move;
1205 } else
1206 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1208 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1209 else ppos_estimate = frame_seq_estimate + 20;
1210 while (++retries < 10) {
1211 if (ppos_estimate > STp->eod_frame_ppos-2) {
1212 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1213 ppos_estimate = STp->eod_frame_ppos - 2;
1215 if (frame_seq_estimate < 0) {
1216 frame_seq_estimate = 0;
1217 ppos_estimate = 10;
1219 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1220 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1221 /* we've located the estimated frame, now does it have our block? */
1222 if (logical_blk_num < STp->logical_blk_num ||
1223 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1224 if (STps->eof == ST_FM_HIT)
1225 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1226 else {
1227 move = logical_blk_num - STp->logical_blk_num;
1228 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1229 move /= (OS_DATA_SIZE / STp->block_size);
1231 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1232 #if DEBUG
1233 printk(OSST_DEB_MSG
1234 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1235 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1236 STp->logical_blk_num, logical_blk_num, move);
1237 #endif
1238 frame_seq_estimate += move;
1239 ppos_estimate += move;
1240 continue;
1241 } else {
1242 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1243 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1244 STp->logical_blk_num = logical_blk_num;
1245 #if DEBUG
1246 printk(OSST_DEB_MSG
1247 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1248 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1249 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1250 STp->block_size);
1251 #endif
1252 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1253 if (STps->eof == ST_FM_HIT) {
1254 STps->drv_file++;
1255 STps->drv_block = 0;
1256 } else {
1257 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1258 STp->logical_blk_num -
1259 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1262 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1263 return 0;
1266 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1267 goto error;
1268 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1269 #if DEBUG
1270 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1271 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1272 STp->logical_blk_num, logical_blk_num);
1273 #endif
1274 if (frame_seq_estimate != STp->frame_seq_number)
1275 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1276 else
1277 break;
1279 error:
1280 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1281 name, logical_blk_num, STp->logical_blk_num, retries);
1282 return (-EIO);
1285 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1286 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1287 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1288 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1290 #define OSST_FRAME_SHIFT 6
1291 #define OSST_SECTOR_SHIFT 9
1292 #define OSST_SECTOR_MASK 0x03F
1294 static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1296 int sector;
1297 #if DEBUG
1298 char * name = tape_name(STp);
1300 printk(OSST_DEB_MSG
1301 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1302 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1303 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1304 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1305 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1306 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1307 #endif
1308 /* do we know where we are inside a file? */
1309 if (STp->ps[STp->partition].drv_block >= 0) {
1310 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1311 STp->first_frame_position) << OSST_FRAME_SHIFT;
1312 if (STp->ps[STp->partition].rw == ST_WRITING)
1313 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1314 else
1315 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1316 } else {
1317 sector = osst_get_frame_position(STp, aSRpnt);
1318 if (sector > 0)
1319 sector <<= OSST_FRAME_SHIFT;
1321 return sector;
1324 static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1326 struct st_partstat * STps = &(STp->ps[STp->partition]);
1327 int frame = sector >> OSST_FRAME_SHIFT,
1328 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1330 #if DEBUG
1331 char * name = tape_name(STp);
1333 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1334 name, sector, frame, offset);
1335 #endif
1336 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1338 if (frame <= STp->first_data_ppos) {
1339 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1340 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1342 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1343 if (r < 0) return r;
1345 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1346 if (r < 0) return r;
1348 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1350 if (offset) {
1351 STp->logical_blk_num += offset / STp->block_size;
1352 STp->buffer->read_pointer = offset;
1353 STp->buffer->buffer_bytes -= offset;
1354 } else {
1355 STp->frame_seq_number++;
1356 STp->frame_in_buffer = 0;
1357 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1358 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1360 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1361 if (STps->eof == ST_FM_HIT) {
1362 STps->drv_file++;
1363 STps->drv_block = 0;
1364 } else {
1365 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1366 STp->logical_blk_num -
1367 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1370 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1371 #if DEBUG
1372 printk(OSST_DEB_MSG
1373 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1374 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1375 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1376 #endif
1377 return 0;
1381 * Read back the drive's internal buffer contents, as a part
1382 * of the write error recovery mechanism for old OnStream
1383 * firmware revisions.
1384 * Precondition for this function to work: all frames in the
1385 * drive's buffer must be of one type (DATA, MARK or EOD)!
1387 static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1388 unsigned int frame, unsigned int skip, int pending)
1390 struct osst_request * SRpnt = * aSRpnt;
1391 unsigned char * buffer, * p;
1392 unsigned char cmd[MAX_COMMAND_SIZE];
1393 int flag, new_frame, i;
1394 int nframes = STp->cur_frames;
1395 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1396 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1397 - (nframes + pending - 1);
1398 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1399 - (nframes + pending - 1) * blks_per_frame;
1400 char * name = tape_name(STp);
1401 unsigned long startwait = jiffies;
1402 #if DEBUG
1403 int dbg = debugging;
1404 #endif
1406 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1407 return (-EIO);
1409 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1410 name, nframes, pending?" and one that was pending":"");
1412 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1413 #if DEBUG
1414 if (pending && debugging)
1415 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1416 name, frame_seq_number + nframes,
1417 logical_blk_num + nframes * blks_per_frame,
1418 p[0], p[1], p[2], p[3]);
1419 #endif
1420 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1422 memset(cmd, 0, MAX_COMMAND_SIZE);
1423 cmd[0] = 0x3C; /* Buffer Read */
1424 cmd[1] = 6; /* Retrieve Faulty Block */
1425 cmd[7] = 32768 >> 8;
1426 cmd[8] = 32768 & 0xff;
1428 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1429 STp->timeout, MAX_RETRIES, 1);
1431 if ((STp->buffer)->syscall_result || !SRpnt) {
1432 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1433 vfree(buffer);
1434 *aSRpnt = SRpnt;
1435 return (-EIO);
1437 osst_copy_from_buffer(STp->buffer, p);
1438 #if DEBUG
1439 if (debugging)
1440 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1441 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1442 #endif
1444 *aSRpnt = SRpnt;
1445 osst_get_frame_position(STp, aSRpnt);
1447 #if DEBUG
1448 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1449 #endif
1450 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1451 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1453 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1455 if (flag) {
1456 if (STp->write_type == OS_WRITE_HEADER) {
1457 i += skip;
1458 p += skip * OS_DATA_SIZE;
1460 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1461 new_frame = 3000-i;
1462 else
1463 new_frame += skip;
1464 #if DEBUG
1465 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1466 name, new_frame+i, frame_seq_number+i);
1467 #endif
1468 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1469 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1470 osst_get_frame_position(STp, aSRpnt);
1471 SRpnt = * aSRpnt;
1473 if (new_frame > frame + 1000) {
1474 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1475 vfree(buffer);
1476 return (-EIO);
1478 if ( i >= nframes + pending ) break;
1479 flag = 0;
1481 osst_copy_to_buffer(STp->buffer, p);
1483 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1485 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1486 logical_blk_num + i*blks_per_frame,
1487 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1488 memset(cmd, 0, MAX_COMMAND_SIZE);
1489 cmd[0] = WRITE_6;
1490 cmd[1] = 1;
1491 cmd[4] = 1;
1493 #if DEBUG
1494 if (debugging)
1495 printk(OSST_DEB_MSG
1496 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1497 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1498 p[0], p[1], p[2], p[3]);
1499 #endif
1500 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1501 STp->timeout, MAX_RETRIES, 1);
1503 if (STp->buffer->syscall_result)
1504 flag = 1;
1505 else {
1506 p += OS_DATA_SIZE; i++;
1508 /* if we just sent the last frame, wait till all successfully written */
1509 if ( i == nframes + pending ) {
1510 #if DEBUG
1511 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1512 #endif
1513 memset(cmd, 0, MAX_COMMAND_SIZE);
1514 cmd[0] = WRITE_FILEMARKS;
1515 cmd[1] = 1;
1516 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1517 STp->timeout, MAX_RETRIES, 1);
1518 #if DEBUG
1519 if (debugging) {
1520 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1521 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1522 debugging = 0;
1524 #endif
1525 flag = STp->buffer->syscall_result;
1526 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1528 memset(cmd, 0, MAX_COMMAND_SIZE);
1529 cmd[0] = TEST_UNIT_READY;
1531 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1532 MAX_RETRIES, 1);
1534 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1535 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1536 /* in the process of becoming ready */
1537 msleep(100);
1538 continue;
1540 if (STp->buffer->syscall_result)
1541 flag = 1;
1542 break;
1544 #if DEBUG
1545 debugging = dbg;
1546 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1547 #endif
1550 *aSRpnt = SRpnt;
1551 if (flag) {
1552 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1553 SRpnt->sense[12] == 0 &&
1554 SRpnt->sense[13] == 2) {
1555 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1556 vfree(buffer);
1557 return (-EIO); /* hit end of tape = fail */
1559 i = ((SRpnt->sense[3] << 24) |
1560 (SRpnt->sense[4] << 16) |
1561 (SRpnt->sense[5] << 8) |
1562 SRpnt->sense[6] ) - new_frame;
1563 p = &buffer[i * OS_DATA_SIZE];
1564 #if DEBUG
1565 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1566 #endif
1567 osst_get_frame_position(STp, aSRpnt);
1568 #if DEBUG
1569 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1570 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1571 #endif
1574 if (flag) {
1575 /* error recovery did not successfully complete */
1576 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1577 STp->write_type == OS_WRITE_HEADER?"header":"body");
1579 if (!pending)
1580 osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
1581 vfree(buffer);
1582 return 0;
1585 static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1586 unsigned int frame, unsigned int skip, int pending)
1588 unsigned char cmd[MAX_COMMAND_SIZE];
1589 struct osst_request * SRpnt;
1590 char * name = tape_name(STp);
1591 int expected = 0;
1592 int attempts = 1000 / skip;
1593 int flag = 1;
1594 unsigned long startwait = jiffies;
1595 #if DEBUG
1596 int dbg = debugging;
1597 #endif
1599 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1600 if (flag) {
1601 #if DEBUG
1602 debugging = dbg;
1603 #endif
1604 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1605 frame = 3000-skip;
1606 expected = frame+skip+STp->cur_frames+pending;
1607 #if DEBUG
1608 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1609 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1610 #endif
1611 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1612 flag = 0;
1613 attempts--;
1614 schedule_timeout_interruptible(msecs_to_jiffies(100));
1616 if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
1617 #if DEBUG
1618 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1619 name, STp->first_frame_position,
1620 STp->last_frame_position, STp->cur_frames);
1621 #endif
1622 frame = STp->last_frame_position;
1623 flag = 1;
1624 continue;
1626 if (pending && STp->cur_frames < 50) {
1628 memset(cmd, 0, MAX_COMMAND_SIZE);
1629 cmd[0] = WRITE_6;
1630 cmd[1] = 1;
1631 cmd[4] = 1;
1632 #if DEBUG
1633 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1634 name, STp->frame_seq_number-1, STp->first_frame_position);
1635 #endif
1636 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1637 STp->timeout, MAX_RETRIES, 1);
1638 *aSRpnt = SRpnt;
1640 if (STp->buffer->syscall_result) { /* additional write error */
1641 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1642 SRpnt->sense[12] == 0 &&
1643 SRpnt->sense[13] == 2) {
1644 printk(KERN_ERR
1645 "%s:E: Volume overflow in write error recovery\n",
1646 name);
1647 break; /* hit end of tape = fail */
1649 flag = 1;
1651 else
1652 pending = 0;
1654 continue;
1656 if (STp->cur_frames == 0) {
1657 #if DEBUG
1658 debugging = dbg;
1659 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1660 #endif
1661 if (STp->first_frame_position != expected) {
1662 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1663 name, STp->first_frame_position, expected);
1664 return (-EIO);
1666 return 0;
1668 #if DEBUG
1669 if (debugging) {
1670 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1671 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1672 debugging = 0;
1674 #endif
1675 schedule_timeout_interruptible(msecs_to_jiffies(100));
1677 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1678 #if DEBUG
1679 debugging = dbg;
1680 #endif
1681 return (-EIO);
1685 * Error recovery algorithm for the OnStream tape.
1688 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1690 struct osst_request * SRpnt = * aSRpnt;
1691 struct st_partstat * STps = & STp->ps[STp->partition];
1692 char * name = tape_name(STp);
1693 int retval = 0;
1694 int rw_state;
1695 unsigned int frame, skip;
1697 rw_state = STps->rw;
1699 if ((SRpnt->sense[ 2] & 0x0f) != 3
1700 || SRpnt->sense[12] != 12
1701 || SRpnt->sense[13] != 0) {
1702 #if DEBUG
1703 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1704 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1705 #endif
1706 return (-EIO);
1708 frame = (SRpnt->sense[3] << 24) |
1709 (SRpnt->sense[4] << 16) |
1710 (SRpnt->sense[5] << 8) |
1711 SRpnt->sense[6];
1712 skip = SRpnt->sense[9];
1714 #if DEBUG
1715 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1716 #endif
1717 osst_get_frame_position(STp, aSRpnt);
1718 #if DEBUG
1719 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1720 name, STp->first_frame_position, STp->last_frame_position);
1721 #endif
1722 switch (STp->write_type) {
1723 case OS_WRITE_DATA:
1724 case OS_WRITE_EOD:
1725 case OS_WRITE_NEW_MARK:
1726 printk(KERN_WARNING
1727 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1728 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1729 if (STp->os_fw_rev >= 10600)
1730 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1731 else
1732 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1733 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1734 retval?"E" :"I",
1735 retval?"" :"Don't worry, ",
1736 retval?" not ":" ");
1737 break;
1738 case OS_WRITE_LAST_MARK:
1739 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1740 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1741 retval = -EIO;
1742 break;
1743 case OS_WRITE_HEADER:
1744 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1745 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1746 break;
1747 default:
1748 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1749 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1751 osst_get_frame_position(STp, aSRpnt);
1752 #if DEBUG
1753 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1754 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1755 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1756 #endif
1757 if (retval == 0) {
1758 STp->recover_count++;
1759 STp->recover_erreg++;
1760 } else
1761 STp->abort_count++;
1763 STps->rw = rw_state;
1764 return retval;
1767 static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1768 int mt_op, int mt_count)
1770 char * name = tape_name(STp);
1771 int cnt;
1772 int last_mark_ppos = -1;
1774 #if DEBUG
1775 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1776 #endif
1777 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1778 #if DEBUG
1779 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1780 #endif
1781 return -EIO;
1783 if (STp->linux_media_version >= 4) {
1785 * direct lookup in header filemark list
1787 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1788 if (STp->header_ok &&
1789 STp->header_cache != NULL &&
1790 (cnt - mt_count) >= 0 &&
1791 (cnt - mt_count) < OS_FM_TAB_MAX &&
1792 (cnt - mt_count) < STp->filemark_cnt &&
1793 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1795 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1796 #if DEBUG
1797 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1798 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1799 STp->header_cache == NULL?"lack of header cache":"count out of range");
1800 else
1801 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1802 name, cnt,
1803 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1804 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1805 STp->buffer->aux->last_mark_ppos))?"match":"error",
1806 mt_count, last_mark_ppos);
1807 #endif
1808 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1809 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1810 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1811 #if DEBUG
1812 printk(OSST_DEB_MSG
1813 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1814 #endif
1815 return (-EIO);
1817 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1818 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1819 name, last_mark_ppos);
1820 return (-EIO);
1822 goto found;
1824 #if DEBUG
1825 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1826 #endif
1828 cnt = 0;
1829 while (cnt != mt_count) {
1830 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1831 if (last_mark_ppos == -1)
1832 return (-EIO);
1833 #if DEBUG
1834 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1835 #endif
1836 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1837 cnt++;
1838 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1839 #if DEBUG
1840 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1841 #endif
1842 return (-EIO);
1844 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1845 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1846 name, last_mark_ppos);
1847 return (-EIO);
1850 found:
1851 if (mt_op == MTBSFM) {
1852 STp->frame_seq_number++;
1853 STp->frame_in_buffer = 0;
1854 STp->buffer->buffer_bytes = 0;
1855 STp->buffer->read_pointer = 0;
1856 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1858 return 0;
1862 * ADRL 1.1 compatible "slow" space filemarks fwd version
1864 * Just scans for the filemark sequentially.
1866 static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1867 int mt_op, int mt_count)
1869 int cnt = 0;
1870 #if DEBUG
1871 char * name = tape_name(STp);
1873 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1874 #endif
1875 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1876 #if DEBUG
1877 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1878 #endif
1879 return (-EIO);
1881 while (1) {
1882 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1883 #if DEBUG
1884 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1885 #endif
1886 return (-EIO);
1888 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1889 cnt++;
1890 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1891 #if DEBUG
1892 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1893 #endif
1894 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1895 #if DEBUG
1896 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1897 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1898 #endif
1899 STp->eod_frame_ppos = STp->first_frame_position-1;
1901 return (-EIO);
1903 if (cnt == mt_count)
1904 break;
1905 STp->frame_in_buffer = 0;
1907 if (mt_op == MTFSF) {
1908 STp->frame_seq_number++;
1909 STp->frame_in_buffer = 0;
1910 STp->buffer->buffer_bytes = 0;
1911 STp->buffer->read_pointer = 0;
1912 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1914 return 0;
1918 * Fast linux specific version of OnStream FSF
1920 static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
1921 int mt_op, int mt_count)
1923 char * name = tape_name(STp);
1924 int cnt = 0,
1925 next_mark_ppos = -1;
1927 #if DEBUG
1928 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
1929 #endif
1930 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1931 #if DEBUG
1932 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1933 #endif
1934 return (-EIO);
1937 if (STp->linux_media_version >= 4) {
1939 * direct lookup in header filemark list
1941 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1942 if (STp->header_ok &&
1943 STp->header_cache != NULL &&
1944 (cnt + mt_count) < OS_FM_TAB_MAX &&
1945 (cnt + mt_count) < STp->filemark_cnt &&
1946 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1947 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1949 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1950 #if DEBUG
1951 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1952 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1953 STp->header_cache == NULL?"lack of header cache":"count out of range");
1954 else
1955 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1956 name, cnt,
1957 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1958 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1959 STp->buffer->aux->last_mark_ppos))?"match":"error",
1960 mt_count, next_mark_ppos);
1961 #endif
1962 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1963 #if DEBUG
1964 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1965 #endif
1966 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1967 } else {
1968 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1969 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1970 #if DEBUG
1971 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
1972 name);
1973 #endif
1974 return (-EIO);
1976 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1977 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1978 name, next_mark_ppos);
1979 return (-EIO);
1981 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1982 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
1983 name, cnt+mt_count, next_mark_ppos,
1984 ntohl(STp->buffer->aux->filemark_cnt));
1985 return (-EIO);
1988 } else {
1990 * Find nearest (usually previous) marker, then jump from marker to marker
1992 while (1) {
1993 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1994 break;
1995 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1996 #if DEBUG
1997 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1998 #endif
1999 return (-EIO);
2001 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2002 if (STp->first_mark_ppos == -1) {
2003 #if DEBUG
2004 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2005 #endif
2006 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2008 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2009 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2010 #if DEBUG
2011 printk(OSST_DEB_MSG
2012 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2013 name);
2014 #endif
2015 return (-EIO);
2017 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2018 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2019 name, STp->first_mark_ppos);
2020 return (-EIO);
2022 } else {
2023 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2024 return (-EIO);
2025 mt_count++;
2028 cnt++;
2029 while (cnt != mt_count) {
2030 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2031 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2032 #if DEBUG
2033 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2034 #endif
2035 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2037 #if DEBUG
2038 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2039 #endif
2040 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2041 cnt++;
2042 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2043 #if DEBUG
2044 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2045 name);
2046 #endif
2047 return (-EIO);
2049 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2050 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2051 name, next_mark_ppos);
2052 return (-EIO);
2056 if (mt_op == MTFSF) {
2057 STp->frame_seq_number++;
2058 STp->frame_in_buffer = 0;
2059 STp->buffer->buffer_bytes = 0;
2060 STp->buffer->read_pointer = 0;
2061 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2063 return 0;
2067 * In debug mode, we want to see as many errors as possible
2068 * to test the error recovery mechanism.
2070 #if DEBUG
2071 static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2073 unsigned char cmd[MAX_COMMAND_SIZE];
2074 struct osst_request * SRpnt = * aSRpnt;
2075 char * name = tape_name(STp);
2077 memset(cmd, 0, MAX_COMMAND_SIZE);
2078 cmd[0] = MODE_SELECT;
2079 cmd[1] = 0x10;
2080 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2082 (STp->buffer)->b_data[0] = cmd[4] - 1;
2083 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
2084 (STp->buffer)->b_data[2] = 0; /* Reserved */
2085 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
2086 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2087 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2088 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2089 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2091 if (debugging)
2092 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2094 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2095 *aSRpnt = SRpnt;
2097 if ((STp->buffer)->syscall_result)
2098 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2100 #endif
2103 static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2105 int result;
2106 int this_mark_ppos = STp->first_frame_position;
2107 int this_mark_lbn = STp->logical_blk_num;
2108 #if DEBUG
2109 char * name = tape_name(STp);
2110 #endif
2112 if (STp->raw) return 0;
2114 STp->write_type = OS_WRITE_NEW_MARK;
2115 #if DEBUG
2116 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2117 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2118 #endif
2119 STp->dirty = 1;
2120 result = osst_flush_write_buffer(STp, aSRpnt);
2121 result |= osst_flush_drive_buffer(STp, aSRpnt);
2122 STp->last_mark_ppos = this_mark_ppos;
2123 STp->last_mark_lbn = this_mark_lbn;
2124 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2125 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2126 if (STp->filemark_cnt++ == 0)
2127 STp->first_mark_ppos = this_mark_ppos;
2128 return result;
2131 static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2133 int result;
2134 #if DEBUG
2135 char * name = tape_name(STp);
2136 #endif
2138 if (STp->raw) return 0;
2140 STp->write_type = OS_WRITE_EOD;
2141 STp->eod_frame_ppos = STp->first_frame_position;
2142 #if DEBUG
2143 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2144 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2145 #endif
2146 STp->dirty = 1;
2148 result = osst_flush_write_buffer(STp, aSRpnt);
2149 result |= osst_flush_drive_buffer(STp, aSRpnt);
2150 STp->eod_frame_lfa = --(STp->frame_seq_number);
2151 return result;
2154 static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2156 char * name = tape_name(STp);
2158 #if DEBUG
2159 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2160 #endif
2161 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2162 osst_set_frame_position(STp, aSRpnt, where, 0);
2163 STp->write_type = OS_WRITE_FILLER;
2164 while (count--) {
2165 memcpy(STp->buffer->b_data, "Filler", 6);
2166 STp->buffer->buffer_bytes = 6;
2167 STp->dirty = 1;
2168 if (osst_flush_write_buffer(STp, aSRpnt)) {
2169 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2170 return (-EIO);
2173 #if DEBUG
2174 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2175 #endif
2176 return osst_flush_drive_buffer(STp, aSRpnt);
2179 static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2181 char * name = tape_name(STp);
2182 int result;
2184 #if DEBUG
2185 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2186 #endif
2187 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2188 osst_set_frame_position(STp, aSRpnt, where, 0);
2189 STp->write_type = OS_WRITE_HEADER;
2190 while (count--) {
2191 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2192 STp->buffer->buffer_bytes = sizeof(os_header_t);
2193 STp->dirty = 1;
2194 if (osst_flush_write_buffer(STp, aSRpnt)) {
2195 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2196 return (-EIO);
2199 result = osst_flush_drive_buffer(STp, aSRpnt);
2200 #if DEBUG
2201 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2202 #endif
2203 return result;
2206 static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2208 os_header_t * header;
2209 int result;
2210 char * name = tape_name(STp);
2212 #if DEBUG
2213 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2214 #endif
2215 if (STp->raw) return 0;
2217 if (STp->header_cache == NULL) {
2218 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2219 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2220 return (-ENOMEM);
2222 memset(STp->header_cache, 0, sizeof(os_header_t));
2223 #if DEBUG
2224 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2225 #endif
2227 if (STp->header_ok) STp->update_frame_cntr++;
2228 else STp->update_frame_cntr = 0;
2230 header = STp->header_cache;
2231 strcpy(header->ident_str, "ADR_SEQ");
2232 header->major_rev = 1;
2233 header->minor_rev = 4;
2234 header->ext_trk_tb_off = htons(17192);
2235 header->pt_par_num = 1;
2236 header->partition[0].partition_num = OS_DATA_PARTITION;
2237 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2238 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2239 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2240 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2241 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2242 header->cfg_col_width = htonl(20);
2243 header->dat_col_width = htonl(1500);
2244 header->qfa_col_width = htonl(0);
2245 header->ext_track_tb.nr_stream_part = 1;
2246 header->ext_track_tb.et_ent_sz = 32;
2247 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2248 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2249 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2250 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2251 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2252 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2253 header->dat_fm_tab.fm_part_num = 0;
2254 header->dat_fm_tab.fm_tab_ent_sz = 4;
2255 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2256 STp->filemark_cnt:OS_FM_TAB_MAX);
2258 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2259 if (STp->update_frame_cntr == 0)
2260 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2261 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2263 if (locate_eod) {
2264 #if DEBUG
2265 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2266 #endif
2267 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2269 if (result)
2270 printk(KERN_ERR "%s:E: Write header failed\n", name);
2271 else {
2272 memcpy(STp->application_sig, "LIN4", 4);
2273 STp->linux_media = 1;
2274 STp->linux_media_version = 4;
2275 STp->header_ok = 1;
2277 return result;
2280 static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2282 if (STp->header_cache != NULL)
2283 memset(STp->header_cache, 0, sizeof(os_header_t));
2285 STp->logical_blk_num = STp->frame_seq_number = 0;
2286 STp->frame_in_buffer = 0;
2287 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2288 STp->filemark_cnt = 0;
2289 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2290 return osst_write_header(STp, aSRpnt, 1);
2293 static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2295 char * name = tape_name(STp);
2296 os_header_t * header;
2297 os_aux_t * aux;
2298 char id_string[8];
2299 int linux_media_version,
2300 update_frame_cntr;
2302 if (STp->raw)
2303 return 1;
2305 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2306 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2307 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2308 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2309 if (osst_initiate_read (STp, aSRpnt)) {
2310 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2311 return 0;
2314 if (osst_read_frame(STp, aSRpnt, 180)) {
2315 #if DEBUG
2316 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2317 #endif
2318 return 0;
2320 header = (os_header_t *) STp->buffer->b_data; /* warning: only first segment addressable */
2321 aux = STp->buffer->aux;
2322 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2323 #if DEBUG
2324 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2325 #endif
2326 return 0;
2328 if (ntohl(aux->frame_seq_num) != 0 ||
2329 ntohl(aux->logical_blk_num) != 0 ||
2330 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2331 ntohl(aux->partition.first_frame_ppos) != 0 ||
2332 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2333 #if DEBUG
2334 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2335 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2336 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2337 ntohl(aux->partition.last_frame_ppos));
2338 #endif
2339 return 0;
2341 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2342 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2343 strlcpy(id_string, header->ident_str, 8);
2344 #if DEBUG
2345 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2346 #endif
2347 return 0;
2349 update_frame_cntr = ntohl(aux->update_frame_cntr);
2350 if (update_frame_cntr < STp->update_frame_cntr) {
2351 #if DEBUG
2352 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2353 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2354 #endif
2355 return 0;
2357 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2358 #if DEBUG
2359 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2360 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2361 header->minor_rev > 4 )? "Invalid" : "Warning:",
2362 header->major_rev, header->minor_rev);
2363 #endif
2364 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2365 return 0;
2367 #if DEBUG
2368 if (header->pt_par_num != 1)
2369 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2370 name, header->pt_par_num);
2371 #endif
2372 memcpy(id_string, aux->application_sig, 4);
2373 id_string[4] = 0;
2374 if (memcmp(id_string, "LIN", 3) == 0) {
2375 STp->linux_media = 1;
2376 linux_media_version = id_string[3] - '0';
2377 if (linux_media_version != 4)
2378 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2379 name, linux_media_version);
2380 } else {
2381 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2382 return 0;
2384 if (linux_media_version < STp->linux_media_version) {
2385 #if DEBUG
2386 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2387 name, ppos, linux_media_version);
2388 #endif
2389 return 0;
2391 if (linux_media_version > STp->linux_media_version) {
2392 #if DEBUG
2393 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2394 name, ppos, linux_media_version);
2395 #endif
2396 memcpy(STp->application_sig, id_string, 5);
2397 STp->linux_media_version = linux_media_version;
2398 STp->update_frame_cntr = -1;
2400 if (update_frame_cntr > STp->update_frame_cntr) {
2401 #if DEBUG
2402 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2403 name, ppos, update_frame_cntr);
2404 #endif
2405 if (STp->header_cache == NULL) {
2406 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2407 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2408 return 0;
2410 #if DEBUG
2411 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2412 #endif
2414 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2415 header = STp->header_cache; /* further accesses from cached (full) copy */
2417 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2418 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2419 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2420 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2421 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2422 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2423 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2424 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2425 STp->update_frame_cntr = update_frame_cntr;
2426 #if DEBUG
2427 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2428 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2429 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2430 STp->first_data_ppos,
2431 ntohl(header->partition[0].last_frame_ppos),
2432 ntohl(header->partition[0].eod_frame_ppos));
2433 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2434 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2435 #endif
2436 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2437 #if DEBUG
2438 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2439 #endif
2440 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2441 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2442 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2444 if (header->minor_rev == 4 &&
2445 (header->ext_trk_tb_off != htons(17192) ||
2446 header->partition[0].partition_num != OS_DATA_PARTITION ||
2447 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2448 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2449 header->cfg_col_width != htonl(20) ||
2450 header->dat_col_width != htonl(1500) ||
2451 header->qfa_col_width != htonl(0) ||
2452 header->ext_track_tb.nr_stream_part != 1 ||
2453 header->ext_track_tb.et_ent_sz != 32 ||
2454 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2455 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2456 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2457 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2458 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2459 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2460 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2461 header->dat_fm_tab.fm_tab_ent_cnt !=
2462 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2463 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2467 return 1;
2470 static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2472 int position, ppos;
2473 int first, last;
2474 int valid = 0;
2475 char * name = tape_name(STp);
2477 position = osst_get_frame_position(STp, aSRpnt);
2479 if (STp->raw) {
2480 STp->header_ok = STp->linux_media = 1;
2481 STp->linux_media_version = 0;
2482 return 1;
2484 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2485 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2486 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2487 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2488 #if DEBUG
2489 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2490 #endif
2492 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2493 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2495 first = position==10?0xbae: 5;
2496 last = position==10?0xbb3:10;
2498 for (ppos = first; ppos < last; ppos++)
2499 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2500 valid = 1;
2502 first = position==10? 5:0xbae;
2503 last = position==10?10:0xbb3;
2505 for (ppos = first; ppos < last; ppos++)
2506 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2507 valid = 1;
2509 if (!valid) {
2510 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2511 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2512 osst_set_frame_position(STp, aSRpnt, 10, 0);
2513 return 0;
2515 if (position <= STp->first_data_ppos) {
2516 position = STp->first_data_ppos;
2517 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2519 osst_set_frame_position(STp, aSRpnt, position, 0);
2520 STp->header_ok = 1;
2522 return 1;
2525 static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2527 int frame_position = STp->first_frame_position;
2528 int frame_seq_numbr = STp->frame_seq_number;
2529 int logical_blk_num = STp->logical_blk_num;
2530 int halfway_frame = STp->frame_in_buffer;
2531 int read_pointer = STp->buffer->read_pointer;
2532 int prev_mark_ppos = -1;
2533 int actual_mark_ppos, i, n;
2534 #if DEBUG
2535 char * name = tape_name(STp);
2537 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2538 #endif
2539 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2540 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2541 #if DEBUG
2542 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2543 #endif
2544 return (-EIO);
2546 if (STp->linux_media_version >= 4) {
2547 for (i=0; i<STp->filemark_cnt; i++)
2548 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2549 prev_mark_ppos = n;
2550 } else
2551 prev_mark_ppos = frame_position - 1; /* usually - we don't really know */
2552 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2553 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2554 if (frame_position != STp->first_frame_position ||
2555 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2556 prev_mark_ppos != actual_mark_ppos ) {
2557 #if DEBUG
2558 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2559 STp->first_frame_position, frame_position,
2560 STp->frame_seq_number + (halfway_frame?0:1),
2561 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2562 #endif
2563 return (-EIO);
2565 if (halfway_frame) {
2566 /* prepare buffer for append and rewrite on top of original */
2567 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2568 STp->buffer->buffer_bytes = read_pointer;
2569 STp->ps[STp->partition].rw = ST_WRITING;
2570 STp->dirty = 1;
2572 STp->frame_in_buffer = halfway_frame;
2573 STp->frame_seq_number = frame_seq_numbr;
2574 STp->logical_blk_num = logical_blk_num;
2575 return 0;
2578 /* Acc. to OnStream, the vers. numbering is the following:
2579 * X.XX for released versions (X=digit),
2580 * XXXY for unreleased versions (Y=letter)
2581 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2582 * This fn makes monoton numbers out of this scheme ...
2584 static unsigned int osst_parse_firmware_rev (const char * str)
2586 if (str[1] == '.') {
2587 return (str[0]-'0')*10000
2588 +(str[2]-'0')*1000
2589 +(str[3]-'0')*100;
2590 } else {
2591 return (str[0]-'0')*10000
2592 +(str[1]-'0')*1000
2593 +(str[2]-'0')*100 - 100
2594 +(str[3]-'@');
2599 * Configure the OnStream SCII tape drive for default operation
2601 static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2603 unsigned char cmd[MAX_COMMAND_SIZE];
2604 char * name = tape_name(STp);
2605 struct osst_request * SRpnt = * aSRpnt;
2606 osst_mode_parameter_header_t * header;
2607 osst_block_size_page_t * bs;
2608 osst_capabilities_page_t * cp;
2609 osst_tape_paramtr_page_t * prm;
2610 int drive_buffer_size;
2612 if (STp->ready != ST_READY) {
2613 #if DEBUG
2614 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2615 #endif
2616 return (-EIO);
2619 if (STp->os_fw_rev < 10600) {
2620 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2621 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2625 * Configure 32.5KB (data+aux) frame size.
2626 * Get the current frame size from the block size mode page
2628 memset(cmd, 0, MAX_COMMAND_SIZE);
2629 cmd[0] = MODE_SENSE;
2630 cmd[1] = 8;
2631 cmd[2] = BLOCK_SIZE_PAGE;
2632 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2634 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2635 if (SRpnt == NULL) {
2636 #if DEBUG
2637 printk(OSST_DEB_MSG "osst :D: Busy\n");
2638 #endif
2639 return (-EBUSY);
2641 *aSRpnt = SRpnt;
2642 if ((STp->buffer)->syscall_result != 0) {
2643 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2644 return (-EIO);
2647 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2648 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2650 #if DEBUG
2651 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2652 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2653 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2654 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2655 #endif
2658 * Configure default auto columns mode, 32.5KB transfer mode
2660 bs->one = 1;
2661 bs->play32 = 0;
2662 bs->play32_5 = 1;
2663 bs->record32 = 0;
2664 bs->record32_5 = 1;
2666 memset(cmd, 0, MAX_COMMAND_SIZE);
2667 cmd[0] = MODE_SELECT;
2668 cmd[1] = 0x10;
2669 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2671 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2672 *aSRpnt = SRpnt;
2673 if ((STp->buffer)->syscall_result != 0) {
2674 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2675 return (-EIO);
2678 #if DEBUG
2679 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2681 * In debug mode, we want to see as many errors as possible
2682 * to test the error recovery mechanism.
2684 osst_set_retries(STp, aSRpnt, 0);
2685 SRpnt = * aSRpnt;
2686 #endif
2689 * Set vendor name to 'LIN4' for "Linux support version 4".
2692 memset(cmd, 0, MAX_COMMAND_SIZE);
2693 cmd[0] = MODE_SELECT;
2694 cmd[1] = 0x10;
2695 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2697 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2698 header->medium_type = 0; /* Medium Type - ignoring */
2699 header->dsp = 0; /* Reserved */
2700 header->bdl = 0; /* Block Descriptor Length */
2702 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2703 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2704 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2705 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2706 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2707 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2708 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2709 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2711 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2712 *aSRpnt = SRpnt;
2714 if ((STp->buffer)->syscall_result != 0) {
2715 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2716 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2717 return (-EIO);
2720 memset(cmd, 0, MAX_COMMAND_SIZE);
2721 cmd[0] = MODE_SENSE;
2722 cmd[1] = 8;
2723 cmd[2] = CAPABILITIES_PAGE;
2724 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2726 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2727 *aSRpnt = SRpnt;
2729 if ((STp->buffer)->syscall_result != 0) {
2730 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2731 return (-EIO);
2734 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2735 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2736 sizeof(osst_mode_parameter_header_t) + header->bdl);
2738 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2740 memset(cmd, 0, MAX_COMMAND_SIZE);
2741 cmd[0] = MODE_SENSE;
2742 cmd[1] = 8;
2743 cmd[2] = TAPE_PARAMTR_PAGE;
2744 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2746 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2747 *aSRpnt = SRpnt;
2749 if ((STp->buffer)->syscall_result != 0) {
2750 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2751 return (-EIO);
2754 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2755 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2756 sizeof(osst_mode_parameter_header_t) + header->bdl);
2758 STp->density = prm->density;
2759 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2760 #if DEBUG
2761 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2762 name, STp->density, STp->capacity / 32, drive_buffer_size);
2763 #endif
2765 return 0;
2770 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2771 it messes up the block number). */
2772 static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2774 int result;
2775 char * name = tape_name(STp);
2777 #if DEBUG
2778 if (debugging)
2779 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2780 name, forward ? "forward" : "backward");
2781 #endif
2783 if (forward) {
2784 /* assumes that the filemark is already read by the drive, so this is low cost */
2785 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2787 else
2788 /* assumes this is only called if we just read the filemark! */
2789 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2791 if (result < 0)
2792 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2793 name, forward ? "forward" : "backward");
2795 return result;
2799 /* Get the tape position. */
2801 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2803 unsigned char scmd[MAX_COMMAND_SIZE];
2804 struct osst_request * SRpnt;
2805 int result = 0;
2806 char * name = tape_name(STp);
2808 /* KG: We want to be able to use it for checking Write Buffer availability
2809 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2810 char mybuf[24];
2811 char * olddata = STp->buffer->b_data;
2812 int oldsize = STp->buffer->buffer_size;
2814 if (STp->ready != ST_READY) return (-EIO);
2816 memset (scmd, 0, MAX_COMMAND_SIZE);
2817 scmd[0] = READ_POSITION;
2819 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2820 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2821 STp->timeout, MAX_RETRIES, 1);
2822 if (!SRpnt) {
2823 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2824 return (-EBUSY);
2826 *aSRpnt = SRpnt;
2828 if (STp->buffer->syscall_result)
2829 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
2831 if (result == -EINVAL)
2832 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2833 else {
2834 if (result == -EIO) { /* re-read position - this needs to preserve media errors */
2835 unsigned char mysense[16];
2836 memcpy (mysense, SRpnt->sense, 16);
2837 memset (scmd, 0, MAX_COMMAND_SIZE);
2838 scmd[0] = READ_POSITION;
2839 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2840 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2841 STp->timeout, MAX_RETRIES, 1);
2842 #if DEBUG
2843 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2844 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2845 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2846 #endif
2847 if (!STp->buffer->syscall_result)
2848 memcpy (SRpnt->sense, mysense, 16);
2849 else
2850 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2852 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2853 + ((STp->buffer)->b_data[5] << 16)
2854 + ((STp->buffer)->b_data[6] << 8)
2855 + (STp->buffer)->b_data[7];
2856 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2857 + ((STp->buffer)->b_data[ 9] << 16)
2858 + ((STp->buffer)->b_data[10] << 8)
2859 + (STp->buffer)->b_data[11];
2860 STp->cur_frames = (STp->buffer)->b_data[15];
2861 #if DEBUG
2862 if (debugging) {
2863 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2864 STp->first_frame_position, STp->last_frame_position,
2865 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2866 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2867 STp->cur_frames);
2869 #endif
2870 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2871 #if DEBUG
2872 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2873 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2874 #endif
2875 STp->first_frame_position = STp->last_frame_position;
2878 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2880 return (result == 0 ? STp->first_frame_position : result);
2884 /* Set the tape block */
2885 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2887 unsigned char scmd[MAX_COMMAND_SIZE];
2888 struct osst_request * SRpnt;
2889 struct st_partstat * STps;
2890 int result = 0;
2891 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2892 char * name = tape_name(STp);
2894 if (STp->ready != ST_READY) return (-EIO);
2896 STps = &(STp->ps[STp->partition]);
2898 if (ppos < 0 || ppos > STp->capacity) {
2899 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2900 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2901 result = (-EINVAL);
2904 do {
2905 #if DEBUG
2906 if (debugging)
2907 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2908 #endif
2909 memset (scmd, 0, MAX_COMMAND_SIZE);
2910 scmd[0] = SEEK_10;
2911 scmd[1] = 1;
2912 scmd[3] = (pp >> 24);
2913 scmd[4] = (pp >> 16);
2914 scmd[5] = (pp >> 8);
2915 scmd[6] = pp;
2916 if (skip)
2917 scmd[9] = 0x80;
2919 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
2920 MAX_RETRIES, 1);
2921 if (!SRpnt)
2922 return (-EBUSY);
2923 *aSRpnt = SRpnt;
2925 if ((STp->buffer)->syscall_result != 0) {
2926 #if DEBUG
2927 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
2928 name, STp->first_frame_position, pp);
2929 #endif
2930 result = (-EIO);
2932 if (pp != ppos)
2933 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
2934 } while ((pp != ppos) && (pp = ppos));
2935 STp->first_frame_position = STp->last_frame_position = ppos;
2936 STps->eof = ST_NOEOF;
2937 STps->at_sm = 0;
2938 STps->rw = ST_IDLE;
2939 STp->frame_in_buffer = 0;
2940 return result;
2943 static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
2945 struct st_partstat * STps = &(STp->ps[STp->partition]);
2946 int result = 0;
2948 if (STp->write_type != OS_WRITE_NEW_MARK) {
2949 /* true unless the user wrote the filemark for us */
2950 result = osst_flush_drive_buffer(STp, aSRpnt);
2951 if (result < 0) goto out;
2952 result = osst_write_filemark(STp, aSRpnt);
2953 if (result < 0) goto out;
2955 if (STps->drv_file >= 0)
2956 STps->drv_file++ ;
2957 STps->drv_block = 0;
2959 result = osst_write_eod(STp, aSRpnt);
2960 osst_write_header(STp, aSRpnt, leave_at_EOT);
2962 STps->eof = ST_FM;
2963 out:
2964 return result;
2967 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2969 /* Flush the write buffer (never need to write if variable blocksize). */
2970 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
2972 int offset, transfer, blks = 0;
2973 int result = 0;
2974 unsigned char cmd[MAX_COMMAND_SIZE];
2975 struct osst_request * SRpnt = *aSRpnt;
2976 struct st_partstat * STps;
2977 char * name = tape_name(STp);
2979 if ((STp->buffer)->writing) {
2980 if (SRpnt == (STp->buffer)->last_SRpnt)
2981 #if DEBUG
2982 { printk(OSST_DEB_MSG
2983 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
2984 #endif
2985 *aSRpnt = SRpnt = NULL;
2986 #if DEBUG
2987 } else if (SRpnt)
2988 printk(OSST_DEB_MSG
2989 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
2990 #endif
2991 osst_write_behind_check(STp);
2992 if ((STp->buffer)->syscall_result) {
2993 #if DEBUG
2994 if (debugging)
2995 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
2996 name, (STp->buffer)->midlevel_result);
2997 #endif
2998 if ((STp->buffer)->midlevel_result == INT_MAX)
2999 return (-ENOSPC);
3000 return (-EIO);
3004 result = 0;
3005 if (STp->dirty == 1) {
3007 STp->write_count++;
3008 STps = &(STp->ps[STp->partition]);
3009 STps->rw = ST_WRITING;
3010 offset = STp->buffer->buffer_bytes;
3011 blks = (offset + STp->block_size - 1) / STp->block_size;
3012 transfer = OS_FRAME_SIZE;
3014 if (offset < OS_DATA_SIZE)
3015 osst_zero_buffer_tail(STp->buffer);
3017 if (STp->poll)
3018 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3019 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3021 memset(cmd, 0, MAX_COMMAND_SIZE);
3022 cmd[0] = WRITE_6;
3023 cmd[1] = 1;
3024 cmd[4] = 1;
3026 switch (STp->write_type) {
3027 case OS_WRITE_DATA:
3028 #if DEBUG
3029 if (debugging)
3030 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3031 name, blks, STp->frame_seq_number,
3032 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3033 #endif
3034 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3035 STp->logical_blk_num - blks, STp->block_size, blks);
3036 break;
3037 case OS_WRITE_EOD:
3038 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3039 STp->logical_blk_num, 0, 0);
3040 break;
3041 case OS_WRITE_NEW_MARK:
3042 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3043 STp->logical_blk_num++, 0, blks=1);
3044 break;
3045 case OS_WRITE_HEADER:
3046 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3047 break;
3048 default: /* probably FILLER */
3049 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3051 #if DEBUG
3052 if (debugging)
3053 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3054 name, offset, transfer, blks);
3055 #endif
3057 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3058 STp->timeout, MAX_RETRIES, 1);
3059 *aSRpnt = SRpnt;
3060 if (!SRpnt)
3061 return (-EBUSY);
3063 if ((STp->buffer)->syscall_result != 0) {
3064 #if DEBUG
3065 printk(OSST_DEB_MSG
3066 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3067 name, SRpnt->sense[0], SRpnt->sense[2],
3068 SRpnt->sense[12], SRpnt->sense[13]);
3069 #endif
3070 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3071 (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3072 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3073 STp->dirty = 0;
3074 (STp->buffer)->buffer_bytes = 0;
3075 result = (-ENOSPC);
3077 else {
3078 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3079 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3080 result = (-EIO);
3083 STps->drv_block = (-1); /* FIXME - even if write recovery succeeds? */
3085 else {
3086 STp->first_frame_position++;
3087 STp->dirty = 0;
3088 (STp->buffer)->buffer_bytes = 0;
3091 #if DEBUG
3092 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3093 #endif
3094 return result;
3098 /* Flush the tape buffer. The tape will be positioned correctly unless
3099 seek_next is true. */
3100 static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3102 struct st_partstat * STps;
3103 int backspace = 0, result = 0;
3104 #if DEBUG
3105 char * name = tape_name(STp);
3106 #endif
3109 * If there was a bus reset, block further access
3110 * to this device.
3112 if( STp->pos_unknown)
3113 return (-EIO);
3115 if (STp->ready != ST_READY)
3116 return 0;
3118 STps = &(STp->ps[STp->partition]);
3119 if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
3120 STp->write_type = OS_WRITE_DATA;
3121 return osst_flush_write_buffer(STp, aSRpnt);
3123 if (STp->block_size == 0)
3124 return 0;
3126 #if DEBUG
3127 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3128 #endif
3130 if (!STp->can_bsr) {
3131 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3132 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3133 (STp->buffer)->buffer_bytes = 0;
3134 (STp->buffer)->read_pointer = 0;
3135 STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */
3138 if (!seek_next) {
3139 if (STps->eof == ST_FM_HIT) {
3140 result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3141 if (!result)
3142 STps->eof = ST_NOEOF;
3143 else {
3144 if (STps->drv_file >= 0)
3145 STps->drv_file++;
3146 STps->drv_block = 0;
3149 if (!result && backspace > 0) /* TODO -- design and run a test case for this */
3150 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3152 else if (STps->eof == ST_FM_HIT) {
3153 if (STps->drv_file >= 0)
3154 STps->drv_file++;
3155 STps->drv_block = 0;
3156 STps->eof = ST_NOEOF;
3159 return result;
3162 static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3164 unsigned char cmd[MAX_COMMAND_SIZE];
3165 struct osst_request * SRpnt;
3166 int blks;
3167 #if DEBUG
3168 char * name = tape_name(STp);
3169 #endif
3171 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3172 #if DEBUG
3173 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3174 #endif
3175 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3176 return (-EIO);
3178 /* error recovery may have bumped us past the header partition */
3179 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3180 #if DEBUG
3181 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3182 #endif
3183 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3187 if (STp->poll)
3188 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3189 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3190 return (-EIO);
3192 // osst_build_stats(STp, &SRpnt);
3194 STp->ps[STp->partition].rw = ST_WRITING;
3195 STp->write_type = OS_WRITE_DATA;
3197 memset(cmd, 0, MAX_COMMAND_SIZE);
3198 cmd[0] = WRITE_6;
3199 cmd[1] = 1;
3200 cmd[4] = 1; /* one frame at a time... */
3201 blks = STp->buffer->buffer_bytes / STp->block_size;
3202 #if DEBUG
3203 if (debugging)
3204 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3205 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3206 #endif
3207 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3208 STp->logical_blk_num - blks, STp->block_size, blks);
3210 #if DEBUG
3211 if (!synchronous)
3212 STp->write_pending = 1;
3213 #endif
3214 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3215 MAX_RETRIES, synchronous);
3216 if (!SRpnt)
3217 return (-EBUSY);
3218 *aSRpnt = SRpnt;
3220 if (synchronous) {
3221 if (STp->buffer->syscall_result != 0) {
3222 #if DEBUG
3223 if (debugging)
3224 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3225 #endif
3226 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3227 (SRpnt->sense[2] & 0x40)) {
3228 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3229 return (-ENOSPC);
3231 else {
3232 if (osst_write_error_recovery(STp, aSRpnt, 1))
3233 return (-EIO);
3236 else
3237 STp->first_frame_position++;
3240 STp->write_count++;
3242 return 0;
3245 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3246 static int do_door_lock(struct osst_tape * STp, int do_lock)
3248 int retval, cmd;
3250 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3251 #if DEBUG
3252 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3253 #endif
3254 retval = scsi_ioctl(STp->device, cmd, NULL);
3255 if (!retval) {
3256 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3258 else {
3259 STp->door_locked = ST_LOCK_FAILS;
3261 return retval;
3264 /* Set the internal state after reset */
3265 static void reset_state(struct osst_tape *STp)
3267 int i;
3268 struct st_partstat *STps;
3270 STp->pos_unknown = 0;
3271 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3272 STps = &(STp->ps[i]);
3273 STps->rw = ST_IDLE;
3274 STps->eof = ST_NOEOF;
3275 STps->at_sm = 0;
3276 STps->last_block_valid = 0;
3277 STps->drv_block = -1;
3278 STps->drv_file = -1;
3283 /* Entry points to osst */
3285 /* Write command */
3286 static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3288 ssize_t total, retval = 0;
3289 ssize_t i, do_count, blks, transfer;
3290 int write_threshold;
3291 int doing_write = 0;
3292 const char __user * b_point;
3293 struct osst_request * SRpnt = NULL;
3294 struct st_modedef * STm;
3295 struct st_partstat * STps;
3296 struct osst_tape * STp = filp->private_data;
3297 char * name = tape_name(STp);
3300 if (down_interruptible(&STp->lock))
3301 return (-ERESTARTSYS);
3304 * If we are in the middle of error recovery, don't let anyone
3305 * else try and use this device. Also, if error recovery fails, it
3306 * may try and take the device offline, in which case all further
3307 * access to the device is prohibited.
3309 if( !scsi_block_when_processing_errors(STp->device) ) {
3310 retval = (-ENXIO);
3311 goto out;
3314 if (STp->ready != ST_READY) {
3315 if (STp->ready == ST_NO_TAPE)
3316 retval = (-ENOMEDIUM);
3317 else
3318 retval = (-EIO);
3319 goto out;
3321 STm = &(STp->modes[STp->current_mode]);
3322 if (!STm->defined) {
3323 retval = (-ENXIO);
3324 goto out;
3326 if (count == 0)
3327 goto out;
3330 * If there was a bus reset, block further access
3331 * to this device.
3333 if (STp->pos_unknown) {
3334 retval = (-EIO);
3335 goto out;
3338 #if DEBUG
3339 if (!STp->in_use) {
3340 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3341 retval = (-EIO);
3342 goto out;
3344 #endif
3346 if (STp->write_prot) {
3347 retval = (-EACCES);
3348 goto out;
3351 /* Write must be integral number of blocks */
3352 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3353 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3354 name, count, STp->block_size<1024?
3355 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3356 retval = (-EINVAL);
3357 goto out;
3360 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3361 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3362 name, STp->first_frame_position);
3363 retval = (-ENOSPC);
3364 goto out;
3367 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3368 STp->door_locked = ST_LOCKED_AUTO;
3370 STps = &(STp->ps[STp->partition]);
3372 if (STps->rw == ST_READING) {
3373 #if DEBUG
3374 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3375 STps->drv_file, STps->drv_block);
3376 #endif
3377 retval = osst_flush_buffer(STp, &SRpnt, 0);
3378 if (retval)
3379 goto out;
3380 STps->rw = ST_IDLE;
3382 if (STps->rw != ST_WRITING) {
3383 /* Are we totally rewriting this tape? */
3384 if (!STp->header_ok ||
3385 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3386 (STps->drv_file == 0 && STps->drv_block == 0)) {
3387 STp->wrt_pass_cntr++;
3388 #if DEBUG
3389 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3390 name, STp->wrt_pass_cntr);
3391 #endif
3392 osst_reset_header(STp, &SRpnt);
3393 STps->drv_file = STps->drv_block = 0;
3395 /* Do we know where we'll be writing on the tape? */
3396 else {
3397 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3398 STps->drv_file < 0 || STps->drv_block < 0) {
3399 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3400 STps->drv_file = STp->filemark_cnt;
3401 STps->drv_block = 0;
3403 else {
3404 /* We have no idea where the tape is positioned - give up */
3405 #if DEBUG
3406 printk(OSST_DEB_MSG
3407 "%s:D: Cannot write at indeterminate position.\n", name);
3408 #endif
3409 retval = (-EIO);
3410 goto out;
3413 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3414 STp->filemark_cnt = STps->drv_file;
3415 STp->last_mark_ppos =
3416 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3417 printk(KERN_WARNING
3418 "%s:W: Overwriting file %d with old write pass counter %d\n",
3419 name, STps->drv_file, STp->wrt_pass_cntr);
3420 printk(KERN_WARNING
3421 "%s:W: may lead to stale data being accepted on reading back!\n",
3422 name);
3423 #if DEBUG
3424 printk(OSST_DEB_MSG
3425 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3426 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3427 #endif
3430 STp->fast_open = 0;
3432 if (!STp->header_ok) {
3433 #if DEBUG
3434 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3435 #endif
3436 retval = (-EIO);
3437 goto out;
3440 if ((STp->buffer)->writing) {
3441 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3442 osst_write_behind_check(STp);
3443 if ((STp->buffer)->syscall_result) {
3444 #if DEBUG
3445 if (debugging)
3446 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3447 (STp->buffer)->midlevel_result);
3448 #endif
3449 if ((STp->buffer)->midlevel_result == INT_MAX)
3450 STps->eof = ST_EOM_OK;
3451 else
3452 STps->eof = ST_EOM_ERROR;
3455 if (STps->eof == ST_EOM_OK) {
3456 retval = (-ENOSPC);
3457 goto out;
3459 else if (STps->eof == ST_EOM_ERROR) {
3460 retval = (-EIO);
3461 goto out;
3464 /* Check the buffer readability in cases where copy_user might catch
3465 the problems after some tape movement. */
3466 if ((copy_from_user(&i, buf, 1) != 0 ||
3467 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3468 retval = (-EFAULT);
3469 goto out;
3472 if (!STm->do_buffer_writes) {
3473 write_threshold = 1;
3475 else
3476 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3477 if (!STm->do_async_writes)
3478 write_threshold--;
3480 total = count;
3481 #if DEBUG
3482 if (debugging)
3483 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3484 name, (int) count, STps->drv_file, STps->drv_block,
3485 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3486 #endif
3487 b_point = buf;
3488 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3490 doing_write = 1;
3491 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3492 (STp->buffer)->buffer_bytes;
3493 if (do_count > count)
3494 do_count = count;
3496 i = append_to_buffer(b_point, STp->buffer, do_count);
3497 if (i) {
3498 retval = i;
3499 goto out;
3502 blks = do_count / STp->block_size;
3503 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3505 i = osst_write_frame(STp, &SRpnt, 1);
3507 if (i == (-ENOSPC)) {
3508 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3509 if (transfer <= do_count) {
3510 filp->f_pos += do_count - transfer;
3511 count -= do_count - transfer;
3512 if (STps->drv_block >= 0) {
3513 STps->drv_block += (do_count - transfer) / STp->block_size;
3515 STps->eof = ST_EOM_OK;
3516 retval = (-ENOSPC); /* EOM within current request */
3517 #if DEBUG
3518 if (debugging)
3519 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3520 name, (int) transfer);
3521 #endif
3523 else {
3524 STps->eof = ST_EOM_ERROR;
3525 STps->drv_block = (-1); /* Too cautious? */
3526 retval = (-EIO); /* EOM for old data */
3527 #if DEBUG
3528 if (debugging)
3529 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3530 #endif
3533 else
3534 retval = i;
3536 if (retval < 0) {
3537 if (SRpnt != NULL) {
3538 osst_release_request(SRpnt);
3539 SRpnt = NULL;
3541 STp->buffer->buffer_bytes = 0;
3542 STp->dirty = 0;
3543 if (count < total)
3544 retval = total - count;
3545 goto out;
3548 filp->f_pos += do_count;
3549 b_point += do_count;
3550 count -= do_count;
3551 if (STps->drv_block >= 0) {
3552 STps->drv_block += blks;
3554 STp->buffer->buffer_bytes = 0;
3555 STp->dirty = 0;
3556 } /* end while write threshold exceeded */
3558 if (count != 0) {
3559 STp->dirty = 1;
3560 i = append_to_buffer(b_point, STp->buffer, count);
3561 if (i) {
3562 retval = i;
3563 goto out;
3565 blks = count / STp->block_size;
3566 STp->logical_blk_num += blks;
3567 if (STps->drv_block >= 0) {
3568 STps->drv_block += blks;
3570 filp->f_pos += count;
3571 count = 0;
3574 if (doing_write && (STp->buffer)->syscall_result != 0) {
3575 retval = (STp->buffer)->syscall_result;
3576 goto out;
3579 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3580 /* Schedule an asynchronous write */
3581 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3582 STp->block_size) * STp->block_size;
3583 STp->dirty = !((STp->buffer)->writing ==
3584 (STp->buffer)->buffer_bytes);
3586 i = osst_write_frame(STp, &SRpnt, 0);
3587 if (i < 0) {
3588 retval = (-EIO);
3589 goto out;
3591 SRpnt = NULL; /* Prevent releasing this request! */
3593 STps->at_sm &= (total == 0);
3594 if (total > 0)
3595 STps->eof = ST_NOEOF;
3597 retval = total;
3599 out:
3600 if (SRpnt != NULL) osst_release_request(SRpnt);
3602 up(&STp->lock);
3604 return retval;
3608 /* Read command */
3609 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3611 ssize_t total, retval = 0;
3612 ssize_t i, transfer;
3613 int special;
3614 struct st_modedef * STm;
3615 struct st_partstat * STps;
3616 struct osst_request * SRpnt = NULL;
3617 struct osst_tape * STp = filp->private_data;
3618 char * name = tape_name(STp);
3621 if (down_interruptible(&STp->lock))
3622 return (-ERESTARTSYS);
3625 * If we are in the middle of error recovery, don't let anyone
3626 * else try and use this device. Also, if error recovery fails, it
3627 * may try and take the device offline, in which case all further
3628 * access to the device is prohibited.
3630 if( !scsi_block_when_processing_errors(STp->device) ) {
3631 retval = (-ENXIO);
3632 goto out;
3635 if (STp->ready != ST_READY) {
3636 if (STp->ready == ST_NO_TAPE)
3637 retval = (-ENOMEDIUM);
3638 else
3639 retval = (-EIO);
3640 goto out;
3642 STm = &(STp->modes[STp->current_mode]);
3643 if (!STm->defined) {
3644 retval = (-ENXIO);
3645 goto out;
3647 #if DEBUG
3648 if (!STp->in_use) {
3649 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3650 retval = (-EIO);
3651 goto out;
3653 #endif
3654 /* Must have initialized medium */
3655 if (!STp->header_ok) {
3656 retval = (-EIO);
3657 goto out;
3660 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3661 STp->door_locked = ST_LOCKED_AUTO;
3663 STps = &(STp->ps[STp->partition]);
3664 if (STps->rw == ST_WRITING) {
3665 retval = osst_flush_buffer(STp, &SRpnt, 0);
3666 if (retval)
3667 goto out;
3668 STps->rw = ST_IDLE;
3669 /* FIXME -- this may leave the tape without EOD and up2date headers */
3672 if ((count % STp->block_size) != 0) {
3673 printk(KERN_WARNING
3674 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3675 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3678 #if DEBUG
3679 if (debugging && STps->eof != ST_NOEOF)
3680 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3681 STps->eof, (STp->buffer)->buffer_bytes);
3682 #endif
3683 if ((STp->buffer)->buffer_bytes == 0 &&
3684 STps->eof >= ST_EOD_1) {
3685 if (STps->eof < ST_EOD) {
3686 STps->eof += 1;
3687 retval = 0;
3688 goto out;
3690 retval = (-EIO); /* EOM or Blank Check */
3691 goto out;
3694 /* Check the buffer writability before any tape movement. Don't alter
3695 buffer data. */
3696 if (copy_from_user(&i, buf, 1) != 0 ||
3697 copy_to_user (buf, &i, 1) != 0 ||
3698 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3699 copy_to_user (buf + count - 1, &i, 1) != 0) {
3700 retval = (-EFAULT);
3701 goto out;
3704 /* Loop until enough data in buffer or a special condition found */
3705 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3707 /* Get new data if the buffer is empty */
3708 if ((STp->buffer)->buffer_bytes == 0) {
3709 if (STps->eof == ST_FM_HIT)
3710 break;
3711 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3712 if (special < 0) { /* No need to continue read */
3713 STp->frame_in_buffer = 0;
3714 retval = special;
3715 goto out;
3719 /* Move the data from driver buffer to user buffer */
3720 if ((STp->buffer)->buffer_bytes > 0) {
3721 #if DEBUG
3722 if (debugging && STps->eof != ST_NOEOF)
3723 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3724 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3725 #endif
3726 /* force multiple of block size, note block_size may have been adjusted */
3727 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3728 (STp->buffer)->buffer_bytes : count - total)/
3729 STp->block_size) * STp->block_size;
3731 if (transfer == 0) {
3732 printk(KERN_WARNING
3733 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3734 name, count, STp->block_size < 1024?
3735 STp->block_size:STp->block_size/1024,
3736 STp->block_size<1024?'b':'k');
3737 break;
3739 i = from_buffer(STp->buffer, buf, transfer);
3740 if (i) {
3741 retval = i;
3742 goto out;
3744 STp->logical_blk_num += transfer / STp->block_size;
3745 STps->drv_block += transfer / STp->block_size;
3746 filp->f_pos += transfer;
3747 buf += transfer;
3748 total += transfer;
3751 if ((STp->buffer)->buffer_bytes == 0) {
3752 #if DEBUG
3753 if (debugging)
3754 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3755 name, STp->frame_seq_number);
3756 #endif
3757 STp->frame_in_buffer = 0;
3758 STp->frame_seq_number++; /* frame to look for next time */
3760 } /* for (total = 0, special = 0; total < count && !special; ) */
3762 /* Change the eof state if no data from tape or buffer */
3763 if (total == 0) {
3764 if (STps->eof == ST_FM_HIT) {
3765 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3766 STps->drv_block = 0;
3767 if (STps->drv_file >= 0)
3768 STps->drv_file++;
3770 else if (STps->eof == ST_EOD_1) {
3771 STps->eof = ST_EOD_2;
3772 if (STps->drv_block > 0 && STps->drv_file >= 0)
3773 STps->drv_file++;
3774 STps->drv_block = 0;
3776 else if (STps->eof == ST_EOD_2)
3777 STps->eof = ST_EOD;
3779 else if (STps->eof == ST_FM)
3780 STps->eof = ST_NOEOF;
3782 retval = total;
3784 out:
3785 if (SRpnt != NULL) osst_release_request(SRpnt);
3787 up(&STp->lock);
3789 return retval;
3793 /* Set the driver options */
3794 static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3796 printk(KERN_INFO
3797 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3798 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3799 STm->do_read_ahead);
3800 printk(KERN_INFO
3801 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3802 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3803 printk(KERN_INFO
3804 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3805 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3806 STp->scsi2_logical);
3807 printk(KERN_INFO
3808 "%s:I: sysv: %d\n", name, STm->sysv);
3809 #if DEBUG
3810 printk(KERN_INFO
3811 "%s:D: debugging: %d\n",
3812 name, debugging);
3813 #endif
3817 static int osst_set_options(struct osst_tape *STp, long options)
3819 int value;
3820 long code;
3821 struct st_modedef * STm;
3822 char * name = tape_name(STp);
3824 STm = &(STp->modes[STp->current_mode]);
3825 if (!STm->defined) {
3826 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3827 modes_defined = 1;
3828 #if DEBUG
3829 if (debugging)
3830 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3831 name, STp->current_mode);
3832 #endif
3835 code = options & MT_ST_OPTIONS;
3836 if (code == MT_ST_BOOLEANS) {
3837 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3838 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3839 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3840 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3841 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3842 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3843 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3844 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3845 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3846 if ((STp->device)->scsi_level >= SCSI_2)
3847 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3848 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3849 STm->sysv = (options & MT_ST_SYSV) != 0;
3850 #if DEBUG
3851 debugging = (options & MT_ST_DEBUGGING) != 0;
3852 #endif
3853 osst_log_options(STp, STm, name);
3855 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3856 value = (code == MT_ST_SETBOOLEANS);
3857 if ((options & MT_ST_BUFFER_WRITES) != 0)
3858 STm->do_buffer_writes = value;
3859 if ((options & MT_ST_ASYNC_WRITES) != 0)
3860 STm->do_async_writes = value;
3861 if ((options & MT_ST_DEF_WRITES) != 0)
3862 STm->defaults_for_writes = value;
3863 if ((options & MT_ST_READ_AHEAD) != 0)
3864 STm->do_read_ahead = value;
3865 if ((options & MT_ST_TWO_FM) != 0)
3866 STp->two_fm = value;
3867 if ((options & MT_ST_FAST_MTEOM) != 0)
3868 STp->fast_mteom = value;
3869 if ((options & MT_ST_AUTO_LOCK) != 0)
3870 STp->do_auto_lock = value;
3871 if ((options & MT_ST_CAN_BSR) != 0)
3872 STp->can_bsr = value;
3873 if ((options & MT_ST_NO_BLKLIMS) != 0)
3874 STp->omit_blklims = value;
3875 if ((STp->device)->scsi_level >= SCSI_2 &&
3876 (options & MT_ST_CAN_PARTITIONS) != 0)
3877 STp->can_partitions = value;
3878 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3879 STp->scsi2_logical = value;
3880 if ((options & MT_ST_SYSV) != 0)
3881 STm->sysv = value;
3882 #if DEBUG
3883 if ((options & MT_ST_DEBUGGING) != 0)
3884 debugging = value;
3885 #endif
3886 osst_log_options(STp, STm, name);
3888 else if (code == MT_ST_WRITE_THRESHOLD) {
3889 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3890 if (value < 1 || value > osst_buffer_size) {
3891 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3892 name, value);
3893 return (-EIO);
3895 STp->write_threshold = value;
3896 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3897 name, value);
3899 else if (code == MT_ST_DEF_BLKSIZE) {
3900 value = (options & ~MT_ST_OPTIONS);
3901 if (value == ~MT_ST_OPTIONS) {
3902 STm->default_blksize = (-1);
3903 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3905 else {
3906 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3907 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3908 name, value);
3909 return (-EINVAL);
3911 STm->default_blksize = value;
3912 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3913 name, STm->default_blksize);
3916 else if (code == MT_ST_TIMEOUTS) {
3917 value = (options & ~MT_ST_OPTIONS);
3918 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3919 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3920 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3921 (value & ~MT_ST_SET_LONG_TIMEOUT));
3923 else {
3924 STp->timeout = value * HZ;
3925 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3928 else if (code == MT_ST_DEF_OPTIONS) {
3929 code = (options & ~MT_ST_CLEAR_DEFAULT);
3930 value = (options & MT_ST_CLEAR_DEFAULT);
3931 if (code == MT_ST_DEF_DENSITY) {
3932 if (value == MT_ST_CLEAR_DEFAULT) {
3933 STm->default_density = (-1);
3934 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3936 else {
3937 STm->default_density = value & 0xff;
3938 printk(KERN_INFO "%s:I: Density default set to %x\n",
3939 name, STm->default_density);
3942 else if (code == MT_ST_DEF_DRVBUFFER) {
3943 if (value == MT_ST_CLEAR_DEFAULT) {
3944 STp->default_drvbuffer = 0xff;
3945 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3947 else {
3948 STp->default_drvbuffer = value & 7;
3949 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3950 name, STp->default_drvbuffer);
3953 else if (code == MT_ST_DEF_COMPRESSION) {
3954 if (value == MT_ST_CLEAR_DEFAULT) {
3955 STm->default_compression = ST_DONT_TOUCH;
3956 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3958 else {
3959 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3960 printk(KERN_INFO "%s:I: Compression default set to %x\n",
3961 name, (value & 1));
3965 else
3966 return (-EIO);
3968 return 0;
3972 /* Internal ioctl function */
3973 static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
3974 unsigned int cmd_in, unsigned long arg)
3976 int timeout;
3977 long ltmp;
3978 int i, ioctl_result;
3979 int chg_eof = 1;
3980 unsigned char cmd[MAX_COMMAND_SIZE];
3981 struct osst_request * SRpnt = * aSRpnt;
3982 struct st_partstat * STps;
3983 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3984 int datalen = 0, direction = DMA_NONE;
3985 char * name = tape_name(STp);
3987 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3988 if (STp->ready == ST_NO_TAPE)
3989 return (-ENOMEDIUM);
3990 else
3991 return (-EIO);
3993 timeout = STp->long_timeout;
3994 STps = &(STp->ps[STp->partition]);
3995 fileno = STps->drv_file;
3996 blkno = STps->drv_block;
3997 at_sm = STps->at_sm;
3998 frame_seq_numbr = STp->frame_seq_number;
3999 logical_blk_num = STp->logical_blk_num;
4001 memset(cmd, 0, MAX_COMMAND_SIZE);
4002 switch (cmd_in) {
4003 case MTFSFM:
4004 chg_eof = 0; /* Changed from the FSF after this */
4005 case MTFSF:
4006 if (STp->raw)
4007 return (-EIO);
4008 if (STp->linux_media)
4009 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4010 else
4011 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4012 if (fileno >= 0)
4013 fileno += arg;
4014 blkno = 0;
4015 at_sm &= (arg == 0);
4016 goto os_bypass;
4018 case MTBSF:
4019 chg_eof = 0; /* Changed from the FSF after this */
4020 case MTBSFM:
4021 if (STp->raw)
4022 return (-EIO);
4023 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4024 if (fileno >= 0)
4025 fileno -= arg;
4026 blkno = (-1); /* We can't know the block number */
4027 at_sm &= (arg == 0);
4028 goto os_bypass;
4030 case MTFSR:
4031 case MTBSR:
4032 #if DEBUG
4033 if (debugging)
4034 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4035 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4036 #endif
4037 if (cmd_in == MTFSR) {
4038 logical_blk_num += arg;
4039 if (blkno >= 0) blkno += arg;
4041 else {
4042 logical_blk_num -= arg;
4043 if (blkno >= 0) blkno -= arg;
4045 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4046 fileno = STps->drv_file;
4047 blkno = STps->drv_block;
4048 at_sm &= (arg == 0);
4049 goto os_bypass;
4051 case MTFSS:
4052 cmd[0] = SPACE;
4053 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4054 cmd[2] = (arg >> 16);
4055 cmd[3] = (arg >> 8);
4056 cmd[4] = arg;
4057 #if DEBUG
4058 if (debugging)
4059 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4060 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4061 #endif
4062 if (arg != 0) {
4063 blkno = fileno = (-1);
4064 at_sm = 1;
4066 break;
4067 case MTBSS:
4068 cmd[0] = SPACE;
4069 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4070 ltmp = (-arg);
4071 cmd[2] = (ltmp >> 16);
4072 cmd[3] = (ltmp >> 8);
4073 cmd[4] = ltmp;
4074 #if DEBUG
4075 if (debugging) {
4076 if (cmd[2] & 0x80)
4077 ltmp = 0xff000000;
4078 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4079 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4080 name, (-ltmp));
4082 #endif
4083 if (arg != 0) {
4084 blkno = fileno = (-1);
4085 at_sm = 1;
4087 break;
4088 case MTWEOF:
4089 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4090 STp->write_type = OS_WRITE_DATA;
4091 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4092 } else
4093 ioctl_result = 0;
4094 #if DEBUG
4095 if (debugging)
4096 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4097 #endif
4098 for (i=0; i<arg; i++)
4099 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4100 if (fileno >= 0) fileno += arg;
4101 if (blkno >= 0) blkno = 0;
4102 goto os_bypass;
4104 case MTWSM:
4105 if (STp->write_prot)
4106 return (-EACCES);
4107 if (!STp->raw)
4108 return 0;
4109 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
4110 if (cmd_in == MTWSM)
4111 cmd[1] = 2;
4112 cmd[2] = (arg >> 16);
4113 cmd[3] = (arg >> 8);
4114 cmd[4] = arg;
4115 timeout = STp->timeout;
4116 #if DEBUG
4117 if (debugging)
4118 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4119 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4120 #endif
4121 if (fileno >= 0)
4122 fileno += arg;
4123 blkno = 0;
4124 at_sm = (cmd_in == MTWSM);
4125 break;
4126 case MTOFFL:
4127 case MTLOAD:
4128 case MTUNLOAD:
4129 case MTRETEN:
4130 cmd[0] = START_STOP;
4131 cmd[1] = 1; /* Don't wait for completion */
4132 if (cmd_in == MTLOAD) {
4133 if (STp->ready == ST_NO_TAPE)
4134 cmd[4] = 4; /* open tray */
4135 else
4136 cmd[4] = 1; /* load */
4138 if (cmd_in == MTRETEN)
4139 cmd[4] = 3; /* retension then mount */
4140 if (cmd_in == MTOFFL)
4141 cmd[4] = 4; /* rewind then eject */
4142 timeout = STp->timeout;
4143 #if DEBUG
4144 if (debugging) {
4145 switch (cmd_in) {
4146 case MTUNLOAD:
4147 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4148 break;
4149 case MTLOAD:
4150 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4151 break;
4152 case MTRETEN:
4153 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4154 break;
4155 case MTOFFL:
4156 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4157 break;
4160 #endif
4161 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4162 break;
4163 case MTNOP:
4164 #if DEBUG
4165 if (debugging)
4166 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4167 #endif
4168 return 0; /* Should do something ? */
4169 break;
4170 case MTEOM:
4171 #if DEBUG
4172 if (debugging)
4173 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4174 #endif
4175 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4176 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4177 ioctl_result = -EIO;
4178 goto os_bypass;
4180 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4181 #if DEBUG
4182 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4183 #endif
4184 ioctl_result = -EIO;
4185 goto os_bypass;
4187 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4188 fileno = STp->filemark_cnt;
4189 blkno = at_sm = 0;
4190 goto os_bypass;
4192 case MTERASE:
4193 if (STp->write_prot)
4194 return (-EACCES);
4195 ioctl_result = osst_reset_header(STp, &SRpnt);
4196 i = osst_write_eod(STp, &SRpnt);
4197 if (i < ioctl_result) ioctl_result = i;
4198 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4199 if (i < ioctl_result) ioctl_result = i;
4200 fileno = blkno = at_sm = 0 ;
4201 goto os_bypass;
4203 case MTREW:
4204 cmd[0] = REZERO_UNIT; /* rewind */
4205 cmd[1] = 1;
4206 #if DEBUG
4207 if (debugging)
4208 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4209 #endif
4210 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4211 break;
4213 case MTSETBLK: /* Set block length */
4214 if ((STps->drv_block == 0 ) &&
4215 !STp->dirty &&
4216 ((STp->buffer)->buffer_bytes == 0) &&
4217 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4218 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4219 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4221 * Only allowed to change the block size if you opened the
4222 * device at the beginning of a file before writing anything.
4223 * Note, that when reading, changing block_size is futile,
4224 * as the size used when writing overrides it.
4226 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4227 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4228 name, STp->block_size);
4229 return 0;
4231 case MTSETDENSITY: /* Set tape density */
4232 case MTSETDRVBUFFER: /* Set drive buffering */
4233 case SET_DENS_AND_BLK: /* Set density and block size */
4234 chg_eof = 0;
4235 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4236 return (-EIO); /* Not allowed if data in buffer */
4237 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4238 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4239 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4240 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4241 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4242 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4243 return (-EINVAL);
4245 return 0; /* FIXME silently ignore if block size didn't change */
4247 default:
4248 return (-ENOSYS);
4251 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4253 ioctl_result = (STp->buffer)->syscall_result;
4255 if (!SRpnt) {
4256 #if DEBUG
4257 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4258 #endif
4259 return ioctl_result;
4262 if (!ioctl_result) { /* SCSI command successful */
4263 STp->frame_seq_number = frame_seq_numbr;
4264 STp->logical_blk_num = logical_blk_num;
4267 os_bypass:
4268 #if DEBUG
4269 if (debugging)
4270 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4271 #endif
4273 if (!ioctl_result) { /* success */
4275 if (cmd_in == MTFSFM) {
4276 fileno--;
4277 blkno--;
4279 if (cmd_in == MTBSFM) {
4280 fileno++;
4281 blkno++;
4283 STps->drv_block = blkno;
4284 STps->drv_file = fileno;
4285 STps->at_sm = at_sm;
4287 if (cmd_in == MTEOM)
4288 STps->eof = ST_EOD;
4289 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4290 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4291 STps->drv_block++;
4292 STp->logical_blk_num++;
4293 STp->frame_seq_number++;
4294 STp->frame_in_buffer = 0;
4295 STp->buffer->read_pointer = 0;
4297 else if (cmd_in == MTFSF)
4298 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4299 else if (chg_eof)
4300 STps->eof = ST_NOEOF;
4302 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4303 STp->rew_at_close = 0;
4304 else if (cmd_in == MTLOAD) {
4305 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4306 STp->ps[i].rw = ST_IDLE;
4307 STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4309 STp->partition = 0;
4312 if (cmd_in == MTREW) {
4313 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4314 if (ioctl_result > 0)
4315 ioctl_result = 0;
4318 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4319 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4320 STps->drv_file = STps->drv_block = -1;
4321 else
4322 STps->drv_file = STps->drv_block = 0;
4323 STps->eof = ST_NOEOF;
4324 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4325 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4326 STps->drv_file = STps->drv_block = -1;
4327 else {
4328 STps->drv_file = STp->filemark_cnt;
4329 STps->drv_block = 0;
4331 STps->eof = ST_EOD;
4332 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4333 STps->drv_file = STps->drv_block = (-1);
4334 STps->eof = ST_NOEOF;
4335 STp->header_ok = 0;
4336 } else if (cmd_in == MTERASE) {
4337 STp->header_ok = 0;
4338 } else if (SRpnt) { /* SCSI command was not completely successful. */
4339 if (SRpnt->sense[2] & 0x40) {
4340 STps->eof = ST_EOM_OK;
4341 STps->drv_block = 0;
4343 if (chg_eof)
4344 STps->eof = ST_NOEOF;
4346 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4347 STps->eof = ST_EOD;
4349 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4350 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4352 *aSRpnt = SRpnt;
4354 return ioctl_result;
4358 /* Open the device */
4359 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4361 unsigned short flags;
4362 int i, b_size, new_session = 0, retval = 0;
4363 unsigned char cmd[MAX_COMMAND_SIZE];
4364 struct osst_request * SRpnt = NULL;
4365 struct osst_tape * STp;
4366 struct st_modedef * STm;
4367 struct st_partstat * STps;
4368 char * name;
4369 int dev = TAPE_NR(inode);
4370 int mode = TAPE_MODE(inode);
4373 * We really want to do nonseekable_open(inode, filp); here, but some
4374 * versions of tar incorrectly call lseek on tapes and bail out if that
4375 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4377 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4379 write_lock(&os_scsi_tapes_lock);
4380 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4381 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4382 write_unlock(&os_scsi_tapes_lock);
4383 return (-ENXIO);
4386 name = tape_name(STp);
4388 if (STp->in_use) {
4389 write_unlock(&os_scsi_tapes_lock);
4390 #if DEBUG
4391 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4392 #endif
4393 return (-EBUSY);
4395 if (scsi_device_get(STp->device)) {
4396 write_unlock(&os_scsi_tapes_lock);
4397 #if DEBUG
4398 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4399 #endif
4400 return (-ENXIO);
4402 filp->private_data = STp;
4403 STp->in_use = 1;
4404 write_unlock(&os_scsi_tapes_lock);
4405 STp->rew_at_close = TAPE_REWIND(inode);
4407 if( !scsi_block_when_processing_errors(STp->device) ) {
4408 return -ENXIO;
4411 if (mode != STp->current_mode) {
4412 #if DEBUG
4413 if (debugging)
4414 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4415 name, STp->current_mode, mode);
4416 #endif
4417 new_session = 1;
4418 STp->current_mode = mode;
4420 STm = &(STp->modes[STp->current_mode]);
4422 flags = filp->f_flags;
4423 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4425 STp->raw = TAPE_IS_RAW(inode);
4426 if (STp->raw)
4427 STp->header_ok = 0;
4429 /* Allocate data segments for this device's tape buffer */
4430 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4431 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4432 retval = (-EOVERFLOW);
4433 goto err_out;
4435 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4436 for (i = 0, b_size = 0;
4437 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4438 b_size += STp->buffer->sg[i++].length);
4439 STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
4440 #if DEBUG
4441 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4442 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4443 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4444 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4445 #endif
4446 } else {
4447 STp->buffer->aux = NULL; /* this had better never happen! */
4448 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4449 retval = (-EIO);
4450 goto err_out;
4452 STp->buffer->writing = 0;
4453 STp->buffer->syscall_result = 0;
4454 STp->dirty = 0;
4455 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4456 STps = &(STp->ps[i]);
4457 STps->rw = ST_IDLE;
4459 STp->ready = ST_READY;
4460 #if DEBUG
4461 STp->nbr_waits = STp->nbr_finished = 0;
4462 #endif
4464 memset (cmd, 0, MAX_COMMAND_SIZE);
4465 cmd[0] = TEST_UNIT_READY;
4467 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4468 if (!SRpnt) {
4469 retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
4470 goto err_out;
4472 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4473 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4474 SRpnt->sense[12] == 4 ) {
4475 #if DEBUG
4476 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4477 #endif
4478 if (filp->f_flags & O_NONBLOCK) {
4479 retval = -EAGAIN;
4480 goto err_out;
4482 if (SRpnt->sense[13] == 2) { /* initialize command required (LOAD) */
4483 memset (cmd, 0, MAX_COMMAND_SIZE);
4484 cmd[0] = START_STOP;
4485 cmd[1] = 1;
4486 cmd[4] = 1;
4487 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4488 STp->timeout, MAX_RETRIES, 1);
4490 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4492 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4493 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4494 #if DEBUG
4495 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4496 #endif
4497 STp->header_ok = 0;
4499 for (i=0; i < 10; i++) {
4501 memset (cmd, 0, MAX_COMMAND_SIZE);
4502 cmd[0] = TEST_UNIT_READY;
4504 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4505 STp->timeout, MAX_RETRIES, 1);
4506 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4507 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4508 break;
4511 STp->pos_unknown = 0;
4512 STp->partition = STp->new_partition = 0;
4513 if (STp->can_partitions)
4514 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4515 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4516 STps = &(STp->ps[i]);
4517 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4518 STps->eof = ST_NOEOF;
4519 STps->at_sm = 0;
4520 STps->last_block_valid = 0;
4521 STps->drv_block = 0;
4522 STps->drv_file = 0 ;
4524 new_session = 1;
4525 STp->recover_count = 0;
4526 STp->abort_count = 0;
4529 * if we have valid headers from before, and the drive/tape seem untouched,
4530 * open without reconfiguring and re-reading the headers
4532 if (!STp->buffer->syscall_result && STp->header_ok &&
4533 !SRpnt->result && SRpnt->sense[0] == 0) {
4535 memset(cmd, 0, MAX_COMMAND_SIZE);
4536 cmd[0] = MODE_SENSE;
4537 cmd[1] = 8;
4538 cmd[2] = VENDOR_IDENT_PAGE;
4539 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4541 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4543 if (STp->buffer->syscall_result ||
4544 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4545 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4546 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4547 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4548 #if DEBUG
4549 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4550 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4551 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4552 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4553 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4554 #endif
4555 STp->header_ok = 0;
4557 i = STp->first_frame_position;
4558 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4559 if (STp->door_locked == ST_UNLOCKED) {
4560 if (do_door_lock(STp, 1))
4561 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4562 else
4563 STp->door_locked = ST_LOCKED_AUTO;
4565 if (!STp->frame_in_buffer) {
4566 STp->block_size = (STm->default_blksize > 0) ?
4567 STm->default_blksize : OS_DATA_SIZE;
4568 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4570 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4571 STp->fast_open = 1;
4572 osst_release_request(SRpnt);
4573 return 0;
4575 #if DEBUG
4576 if (i != STp->first_frame_position)
4577 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4578 name, i, STp->first_frame_position);
4579 #endif
4580 STp->header_ok = 0;
4582 STp->fast_open = 0;
4584 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4585 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4587 memset(cmd, 0, MAX_COMMAND_SIZE);
4588 cmd[0] = MODE_SELECT;
4589 cmd[1] = 0x10;
4590 cmd[4] = 4 + MODE_HEADER_LENGTH;
4592 (STp->buffer)->b_data[0] = cmd[4] - 1;
4593 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4594 (STp->buffer)->b_data[2] = 0; /* Reserved */
4595 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4596 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4597 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4598 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4599 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4601 #if DEBUG
4602 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4603 #endif
4604 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4606 STp->header_ok = 0;
4608 for (i=0; i < 10; i++) {
4610 memset (cmd, 0, MAX_COMMAND_SIZE);
4611 cmd[0] = TEST_UNIT_READY;
4613 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4614 STp->timeout, MAX_RETRIES, 1);
4615 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4616 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4617 break;
4619 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4620 STp->pos_unknown = 0;
4621 STp->partition = STp->new_partition = 0;
4622 if (STp->can_partitions)
4623 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4624 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4625 STps = &(STp->ps[i]);
4626 STps->rw = ST_IDLE;
4627 STps->eof = ST_NOEOF;
4628 STps->at_sm = 0;
4629 STps->last_block_valid = 0;
4630 STps->drv_block = 0;
4631 STps->drv_file = 0 ;
4633 new_session = 1;
4638 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4639 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4641 if ((STp->buffer)->syscall_result != 0) {
4642 if ((STp->device)->scsi_level >= SCSI_2 &&
4643 (SRpnt->sense[0] & 0x70) == 0x70 &&
4644 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4645 SRpnt->sense[12] == 0x3a) { /* Check ASC */
4646 STp->ready = ST_NO_TAPE;
4647 } else
4648 STp->ready = ST_NOT_READY;
4649 osst_release_request(SRpnt);
4650 SRpnt = NULL;
4651 STp->density = 0; /* Clear the erroneous "residue" */
4652 STp->write_prot = 0;
4653 STp->block_size = 0;
4654 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4655 STp->partition = STp->new_partition = 0;
4656 STp->door_locked = ST_UNLOCKED;
4657 return 0;
4660 osst_configure_onstream(STp, &SRpnt);
4662 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4663 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4664 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4665 STp->buffer->buffer_bytes =
4666 STp->buffer->read_pointer =
4667 STp->frame_in_buffer = 0;
4669 #if DEBUG
4670 if (debugging)
4671 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4672 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4673 (STp->buffer)->buffer_blocks);
4674 #endif
4676 if (STp->drv_write_prot) {
4677 STp->write_prot = 1;
4678 #if DEBUG
4679 if (debugging)
4680 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4681 #endif
4682 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4683 retval = (-EROFS);
4684 goto err_out;
4688 if (new_session) { /* Change the drive parameters for the new mode */
4689 #if DEBUG
4690 if (debugging)
4691 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4692 #endif
4693 STp->density_changed = STp->blksize_changed = 0;
4694 STp->compression_changed = 0;
4698 * properly position the tape and check the ADR headers
4700 if (STp->door_locked == ST_UNLOCKED) {
4701 if (do_door_lock(STp, 1))
4702 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4703 else
4704 STp->door_locked = ST_LOCKED_AUTO;
4707 osst_analyze_headers(STp, &SRpnt);
4709 osst_release_request(SRpnt);
4710 SRpnt = NULL;
4712 return 0;
4714 err_out:
4715 if (SRpnt != NULL)
4716 osst_release_request(SRpnt);
4717 normalize_buffer(STp->buffer);
4718 STp->header_ok = 0;
4719 STp->in_use = 0;
4720 scsi_device_put(STp->device);
4722 return retval;
4726 /* Flush the tape buffer before close */
4727 static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4729 int result = 0, result2;
4730 struct osst_tape * STp = filp->private_data;
4731 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4732 struct st_partstat * STps = &(STp->ps[STp->partition]);
4733 struct osst_request * SRpnt = NULL;
4734 char * name = tape_name(STp);
4736 if (file_count(filp) > 1)
4737 return 0;
4739 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4740 STp->write_type = OS_WRITE_DATA;
4741 result = osst_flush_write_buffer(STp, &SRpnt);
4742 if (result != 0 && result != (-ENOSPC))
4743 goto out;
4745 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4747 #if DEBUG
4748 if (debugging) {
4749 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4750 name, (long)(filp->f_pos));
4751 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4752 name, STp->nbr_waits, STp->nbr_finished);
4754 #endif
4755 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4756 #if DEBUG
4757 if (debugging)
4758 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4759 name, 1+STp->two_fm);
4760 #endif
4762 else if (!STp->rew_at_close) {
4763 STps = &(STp->ps[STp->partition]);
4764 if (!STm->sysv || STps->rw != ST_READING) {
4765 if (STp->can_bsr)
4766 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4767 else if (STps->eof == ST_FM_HIT) {
4768 result = cross_eof(STp, &SRpnt, 0);
4769 if (result) {
4770 if (STps->drv_file >= 0)
4771 STps->drv_file++;
4772 STps->drv_block = 0;
4773 STps->eof = ST_FM;
4775 else
4776 STps->eof = ST_NOEOF;
4779 else if ((STps->eof == ST_NOEOF &&
4780 !(result = cross_eof(STp, &SRpnt, 1))) ||
4781 STps->eof == ST_FM_HIT) {
4782 if (STps->drv_file >= 0)
4783 STps->drv_file++;
4784 STps->drv_block = 0;
4785 STps->eof = ST_FM;
4789 out:
4790 if (STp->rew_at_close) {
4791 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4792 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4793 if (result == 0 && result2 < 0)
4794 result = result2;
4796 if (SRpnt) osst_release_request(SRpnt);
4798 if (STp->abort_count || STp->recover_count) {
4799 printk(KERN_INFO "%s:I:", name);
4800 if (STp->abort_count)
4801 printk(" %d unrecovered errors", STp->abort_count);
4802 if (STp->recover_count)
4803 printk(" %d recovered errors", STp->recover_count);
4804 if (STp->write_count)
4805 printk(" in %d frames written", STp->write_count);
4806 if (STp->read_count)
4807 printk(" in %d frames read", STp->read_count);
4808 printk("\n");
4809 STp->recover_count = 0;
4810 STp->abort_count = 0;
4812 STp->write_count = 0;
4813 STp->read_count = 0;
4815 return result;
4819 /* Close the device and release it */
4820 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4822 int result = 0;
4823 struct osst_tape * STp = filp->private_data;
4825 if (STp->door_locked == ST_LOCKED_AUTO)
4826 do_door_lock(STp, 0);
4828 if (STp->raw)
4829 STp->header_ok = 0;
4831 normalize_buffer(STp->buffer);
4832 write_lock(&os_scsi_tapes_lock);
4833 STp->in_use = 0;
4834 write_unlock(&os_scsi_tapes_lock);
4836 scsi_device_put(STp->device);
4838 return result;
4842 /* The ioctl command */
4843 static int osst_ioctl(struct inode * inode,struct file * file,
4844 unsigned int cmd_in, unsigned long arg)
4846 int i, cmd_nr, cmd_type, blk, retval = 0;
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 = kzalloc(i, priority);
5210 if (!tb) {
5211 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5212 return NULL;
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 >= ARRAY_SIZE(parms))
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 int osst_create_driverfs_files(struct device_driver *driverfs)
5579 return 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_init(void)
5667 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5668 if (IS_ERR(osst_sysfs_class)) {
5669 printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5670 return PTR_ERR(osst_sysfs_class);
5673 return 0;
5676 static void osst_sysfs_destroy(dev_t dev)
5678 class_device_destroy(osst_sysfs_class, dev);
5681 static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5683 struct class_device *osst_class_member;
5684 int err;
5686 osst_class_member = class_device_create(osst_sysfs_class, NULL, dev,
5687 device, "%s", name);
5688 if (IS_ERR(osst_class_member)) {
5689 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5690 return PTR_ERR(osst_class_member);
5693 class_set_devdata(osst_class_member, STp);
5694 err = class_device_create_file(osst_class_member,
5695 &class_device_attr_ADR_rev);
5696 if (err)
5697 goto err_out;
5698 err = class_device_create_file(osst_class_member,
5699 &class_device_attr_media_version);
5700 if (err)
5701 goto err_out;
5702 err = class_device_create_file(osst_class_member,
5703 &class_device_attr_capacity);
5704 if (err)
5705 goto err_out;
5706 err = class_device_create_file(osst_class_member,
5707 &class_device_attr_BOT_frame);
5708 if (err)
5709 goto err_out;
5710 err = class_device_create_file(osst_class_member,
5711 &class_device_attr_EOD_frame);
5712 if (err)
5713 goto err_out;
5714 err = class_device_create_file(osst_class_member,
5715 &class_device_attr_file_count);
5716 if (err)
5717 goto err_out;
5719 return 0;
5721 err_out:
5722 osst_sysfs_destroy(dev);
5723 return err;
5726 static void osst_sysfs_cleanup(void)
5728 class_destroy(osst_sysfs_class);
5732 * osst startup / cleanup code
5735 static int osst_probe(struct device *dev)
5737 struct scsi_device * SDp = to_scsi_device(dev);
5738 struct osst_tape * tpnt;
5739 struct st_modedef * STm;
5740 struct st_partstat * STps;
5741 struct osst_buffer * buffer;
5742 struct gendisk * drive;
5743 int i, dev_num, err = -ENODEV;
5745 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5746 return -ENODEV;
5748 drive = alloc_disk(1);
5749 if (!drive) {
5750 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5751 return -ENODEV;
5754 /* if this is the first attach, build the infrastructure */
5755 write_lock(&os_scsi_tapes_lock);
5756 if (os_scsi_tapes == NULL) {
5757 os_scsi_tapes =
5758 (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
5759 GFP_ATOMIC);
5760 if (os_scsi_tapes == NULL) {
5761 write_unlock(&os_scsi_tapes_lock);
5762 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5763 goto out_put_disk;
5765 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5768 if (osst_nr_dev >= osst_max_dev) {
5769 write_unlock(&os_scsi_tapes_lock);
5770 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5771 goto out_put_disk;
5774 /* find a free minor number */
5775 for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++);
5776 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5777 dev_num = i;
5779 /* allocate a struct osst_tape for this device */
5780 tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5781 if (tpnt == NULL) {
5782 write_unlock(&os_scsi_tapes_lock);
5783 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5784 goto out_put_disk;
5786 memset(tpnt, 0, sizeof(struct osst_tape));
5788 /* allocate a buffer for this device */
5789 i = SDp->host->sg_tablesize;
5790 if (osst_max_sg_segs < i)
5791 i = osst_max_sg_segs;
5792 buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5793 if (buffer == NULL) {
5794 write_unlock(&os_scsi_tapes_lock);
5795 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5796 kfree(tpnt);
5797 goto out_put_disk;
5799 os_scsi_tapes[dev_num] = tpnt;
5800 tpnt->buffer = buffer;
5801 tpnt->device = SDp;
5802 drive->private_data = &tpnt->driver;
5803 sprintf(drive->disk_name, "osst%d", dev_num);
5804 tpnt->driver = &osst_template;
5805 tpnt->drive = drive;
5806 tpnt->in_use = 0;
5807 tpnt->capacity = 0xfffff;
5808 tpnt->dirty = 0;
5809 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
5810 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5811 tpnt->density = 0;
5812 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5813 tpnt->can_bsr = OSST_IN_FILE_POS;
5814 tpnt->can_partitions = 0;
5815 tpnt->two_fm = OSST_TWO_FM;
5816 tpnt->fast_mteom = OSST_FAST_MTEOM;
5817 tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5818 tpnt->write_threshold = osst_write_threshold;
5819 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5820 tpnt->partition = 0;
5821 tpnt->new_partition = 0;
5822 tpnt->nbr_partitions = 0;
5823 tpnt->min_block = 512;
5824 tpnt->max_block = OS_DATA_SIZE;
5825 tpnt->timeout = OSST_TIMEOUT;
5826 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5828 /* Recognize OnStream tapes */
5829 /* We don't need to test for OnStream, as this has been done in detect () */
5830 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5831 tpnt->omit_blklims = 1;
5833 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5834 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5835 tpnt->frame_in_buffer = 0;
5836 tpnt->header_ok = 0;
5837 tpnt->linux_media = 0;
5838 tpnt->header_cache = NULL;
5840 for (i=0; i < ST_NBR_MODES; i++) {
5841 STm = &(tpnt->modes[i]);
5842 STm->defined = 0;
5843 STm->sysv = OSST_SYSV;
5844 STm->defaults_for_writes = 0;
5845 STm->do_async_writes = OSST_ASYNC_WRITES;
5846 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5847 STm->do_read_ahead = OSST_READ_AHEAD;
5848 STm->default_compression = ST_DONT_TOUCH;
5849 STm->default_blksize = 512;
5850 STm->default_density = (-1); /* No forced density */
5853 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5854 STps = &(tpnt->ps[i]);
5855 STps->rw = ST_IDLE;
5856 STps->eof = ST_NOEOF;
5857 STps->at_sm = 0;
5858 STps->last_block_valid = 0;
5859 STps->drv_block = (-1);
5860 STps->drv_file = (-1);
5863 tpnt->current_mode = 0;
5864 tpnt->modes[0].defined = 1;
5865 tpnt->modes[2].defined = 1;
5866 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5868 init_MUTEX(&tpnt->lock);
5869 osst_nr_dev++;
5870 write_unlock(&os_scsi_tapes_lock);
5873 char name[8];
5875 /* Rewind entry */
5876 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5877 if (err)
5878 goto out_free_buffer;
5880 /* No-rewind entry */
5881 snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5882 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5883 if (err)
5884 goto out_free_sysfs1;
5887 sdev_printk(KERN_INFO, SDp,
5888 "osst :I: Attached OnStream %.5s tape as %s\n",
5889 SDp->model, tape_name(tpnt));
5891 return 0;
5893 out_free_sysfs1:
5894 osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5895 out_free_buffer:
5896 kfree(buffer);
5897 out_put_disk:
5898 put_disk(drive);
5899 return err;
5902 static int osst_remove(struct device *dev)
5904 struct scsi_device * SDp = to_scsi_device(dev);
5905 struct osst_tape * tpnt;
5906 int i;
5908 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
5909 return 0;
5911 write_lock(&os_scsi_tapes_lock);
5912 for(i=0; i < osst_max_dev; i++) {
5913 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
5914 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
5915 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
5916 tpnt->device = NULL;
5917 put_disk(tpnt->drive);
5918 os_scsi_tapes[i] = NULL;
5919 osst_nr_dev--;
5920 write_unlock(&os_scsi_tapes_lock);
5921 vfree(tpnt->header_cache);
5922 if (tpnt->buffer) {
5923 normalize_buffer(tpnt->buffer);
5924 kfree(tpnt->buffer);
5926 kfree(tpnt);
5927 return 0;
5930 write_unlock(&os_scsi_tapes_lock);
5931 return 0;
5934 static int __init init_osst(void)
5936 int err;
5938 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5940 validate_options();
5942 err = osst_sysfs_init();
5943 if (err)
5944 return err;
5946 err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
5947 if (err < 0) {
5948 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
5949 goto err_out;
5952 err = scsi_register_driver(&osst_template.gendrv);
5953 if (err)
5954 goto err_out_chrdev;
5956 err = osst_create_driverfs_files(&osst_template.gendrv);
5957 if (err)
5958 goto err_out_scsidrv;
5960 return 0;
5962 err_out_scsidrv:
5963 scsi_unregister_driver(&osst_template.gendrv);
5964 err_out_chrdev:
5965 unregister_chrdev(OSST_MAJOR, "osst");
5966 err_out:
5967 osst_sysfs_cleanup();
5968 return err;
5971 static void __exit exit_osst (void)
5973 int i;
5974 struct osst_tape * STp;
5976 osst_remove_driverfs_files(&osst_template.gendrv);
5977 scsi_unregister_driver(&osst_template.gendrv);
5978 unregister_chrdev(OSST_MAJOR, "osst");
5979 osst_sysfs_cleanup();
5981 if (os_scsi_tapes) {
5982 for (i=0; i < osst_max_dev; ++i) {
5983 if (!(STp = os_scsi_tapes[i])) continue;
5984 /* This is defensive, supposed to happen during detach */
5985 vfree(STp->header_cache);
5986 if (STp->buffer) {
5987 normalize_buffer(STp->buffer);
5988 kfree(STp->buffer);
5990 put_disk(STp->drive);
5991 kfree(STp);
5993 kfree(os_scsi_tapes);
5995 printk(KERN_INFO "osst :I: Unloaded.\n");
5998 module_init(init_osst);
5999 module_exit(exit_osst);