pcmcia: CompactFlash driver for PA Semi Electra boards
[pv_ops_mirror.git] / drivers / scsi / osst.c
blob331b789937c4e0a700e4d1406f8e6a708e9a3e03
1 /*
2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
5 History:
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
17 email osst@riede.org
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
26 static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27 static const char * osst_version = "0.99.4";
29 /* The "failure to reconnect" firmware bug */
30 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31 #define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
34 #include <linux/module.h>
36 #include <linux/fs.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
40 #include <linux/mm.h>
41 #include <linux/init.h>
42 #include <linux/string.h>
43 #include <linux/errno.h>
44 #include <linux/mtio.h>
45 #include <linux/ioctl.h>
46 #include <linux/fcntl.h>
47 #include <linux/spinlock.h>
48 #include <linux/vmalloc.h>
49 #include <linux/blkdev.h>
50 #include <linux/moduleparam.h>
51 #include <linux/delay.h>
52 #include <linux/jiffies.h>
53 #include <asm/uaccess.h>
54 #include <asm/dma.h>
55 #include <asm/system.h>
57 /* The driver prints some debugging information on the console if DEBUG
58 is defined and non-zero. */
59 #define DEBUG 0
61 /* The message level for the debug messages is currently set to KERN_NOTICE
62 so that people can easily see the messages. Later when the debugging messages
63 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
64 #define OSST_DEB_MSG KERN_NOTICE
66 #include <scsi/scsi.h>
67 #include <scsi/scsi_dbg.h>
68 #include <scsi/scsi_device.h>
69 #include <scsi/scsi_driver.h>
70 #include <scsi/scsi_eh.h>
71 #include <scsi/scsi_host.h>
72 #include <scsi/scsi_ioctl.h>
74 #define ST_KILOBYTE 1024
76 #include "st.h"
77 #include "osst.h"
78 #include "osst_options.h"
79 #include "osst_detect.h"
81 static int max_dev = 0;
82 static int write_threshold_kbs = 0;
83 static int max_sg_segs = 0;
85 #ifdef MODULE
86 MODULE_AUTHOR("Willem Riede");
87 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
88 MODULE_LICENSE("GPL");
89 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
90 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
92 module_param(max_dev, int, 0444);
93 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
95 module_param(write_threshold_kbs, int, 0644);
96 MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
98 module_param(max_sg_segs, int, 0644);
99 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
100 #else
101 static struct osst_dev_parm {
102 char *name;
103 int *val;
104 } parms[] __initdata = {
105 { "max_dev", &max_dev },
106 { "write_threshold_kbs", &write_threshold_kbs },
107 { "max_sg_segs", &max_sg_segs }
109 #endif
111 /* Some default definitions have been moved to osst_options.h */
112 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
113 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
115 /* The buffer size should fit into the 24 bits for length in the
116 6-byte SCSI read and write commands. */
117 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
118 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
119 #endif
121 #if DEBUG
122 static int debugging = 1;
123 /* uncomment define below to test error recovery */
124 // #define OSST_INJECT_ERRORS 1
125 #endif
127 /* Do not retry! The drive firmware already retries when appropriate,
128 and when it tries to tell us something, we had better listen... */
129 #define MAX_RETRIES 0
131 #define NO_TAPE NOT_READY
133 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
134 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
135 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
137 #define OSST_TIMEOUT (200 * HZ)
138 #define OSST_LONG_TIMEOUT (1800 * HZ)
140 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
141 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
142 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
143 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
145 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
146 24 bits) */
147 #define SET_DENS_AND_BLK 0x10001
149 static int osst_buffer_size = OSST_BUFFER_SIZE;
150 static int osst_write_threshold = OSST_WRITE_THRESHOLD;
151 static int osst_max_sg_segs = OSST_MAX_SG;
152 static int osst_max_dev = OSST_MAX_TAPES;
153 static int osst_nr_dev;
155 static struct osst_tape **os_scsi_tapes = NULL;
156 static DEFINE_RWLOCK(os_scsi_tapes_lock);
158 static int modes_defined = 0;
160 static struct osst_buffer *new_tape_buffer(int, int, int);
161 static int enlarge_buffer(struct osst_buffer *, int);
162 static void normalize_buffer(struct osst_buffer *);
163 static int append_to_buffer(const char __user *, struct osst_buffer *, int);
164 static int from_buffer(struct osst_buffer *, char __user *, int);
165 static int osst_zero_buffer_tail(struct osst_buffer *);
166 static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
167 static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
169 static int osst_probe(struct device *);
170 static int osst_remove(struct device *);
172 static struct scsi_driver osst_template = {
173 .owner = THIS_MODULE,
174 .gendrv = {
175 .name = "osst",
176 .probe = osst_probe,
177 .remove = osst_remove,
181 static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
182 unsigned int cmd_in, unsigned long arg);
184 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
186 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
188 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
190 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
192 static inline char *tape_name(struct osst_tape *tape)
194 return tape->drive->disk_name;
197 /* Routines that handle the interaction with mid-layer SCSI routines */
200 /* Normalize Sense */
201 static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
203 const u8 *ucp;
204 const u8 *sense = SRpnt->sense;
206 s->have_sense = scsi_normalize_sense(SRpnt->sense,
207 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
208 s->flags = 0;
210 if (s->have_sense) {
211 s->deferred = 0;
212 s->remainder_valid =
213 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
214 switch (sense[0] & 0x7f) {
215 case 0x71:
216 s->deferred = 1;
217 case 0x70:
218 s->fixed_format = 1;
219 s->flags = sense[2] & 0xe0;
220 break;
221 case 0x73:
222 s->deferred = 1;
223 case 0x72:
224 s->fixed_format = 0;
225 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
226 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
227 break;
232 /* Convert the result to success code */
233 static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
235 char *name = tape_name(STp);
236 int result = SRpnt->result;
237 u8 * sense = SRpnt->sense, scode;
238 #if DEBUG
239 const char *stp;
240 #endif
241 struct st_cmdstatus *cmdstatp;
243 if (!result)
244 return 0;
246 cmdstatp = &STp->buffer->cmdstat;
247 osst_analyze_sense(SRpnt, cmdstatp);
249 if (cmdstatp->have_sense)
250 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
251 else
252 scode = 0;
253 #if DEBUG
254 if (debugging) {
255 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
256 name, result,
257 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
258 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
259 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
260 name, scode, sense[12], sense[13]);
261 if (cmdstatp->have_sense)
262 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
264 else
265 #endif
266 if (cmdstatp->have_sense && (
267 scode != NO_SENSE &&
268 scode != RECOVERED_ERROR &&
269 /* scode != UNIT_ATTENTION && */
270 scode != BLANK_CHECK &&
271 scode != VOLUME_OVERFLOW &&
272 SRpnt->cmd[0] != MODE_SENSE &&
273 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
274 if (cmdstatp->have_sense) {
275 printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
276 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
278 else {
279 static int notyetprinted = 1;
281 printk(KERN_WARNING
282 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
283 name, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
284 host_byte(result));
285 if (notyetprinted) {
286 notyetprinted = 0;
287 printk(KERN_INFO
288 "%s:I: This warning may be caused by your scsi controller,\n", name);
289 printk(KERN_INFO
290 "%s:I: it has been reported with some Buslogic cards.\n", name);
294 STp->pos_unknown |= STp->device->was_reset;
296 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
297 STp->recover_count++;
298 STp->recover_erreg++;
299 #if DEBUG
300 if (debugging) {
301 if (SRpnt->cmd[0] == READ_6)
302 stp = "read";
303 else if (SRpnt->cmd[0] == WRITE_6)
304 stp = "write";
305 else
306 stp = "ioctl";
307 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
308 STp->recover_count);
310 #endif
311 if ((sense[2] & 0xe0) == 0)
312 return 0;
314 return (-EIO);
318 /* Wakeup from interrupt */
319 static void osst_sleep_done(void *data, char *sense, int result, int resid)
321 struct osst_request *SRpnt = data;
322 struct osst_tape *STp = SRpnt->stp;
324 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
325 STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
326 #if DEBUG
327 STp->write_pending = 0;
328 #endif
329 if (SRpnt->waiting)
330 complete(SRpnt->waiting);
333 /* osst_request memory management */
334 static struct osst_request *osst_allocate_request(void)
336 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
339 static void osst_release_request(struct osst_request *streq)
341 kfree(streq);
344 /* Do the scsi command. Waits until command performed if do_wait is true.
345 Otherwise osst_write_behind_check() is used to check that the command
346 has finished. */
347 static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
348 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
350 unsigned char *bp;
351 unsigned short use_sg;
352 #ifdef OSST_INJECT_ERRORS
353 static int inject = 0;
354 static int repeat = 0;
355 #endif
356 struct completion *waiting;
358 /* if async, make sure there's no command outstanding */
359 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
360 printk(KERN_ERR "%s: Async command already active.\n",
361 tape_name(STp));
362 if (signal_pending(current))
363 (STp->buffer)->syscall_result = (-EINTR);
364 else
365 (STp->buffer)->syscall_result = (-EBUSY);
366 return NULL;
369 if (SRpnt == NULL) {
370 SRpnt = osst_allocate_request();
371 if (SRpnt == NULL) {
372 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
373 tape_name(STp));
374 if (signal_pending(current))
375 (STp->buffer)->syscall_result = (-EINTR);
376 else
377 (STp->buffer)->syscall_result = (-EBUSY);
378 return NULL;
380 SRpnt->stp = STp;
383 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
384 which IO is outstanding. It's nulled out when the IO completes. */
385 if (!do_wait)
386 (STp->buffer)->last_SRpnt = SRpnt;
388 waiting = &STp->wait;
389 init_completion(waiting);
390 SRpnt->waiting = waiting;
392 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
393 if (use_sg) {
394 bp = (char *)&(STp->buffer->sg[0]);
395 if (STp->buffer->sg_segs < use_sg)
396 use_sg = STp->buffer->sg_segs;
398 else
399 bp = (STp->buffer)->b_data;
401 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
402 STp->buffer->cmdstat.have_sense = 0;
403 STp->buffer->syscall_result = 0;
405 if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
406 use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL))
407 /* could not allocate the buffer or request was too large */
408 (STp->buffer)->syscall_result = (-EBUSY);
409 else if (do_wait) {
410 wait_for_completion(waiting);
411 SRpnt->waiting = NULL;
412 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
413 #ifdef OSST_INJECT_ERRORS
414 if (STp->buffer->syscall_result == 0 &&
415 cmd[0] == READ_6 &&
416 cmd[4] &&
417 ( (++ inject % 83) == 29 ||
418 (STp->first_frame_position == 240
419 /* or STp->read_error_frame to fail again on the block calculated above */ &&
420 ++repeat < 3))) {
421 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
422 STp->buffer->last_result_fatal = 1;
424 #endif
426 return SRpnt;
430 /* Handle the write-behind checking (downs the semaphore) */
431 static void osst_write_behind_check(struct osst_tape *STp)
433 struct osst_buffer * STbuffer;
435 STbuffer = STp->buffer;
437 #if DEBUG
438 if (STp->write_pending)
439 STp->nbr_waits++;
440 else
441 STp->nbr_finished++;
442 #endif
443 wait_for_completion(&(STp->wait));
444 STp->buffer->last_SRpnt->waiting = NULL;
446 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
448 if (STp->buffer->syscall_result)
449 STp->buffer->syscall_result =
450 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
451 else
452 STp->first_frame_position++;
454 osst_release_request(STp->buffer->last_SRpnt);
456 if (STbuffer->writing < STbuffer->buffer_bytes)
457 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
459 STbuffer->last_SRpnt = NULL;
460 STbuffer->buffer_bytes -= STbuffer->writing;
461 STbuffer->writing = 0;
463 return;
468 /* Onstream specific Routines */
470 * Initialize the OnStream AUX
472 static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
473 int logical_blk_num, int blk_sz, int blk_cnt)
475 os_aux_t *aux = STp->buffer->aux;
476 os_partition_t *par = &aux->partition;
477 os_dat_t *dat = &aux->dat;
479 if (STp->raw) return;
481 memset(aux, 0, sizeof(*aux));
482 aux->format_id = htonl(0);
483 memcpy(aux->application_sig, "LIN4", 4);
484 aux->hdwr = htonl(0);
485 aux->frame_type = frame_type;
487 switch (frame_type) {
488 case OS_FRAME_TYPE_HEADER:
489 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
490 par->partition_num = OS_CONFIG_PARTITION;
491 par->par_desc_ver = OS_PARTITION_VERSION;
492 par->wrt_pass_cntr = htons(0xffff);
493 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
494 par->first_frame_ppos = htonl(0);
495 par->last_frame_ppos = htonl(0xbb7);
496 aux->frame_seq_num = htonl(0);
497 aux->logical_blk_num_high = htonl(0);
498 aux->logical_blk_num = htonl(0);
499 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
500 break;
501 case OS_FRAME_TYPE_DATA:
502 case OS_FRAME_TYPE_MARKER:
503 dat->dat_sz = 8;
504 dat->reserved1 = 0;
505 dat->entry_cnt = 1;
506 dat->reserved3 = 0;
507 dat->dat_list[0].blk_sz = htonl(blk_sz);
508 dat->dat_list[0].blk_cnt = htons(blk_cnt);
509 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
510 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
511 dat->dat_list[0].reserved = 0;
512 case OS_FRAME_TYPE_EOD:
513 aux->update_frame_cntr = htonl(0);
514 par->partition_num = OS_DATA_PARTITION;
515 par->par_desc_ver = OS_PARTITION_VERSION;
516 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
517 par->first_frame_ppos = htonl(STp->first_data_ppos);
518 par->last_frame_ppos = htonl(STp->capacity);
519 aux->frame_seq_num = htonl(frame_seq_number);
520 aux->logical_blk_num_high = htonl(0);
521 aux->logical_blk_num = htonl(logical_blk_num);
522 break;
523 default: ; /* probably FILL */
525 aux->filemark_cnt = htonl(STp->filemark_cnt);
526 aux->phys_fm = htonl(0xffffffff);
527 aux->last_mark_ppos = htonl(STp->last_mark_ppos);
528 aux->last_mark_lbn = htonl(STp->last_mark_lbn);
532 * Verify that we have the correct tape frame
534 static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
536 char * name = tape_name(STp);
537 os_aux_t * aux = STp->buffer->aux;
538 os_partition_t * par = &(aux->partition);
539 struct st_partstat * STps = &(STp->ps[STp->partition]);
540 int blk_cnt, blk_sz, i;
542 if (STp->raw) {
543 if (STp->buffer->syscall_result) {
544 for (i=0; i < STp->buffer->sg_segs; i++)
545 memset(page_address(STp->buffer->sg[i].page),
546 0, STp->buffer->sg[i].length);
547 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
548 } else
549 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
550 return 1;
552 if (STp->buffer->syscall_result) {
553 #if DEBUG
554 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
555 #endif
556 return 0;
558 if (ntohl(aux->format_id) != 0) {
559 #if DEBUG
560 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
561 #endif
562 goto err_out;
564 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
565 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
566 #if DEBUG
567 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
568 #endif
569 goto err_out;
571 if (par->partition_num != OS_DATA_PARTITION) {
572 if (!STp->linux_media || STp->linux_media_version != 2) {
573 #if DEBUG
574 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
575 name, par->partition_num);
576 #endif
577 goto err_out;
580 if (par->par_desc_ver != OS_PARTITION_VERSION) {
581 #if DEBUG
582 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
583 #endif
584 goto err_out;
586 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
587 #if DEBUG
588 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
589 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
590 #endif
591 goto err_out;
593 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
594 aux->frame_type != OS_FRAME_TYPE_EOD &&
595 aux->frame_type != OS_FRAME_TYPE_MARKER) {
596 if (!quiet)
597 #if DEBUG
598 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
599 #endif
600 goto err_out;
602 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
603 STp->first_frame_position < STp->eod_frame_ppos) {
604 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
605 STp->first_frame_position);
606 goto err_out;
608 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
609 if (!quiet)
610 #if DEBUG
611 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
612 name, ntohl(aux->frame_seq_num), frame_seq_number);
613 #endif
614 goto err_out;
616 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
617 STps->eof = ST_FM_HIT;
619 i = ntohl(aux->filemark_cnt);
620 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
621 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
622 #if DEBUG
623 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
624 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
625 i, STp->first_frame_position - 1);
626 #endif
627 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
628 if (i >= STp->filemark_cnt)
629 STp->filemark_cnt = i+1;
632 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
633 STps->eof = ST_EOD_1;
634 STp->frame_in_buffer = 1;
636 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
637 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
638 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
639 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
640 STp->buffer->read_pointer = 0;
641 STp->frame_in_buffer = 1;
643 /* See what block size was used to write file */
644 if (STp->block_size != blk_sz && blk_sz > 0) {
645 printk(KERN_INFO
646 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
647 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
648 STp->block_size<1024?STp->block_size:STp->block_size/1024,
649 STp->block_size<1024?'b':'k');
650 STp->block_size = blk_sz;
651 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
653 STps->eof = ST_NOEOF;
655 STp->frame_seq_number = ntohl(aux->frame_seq_num);
656 STp->logical_blk_num = ntohl(aux->logical_blk_num);
657 return 1;
659 err_out:
660 if (STp->read_error_frame == 0)
661 STp->read_error_frame = STp->first_frame_position - 1;
662 return 0;
666 * Wait for the unit to become Ready
668 static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
669 unsigned timeout, int initial_delay)
671 unsigned char cmd[MAX_COMMAND_SIZE];
672 struct osst_request * SRpnt;
673 unsigned long startwait = jiffies;
674 #if DEBUG
675 int dbg = debugging;
676 char * name = tape_name(STp);
678 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
679 #endif
681 if (initial_delay > 0)
682 msleep(jiffies_to_msecs(initial_delay));
684 memset(cmd, 0, MAX_COMMAND_SIZE);
685 cmd[0] = TEST_UNIT_READY;
687 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
688 *aSRpnt = SRpnt;
689 if (!SRpnt) return (-EBUSY);
691 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
692 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
693 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
694 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
695 SRpnt->sense[13] == 0 ) )) {
696 #if DEBUG
697 if (debugging) {
698 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
699 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
700 debugging = 0;
702 #endif
703 msleep(100);
705 memset(cmd, 0, MAX_COMMAND_SIZE);
706 cmd[0] = TEST_UNIT_READY;
708 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
710 *aSRpnt = SRpnt;
711 #if DEBUG
712 debugging = dbg;
713 #endif
714 if ( STp->buffer->syscall_result &&
715 osst_write_error_recovery(STp, aSRpnt, 0) ) {
716 #if DEBUG
717 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
718 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
719 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
720 SRpnt->sense[12], SRpnt->sense[13]);
721 #endif
722 return (-EIO);
724 #if DEBUG
725 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
726 #endif
727 return 0;
731 * Wait for a tape to be inserted in the unit
733 static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
735 unsigned char cmd[MAX_COMMAND_SIZE];
736 struct osst_request * SRpnt;
737 unsigned long startwait = jiffies;
738 #if DEBUG
739 int dbg = debugging;
740 char * name = tape_name(STp);
742 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
743 #endif
745 memset(cmd, 0, MAX_COMMAND_SIZE);
746 cmd[0] = TEST_UNIT_READY;
748 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
749 *aSRpnt = SRpnt;
750 if (!SRpnt) return (-EBUSY);
752 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
753 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
754 #if DEBUG
755 if (debugging) {
756 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
757 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
758 debugging = 0;
760 #endif
761 msleep(100);
763 memset(cmd, 0, MAX_COMMAND_SIZE);
764 cmd[0] = TEST_UNIT_READY;
766 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
768 *aSRpnt = SRpnt;
769 #if DEBUG
770 debugging = dbg;
771 #endif
772 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
773 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
774 #if DEBUG
775 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
776 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
777 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
778 SRpnt->sense[12], SRpnt->sense[13]);
779 #endif
780 return 0;
782 #if DEBUG
783 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
784 #endif
785 return 1;
788 static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
790 int retval;
792 osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
793 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
794 if (retval) return (retval);
795 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
796 return (osst_get_frame_position(STp, aSRpnt));
800 * Wait for write(s) to complete
802 static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
804 unsigned char cmd[MAX_COMMAND_SIZE];
805 struct osst_request * SRpnt;
806 int result = 0;
807 int delay = OSST_WAIT_WRITE_COMPLETE;
808 #if DEBUG
809 char * name = tape_name(STp);
811 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
812 #endif
814 memset(cmd, 0, MAX_COMMAND_SIZE);
815 cmd[0] = WRITE_FILEMARKS;
816 cmd[1] = 1;
818 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
819 *aSRpnt = SRpnt;
820 if (!SRpnt) return (-EBUSY);
821 if (STp->buffer->syscall_result) {
822 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
823 if (SRpnt->sense[13] == 8) {
824 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
826 } else
827 result = osst_write_error_recovery(STp, aSRpnt, 0);
829 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
830 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
832 return (result);
835 #define OSST_POLL_PER_SEC 10
836 static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
838 unsigned long startwait = jiffies;
839 char * name = tape_name(STp);
840 #if DEBUG
841 char notyetprinted = 1;
842 #endif
843 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
844 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
846 while (time_before (jiffies, startwait + to*HZ))
848 int result;
849 result = osst_get_frame_position(STp, aSRpnt);
850 if (result == -EIO)
851 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
852 return 0; /* successful recovery leaves drive ready for frame */
853 if (result < 0) break;
854 if (STp->first_frame_position == curr &&
855 ((minlast < 0 &&
856 (signed)STp->last_frame_position > (signed)curr + minlast) ||
857 (minlast >= 0 && STp->cur_frames > minlast)
858 ) && result >= 0)
860 #if DEBUG
861 if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
862 printk (OSST_DEB_MSG
863 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
864 name, curr, curr+minlast, STp->first_frame_position,
865 STp->last_frame_position, STp->cur_frames,
866 result, (jiffies-startwait)/HZ,
867 (((jiffies-startwait)%HZ)*10)/HZ);
868 #endif
869 return 0;
871 #if DEBUG
872 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
874 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
875 name, curr, curr+minlast, STp->first_frame_position,
876 STp->last_frame_position, STp->cur_frames, result);
877 notyetprinted--;
879 #endif
880 msleep(1000 / OSST_POLL_PER_SEC);
882 #if DEBUG
883 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
884 name, curr, curr+minlast, STp->first_frame_position,
885 STp->last_frame_position, STp->cur_frames,
886 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
887 #endif
888 return -EBUSY;
891 static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
893 struct osst_request * SRpnt;
894 unsigned char cmd[MAX_COMMAND_SIZE];
895 unsigned long startwait = jiffies;
896 int retval = 1;
897 char * name = tape_name(STp);
899 if (writing) {
900 char mybuf[24];
901 char * olddata = STp->buffer->b_data;
902 int oldsize = STp->buffer->buffer_size;
904 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
906 memset(cmd, 0, MAX_COMMAND_SIZE);
907 cmd[0] = WRITE_FILEMARKS;
908 cmd[1] = 1;
909 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
910 MAX_RETRIES, 1);
912 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
914 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
916 /* some failure - not just not-ready */
917 retval = osst_write_error_recovery(STp, aSRpnt, 0);
918 break;
920 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
922 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
923 memset(cmd, 0, MAX_COMMAND_SIZE);
924 cmd[0] = READ_POSITION;
926 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
927 MAX_RETRIES, 1);
929 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
930 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
932 if (retval)
933 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
934 } else
935 /* TODO - figure out which error conditions can be handled */
936 if (STp->buffer->syscall_result)
937 printk(KERN_WARNING
938 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
939 (*aSRpnt)->sense[ 2] & 0x0f,
940 (*aSRpnt)->sense[12],
941 (*aSRpnt)->sense[13]);
943 return retval;
947 * Read the next OnStream tape frame at the current location
949 static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
951 unsigned char cmd[MAX_COMMAND_SIZE];
952 struct osst_request * SRpnt;
953 int retval = 0;
954 #if DEBUG
955 os_aux_t * aux = STp->buffer->aux;
956 char * name = tape_name(STp);
957 #endif
959 if (STp->poll)
960 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
961 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
963 memset(cmd, 0, MAX_COMMAND_SIZE);
964 cmd[0] = READ_6;
965 cmd[1] = 1;
966 cmd[4] = 1;
968 #if DEBUG
969 if (debugging)
970 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
971 #endif
972 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
973 STp->timeout, MAX_RETRIES, 1);
974 *aSRpnt = SRpnt;
975 if (!SRpnt)
976 return (-EBUSY);
978 if ((STp->buffer)->syscall_result) {
979 retval = 1;
980 if (STp->read_error_frame == 0) {
981 STp->read_error_frame = STp->first_frame_position;
982 #if DEBUG
983 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
984 #endif
986 #if DEBUG
987 if (debugging)
988 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
989 name,
990 SRpnt->sense[0], SRpnt->sense[1],
991 SRpnt->sense[2], SRpnt->sense[3],
992 SRpnt->sense[4], SRpnt->sense[5],
993 SRpnt->sense[6], SRpnt->sense[7]);
994 #endif
996 else
997 STp->first_frame_position++;
998 #if DEBUG
999 if (debugging) {
1000 char sig[8]; int i;
1001 for (i=0;i<4;i++)
1002 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1003 sig[4] = '\0';
1004 printk(OSST_DEB_MSG
1005 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1006 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1007 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1008 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1009 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1010 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1011 if (aux->frame_type==2)
1012 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1013 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1014 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1016 #endif
1017 return (retval);
1020 static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1022 struct st_partstat * STps = &(STp->ps[STp->partition]);
1023 struct osst_request * SRpnt ;
1024 unsigned char cmd[MAX_COMMAND_SIZE];
1025 int retval = 0;
1026 char * name = tape_name(STp);
1028 if (STps->rw != ST_READING) { /* Initialize read operation */
1029 if (STps->rw == ST_WRITING || STp->dirty) {
1030 STp->write_type = OS_WRITE_DATA;
1031 osst_flush_write_buffer(STp, aSRpnt);
1032 osst_flush_drive_buffer(STp, aSRpnt);
1034 STps->rw = ST_READING;
1035 STp->frame_in_buffer = 0;
1038 * Issue a read 0 command to get the OnStream drive
1039 * read frames into its buffer.
1041 memset(cmd, 0, MAX_COMMAND_SIZE);
1042 cmd[0] = READ_6;
1043 cmd[1] = 1;
1045 #if DEBUG
1046 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1047 #endif
1048 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1049 *aSRpnt = SRpnt;
1050 if ((retval = STp->buffer->syscall_result))
1051 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1054 return retval;
1057 static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1058 int frame_seq_number, int quiet)
1060 struct st_partstat * STps = &(STp->ps[STp->partition]);
1061 char * name = tape_name(STp);
1062 int cnt = 0,
1063 bad = 0,
1064 past = 0,
1066 position;
1069 * If we want just any frame (-1) and there is a frame in the buffer, return it
1071 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1072 #if DEBUG
1073 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1074 #endif
1075 return (STps->eof);
1078 * Search and wait for the next logical tape frame
1080 while (1) {
1081 if (cnt++ > 400) {
1082 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1083 name, frame_seq_number);
1084 if (STp->read_error_frame) {
1085 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1086 #if DEBUG
1087 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1088 name, STp->read_error_frame);
1089 #endif
1090 STp->read_error_frame = 0;
1091 STp->abort_count++;
1093 return (-EIO);
1095 #if DEBUG
1096 if (debugging)
1097 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1098 name, frame_seq_number, cnt);
1099 #endif
1100 if ( osst_initiate_read(STp, aSRpnt)
1101 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1102 if (STp->raw)
1103 return (-EIO);
1104 position = osst_get_frame_position(STp, aSRpnt);
1105 if (position >= 0xbae && position < 0xbb8)
1106 position = 0xbb8;
1107 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1108 position = STp->read_error_frame - 1;
1109 bad = 0;
1111 else {
1112 position += 29;
1113 cnt += 19;
1115 #if DEBUG
1116 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1117 name, position);
1118 #endif
1119 osst_set_frame_position(STp, aSRpnt, position, 0);
1120 continue;
1122 if (osst_verify_frame(STp, frame_seq_number, quiet))
1123 break;
1124 if (osst_verify_frame(STp, -1, quiet)) {
1125 x = ntohl(STp->buffer->aux->frame_seq_num);
1126 if (STp->fast_open) {
1127 printk(KERN_WARNING
1128 "%s:W: Found logical frame %d instead of %d after fast open\n",
1129 name, x, frame_seq_number);
1130 STp->header_ok = 0;
1131 STp->read_error_frame = 0;
1132 return (-EIO);
1134 if (x > frame_seq_number) {
1135 if (++past > 3) {
1136 /* positioning backwards did not bring us to the desired frame */
1137 position = STp->read_error_frame - 1;
1139 else {
1140 position = osst_get_frame_position(STp, aSRpnt)
1141 + frame_seq_number - x - 1;
1143 if (STp->first_frame_position >= 3000 && position < 3000)
1144 position -= 10;
1146 #if DEBUG
1147 printk(OSST_DEB_MSG
1148 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1149 name, x, frame_seq_number,
1150 STp->first_frame_position - position);
1151 #endif
1152 osst_set_frame_position(STp, aSRpnt, position, 0);
1153 cnt += 10;
1155 else
1156 past = 0;
1158 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1159 #if DEBUG
1160 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1161 #endif
1162 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1163 cnt--;
1165 STp->frame_in_buffer = 0;
1167 if (cnt > 1) {
1168 STp->recover_count++;
1169 STp->recover_erreg++;
1170 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1171 name, STp->read_error_frame);
1173 STp->read_count++;
1175 #if DEBUG
1176 if (debugging || STps->eof)
1177 printk(OSST_DEB_MSG
1178 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1179 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1180 #endif
1181 STp->fast_open = 0;
1182 STp->read_error_frame = 0;
1183 return (STps->eof);
1186 static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1188 struct st_partstat * STps = &(STp->ps[STp->partition]);
1189 char * name = tape_name(STp);
1190 int retries = 0;
1191 int frame_seq_estimate, ppos_estimate, move;
1193 if (logical_blk_num < 0) logical_blk_num = 0;
1194 #if DEBUG
1195 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1196 name, logical_blk_num, STp->logical_blk_num,
1197 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1198 STp->block_size<1024?'b':'k');
1199 #endif
1200 /* Do we know where we are? */
1201 if (STps->drv_block >= 0) {
1202 move = logical_blk_num - STp->logical_blk_num;
1203 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1204 move /= (OS_DATA_SIZE / STp->block_size);
1205 frame_seq_estimate = STp->frame_seq_number + move;
1206 } else
1207 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1209 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1210 else ppos_estimate = frame_seq_estimate + 20;
1211 while (++retries < 10) {
1212 if (ppos_estimate > STp->eod_frame_ppos-2) {
1213 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1214 ppos_estimate = STp->eod_frame_ppos - 2;
1216 if (frame_seq_estimate < 0) {
1217 frame_seq_estimate = 0;
1218 ppos_estimate = 10;
1220 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1221 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1222 /* we've located the estimated frame, now does it have our block? */
1223 if (logical_blk_num < STp->logical_blk_num ||
1224 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1225 if (STps->eof == ST_FM_HIT)
1226 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1227 else {
1228 move = logical_blk_num - STp->logical_blk_num;
1229 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1230 move /= (OS_DATA_SIZE / STp->block_size);
1232 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1233 #if DEBUG
1234 printk(OSST_DEB_MSG
1235 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1236 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1237 STp->logical_blk_num, logical_blk_num, move);
1238 #endif
1239 frame_seq_estimate += move;
1240 ppos_estimate += move;
1241 continue;
1242 } else {
1243 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1244 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1245 STp->logical_blk_num = logical_blk_num;
1246 #if DEBUG
1247 printk(OSST_DEB_MSG
1248 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1249 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1250 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1251 STp->block_size);
1252 #endif
1253 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1254 if (STps->eof == ST_FM_HIT) {
1255 STps->drv_file++;
1256 STps->drv_block = 0;
1257 } else {
1258 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1259 STp->logical_blk_num -
1260 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1263 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1264 return 0;
1267 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1268 goto error;
1269 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1270 #if DEBUG
1271 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1272 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1273 STp->logical_blk_num, logical_blk_num);
1274 #endif
1275 if (frame_seq_estimate != STp->frame_seq_number)
1276 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1277 else
1278 break;
1280 error:
1281 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1282 name, logical_blk_num, STp->logical_blk_num, retries);
1283 return (-EIO);
1286 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1287 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1288 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1289 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1291 #define OSST_FRAME_SHIFT 6
1292 #define OSST_SECTOR_SHIFT 9
1293 #define OSST_SECTOR_MASK 0x03F
1295 static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1297 int sector;
1298 #if DEBUG
1299 char * name = tape_name(STp);
1301 printk(OSST_DEB_MSG
1302 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1303 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1304 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1305 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1306 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1307 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1308 #endif
1309 /* do we know where we are inside a file? */
1310 if (STp->ps[STp->partition].drv_block >= 0) {
1311 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1312 STp->first_frame_position) << OSST_FRAME_SHIFT;
1313 if (STp->ps[STp->partition].rw == ST_WRITING)
1314 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1315 else
1316 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1317 } else {
1318 sector = osst_get_frame_position(STp, aSRpnt);
1319 if (sector > 0)
1320 sector <<= OSST_FRAME_SHIFT;
1322 return sector;
1325 static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1327 struct st_partstat * STps = &(STp->ps[STp->partition]);
1328 int frame = sector >> OSST_FRAME_SHIFT,
1329 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1331 #if DEBUG
1332 char * name = tape_name(STp);
1334 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1335 name, sector, frame, offset);
1336 #endif
1337 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1339 if (frame <= STp->first_data_ppos) {
1340 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1341 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1343 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1344 if (r < 0) return r;
1346 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1347 if (r < 0) return r;
1349 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1351 if (offset) {
1352 STp->logical_blk_num += offset / STp->block_size;
1353 STp->buffer->read_pointer = offset;
1354 STp->buffer->buffer_bytes -= offset;
1355 } else {
1356 STp->frame_seq_number++;
1357 STp->frame_in_buffer = 0;
1358 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1359 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1361 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1362 if (STps->eof == ST_FM_HIT) {
1363 STps->drv_file++;
1364 STps->drv_block = 0;
1365 } else {
1366 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1367 STp->logical_blk_num -
1368 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1371 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1372 #if DEBUG
1373 printk(OSST_DEB_MSG
1374 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1375 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1376 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1377 #endif
1378 return 0;
1382 * Read back the drive's internal buffer contents, as a part
1383 * of the write error recovery mechanism for old OnStream
1384 * firmware revisions.
1385 * Precondition for this function to work: all frames in the
1386 * drive's buffer must be of one type (DATA, MARK or EOD)!
1388 static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1389 unsigned int frame, unsigned int skip, int pending)
1391 struct osst_request * SRpnt = * aSRpnt;
1392 unsigned char * buffer, * p;
1393 unsigned char cmd[MAX_COMMAND_SIZE];
1394 int flag, new_frame, i;
1395 int nframes = STp->cur_frames;
1396 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1397 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1398 - (nframes + pending - 1);
1399 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1400 - (nframes + pending - 1) * blks_per_frame;
1401 char * name = tape_name(STp);
1402 unsigned long startwait = jiffies;
1403 #if DEBUG
1404 int dbg = debugging;
1405 #endif
1407 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1408 return (-EIO);
1410 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1411 name, nframes, pending?" and one that was pending":"");
1413 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1414 #if DEBUG
1415 if (pending && debugging)
1416 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1417 name, frame_seq_number + nframes,
1418 logical_blk_num + nframes * blks_per_frame,
1419 p[0], p[1], p[2], p[3]);
1420 #endif
1421 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1423 memset(cmd, 0, MAX_COMMAND_SIZE);
1424 cmd[0] = 0x3C; /* Buffer Read */
1425 cmd[1] = 6; /* Retrieve Faulty Block */
1426 cmd[7] = 32768 >> 8;
1427 cmd[8] = 32768 & 0xff;
1429 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1430 STp->timeout, MAX_RETRIES, 1);
1432 if ((STp->buffer)->syscall_result || !SRpnt) {
1433 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1434 vfree(buffer);
1435 *aSRpnt = SRpnt;
1436 return (-EIO);
1438 osst_copy_from_buffer(STp->buffer, p);
1439 #if DEBUG
1440 if (debugging)
1441 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1442 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1443 #endif
1445 *aSRpnt = SRpnt;
1446 osst_get_frame_position(STp, aSRpnt);
1448 #if DEBUG
1449 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1450 #endif
1451 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1452 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1454 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1456 if (flag) {
1457 if (STp->write_type == OS_WRITE_HEADER) {
1458 i += skip;
1459 p += skip * OS_DATA_SIZE;
1461 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1462 new_frame = 3000-i;
1463 else
1464 new_frame += skip;
1465 #if DEBUG
1466 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1467 name, new_frame+i, frame_seq_number+i);
1468 #endif
1469 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1470 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1471 osst_get_frame_position(STp, aSRpnt);
1472 SRpnt = * aSRpnt;
1474 if (new_frame > frame + 1000) {
1475 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1476 vfree(buffer);
1477 return (-EIO);
1479 if ( i >= nframes + pending ) break;
1480 flag = 0;
1482 osst_copy_to_buffer(STp->buffer, p);
1484 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1486 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1487 logical_blk_num + i*blks_per_frame,
1488 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1489 memset(cmd, 0, MAX_COMMAND_SIZE);
1490 cmd[0] = WRITE_6;
1491 cmd[1] = 1;
1492 cmd[4] = 1;
1494 #if DEBUG
1495 if (debugging)
1496 printk(OSST_DEB_MSG
1497 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1498 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1499 p[0], p[1], p[2], p[3]);
1500 #endif
1501 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1502 STp->timeout, MAX_RETRIES, 1);
1504 if (STp->buffer->syscall_result)
1505 flag = 1;
1506 else {
1507 p += OS_DATA_SIZE; i++;
1509 /* if we just sent the last frame, wait till all successfully written */
1510 if ( i == nframes + pending ) {
1511 #if DEBUG
1512 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1513 #endif
1514 memset(cmd, 0, MAX_COMMAND_SIZE);
1515 cmd[0] = WRITE_FILEMARKS;
1516 cmd[1] = 1;
1517 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1518 STp->timeout, MAX_RETRIES, 1);
1519 #if DEBUG
1520 if (debugging) {
1521 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1522 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1523 debugging = 0;
1525 #endif
1526 flag = STp->buffer->syscall_result;
1527 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1529 memset(cmd, 0, MAX_COMMAND_SIZE);
1530 cmd[0] = TEST_UNIT_READY;
1532 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1533 MAX_RETRIES, 1);
1535 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1536 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1537 /* in the process of becoming ready */
1538 msleep(100);
1539 continue;
1541 if (STp->buffer->syscall_result)
1542 flag = 1;
1543 break;
1545 #if DEBUG
1546 debugging = dbg;
1547 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1548 #endif
1551 *aSRpnt = SRpnt;
1552 if (flag) {
1553 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1554 SRpnt->sense[12] == 0 &&
1555 SRpnt->sense[13] == 2) {
1556 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1557 vfree(buffer);
1558 return (-EIO); /* hit end of tape = fail */
1560 i = ((SRpnt->sense[3] << 24) |
1561 (SRpnt->sense[4] << 16) |
1562 (SRpnt->sense[5] << 8) |
1563 SRpnt->sense[6] ) - new_frame;
1564 p = &buffer[i * OS_DATA_SIZE];
1565 #if DEBUG
1566 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1567 #endif
1568 osst_get_frame_position(STp, aSRpnt);
1569 #if DEBUG
1570 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1571 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1572 #endif
1575 if (flag) {
1576 /* error recovery did not successfully complete */
1577 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1578 STp->write_type == OS_WRITE_HEADER?"header":"body");
1580 if (!pending)
1581 osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
1582 vfree(buffer);
1583 return 0;
1586 static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1587 unsigned int frame, unsigned int skip, int pending)
1589 unsigned char cmd[MAX_COMMAND_SIZE];
1590 struct osst_request * SRpnt;
1591 char * name = tape_name(STp);
1592 int expected = 0;
1593 int attempts = 1000 / skip;
1594 int flag = 1;
1595 unsigned long startwait = jiffies;
1596 #if DEBUG
1597 int dbg = debugging;
1598 #endif
1600 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1601 if (flag) {
1602 #if DEBUG
1603 debugging = dbg;
1604 #endif
1605 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1606 frame = 3000-skip;
1607 expected = frame+skip+STp->cur_frames+pending;
1608 #if DEBUG
1609 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1610 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1611 #endif
1612 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1613 flag = 0;
1614 attempts--;
1615 schedule_timeout_interruptible(msecs_to_jiffies(100));
1617 if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
1618 #if DEBUG
1619 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1620 name, STp->first_frame_position,
1621 STp->last_frame_position, STp->cur_frames);
1622 #endif
1623 frame = STp->last_frame_position;
1624 flag = 1;
1625 continue;
1627 if (pending && STp->cur_frames < 50) {
1629 memset(cmd, 0, MAX_COMMAND_SIZE);
1630 cmd[0] = WRITE_6;
1631 cmd[1] = 1;
1632 cmd[4] = 1;
1633 #if DEBUG
1634 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1635 name, STp->frame_seq_number-1, STp->first_frame_position);
1636 #endif
1637 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1638 STp->timeout, MAX_RETRIES, 1);
1639 *aSRpnt = SRpnt;
1641 if (STp->buffer->syscall_result) { /* additional write error */
1642 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1643 SRpnt->sense[12] == 0 &&
1644 SRpnt->sense[13] == 2) {
1645 printk(KERN_ERR
1646 "%s:E: Volume overflow in write error recovery\n",
1647 name);
1648 break; /* hit end of tape = fail */
1650 flag = 1;
1652 else
1653 pending = 0;
1655 continue;
1657 if (STp->cur_frames == 0) {
1658 #if DEBUG
1659 debugging = dbg;
1660 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1661 #endif
1662 if (STp->first_frame_position != expected) {
1663 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1664 name, STp->first_frame_position, expected);
1665 return (-EIO);
1667 return 0;
1669 #if DEBUG
1670 if (debugging) {
1671 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1672 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1673 debugging = 0;
1675 #endif
1676 schedule_timeout_interruptible(msecs_to_jiffies(100));
1678 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1679 #if DEBUG
1680 debugging = dbg;
1681 #endif
1682 return (-EIO);
1686 * Error recovery algorithm for the OnStream tape.
1689 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1691 struct osst_request * SRpnt = * aSRpnt;
1692 struct st_partstat * STps = & STp->ps[STp->partition];
1693 char * name = tape_name(STp);
1694 int retval = 0;
1695 int rw_state;
1696 unsigned int frame, skip;
1698 rw_state = STps->rw;
1700 if ((SRpnt->sense[ 2] & 0x0f) != 3
1701 || SRpnt->sense[12] != 12
1702 || SRpnt->sense[13] != 0) {
1703 #if DEBUG
1704 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1705 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1706 #endif
1707 return (-EIO);
1709 frame = (SRpnt->sense[3] << 24) |
1710 (SRpnt->sense[4] << 16) |
1711 (SRpnt->sense[5] << 8) |
1712 SRpnt->sense[6];
1713 skip = SRpnt->sense[9];
1715 #if DEBUG
1716 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1717 #endif
1718 osst_get_frame_position(STp, aSRpnt);
1719 #if DEBUG
1720 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1721 name, STp->first_frame_position, STp->last_frame_position);
1722 #endif
1723 switch (STp->write_type) {
1724 case OS_WRITE_DATA:
1725 case OS_WRITE_EOD:
1726 case OS_WRITE_NEW_MARK:
1727 printk(KERN_WARNING
1728 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1729 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1730 if (STp->os_fw_rev >= 10600)
1731 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1732 else
1733 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1734 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1735 retval?"E" :"I",
1736 retval?"" :"Don't worry, ",
1737 retval?" not ":" ");
1738 break;
1739 case OS_WRITE_LAST_MARK:
1740 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1741 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1742 retval = -EIO;
1743 break;
1744 case OS_WRITE_HEADER:
1745 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1746 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1747 break;
1748 default:
1749 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1750 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1752 osst_get_frame_position(STp, aSRpnt);
1753 #if DEBUG
1754 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1755 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1756 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1757 #endif
1758 if (retval == 0) {
1759 STp->recover_count++;
1760 STp->recover_erreg++;
1761 } else
1762 STp->abort_count++;
1764 STps->rw = rw_state;
1765 return retval;
1768 static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1769 int mt_op, int mt_count)
1771 char * name = tape_name(STp);
1772 int cnt;
1773 int last_mark_ppos = -1;
1775 #if DEBUG
1776 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1777 #endif
1778 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1779 #if DEBUG
1780 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1781 #endif
1782 return -EIO;
1784 if (STp->linux_media_version >= 4) {
1786 * direct lookup in header filemark list
1788 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1789 if (STp->header_ok &&
1790 STp->header_cache != NULL &&
1791 (cnt - mt_count) >= 0 &&
1792 (cnt - mt_count) < OS_FM_TAB_MAX &&
1793 (cnt - mt_count) < STp->filemark_cnt &&
1794 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1796 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1797 #if DEBUG
1798 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1799 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1800 STp->header_cache == NULL?"lack of header cache":"count out of range");
1801 else
1802 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1803 name, cnt,
1804 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1805 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1806 STp->buffer->aux->last_mark_ppos))?"match":"error",
1807 mt_count, last_mark_ppos);
1808 #endif
1809 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1810 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1811 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1812 #if DEBUG
1813 printk(OSST_DEB_MSG
1814 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1815 #endif
1816 return (-EIO);
1818 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1819 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1820 name, last_mark_ppos);
1821 return (-EIO);
1823 goto found;
1825 #if DEBUG
1826 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1827 #endif
1829 cnt = 0;
1830 while (cnt != mt_count) {
1831 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1832 if (last_mark_ppos == -1)
1833 return (-EIO);
1834 #if DEBUG
1835 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1836 #endif
1837 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1838 cnt++;
1839 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1840 #if DEBUG
1841 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1842 #endif
1843 return (-EIO);
1845 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1846 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1847 name, last_mark_ppos);
1848 return (-EIO);
1851 found:
1852 if (mt_op == MTBSFM) {
1853 STp->frame_seq_number++;
1854 STp->frame_in_buffer = 0;
1855 STp->buffer->buffer_bytes = 0;
1856 STp->buffer->read_pointer = 0;
1857 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1859 return 0;
1863 * ADRL 1.1 compatible "slow" space filemarks fwd version
1865 * Just scans for the filemark sequentially.
1867 static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1868 int mt_op, int mt_count)
1870 int cnt = 0;
1871 #if DEBUG
1872 char * name = tape_name(STp);
1874 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1875 #endif
1876 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1877 #if DEBUG
1878 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1879 #endif
1880 return (-EIO);
1882 while (1) {
1883 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1884 #if DEBUG
1885 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1886 #endif
1887 return (-EIO);
1889 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1890 cnt++;
1891 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1892 #if DEBUG
1893 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1894 #endif
1895 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1896 #if DEBUG
1897 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1898 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1899 #endif
1900 STp->eod_frame_ppos = STp->first_frame_position-1;
1902 return (-EIO);
1904 if (cnt == mt_count)
1905 break;
1906 STp->frame_in_buffer = 0;
1908 if (mt_op == MTFSF) {
1909 STp->frame_seq_number++;
1910 STp->frame_in_buffer = 0;
1911 STp->buffer->buffer_bytes = 0;
1912 STp->buffer->read_pointer = 0;
1913 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1915 return 0;
1919 * Fast linux specific version of OnStream FSF
1921 static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
1922 int mt_op, int mt_count)
1924 char * name = tape_name(STp);
1925 int cnt = 0,
1926 next_mark_ppos = -1;
1928 #if DEBUG
1929 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
1930 #endif
1931 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1932 #if DEBUG
1933 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1934 #endif
1935 return (-EIO);
1938 if (STp->linux_media_version >= 4) {
1940 * direct lookup in header filemark list
1942 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1943 if (STp->header_ok &&
1944 STp->header_cache != NULL &&
1945 (cnt + mt_count) < OS_FM_TAB_MAX &&
1946 (cnt + mt_count) < STp->filemark_cnt &&
1947 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1948 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1950 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1951 #if DEBUG
1952 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1953 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1954 STp->header_cache == NULL?"lack of header cache":"count out of range");
1955 else
1956 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1957 name, cnt,
1958 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1959 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1960 STp->buffer->aux->last_mark_ppos))?"match":"error",
1961 mt_count, next_mark_ppos);
1962 #endif
1963 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1964 #if DEBUG
1965 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1966 #endif
1967 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1968 } else {
1969 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1970 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1971 #if DEBUG
1972 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
1973 name);
1974 #endif
1975 return (-EIO);
1977 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1978 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1979 name, next_mark_ppos);
1980 return (-EIO);
1982 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1983 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
1984 name, cnt+mt_count, next_mark_ppos,
1985 ntohl(STp->buffer->aux->filemark_cnt));
1986 return (-EIO);
1989 } else {
1991 * Find nearest (usually previous) marker, then jump from marker to marker
1993 while (1) {
1994 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1995 break;
1996 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1997 #if DEBUG
1998 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1999 #endif
2000 return (-EIO);
2002 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2003 if (STp->first_mark_ppos == -1) {
2004 #if DEBUG
2005 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2006 #endif
2007 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2009 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2010 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2011 #if DEBUG
2012 printk(OSST_DEB_MSG
2013 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2014 name);
2015 #endif
2016 return (-EIO);
2018 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2019 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2020 name, STp->first_mark_ppos);
2021 return (-EIO);
2023 } else {
2024 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2025 return (-EIO);
2026 mt_count++;
2029 cnt++;
2030 while (cnt != mt_count) {
2031 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2032 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2033 #if DEBUG
2034 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2035 #endif
2036 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2038 #if DEBUG
2039 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2040 #endif
2041 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2042 cnt++;
2043 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2044 #if DEBUG
2045 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2046 name);
2047 #endif
2048 return (-EIO);
2050 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2051 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2052 name, next_mark_ppos);
2053 return (-EIO);
2057 if (mt_op == MTFSF) {
2058 STp->frame_seq_number++;
2059 STp->frame_in_buffer = 0;
2060 STp->buffer->buffer_bytes = 0;
2061 STp->buffer->read_pointer = 0;
2062 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2064 return 0;
2068 * In debug mode, we want to see as many errors as possible
2069 * to test the error recovery mechanism.
2071 #if DEBUG
2072 static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2074 unsigned char cmd[MAX_COMMAND_SIZE];
2075 struct osst_request * SRpnt = * aSRpnt;
2076 char * name = tape_name(STp);
2078 memset(cmd, 0, MAX_COMMAND_SIZE);
2079 cmd[0] = MODE_SELECT;
2080 cmd[1] = 0x10;
2081 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2083 (STp->buffer)->b_data[0] = cmd[4] - 1;
2084 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
2085 (STp->buffer)->b_data[2] = 0; /* Reserved */
2086 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
2087 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2088 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2089 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2090 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2092 if (debugging)
2093 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2095 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2096 *aSRpnt = SRpnt;
2098 if ((STp->buffer)->syscall_result)
2099 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2101 #endif
2104 static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2106 int result;
2107 int this_mark_ppos = STp->first_frame_position;
2108 int this_mark_lbn = STp->logical_blk_num;
2109 #if DEBUG
2110 char * name = tape_name(STp);
2111 #endif
2113 if (STp->raw) return 0;
2115 STp->write_type = OS_WRITE_NEW_MARK;
2116 #if DEBUG
2117 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2118 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2119 #endif
2120 STp->dirty = 1;
2121 result = osst_flush_write_buffer(STp, aSRpnt);
2122 result |= osst_flush_drive_buffer(STp, aSRpnt);
2123 STp->last_mark_ppos = this_mark_ppos;
2124 STp->last_mark_lbn = this_mark_lbn;
2125 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2126 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2127 if (STp->filemark_cnt++ == 0)
2128 STp->first_mark_ppos = this_mark_ppos;
2129 return result;
2132 static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2134 int result;
2135 #if DEBUG
2136 char * name = tape_name(STp);
2137 #endif
2139 if (STp->raw) return 0;
2141 STp->write_type = OS_WRITE_EOD;
2142 STp->eod_frame_ppos = STp->first_frame_position;
2143 #if DEBUG
2144 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2145 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2146 #endif
2147 STp->dirty = 1;
2149 result = osst_flush_write_buffer(STp, aSRpnt);
2150 result |= osst_flush_drive_buffer(STp, aSRpnt);
2151 STp->eod_frame_lfa = --(STp->frame_seq_number);
2152 return result;
2155 static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2157 char * name = tape_name(STp);
2159 #if DEBUG
2160 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2161 #endif
2162 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2163 osst_set_frame_position(STp, aSRpnt, where, 0);
2164 STp->write_type = OS_WRITE_FILLER;
2165 while (count--) {
2166 memcpy(STp->buffer->b_data, "Filler", 6);
2167 STp->buffer->buffer_bytes = 6;
2168 STp->dirty = 1;
2169 if (osst_flush_write_buffer(STp, aSRpnt)) {
2170 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2171 return (-EIO);
2174 #if DEBUG
2175 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2176 #endif
2177 return osst_flush_drive_buffer(STp, aSRpnt);
2180 static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2182 char * name = tape_name(STp);
2183 int result;
2185 #if DEBUG
2186 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2187 #endif
2188 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2189 osst_set_frame_position(STp, aSRpnt, where, 0);
2190 STp->write_type = OS_WRITE_HEADER;
2191 while (count--) {
2192 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2193 STp->buffer->buffer_bytes = sizeof(os_header_t);
2194 STp->dirty = 1;
2195 if (osst_flush_write_buffer(STp, aSRpnt)) {
2196 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2197 return (-EIO);
2200 result = osst_flush_drive_buffer(STp, aSRpnt);
2201 #if DEBUG
2202 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2203 #endif
2204 return result;
2207 static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2209 os_header_t * header;
2210 int result;
2211 char * name = tape_name(STp);
2213 #if DEBUG
2214 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2215 #endif
2216 if (STp->raw) return 0;
2218 if (STp->header_cache == NULL) {
2219 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2220 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2221 return (-ENOMEM);
2223 memset(STp->header_cache, 0, sizeof(os_header_t));
2224 #if DEBUG
2225 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2226 #endif
2228 if (STp->header_ok) STp->update_frame_cntr++;
2229 else STp->update_frame_cntr = 0;
2231 header = STp->header_cache;
2232 strcpy(header->ident_str, "ADR_SEQ");
2233 header->major_rev = 1;
2234 header->minor_rev = 4;
2235 header->ext_trk_tb_off = htons(17192);
2236 header->pt_par_num = 1;
2237 header->partition[0].partition_num = OS_DATA_PARTITION;
2238 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2239 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2240 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2241 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2242 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2243 header->cfg_col_width = htonl(20);
2244 header->dat_col_width = htonl(1500);
2245 header->qfa_col_width = htonl(0);
2246 header->ext_track_tb.nr_stream_part = 1;
2247 header->ext_track_tb.et_ent_sz = 32;
2248 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2249 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2250 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2251 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2252 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2253 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2254 header->dat_fm_tab.fm_part_num = 0;
2255 header->dat_fm_tab.fm_tab_ent_sz = 4;
2256 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2257 STp->filemark_cnt:OS_FM_TAB_MAX);
2259 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2260 if (STp->update_frame_cntr == 0)
2261 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2262 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2264 if (locate_eod) {
2265 #if DEBUG
2266 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2267 #endif
2268 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2270 if (result)
2271 printk(KERN_ERR "%s:E: Write header failed\n", name);
2272 else {
2273 memcpy(STp->application_sig, "LIN4", 4);
2274 STp->linux_media = 1;
2275 STp->linux_media_version = 4;
2276 STp->header_ok = 1;
2278 return result;
2281 static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2283 if (STp->header_cache != NULL)
2284 memset(STp->header_cache, 0, sizeof(os_header_t));
2286 STp->logical_blk_num = STp->frame_seq_number = 0;
2287 STp->frame_in_buffer = 0;
2288 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2289 STp->filemark_cnt = 0;
2290 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2291 return osst_write_header(STp, aSRpnt, 1);
2294 static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2296 char * name = tape_name(STp);
2297 os_header_t * header;
2298 os_aux_t * aux;
2299 char id_string[8];
2300 int linux_media_version,
2301 update_frame_cntr;
2303 if (STp->raw)
2304 return 1;
2306 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2307 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2308 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2309 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2310 if (osst_initiate_read (STp, aSRpnt)) {
2311 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2312 return 0;
2315 if (osst_read_frame(STp, aSRpnt, 180)) {
2316 #if DEBUG
2317 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2318 #endif
2319 return 0;
2321 header = (os_header_t *) STp->buffer->b_data; /* warning: only first segment addressable */
2322 aux = STp->buffer->aux;
2323 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2324 #if DEBUG
2325 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2326 #endif
2327 return 0;
2329 if (ntohl(aux->frame_seq_num) != 0 ||
2330 ntohl(aux->logical_blk_num) != 0 ||
2331 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2332 ntohl(aux->partition.first_frame_ppos) != 0 ||
2333 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2334 #if DEBUG
2335 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2336 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2337 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2338 ntohl(aux->partition.last_frame_ppos));
2339 #endif
2340 return 0;
2342 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2343 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2344 strlcpy(id_string, header->ident_str, 8);
2345 #if DEBUG
2346 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2347 #endif
2348 return 0;
2350 update_frame_cntr = ntohl(aux->update_frame_cntr);
2351 if (update_frame_cntr < STp->update_frame_cntr) {
2352 #if DEBUG
2353 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2354 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2355 #endif
2356 return 0;
2358 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2359 #if DEBUG
2360 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2361 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2362 header->minor_rev > 4 )? "Invalid" : "Warning:",
2363 header->major_rev, header->minor_rev);
2364 #endif
2365 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2366 return 0;
2368 #if DEBUG
2369 if (header->pt_par_num != 1)
2370 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2371 name, header->pt_par_num);
2372 #endif
2373 memcpy(id_string, aux->application_sig, 4);
2374 id_string[4] = 0;
2375 if (memcmp(id_string, "LIN", 3) == 0) {
2376 STp->linux_media = 1;
2377 linux_media_version = id_string[3] - '0';
2378 if (linux_media_version != 4)
2379 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2380 name, linux_media_version);
2381 } else {
2382 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2383 return 0;
2385 if (linux_media_version < STp->linux_media_version) {
2386 #if DEBUG
2387 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2388 name, ppos, linux_media_version);
2389 #endif
2390 return 0;
2392 if (linux_media_version > STp->linux_media_version) {
2393 #if DEBUG
2394 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2395 name, ppos, linux_media_version);
2396 #endif
2397 memcpy(STp->application_sig, id_string, 5);
2398 STp->linux_media_version = linux_media_version;
2399 STp->update_frame_cntr = -1;
2401 if (update_frame_cntr > STp->update_frame_cntr) {
2402 #if DEBUG
2403 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2404 name, ppos, update_frame_cntr);
2405 #endif
2406 if (STp->header_cache == NULL) {
2407 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2408 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2409 return 0;
2411 #if DEBUG
2412 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2413 #endif
2415 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2416 header = STp->header_cache; /* further accesses from cached (full) copy */
2418 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2419 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2420 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2421 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2422 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2423 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2424 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2425 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2426 STp->update_frame_cntr = update_frame_cntr;
2427 #if DEBUG
2428 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2429 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2430 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2431 STp->first_data_ppos,
2432 ntohl(header->partition[0].last_frame_ppos),
2433 ntohl(header->partition[0].eod_frame_ppos));
2434 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2435 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2436 #endif
2437 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2438 #if DEBUG
2439 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2440 #endif
2441 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2442 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2443 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2445 if (header->minor_rev == 4 &&
2446 (header->ext_trk_tb_off != htons(17192) ||
2447 header->partition[0].partition_num != OS_DATA_PARTITION ||
2448 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2449 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2450 header->cfg_col_width != htonl(20) ||
2451 header->dat_col_width != htonl(1500) ||
2452 header->qfa_col_width != htonl(0) ||
2453 header->ext_track_tb.nr_stream_part != 1 ||
2454 header->ext_track_tb.et_ent_sz != 32 ||
2455 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2456 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2457 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2458 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2459 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2460 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2461 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2462 header->dat_fm_tab.fm_tab_ent_cnt !=
2463 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2464 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2468 return 1;
2471 static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2473 int position, ppos;
2474 int first, last;
2475 int valid = 0;
2476 char * name = tape_name(STp);
2478 position = osst_get_frame_position(STp, aSRpnt);
2480 if (STp->raw) {
2481 STp->header_ok = STp->linux_media = 1;
2482 STp->linux_media_version = 0;
2483 return 1;
2485 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2486 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2487 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2488 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2489 #if DEBUG
2490 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2491 #endif
2493 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2494 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2496 first = position==10?0xbae: 5;
2497 last = position==10?0xbb3:10;
2499 for (ppos = first; ppos < last; ppos++)
2500 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2501 valid = 1;
2503 first = position==10? 5:0xbae;
2504 last = position==10?10:0xbb3;
2506 for (ppos = first; ppos < last; ppos++)
2507 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2508 valid = 1;
2510 if (!valid) {
2511 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2512 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2513 osst_set_frame_position(STp, aSRpnt, 10, 0);
2514 return 0;
2516 if (position <= STp->first_data_ppos) {
2517 position = STp->first_data_ppos;
2518 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2520 osst_set_frame_position(STp, aSRpnt, position, 0);
2521 STp->header_ok = 1;
2523 return 1;
2526 static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2528 int frame_position = STp->first_frame_position;
2529 int frame_seq_numbr = STp->frame_seq_number;
2530 int logical_blk_num = STp->logical_blk_num;
2531 int halfway_frame = STp->frame_in_buffer;
2532 int read_pointer = STp->buffer->read_pointer;
2533 int prev_mark_ppos = -1;
2534 int actual_mark_ppos, i, n;
2535 #if DEBUG
2536 char * name = tape_name(STp);
2538 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2539 #endif
2540 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2541 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2542 #if DEBUG
2543 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2544 #endif
2545 return (-EIO);
2547 if (STp->linux_media_version >= 4) {
2548 for (i=0; i<STp->filemark_cnt; i++)
2549 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2550 prev_mark_ppos = n;
2551 } else
2552 prev_mark_ppos = frame_position - 1; /* usually - we don't really know */
2553 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2554 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2555 if (frame_position != STp->first_frame_position ||
2556 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2557 prev_mark_ppos != actual_mark_ppos ) {
2558 #if DEBUG
2559 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2560 STp->first_frame_position, frame_position,
2561 STp->frame_seq_number + (halfway_frame?0:1),
2562 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2563 #endif
2564 return (-EIO);
2566 if (halfway_frame) {
2567 /* prepare buffer for append and rewrite on top of original */
2568 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2569 STp->buffer->buffer_bytes = read_pointer;
2570 STp->ps[STp->partition].rw = ST_WRITING;
2571 STp->dirty = 1;
2573 STp->frame_in_buffer = halfway_frame;
2574 STp->frame_seq_number = frame_seq_numbr;
2575 STp->logical_blk_num = logical_blk_num;
2576 return 0;
2579 /* Acc. to OnStream, the vers. numbering is the following:
2580 * X.XX for released versions (X=digit),
2581 * XXXY for unreleased versions (Y=letter)
2582 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2583 * This fn makes monoton numbers out of this scheme ...
2585 static unsigned int osst_parse_firmware_rev (const char * str)
2587 if (str[1] == '.') {
2588 return (str[0]-'0')*10000
2589 +(str[2]-'0')*1000
2590 +(str[3]-'0')*100;
2591 } else {
2592 return (str[0]-'0')*10000
2593 +(str[1]-'0')*1000
2594 +(str[2]-'0')*100 - 100
2595 +(str[3]-'@');
2600 * Configure the OnStream SCII tape drive for default operation
2602 static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2604 unsigned char cmd[MAX_COMMAND_SIZE];
2605 char * name = tape_name(STp);
2606 struct osst_request * SRpnt = * aSRpnt;
2607 osst_mode_parameter_header_t * header;
2608 osst_block_size_page_t * bs;
2609 osst_capabilities_page_t * cp;
2610 osst_tape_paramtr_page_t * prm;
2611 int drive_buffer_size;
2613 if (STp->ready != ST_READY) {
2614 #if DEBUG
2615 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2616 #endif
2617 return (-EIO);
2620 if (STp->os_fw_rev < 10600) {
2621 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2622 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2626 * Configure 32.5KB (data+aux) frame size.
2627 * Get the current frame size from the block size mode page
2629 memset(cmd, 0, MAX_COMMAND_SIZE);
2630 cmd[0] = MODE_SENSE;
2631 cmd[1] = 8;
2632 cmd[2] = BLOCK_SIZE_PAGE;
2633 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2635 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2636 if (SRpnt == NULL) {
2637 #if DEBUG
2638 printk(OSST_DEB_MSG "osst :D: Busy\n");
2639 #endif
2640 return (-EBUSY);
2642 *aSRpnt = SRpnt;
2643 if ((STp->buffer)->syscall_result != 0) {
2644 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2645 return (-EIO);
2648 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2649 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2651 #if DEBUG
2652 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2653 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2654 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2655 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2656 #endif
2659 * Configure default auto columns mode, 32.5KB transfer mode
2661 bs->one = 1;
2662 bs->play32 = 0;
2663 bs->play32_5 = 1;
2664 bs->record32 = 0;
2665 bs->record32_5 = 1;
2667 memset(cmd, 0, MAX_COMMAND_SIZE);
2668 cmd[0] = MODE_SELECT;
2669 cmd[1] = 0x10;
2670 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2672 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2673 *aSRpnt = SRpnt;
2674 if ((STp->buffer)->syscall_result != 0) {
2675 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2676 return (-EIO);
2679 #if DEBUG
2680 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2682 * In debug mode, we want to see as many errors as possible
2683 * to test the error recovery mechanism.
2685 osst_set_retries(STp, aSRpnt, 0);
2686 SRpnt = * aSRpnt;
2687 #endif
2690 * Set vendor name to 'LIN4' for "Linux support version 4".
2693 memset(cmd, 0, MAX_COMMAND_SIZE);
2694 cmd[0] = MODE_SELECT;
2695 cmd[1] = 0x10;
2696 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2698 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2699 header->medium_type = 0; /* Medium Type - ignoring */
2700 header->dsp = 0; /* Reserved */
2701 header->bdl = 0; /* Block Descriptor Length */
2703 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2704 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2705 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2706 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2707 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2708 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2709 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2710 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2712 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2713 *aSRpnt = SRpnt;
2715 if ((STp->buffer)->syscall_result != 0) {
2716 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2717 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2718 return (-EIO);
2721 memset(cmd, 0, MAX_COMMAND_SIZE);
2722 cmd[0] = MODE_SENSE;
2723 cmd[1] = 8;
2724 cmd[2] = CAPABILITIES_PAGE;
2725 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2727 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2728 *aSRpnt = SRpnt;
2730 if ((STp->buffer)->syscall_result != 0) {
2731 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2732 return (-EIO);
2735 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2736 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2737 sizeof(osst_mode_parameter_header_t) + header->bdl);
2739 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2741 memset(cmd, 0, MAX_COMMAND_SIZE);
2742 cmd[0] = MODE_SENSE;
2743 cmd[1] = 8;
2744 cmd[2] = TAPE_PARAMTR_PAGE;
2745 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2747 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2748 *aSRpnt = SRpnt;
2750 if ((STp->buffer)->syscall_result != 0) {
2751 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2752 return (-EIO);
2755 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2756 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2757 sizeof(osst_mode_parameter_header_t) + header->bdl);
2759 STp->density = prm->density;
2760 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2761 #if DEBUG
2762 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2763 name, STp->density, STp->capacity / 32, drive_buffer_size);
2764 #endif
2766 return 0;
2771 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2772 it messes up the block number). */
2773 static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2775 int result;
2776 char * name = tape_name(STp);
2778 #if DEBUG
2779 if (debugging)
2780 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2781 name, forward ? "forward" : "backward");
2782 #endif
2784 if (forward) {
2785 /* assumes that the filemark is already read by the drive, so this is low cost */
2786 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2788 else
2789 /* assumes this is only called if we just read the filemark! */
2790 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2792 if (result < 0)
2793 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2794 name, forward ? "forward" : "backward");
2796 return result;
2800 /* Get the tape position. */
2802 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2804 unsigned char scmd[MAX_COMMAND_SIZE];
2805 struct osst_request * SRpnt;
2806 int result = 0;
2807 char * name = tape_name(STp);
2809 /* KG: We want to be able to use it for checking Write Buffer availability
2810 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2811 char mybuf[24];
2812 char * olddata = STp->buffer->b_data;
2813 int oldsize = STp->buffer->buffer_size;
2815 if (STp->ready != ST_READY) return (-EIO);
2817 memset (scmd, 0, MAX_COMMAND_SIZE);
2818 scmd[0] = READ_POSITION;
2820 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2821 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2822 STp->timeout, MAX_RETRIES, 1);
2823 if (!SRpnt) {
2824 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2825 return (-EBUSY);
2827 *aSRpnt = SRpnt;
2829 if (STp->buffer->syscall_result)
2830 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
2832 if (result == -EINVAL)
2833 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2834 else {
2835 if (result == -EIO) { /* re-read position - this needs to preserve media errors */
2836 unsigned char mysense[16];
2837 memcpy (mysense, SRpnt->sense, 16);
2838 memset (scmd, 0, MAX_COMMAND_SIZE);
2839 scmd[0] = READ_POSITION;
2840 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2841 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2842 STp->timeout, MAX_RETRIES, 1);
2843 #if DEBUG
2844 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2845 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2846 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2847 #endif
2848 if (!STp->buffer->syscall_result)
2849 memcpy (SRpnt->sense, mysense, 16);
2850 else
2851 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2853 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2854 + ((STp->buffer)->b_data[5] << 16)
2855 + ((STp->buffer)->b_data[6] << 8)
2856 + (STp->buffer)->b_data[7];
2857 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2858 + ((STp->buffer)->b_data[ 9] << 16)
2859 + ((STp->buffer)->b_data[10] << 8)
2860 + (STp->buffer)->b_data[11];
2861 STp->cur_frames = (STp->buffer)->b_data[15];
2862 #if DEBUG
2863 if (debugging) {
2864 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2865 STp->first_frame_position, STp->last_frame_position,
2866 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2867 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2868 STp->cur_frames);
2870 #endif
2871 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2872 #if DEBUG
2873 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2874 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2875 #endif
2876 STp->first_frame_position = STp->last_frame_position;
2879 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2881 return (result == 0 ? STp->first_frame_position : result);
2885 /* Set the tape block */
2886 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2888 unsigned char scmd[MAX_COMMAND_SIZE];
2889 struct osst_request * SRpnt;
2890 struct st_partstat * STps;
2891 int result = 0;
2892 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2893 char * name = tape_name(STp);
2895 if (STp->ready != ST_READY) return (-EIO);
2897 STps = &(STp->ps[STp->partition]);
2899 if (ppos < 0 || ppos > STp->capacity) {
2900 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2901 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2902 result = (-EINVAL);
2905 do {
2906 #if DEBUG
2907 if (debugging)
2908 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2909 #endif
2910 memset (scmd, 0, MAX_COMMAND_SIZE);
2911 scmd[0] = SEEK_10;
2912 scmd[1] = 1;
2913 scmd[3] = (pp >> 24);
2914 scmd[4] = (pp >> 16);
2915 scmd[5] = (pp >> 8);
2916 scmd[6] = pp;
2917 if (skip)
2918 scmd[9] = 0x80;
2920 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
2921 MAX_RETRIES, 1);
2922 if (!SRpnt)
2923 return (-EBUSY);
2924 *aSRpnt = SRpnt;
2926 if ((STp->buffer)->syscall_result != 0) {
2927 #if DEBUG
2928 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
2929 name, STp->first_frame_position, pp);
2930 #endif
2931 result = (-EIO);
2933 if (pp != ppos)
2934 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
2935 } while ((pp != ppos) && (pp = ppos));
2936 STp->first_frame_position = STp->last_frame_position = ppos;
2937 STps->eof = ST_NOEOF;
2938 STps->at_sm = 0;
2939 STps->rw = ST_IDLE;
2940 STp->frame_in_buffer = 0;
2941 return result;
2944 static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
2946 struct st_partstat * STps = &(STp->ps[STp->partition]);
2947 int result = 0;
2949 if (STp->write_type != OS_WRITE_NEW_MARK) {
2950 /* true unless the user wrote the filemark for us */
2951 result = osst_flush_drive_buffer(STp, aSRpnt);
2952 if (result < 0) goto out;
2953 result = osst_write_filemark(STp, aSRpnt);
2954 if (result < 0) goto out;
2956 if (STps->drv_file >= 0)
2957 STps->drv_file++ ;
2958 STps->drv_block = 0;
2960 result = osst_write_eod(STp, aSRpnt);
2961 osst_write_header(STp, aSRpnt, leave_at_EOT);
2963 STps->eof = ST_FM;
2964 out:
2965 return result;
2968 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2970 /* Flush the write buffer (never need to write if variable blocksize). */
2971 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
2973 int offset, transfer, blks = 0;
2974 int result = 0;
2975 unsigned char cmd[MAX_COMMAND_SIZE];
2976 struct osst_request * SRpnt = *aSRpnt;
2977 struct st_partstat * STps;
2978 char * name = tape_name(STp);
2980 if ((STp->buffer)->writing) {
2981 if (SRpnt == (STp->buffer)->last_SRpnt)
2982 #if DEBUG
2983 { printk(OSST_DEB_MSG
2984 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
2985 #endif
2986 *aSRpnt = SRpnt = NULL;
2987 #if DEBUG
2988 } else if (SRpnt)
2989 printk(OSST_DEB_MSG
2990 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
2991 #endif
2992 osst_write_behind_check(STp);
2993 if ((STp->buffer)->syscall_result) {
2994 #if DEBUG
2995 if (debugging)
2996 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
2997 name, (STp->buffer)->midlevel_result);
2998 #endif
2999 if ((STp->buffer)->midlevel_result == INT_MAX)
3000 return (-ENOSPC);
3001 return (-EIO);
3005 result = 0;
3006 if (STp->dirty == 1) {
3008 STp->write_count++;
3009 STps = &(STp->ps[STp->partition]);
3010 STps->rw = ST_WRITING;
3011 offset = STp->buffer->buffer_bytes;
3012 blks = (offset + STp->block_size - 1) / STp->block_size;
3013 transfer = OS_FRAME_SIZE;
3015 if (offset < OS_DATA_SIZE)
3016 osst_zero_buffer_tail(STp->buffer);
3018 if (STp->poll)
3019 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3020 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3022 memset(cmd, 0, MAX_COMMAND_SIZE);
3023 cmd[0] = WRITE_6;
3024 cmd[1] = 1;
3025 cmd[4] = 1;
3027 switch (STp->write_type) {
3028 case OS_WRITE_DATA:
3029 #if DEBUG
3030 if (debugging)
3031 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3032 name, blks, STp->frame_seq_number,
3033 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3034 #endif
3035 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3036 STp->logical_blk_num - blks, STp->block_size, blks);
3037 break;
3038 case OS_WRITE_EOD:
3039 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3040 STp->logical_blk_num, 0, 0);
3041 break;
3042 case OS_WRITE_NEW_MARK:
3043 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3044 STp->logical_blk_num++, 0, blks=1);
3045 break;
3046 case OS_WRITE_HEADER:
3047 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3048 break;
3049 default: /* probably FILLER */
3050 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3052 #if DEBUG
3053 if (debugging)
3054 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3055 name, offset, transfer, blks);
3056 #endif
3058 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3059 STp->timeout, MAX_RETRIES, 1);
3060 *aSRpnt = SRpnt;
3061 if (!SRpnt)
3062 return (-EBUSY);
3064 if ((STp->buffer)->syscall_result != 0) {
3065 #if DEBUG
3066 printk(OSST_DEB_MSG
3067 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3068 name, SRpnt->sense[0], SRpnt->sense[2],
3069 SRpnt->sense[12], SRpnt->sense[13]);
3070 #endif
3071 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3072 (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3073 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3074 STp->dirty = 0;
3075 (STp->buffer)->buffer_bytes = 0;
3076 result = (-ENOSPC);
3078 else {
3079 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3080 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3081 result = (-EIO);
3084 STps->drv_block = (-1); /* FIXME - even if write recovery succeeds? */
3086 else {
3087 STp->first_frame_position++;
3088 STp->dirty = 0;
3089 (STp->buffer)->buffer_bytes = 0;
3092 #if DEBUG
3093 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3094 #endif
3095 return result;
3099 /* Flush the tape buffer. The tape will be positioned correctly unless
3100 seek_next is true. */
3101 static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3103 struct st_partstat * STps;
3104 int backspace = 0, result = 0;
3105 #if DEBUG
3106 char * name = tape_name(STp);
3107 #endif
3110 * If there was a bus reset, block further access
3111 * to this device.
3113 if( STp->pos_unknown)
3114 return (-EIO);
3116 if (STp->ready != ST_READY)
3117 return 0;
3119 STps = &(STp->ps[STp->partition]);
3120 if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
3121 STp->write_type = OS_WRITE_DATA;
3122 return osst_flush_write_buffer(STp, aSRpnt);
3124 if (STp->block_size == 0)
3125 return 0;
3127 #if DEBUG
3128 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3129 #endif
3131 if (!STp->can_bsr) {
3132 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3133 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3134 (STp->buffer)->buffer_bytes = 0;
3135 (STp->buffer)->read_pointer = 0;
3136 STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */
3139 if (!seek_next) {
3140 if (STps->eof == ST_FM_HIT) {
3141 result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3142 if (!result)
3143 STps->eof = ST_NOEOF;
3144 else {
3145 if (STps->drv_file >= 0)
3146 STps->drv_file++;
3147 STps->drv_block = 0;
3150 if (!result && backspace > 0) /* TODO -- design and run a test case for this */
3151 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3153 else if (STps->eof == ST_FM_HIT) {
3154 if (STps->drv_file >= 0)
3155 STps->drv_file++;
3156 STps->drv_block = 0;
3157 STps->eof = ST_NOEOF;
3160 return result;
3163 static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3165 unsigned char cmd[MAX_COMMAND_SIZE];
3166 struct osst_request * SRpnt;
3167 int blks;
3168 #if DEBUG
3169 char * name = tape_name(STp);
3170 #endif
3172 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3173 #if DEBUG
3174 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3175 #endif
3176 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3177 return (-EIO);
3179 /* error recovery may have bumped us past the header partition */
3180 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3181 #if DEBUG
3182 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3183 #endif
3184 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3188 if (STp->poll)
3189 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3190 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3191 return (-EIO);
3193 // osst_build_stats(STp, &SRpnt);
3195 STp->ps[STp->partition].rw = ST_WRITING;
3196 STp->write_type = OS_WRITE_DATA;
3198 memset(cmd, 0, MAX_COMMAND_SIZE);
3199 cmd[0] = WRITE_6;
3200 cmd[1] = 1;
3201 cmd[4] = 1; /* one frame at a time... */
3202 blks = STp->buffer->buffer_bytes / STp->block_size;
3203 #if DEBUG
3204 if (debugging)
3205 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3206 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3207 #endif
3208 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3209 STp->logical_blk_num - blks, STp->block_size, blks);
3211 #if DEBUG
3212 if (!synchronous)
3213 STp->write_pending = 1;
3214 #endif
3215 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3216 MAX_RETRIES, synchronous);
3217 if (!SRpnt)
3218 return (-EBUSY);
3219 *aSRpnt = SRpnt;
3221 if (synchronous) {
3222 if (STp->buffer->syscall_result != 0) {
3223 #if DEBUG
3224 if (debugging)
3225 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3226 #endif
3227 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3228 (SRpnt->sense[2] & 0x40)) {
3229 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3230 return (-ENOSPC);
3232 else {
3233 if (osst_write_error_recovery(STp, aSRpnt, 1))
3234 return (-EIO);
3237 else
3238 STp->first_frame_position++;
3241 STp->write_count++;
3243 return 0;
3246 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3247 static int do_door_lock(struct osst_tape * STp, int do_lock)
3249 int retval, cmd;
3251 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3252 #if DEBUG
3253 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3254 #endif
3255 retval = scsi_ioctl(STp->device, cmd, NULL);
3256 if (!retval) {
3257 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3259 else {
3260 STp->door_locked = ST_LOCK_FAILS;
3262 return retval;
3265 /* Set the internal state after reset */
3266 static void reset_state(struct osst_tape *STp)
3268 int i;
3269 struct st_partstat *STps;
3271 STp->pos_unknown = 0;
3272 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3273 STps = &(STp->ps[i]);
3274 STps->rw = ST_IDLE;
3275 STps->eof = ST_NOEOF;
3276 STps->at_sm = 0;
3277 STps->last_block_valid = 0;
3278 STps->drv_block = -1;
3279 STps->drv_file = -1;
3284 /* Entry points to osst */
3286 /* Write command */
3287 static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3289 ssize_t total, retval = 0;
3290 ssize_t i, do_count, blks, transfer;
3291 int write_threshold;
3292 int doing_write = 0;
3293 const char __user * b_point;
3294 struct osst_request * SRpnt = NULL;
3295 struct st_modedef * STm;
3296 struct st_partstat * STps;
3297 struct osst_tape * STp = filp->private_data;
3298 char * name = tape_name(STp);
3301 if (mutex_lock_interruptible(&STp->lock))
3302 return (-ERESTARTSYS);
3305 * If we are in the middle of error recovery, don't let anyone
3306 * else try and use this device. Also, if error recovery fails, it
3307 * may try and take the device offline, in which case all further
3308 * access to the device is prohibited.
3310 if( !scsi_block_when_processing_errors(STp->device) ) {
3311 retval = (-ENXIO);
3312 goto out;
3315 if (STp->ready != ST_READY) {
3316 if (STp->ready == ST_NO_TAPE)
3317 retval = (-ENOMEDIUM);
3318 else
3319 retval = (-EIO);
3320 goto out;
3322 STm = &(STp->modes[STp->current_mode]);
3323 if (!STm->defined) {
3324 retval = (-ENXIO);
3325 goto out;
3327 if (count == 0)
3328 goto out;
3331 * If there was a bus reset, block further access
3332 * to this device.
3334 if (STp->pos_unknown) {
3335 retval = (-EIO);
3336 goto out;
3339 #if DEBUG
3340 if (!STp->in_use) {
3341 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3342 retval = (-EIO);
3343 goto out;
3345 #endif
3347 if (STp->write_prot) {
3348 retval = (-EACCES);
3349 goto out;
3352 /* Write must be integral number of blocks */
3353 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3354 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3355 name, count, STp->block_size<1024?
3356 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3357 retval = (-EINVAL);
3358 goto out;
3361 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3362 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3363 name, STp->first_frame_position);
3364 retval = (-ENOSPC);
3365 goto out;
3368 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3369 STp->door_locked = ST_LOCKED_AUTO;
3371 STps = &(STp->ps[STp->partition]);
3373 if (STps->rw == ST_READING) {
3374 #if DEBUG
3375 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3376 STps->drv_file, STps->drv_block);
3377 #endif
3378 retval = osst_flush_buffer(STp, &SRpnt, 0);
3379 if (retval)
3380 goto out;
3381 STps->rw = ST_IDLE;
3383 if (STps->rw != ST_WRITING) {
3384 /* Are we totally rewriting this tape? */
3385 if (!STp->header_ok ||
3386 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3387 (STps->drv_file == 0 && STps->drv_block == 0)) {
3388 STp->wrt_pass_cntr++;
3389 #if DEBUG
3390 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3391 name, STp->wrt_pass_cntr);
3392 #endif
3393 osst_reset_header(STp, &SRpnt);
3394 STps->drv_file = STps->drv_block = 0;
3396 /* Do we know where we'll be writing on the tape? */
3397 else {
3398 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3399 STps->drv_file < 0 || STps->drv_block < 0) {
3400 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3401 STps->drv_file = STp->filemark_cnt;
3402 STps->drv_block = 0;
3404 else {
3405 /* We have no idea where the tape is positioned - give up */
3406 #if DEBUG
3407 printk(OSST_DEB_MSG
3408 "%s:D: Cannot write at indeterminate position.\n", name);
3409 #endif
3410 retval = (-EIO);
3411 goto out;
3414 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3415 STp->filemark_cnt = STps->drv_file;
3416 STp->last_mark_ppos =
3417 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3418 printk(KERN_WARNING
3419 "%s:W: Overwriting file %d with old write pass counter %d\n",
3420 name, STps->drv_file, STp->wrt_pass_cntr);
3421 printk(KERN_WARNING
3422 "%s:W: may lead to stale data being accepted on reading back!\n",
3423 name);
3424 #if DEBUG
3425 printk(OSST_DEB_MSG
3426 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3427 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3428 #endif
3431 STp->fast_open = 0;
3433 if (!STp->header_ok) {
3434 #if DEBUG
3435 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3436 #endif
3437 retval = (-EIO);
3438 goto out;
3441 if ((STp->buffer)->writing) {
3442 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3443 osst_write_behind_check(STp);
3444 if ((STp->buffer)->syscall_result) {
3445 #if DEBUG
3446 if (debugging)
3447 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3448 (STp->buffer)->midlevel_result);
3449 #endif
3450 if ((STp->buffer)->midlevel_result == INT_MAX)
3451 STps->eof = ST_EOM_OK;
3452 else
3453 STps->eof = ST_EOM_ERROR;
3456 if (STps->eof == ST_EOM_OK) {
3457 retval = (-ENOSPC);
3458 goto out;
3460 else if (STps->eof == ST_EOM_ERROR) {
3461 retval = (-EIO);
3462 goto out;
3465 /* Check the buffer readability in cases where copy_user might catch
3466 the problems after some tape movement. */
3467 if ((copy_from_user(&i, buf, 1) != 0 ||
3468 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3469 retval = (-EFAULT);
3470 goto out;
3473 if (!STm->do_buffer_writes) {
3474 write_threshold = 1;
3476 else
3477 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3478 if (!STm->do_async_writes)
3479 write_threshold--;
3481 total = count;
3482 #if DEBUG
3483 if (debugging)
3484 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3485 name, (int) count, STps->drv_file, STps->drv_block,
3486 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3487 #endif
3488 b_point = buf;
3489 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3491 doing_write = 1;
3492 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3493 (STp->buffer)->buffer_bytes;
3494 if (do_count > count)
3495 do_count = count;
3497 i = append_to_buffer(b_point, STp->buffer, do_count);
3498 if (i) {
3499 retval = i;
3500 goto out;
3503 blks = do_count / STp->block_size;
3504 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3506 i = osst_write_frame(STp, &SRpnt, 1);
3508 if (i == (-ENOSPC)) {
3509 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3510 if (transfer <= do_count) {
3511 filp->f_pos += do_count - transfer;
3512 count -= do_count - transfer;
3513 if (STps->drv_block >= 0) {
3514 STps->drv_block += (do_count - transfer) / STp->block_size;
3516 STps->eof = ST_EOM_OK;
3517 retval = (-ENOSPC); /* EOM within current request */
3518 #if DEBUG
3519 if (debugging)
3520 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3521 name, (int) transfer);
3522 #endif
3524 else {
3525 STps->eof = ST_EOM_ERROR;
3526 STps->drv_block = (-1); /* Too cautious? */
3527 retval = (-EIO); /* EOM for old data */
3528 #if DEBUG
3529 if (debugging)
3530 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3531 #endif
3534 else
3535 retval = i;
3537 if (retval < 0) {
3538 if (SRpnt != NULL) {
3539 osst_release_request(SRpnt);
3540 SRpnt = NULL;
3542 STp->buffer->buffer_bytes = 0;
3543 STp->dirty = 0;
3544 if (count < total)
3545 retval = total - count;
3546 goto out;
3549 filp->f_pos += do_count;
3550 b_point += do_count;
3551 count -= do_count;
3552 if (STps->drv_block >= 0) {
3553 STps->drv_block += blks;
3555 STp->buffer->buffer_bytes = 0;
3556 STp->dirty = 0;
3557 } /* end while write threshold exceeded */
3559 if (count != 0) {
3560 STp->dirty = 1;
3561 i = append_to_buffer(b_point, STp->buffer, count);
3562 if (i) {
3563 retval = i;
3564 goto out;
3566 blks = count / STp->block_size;
3567 STp->logical_blk_num += blks;
3568 if (STps->drv_block >= 0) {
3569 STps->drv_block += blks;
3571 filp->f_pos += count;
3572 count = 0;
3575 if (doing_write && (STp->buffer)->syscall_result != 0) {
3576 retval = (STp->buffer)->syscall_result;
3577 goto out;
3580 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3581 /* Schedule an asynchronous write */
3582 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3583 STp->block_size) * STp->block_size;
3584 STp->dirty = !((STp->buffer)->writing ==
3585 (STp->buffer)->buffer_bytes);
3587 i = osst_write_frame(STp, &SRpnt, 0);
3588 if (i < 0) {
3589 retval = (-EIO);
3590 goto out;
3592 SRpnt = NULL; /* Prevent releasing this request! */
3594 STps->at_sm &= (total == 0);
3595 if (total > 0)
3596 STps->eof = ST_NOEOF;
3598 retval = total;
3600 out:
3601 if (SRpnt != NULL) osst_release_request(SRpnt);
3603 mutex_unlock(&STp->lock);
3605 return retval;
3609 /* Read command */
3610 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3612 ssize_t total, retval = 0;
3613 ssize_t i, transfer;
3614 int special;
3615 struct st_modedef * STm;
3616 struct st_partstat * STps;
3617 struct osst_request * SRpnt = NULL;
3618 struct osst_tape * STp = filp->private_data;
3619 char * name = tape_name(STp);
3622 if (mutex_lock_interruptible(&STp->lock))
3623 return (-ERESTARTSYS);
3626 * If we are in the middle of error recovery, don't let anyone
3627 * else try and use this device. Also, if error recovery fails, it
3628 * may try and take the device offline, in which case all further
3629 * access to the device is prohibited.
3631 if( !scsi_block_when_processing_errors(STp->device) ) {
3632 retval = (-ENXIO);
3633 goto out;
3636 if (STp->ready != ST_READY) {
3637 if (STp->ready == ST_NO_TAPE)
3638 retval = (-ENOMEDIUM);
3639 else
3640 retval = (-EIO);
3641 goto out;
3643 STm = &(STp->modes[STp->current_mode]);
3644 if (!STm->defined) {
3645 retval = (-ENXIO);
3646 goto out;
3648 #if DEBUG
3649 if (!STp->in_use) {
3650 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3651 retval = (-EIO);
3652 goto out;
3654 #endif
3655 /* Must have initialized medium */
3656 if (!STp->header_ok) {
3657 retval = (-EIO);
3658 goto out;
3661 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3662 STp->door_locked = ST_LOCKED_AUTO;
3664 STps = &(STp->ps[STp->partition]);
3665 if (STps->rw == ST_WRITING) {
3666 retval = osst_flush_buffer(STp, &SRpnt, 0);
3667 if (retval)
3668 goto out;
3669 STps->rw = ST_IDLE;
3670 /* FIXME -- this may leave the tape without EOD and up2date headers */
3673 if ((count % STp->block_size) != 0) {
3674 printk(KERN_WARNING
3675 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3676 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3679 #if DEBUG
3680 if (debugging && STps->eof != ST_NOEOF)
3681 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3682 STps->eof, (STp->buffer)->buffer_bytes);
3683 #endif
3684 if ((STp->buffer)->buffer_bytes == 0 &&
3685 STps->eof >= ST_EOD_1) {
3686 if (STps->eof < ST_EOD) {
3687 STps->eof += 1;
3688 retval = 0;
3689 goto out;
3691 retval = (-EIO); /* EOM or Blank Check */
3692 goto out;
3695 /* Check the buffer writability before any tape movement. Don't alter
3696 buffer data. */
3697 if (copy_from_user(&i, buf, 1) != 0 ||
3698 copy_to_user (buf, &i, 1) != 0 ||
3699 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3700 copy_to_user (buf + count - 1, &i, 1) != 0) {
3701 retval = (-EFAULT);
3702 goto out;
3705 /* Loop until enough data in buffer or a special condition found */
3706 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3708 /* Get new data if the buffer is empty */
3709 if ((STp->buffer)->buffer_bytes == 0) {
3710 if (STps->eof == ST_FM_HIT)
3711 break;
3712 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3713 if (special < 0) { /* No need to continue read */
3714 STp->frame_in_buffer = 0;
3715 retval = special;
3716 goto out;
3720 /* Move the data from driver buffer to user buffer */
3721 if ((STp->buffer)->buffer_bytes > 0) {
3722 #if DEBUG
3723 if (debugging && STps->eof != ST_NOEOF)
3724 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3725 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3726 #endif
3727 /* force multiple of block size, note block_size may have been adjusted */
3728 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3729 (STp->buffer)->buffer_bytes : count - total)/
3730 STp->block_size) * STp->block_size;
3732 if (transfer == 0) {
3733 printk(KERN_WARNING
3734 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3735 name, count, STp->block_size < 1024?
3736 STp->block_size:STp->block_size/1024,
3737 STp->block_size<1024?'b':'k');
3738 break;
3740 i = from_buffer(STp->buffer, buf, transfer);
3741 if (i) {
3742 retval = i;
3743 goto out;
3745 STp->logical_blk_num += transfer / STp->block_size;
3746 STps->drv_block += transfer / STp->block_size;
3747 filp->f_pos += transfer;
3748 buf += transfer;
3749 total += transfer;
3752 if ((STp->buffer)->buffer_bytes == 0) {
3753 #if DEBUG
3754 if (debugging)
3755 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3756 name, STp->frame_seq_number);
3757 #endif
3758 STp->frame_in_buffer = 0;
3759 STp->frame_seq_number++; /* frame to look for next time */
3761 } /* for (total = 0, special = 0; total < count && !special; ) */
3763 /* Change the eof state if no data from tape or buffer */
3764 if (total == 0) {
3765 if (STps->eof == ST_FM_HIT) {
3766 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3767 STps->drv_block = 0;
3768 if (STps->drv_file >= 0)
3769 STps->drv_file++;
3771 else if (STps->eof == ST_EOD_1) {
3772 STps->eof = ST_EOD_2;
3773 if (STps->drv_block > 0 && STps->drv_file >= 0)
3774 STps->drv_file++;
3775 STps->drv_block = 0;
3777 else if (STps->eof == ST_EOD_2)
3778 STps->eof = ST_EOD;
3780 else if (STps->eof == ST_FM)
3781 STps->eof = ST_NOEOF;
3783 retval = total;
3785 out:
3786 if (SRpnt != NULL) osst_release_request(SRpnt);
3788 mutex_unlock(&STp->lock);
3790 return retval;
3794 /* Set the driver options */
3795 static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3797 printk(KERN_INFO
3798 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3799 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3800 STm->do_read_ahead);
3801 printk(KERN_INFO
3802 "%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3803 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3804 printk(KERN_INFO
3805 "%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3806 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3807 STp->scsi2_logical);
3808 printk(KERN_INFO
3809 "%s:I: sysv: %d\n", name, STm->sysv);
3810 #if DEBUG
3811 printk(KERN_INFO
3812 "%s:D: debugging: %d\n",
3813 name, debugging);
3814 #endif
3818 static int osst_set_options(struct osst_tape *STp, long options)
3820 int value;
3821 long code;
3822 struct st_modedef * STm;
3823 char * name = tape_name(STp);
3825 STm = &(STp->modes[STp->current_mode]);
3826 if (!STm->defined) {
3827 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3828 modes_defined = 1;
3829 #if DEBUG
3830 if (debugging)
3831 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3832 name, STp->current_mode);
3833 #endif
3836 code = options & MT_ST_OPTIONS;
3837 if (code == MT_ST_BOOLEANS) {
3838 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3839 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3840 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3841 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3842 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3843 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3844 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3845 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3846 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3847 if ((STp->device)->scsi_level >= SCSI_2)
3848 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3849 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3850 STm->sysv = (options & MT_ST_SYSV) != 0;
3851 #if DEBUG
3852 debugging = (options & MT_ST_DEBUGGING) != 0;
3853 #endif
3854 osst_log_options(STp, STm, name);
3856 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3857 value = (code == MT_ST_SETBOOLEANS);
3858 if ((options & MT_ST_BUFFER_WRITES) != 0)
3859 STm->do_buffer_writes = value;
3860 if ((options & MT_ST_ASYNC_WRITES) != 0)
3861 STm->do_async_writes = value;
3862 if ((options & MT_ST_DEF_WRITES) != 0)
3863 STm->defaults_for_writes = value;
3864 if ((options & MT_ST_READ_AHEAD) != 0)
3865 STm->do_read_ahead = value;
3866 if ((options & MT_ST_TWO_FM) != 0)
3867 STp->two_fm = value;
3868 if ((options & MT_ST_FAST_MTEOM) != 0)
3869 STp->fast_mteom = value;
3870 if ((options & MT_ST_AUTO_LOCK) != 0)
3871 STp->do_auto_lock = value;
3872 if ((options & MT_ST_CAN_BSR) != 0)
3873 STp->can_bsr = value;
3874 if ((options & MT_ST_NO_BLKLIMS) != 0)
3875 STp->omit_blklims = value;
3876 if ((STp->device)->scsi_level >= SCSI_2 &&
3877 (options & MT_ST_CAN_PARTITIONS) != 0)
3878 STp->can_partitions = value;
3879 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3880 STp->scsi2_logical = value;
3881 if ((options & MT_ST_SYSV) != 0)
3882 STm->sysv = value;
3883 #if DEBUG
3884 if ((options & MT_ST_DEBUGGING) != 0)
3885 debugging = value;
3886 #endif
3887 osst_log_options(STp, STm, name);
3889 else if (code == MT_ST_WRITE_THRESHOLD) {
3890 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3891 if (value < 1 || value > osst_buffer_size) {
3892 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3893 name, value);
3894 return (-EIO);
3896 STp->write_threshold = value;
3897 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3898 name, value);
3900 else if (code == MT_ST_DEF_BLKSIZE) {
3901 value = (options & ~MT_ST_OPTIONS);
3902 if (value == ~MT_ST_OPTIONS) {
3903 STm->default_blksize = (-1);
3904 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3906 else {
3907 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3908 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3909 name, value);
3910 return (-EINVAL);
3912 STm->default_blksize = value;
3913 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3914 name, STm->default_blksize);
3917 else if (code == MT_ST_TIMEOUTS) {
3918 value = (options & ~MT_ST_OPTIONS);
3919 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3920 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3921 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3922 (value & ~MT_ST_SET_LONG_TIMEOUT));
3924 else {
3925 STp->timeout = value * HZ;
3926 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3929 else if (code == MT_ST_DEF_OPTIONS) {
3930 code = (options & ~MT_ST_CLEAR_DEFAULT);
3931 value = (options & MT_ST_CLEAR_DEFAULT);
3932 if (code == MT_ST_DEF_DENSITY) {
3933 if (value == MT_ST_CLEAR_DEFAULT) {
3934 STm->default_density = (-1);
3935 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3937 else {
3938 STm->default_density = value & 0xff;
3939 printk(KERN_INFO "%s:I: Density default set to %x\n",
3940 name, STm->default_density);
3943 else if (code == MT_ST_DEF_DRVBUFFER) {
3944 if (value == MT_ST_CLEAR_DEFAULT) {
3945 STp->default_drvbuffer = 0xff;
3946 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3948 else {
3949 STp->default_drvbuffer = value & 7;
3950 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3951 name, STp->default_drvbuffer);
3954 else if (code == MT_ST_DEF_COMPRESSION) {
3955 if (value == MT_ST_CLEAR_DEFAULT) {
3956 STm->default_compression = ST_DONT_TOUCH;
3957 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3959 else {
3960 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3961 printk(KERN_INFO "%s:I: Compression default set to %x\n",
3962 name, (value & 1));
3966 else
3967 return (-EIO);
3969 return 0;
3973 /* Internal ioctl function */
3974 static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
3975 unsigned int cmd_in, unsigned long arg)
3977 int timeout;
3978 long ltmp;
3979 int i, ioctl_result;
3980 int chg_eof = 1;
3981 unsigned char cmd[MAX_COMMAND_SIZE];
3982 struct osst_request * SRpnt = * aSRpnt;
3983 struct st_partstat * STps;
3984 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3985 int datalen = 0, direction = DMA_NONE;
3986 char * name = tape_name(STp);
3988 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3989 if (STp->ready == ST_NO_TAPE)
3990 return (-ENOMEDIUM);
3991 else
3992 return (-EIO);
3994 timeout = STp->long_timeout;
3995 STps = &(STp->ps[STp->partition]);
3996 fileno = STps->drv_file;
3997 blkno = STps->drv_block;
3998 at_sm = STps->at_sm;
3999 frame_seq_numbr = STp->frame_seq_number;
4000 logical_blk_num = STp->logical_blk_num;
4002 memset(cmd, 0, MAX_COMMAND_SIZE);
4003 switch (cmd_in) {
4004 case MTFSFM:
4005 chg_eof = 0; /* Changed from the FSF after this */
4006 case MTFSF:
4007 if (STp->raw)
4008 return (-EIO);
4009 if (STp->linux_media)
4010 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4011 else
4012 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4013 if (fileno >= 0)
4014 fileno += arg;
4015 blkno = 0;
4016 at_sm &= (arg == 0);
4017 goto os_bypass;
4019 case MTBSF:
4020 chg_eof = 0; /* Changed from the FSF after this */
4021 case MTBSFM:
4022 if (STp->raw)
4023 return (-EIO);
4024 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4025 if (fileno >= 0)
4026 fileno -= arg;
4027 blkno = (-1); /* We can't know the block number */
4028 at_sm &= (arg == 0);
4029 goto os_bypass;
4031 case MTFSR:
4032 case MTBSR:
4033 #if DEBUG
4034 if (debugging)
4035 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4036 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4037 #endif
4038 if (cmd_in == MTFSR) {
4039 logical_blk_num += arg;
4040 if (blkno >= 0) blkno += arg;
4042 else {
4043 logical_blk_num -= arg;
4044 if (blkno >= 0) blkno -= arg;
4046 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4047 fileno = STps->drv_file;
4048 blkno = STps->drv_block;
4049 at_sm &= (arg == 0);
4050 goto os_bypass;
4052 case MTFSS:
4053 cmd[0] = SPACE;
4054 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4055 cmd[2] = (arg >> 16);
4056 cmd[3] = (arg >> 8);
4057 cmd[4] = arg;
4058 #if DEBUG
4059 if (debugging)
4060 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4061 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4062 #endif
4063 if (arg != 0) {
4064 blkno = fileno = (-1);
4065 at_sm = 1;
4067 break;
4068 case MTBSS:
4069 cmd[0] = SPACE;
4070 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4071 ltmp = (-arg);
4072 cmd[2] = (ltmp >> 16);
4073 cmd[3] = (ltmp >> 8);
4074 cmd[4] = ltmp;
4075 #if DEBUG
4076 if (debugging) {
4077 if (cmd[2] & 0x80)
4078 ltmp = 0xff000000;
4079 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4080 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4081 name, (-ltmp));
4083 #endif
4084 if (arg != 0) {
4085 blkno = fileno = (-1);
4086 at_sm = 1;
4088 break;
4089 case MTWEOF:
4090 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4091 STp->write_type = OS_WRITE_DATA;
4092 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4093 } else
4094 ioctl_result = 0;
4095 #if DEBUG
4096 if (debugging)
4097 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4098 #endif
4099 for (i=0; i<arg; i++)
4100 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4101 if (fileno >= 0) fileno += arg;
4102 if (blkno >= 0) blkno = 0;
4103 goto os_bypass;
4105 case MTWSM:
4106 if (STp->write_prot)
4107 return (-EACCES);
4108 if (!STp->raw)
4109 return 0;
4110 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
4111 if (cmd_in == MTWSM)
4112 cmd[1] = 2;
4113 cmd[2] = (arg >> 16);
4114 cmd[3] = (arg >> 8);
4115 cmd[4] = arg;
4116 timeout = STp->timeout;
4117 #if DEBUG
4118 if (debugging)
4119 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4120 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4121 #endif
4122 if (fileno >= 0)
4123 fileno += arg;
4124 blkno = 0;
4125 at_sm = (cmd_in == MTWSM);
4126 break;
4127 case MTOFFL:
4128 case MTLOAD:
4129 case MTUNLOAD:
4130 case MTRETEN:
4131 cmd[0] = START_STOP;
4132 cmd[1] = 1; /* Don't wait for completion */
4133 if (cmd_in == MTLOAD) {
4134 if (STp->ready == ST_NO_TAPE)
4135 cmd[4] = 4; /* open tray */
4136 else
4137 cmd[4] = 1; /* load */
4139 if (cmd_in == MTRETEN)
4140 cmd[4] = 3; /* retension then mount */
4141 if (cmd_in == MTOFFL)
4142 cmd[4] = 4; /* rewind then eject */
4143 timeout = STp->timeout;
4144 #if DEBUG
4145 if (debugging) {
4146 switch (cmd_in) {
4147 case MTUNLOAD:
4148 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4149 break;
4150 case MTLOAD:
4151 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4152 break;
4153 case MTRETEN:
4154 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4155 break;
4156 case MTOFFL:
4157 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4158 break;
4161 #endif
4162 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4163 break;
4164 case MTNOP:
4165 #if DEBUG
4166 if (debugging)
4167 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4168 #endif
4169 return 0; /* Should do something ? */
4170 break;
4171 case MTEOM:
4172 #if DEBUG
4173 if (debugging)
4174 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4175 #endif
4176 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4177 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4178 ioctl_result = -EIO;
4179 goto os_bypass;
4181 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4182 #if DEBUG
4183 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4184 #endif
4185 ioctl_result = -EIO;
4186 goto os_bypass;
4188 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4189 fileno = STp->filemark_cnt;
4190 blkno = at_sm = 0;
4191 goto os_bypass;
4193 case MTERASE:
4194 if (STp->write_prot)
4195 return (-EACCES);
4196 ioctl_result = osst_reset_header(STp, &SRpnt);
4197 i = osst_write_eod(STp, &SRpnt);
4198 if (i < ioctl_result) ioctl_result = i;
4199 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4200 if (i < ioctl_result) ioctl_result = i;
4201 fileno = blkno = at_sm = 0 ;
4202 goto os_bypass;
4204 case MTREW:
4205 cmd[0] = REZERO_UNIT; /* rewind */
4206 cmd[1] = 1;
4207 #if DEBUG
4208 if (debugging)
4209 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4210 #endif
4211 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4212 break;
4214 case MTSETBLK: /* Set block length */
4215 if ((STps->drv_block == 0 ) &&
4216 !STp->dirty &&
4217 ((STp->buffer)->buffer_bytes == 0) &&
4218 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4219 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4220 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4222 * Only allowed to change the block size if you opened the
4223 * device at the beginning of a file before writing anything.
4224 * Note, that when reading, changing block_size is futile,
4225 * as the size used when writing overrides it.
4227 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4228 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4229 name, STp->block_size);
4230 return 0;
4232 case MTSETDENSITY: /* Set tape density */
4233 case MTSETDRVBUFFER: /* Set drive buffering */
4234 case SET_DENS_AND_BLK: /* Set density and block size */
4235 chg_eof = 0;
4236 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4237 return (-EIO); /* Not allowed if data in buffer */
4238 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4239 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4240 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4241 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4242 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4243 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4244 return (-EINVAL);
4246 return 0; /* FIXME silently ignore if block size didn't change */
4248 default:
4249 return (-ENOSYS);
4252 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4254 ioctl_result = (STp->buffer)->syscall_result;
4256 if (!SRpnt) {
4257 #if DEBUG
4258 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4259 #endif
4260 return ioctl_result;
4263 if (!ioctl_result) { /* SCSI command successful */
4264 STp->frame_seq_number = frame_seq_numbr;
4265 STp->logical_blk_num = logical_blk_num;
4268 os_bypass:
4269 #if DEBUG
4270 if (debugging)
4271 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4272 #endif
4274 if (!ioctl_result) { /* success */
4276 if (cmd_in == MTFSFM) {
4277 fileno--;
4278 blkno--;
4280 if (cmd_in == MTBSFM) {
4281 fileno++;
4282 blkno++;
4284 STps->drv_block = blkno;
4285 STps->drv_file = fileno;
4286 STps->at_sm = at_sm;
4288 if (cmd_in == MTEOM)
4289 STps->eof = ST_EOD;
4290 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4291 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4292 STps->drv_block++;
4293 STp->logical_blk_num++;
4294 STp->frame_seq_number++;
4295 STp->frame_in_buffer = 0;
4296 STp->buffer->read_pointer = 0;
4298 else if (cmd_in == MTFSF)
4299 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4300 else if (chg_eof)
4301 STps->eof = ST_NOEOF;
4303 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4304 STp->rew_at_close = 0;
4305 else if (cmd_in == MTLOAD) {
4306 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4307 STp->ps[i].rw = ST_IDLE;
4308 STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4310 STp->partition = 0;
4313 if (cmd_in == MTREW) {
4314 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4315 if (ioctl_result > 0)
4316 ioctl_result = 0;
4319 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4320 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4321 STps->drv_file = STps->drv_block = -1;
4322 else
4323 STps->drv_file = STps->drv_block = 0;
4324 STps->eof = ST_NOEOF;
4325 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4326 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4327 STps->drv_file = STps->drv_block = -1;
4328 else {
4329 STps->drv_file = STp->filemark_cnt;
4330 STps->drv_block = 0;
4332 STps->eof = ST_EOD;
4333 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4334 STps->drv_file = STps->drv_block = (-1);
4335 STps->eof = ST_NOEOF;
4336 STp->header_ok = 0;
4337 } else if (cmd_in == MTERASE) {
4338 STp->header_ok = 0;
4339 } else if (SRpnt) { /* SCSI command was not completely successful. */
4340 if (SRpnt->sense[2] & 0x40) {
4341 STps->eof = ST_EOM_OK;
4342 STps->drv_block = 0;
4344 if (chg_eof)
4345 STps->eof = ST_NOEOF;
4347 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4348 STps->eof = ST_EOD;
4350 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4351 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4353 *aSRpnt = SRpnt;
4355 return ioctl_result;
4359 /* Open the device */
4360 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4362 unsigned short flags;
4363 int i, b_size, new_session = 0, retval = 0;
4364 unsigned char cmd[MAX_COMMAND_SIZE];
4365 struct osst_request * SRpnt = NULL;
4366 struct osst_tape * STp;
4367 struct st_modedef * STm;
4368 struct st_partstat * STps;
4369 char * name;
4370 int dev = TAPE_NR(inode);
4371 int mode = TAPE_MODE(inode);
4374 * We really want to do nonseekable_open(inode, filp); here, but some
4375 * versions of tar incorrectly call lseek on tapes and bail out if that
4376 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4378 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4380 write_lock(&os_scsi_tapes_lock);
4381 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4382 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4383 write_unlock(&os_scsi_tapes_lock);
4384 return (-ENXIO);
4387 name = tape_name(STp);
4389 if (STp->in_use) {
4390 write_unlock(&os_scsi_tapes_lock);
4391 #if DEBUG
4392 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4393 #endif
4394 return (-EBUSY);
4396 if (scsi_device_get(STp->device)) {
4397 write_unlock(&os_scsi_tapes_lock);
4398 #if DEBUG
4399 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4400 #endif
4401 return (-ENXIO);
4403 filp->private_data = STp;
4404 STp->in_use = 1;
4405 write_unlock(&os_scsi_tapes_lock);
4406 STp->rew_at_close = TAPE_REWIND(inode);
4408 if( !scsi_block_when_processing_errors(STp->device) ) {
4409 return -ENXIO;
4412 if (mode != STp->current_mode) {
4413 #if DEBUG
4414 if (debugging)
4415 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4416 name, STp->current_mode, mode);
4417 #endif
4418 new_session = 1;
4419 STp->current_mode = mode;
4421 STm = &(STp->modes[STp->current_mode]);
4423 flags = filp->f_flags;
4424 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4426 STp->raw = TAPE_IS_RAW(inode);
4427 if (STp->raw)
4428 STp->header_ok = 0;
4430 /* Allocate data segments for this device's tape buffer */
4431 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4432 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4433 retval = (-EOVERFLOW);
4434 goto err_out;
4436 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4437 for (i = 0, b_size = 0;
4438 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4439 b_size += STp->buffer->sg[i++].length);
4440 STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
4441 #if DEBUG
4442 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4443 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4444 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4445 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4446 #endif
4447 } else {
4448 STp->buffer->aux = NULL; /* this had better never happen! */
4449 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4450 retval = (-EIO);
4451 goto err_out;
4453 STp->buffer->writing = 0;
4454 STp->buffer->syscall_result = 0;
4455 STp->dirty = 0;
4456 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4457 STps = &(STp->ps[i]);
4458 STps->rw = ST_IDLE;
4460 STp->ready = ST_READY;
4461 #if DEBUG
4462 STp->nbr_waits = STp->nbr_finished = 0;
4463 #endif
4465 memset (cmd, 0, MAX_COMMAND_SIZE);
4466 cmd[0] = TEST_UNIT_READY;
4468 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4469 if (!SRpnt) {
4470 retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
4471 goto err_out;
4473 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4474 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4475 SRpnt->sense[12] == 4 ) {
4476 #if DEBUG
4477 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4478 #endif
4479 if (filp->f_flags & O_NONBLOCK) {
4480 retval = -EAGAIN;
4481 goto err_out;
4483 if (SRpnt->sense[13] == 2) { /* initialize command required (LOAD) */
4484 memset (cmd, 0, MAX_COMMAND_SIZE);
4485 cmd[0] = START_STOP;
4486 cmd[1] = 1;
4487 cmd[4] = 1;
4488 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4489 STp->timeout, MAX_RETRIES, 1);
4491 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4493 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4494 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4495 #if DEBUG
4496 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4497 #endif
4498 STp->header_ok = 0;
4500 for (i=0; i < 10; i++) {
4502 memset (cmd, 0, MAX_COMMAND_SIZE);
4503 cmd[0] = TEST_UNIT_READY;
4505 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4506 STp->timeout, MAX_RETRIES, 1);
4507 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4508 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4509 break;
4512 STp->pos_unknown = 0;
4513 STp->partition = STp->new_partition = 0;
4514 if (STp->can_partitions)
4515 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4516 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4517 STps = &(STp->ps[i]);
4518 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4519 STps->eof = ST_NOEOF;
4520 STps->at_sm = 0;
4521 STps->last_block_valid = 0;
4522 STps->drv_block = 0;
4523 STps->drv_file = 0 ;
4525 new_session = 1;
4526 STp->recover_count = 0;
4527 STp->abort_count = 0;
4530 * if we have valid headers from before, and the drive/tape seem untouched,
4531 * open without reconfiguring and re-reading the headers
4533 if (!STp->buffer->syscall_result && STp->header_ok &&
4534 !SRpnt->result && SRpnt->sense[0] == 0) {
4536 memset(cmd, 0, MAX_COMMAND_SIZE);
4537 cmd[0] = MODE_SENSE;
4538 cmd[1] = 8;
4539 cmd[2] = VENDOR_IDENT_PAGE;
4540 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4542 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4544 if (STp->buffer->syscall_result ||
4545 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4546 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4547 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4548 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4549 #if DEBUG
4550 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4551 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4552 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4553 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4554 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4555 #endif
4556 STp->header_ok = 0;
4558 i = STp->first_frame_position;
4559 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4560 if (STp->door_locked == ST_UNLOCKED) {
4561 if (do_door_lock(STp, 1))
4562 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4563 else
4564 STp->door_locked = ST_LOCKED_AUTO;
4566 if (!STp->frame_in_buffer) {
4567 STp->block_size = (STm->default_blksize > 0) ?
4568 STm->default_blksize : OS_DATA_SIZE;
4569 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4571 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4572 STp->fast_open = 1;
4573 osst_release_request(SRpnt);
4574 return 0;
4576 #if DEBUG
4577 if (i != STp->first_frame_position)
4578 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4579 name, i, STp->first_frame_position);
4580 #endif
4581 STp->header_ok = 0;
4583 STp->fast_open = 0;
4585 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4586 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4588 memset(cmd, 0, MAX_COMMAND_SIZE);
4589 cmd[0] = MODE_SELECT;
4590 cmd[1] = 0x10;
4591 cmd[4] = 4 + MODE_HEADER_LENGTH;
4593 (STp->buffer)->b_data[0] = cmd[4] - 1;
4594 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4595 (STp->buffer)->b_data[2] = 0; /* Reserved */
4596 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4597 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4598 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4599 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4600 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4602 #if DEBUG
4603 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4604 #endif
4605 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4607 STp->header_ok = 0;
4609 for (i=0; i < 10; i++) {
4611 memset (cmd, 0, MAX_COMMAND_SIZE);
4612 cmd[0] = TEST_UNIT_READY;
4614 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4615 STp->timeout, MAX_RETRIES, 1);
4616 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4617 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4618 break;
4620 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4621 STp->pos_unknown = 0;
4622 STp->partition = STp->new_partition = 0;
4623 if (STp->can_partitions)
4624 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4625 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4626 STps = &(STp->ps[i]);
4627 STps->rw = ST_IDLE;
4628 STps->eof = ST_NOEOF;
4629 STps->at_sm = 0;
4630 STps->last_block_valid = 0;
4631 STps->drv_block = 0;
4632 STps->drv_file = 0 ;
4634 new_session = 1;
4639 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4640 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4642 if ((STp->buffer)->syscall_result != 0) {
4643 if ((STp->device)->scsi_level >= SCSI_2 &&
4644 (SRpnt->sense[0] & 0x70) == 0x70 &&
4645 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4646 SRpnt->sense[12] == 0x3a) { /* Check ASC */
4647 STp->ready = ST_NO_TAPE;
4648 } else
4649 STp->ready = ST_NOT_READY;
4650 osst_release_request(SRpnt);
4651 SRpnt = NULL;
4652 STp->density = 0; /* Clear the erroneous "residue" */
4653 STp->write_prot = 0;
4654 STp->block_size = 0;
4655 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4656 STp->partition = STp->new_partition = 0;
4657 STp->door_locked = ST_UNLOCKED;
4658 return 0;
4661 osst_configure_onstream(STp, &SRpnt);
4663 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4664 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4665 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4666 STp->buffer->buffer_bytes =
4667 STp->buffer->read_pointer =
4668 STp->frame_in_buffer = 0;
4670 #if DEBUG
4671 if (debugging)
4672 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4673 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4674 (STp->buffer)->buffer_blocks);
4675 #endif
4677 if (STp->drv_write_prot) {
4678 STp->write_prot = 1;
4679 #if DEBUG
4680 if (debugging)
4681 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4682 #endif
4683 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4684 retval = (-EROFS);
4685 goto err_out;
4689 if (new_session) { /* Change the drive parameters for the new mode */
4690 #if DEBUG
4691 if (debugging)
4692 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4693 #endif
4694 STp->density_changed = STp->blksize_changed = 0;
4695 STp->compression_changed = 0;
4699 * properly position the tape and check the ADR headers
4701 if (STp->door_locked == ST_UNLOCKED) {
4702 if (do_door_lock(STp, 1))
4703 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4704 else
4705 STp->door_locked = ST_LOCKED_AUTO;
4708 osst_analyze_headers(STp, &SRpnt);
4710 osst_release_request(SRpnt);
4711 SRpnt = NULL;
4713 return 0;
4715 err_out:
4716 if (SRpnt != NULL)
4717 osst_release_request(SRpnt);
4718 normalize_buffer(STp->buffer);
4719 STp->header_ok = 0;
4720 STp->in_use = 0;
4721 scsi_device_put(STp->device);
4723 return retval;
4727 /* Flush the tape buffer before close */
4728 static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4730 int result = 0, result2;
4731 struct osst_tape * STp = filp->private_data;
4732 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4733 struct st_partstat * STps = &(STp->ps[STp->partition]);
4734 struct osst_request * SRpnt = NULL;
4735 char * name = tape_name(STp);
4737 if (file_count(filp) > 1)
4738 return 0;
4740 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4741 STp->write_type = OS_WRITE_DATA;
4742 result = osst_flush_write_buffer(STp, &SRpnt);
4743 if (result != 0 && result != (-ENOSPC))
4744 goto out;
4746 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4748 #if DEBUG
4749 if (debugging) {
4750 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4751 name, (long)(filp->f_pos));
4752 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4753 name, STp->nbr_waits, STp->nbr_finished);
4755 #endif
4756 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4757 #if DEBUG
4758 if (debugging)
4759 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4760 name, 1+STp->two_fm);
4761 #endif
4763 else if (!STp->rew_at_close) {
4764 STps = &(STp->ps[STp->partition]);
4765 if (!STm->sysv || STps->rw != ST_READING) {
4766 if (STp->can_bsr)
4767 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4768 else if (STps->eof == ST_FM_HIT) {
4769 result = cross_eof(STp, &SRpnt, 0);
4770 if (result) {
4771 if (STps->drv_file >= 0)
4772 STps->drv_file++;
4773 STps->drv_block = 0;
4774 STps->eof = ST_FM;
4776 else
4777 STps->eof = ST_NOEOF;
4780 else if ((STps->eof == ST_NOEOF &&
4781 !(result = cross_eof(STp, &SRpnt, 1))) ||
4782 STps->eof == ST_FM_HIT) {
4783 if (STps->drv_file >= 0)
4784 STps->drv_file++;
4785 STps->drv_block = 0;
4786 STps->eof = ST_FM;
4790 out:
4791 if (STp->rew_at_close) {
4792 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4793 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4794 if (result == 0 && result2 < 0)
4795 result = result2;
4797 if (SRpnt) osst_release_request(SRpnt);
4799 if (STp->abort_count || STp->recover_count) {
4800 printk(KERN_INFO "%s:I:", name);
4801 if (STp->abort_count)
4802 printk(" %d unrecovered errors", STp->abort_count);
4803 if (STp->recover_count)
4804 printk(" %d recovered errors", STp->recover_count);
4805 if (STp->write_count)
4806 printk(" in %d frames written", STp->write_count);
4807 if (STp->read_count)
4808 printk(" in %d frames read", STp->read_count);
4809 printk("\n");
4810 STp->recover_count = 0;
4811 STp->abort_count = 0;
4813 STp->write_count = 0;
4814 STp->read_count = 0;
4816 return result;
4820 /* Close the device and release it */
4821 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4823 int result = 0;
4824 struct osst_tape * STp = filp->private_data;
4826 if (STp->door_locked == ST_LOCKED_AUTO)
4827 do_door_lock(STp, 0);
4829 if (STp->raw)
4830 STp->header_ok = 0;
4832 normalize_buffer(STp->buffer);
4833 write_lock(&os_scsi_tapes_lock);
4834 STp->in_use = 0;
4835 write_unlock(&os_scsi_tapes_lock);
4837 scsi_device_put(STp->device);
4839 return result;
4843 /* The ioctl command */
4844 static int osst_ioctl(struct inode * inode,struct file * file,
4845 unsigned int cmd_in, unsigned long arg)
4847 int i, cmd_nr, cmd_type, blk, retval = 0;
4848 struct st_modedef * STm;
4849 struct st_partstat * STps;
4850 struct osst_request * SRpnt = NULL;
4851 struct osst_tape * STp = file->private_data;
4852 char * name = tape_name(STp);
4853 void __user * p = (void __user *)arg;
4855 if (mutex_lock_interruptible(&STp->lock))
4856 return -ERESTARTSYS;
4858 #if DEBUG
4859 if (debugging && !STp->in_use) {
4860 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4861 retval = (-EIO);
4862 goto out;
4864 #endif
4865 STm = &(STp->modes[STp->current_mode]);
4866 STps = &(STp->ps[STp->partition]);
4869 * If we are in the middle of error recovery, don't let anyone
4870 * else try and use this device. Also, if error recovery fails, it
4871 * may try and take the device offline, in which case all further
4872 * access to the device is prohibited.
4874 if( !scsi_block_when_processing_errors(STp->device) ) {
4875 retval = (-ENXIO);
4876 goto out;
4879 cmd_type = _IOC_TYPE(cmd_in);
4880 cmd_nr = _IOC_NR(cmd_in);
4881 #if DEBUG
4882 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4883 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4884 #endif
4885 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4886 struct mtop mtc;
4887 int auto_weof = 0;
4889 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4890 retval = (-EINVAL);
4891 goto out;
4894 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4895 if (i) {
4896 retval = (-EFAULT);
4897 goto out;
4900 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4901 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4902 retval = (-EPERM);
4903 goto out;
4906 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4907 retval = (-ENXIO);
4908 goto out;
4911 if (!STp->pos_unknown) {
4913 if (STps->eof == ST_FM_HIT) {
4914 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4915 mtc.mt_count -= 1;
4916 if (STps->drv_file >= 0)
4917 STps->drv_file += 1;
4919 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4920 mtc.mt_count += 1;
4921 if (STps->drv_file >= 0)
4922 STps->drv_file += 1;
4926 if (mtc.mt_op == MTSEEK) {
4927 /* Old position must be restored if partition will be changed */
4928 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4930 else {
4931 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
4932 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
4933 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
4934 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
4935 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
4936 mtc.mt_op == MTCOMPRESSION;
4938 i = osst_flush_buffer(STp, &SRpnt, i);
4939 if (i < 0) {
4940 retval = i;
4941 goto out;
4944 else {
4946 * If there was a bus reset, block further access
4947 * to this device. If the user wants to rewind the tape,
4948 * then reset the flag and allow access again.
4950 if(mtc.mt_op != MTREW &&
4951 mtc.mt_op != MTOFFL &&
4952 mtc.mt_op != MTRETEN &&
4953 mtc.mt_op != MTERASE &&
4954 mtc.mt_op != MTSEEK &&
4955 mtc.mt_op != MTEOM) {
4956 retval = (-EIO);
4957 goto out;
4959 reset_state(STp);
4960 /* remove this when the midlevel properly clears was_reset */
4961 STp->device->was_reset = 0;
4964 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
4965 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
4966 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
4967 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
4968 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
4971 * The user tells us to move to another position on the tape.
4972 * If we were appending to the tape content, that would leave
4973 * the tape without proper end, in that case write EOD and
4974 * update the header to reflect its position.
4976 #if DEBUG
4977 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
4978 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
4979 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
4980 STp->logical_blk_num, STps->drv_file, STps->drv_block );
4981 #endif
4982 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
4983 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
4984 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4985 i = osst_write_trailer(STp, &SRpnt,
4986 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4987 #if DEBUG
4988 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4989 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
4990 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
4991 #endif
4992 if (i < 0) {
4993 retval = i;
4994 goto out;
4997 STps->rw = ST_IDLE;
5000 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5001 do_door_lock(STp, 0); /* Ignore result! */
5003 if (mtc.mt_op == MTSETDRVBUFFER &&
5004 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5005 retval = osst_set_options(STp, mtc.mt_count);
5006 goto out;
5009 if (mtc.mt_op == MTSETPART) {
5010 if (mtc.mt_count >= STp->nbr_partitions)
5011 retval = -EINVAL;
5012 else {
5013 STp->new_partition = mtc.mt_count;
5014 retval = 0;
5016 goto out;
5019 if (mtc.mt_op == MTMKPART) {
5020 if (!STp->can_partitions) {
5021 retval = (-EINVAL);
5022 goto out;
5024 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5025 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5026 retval = i;
5027 goto out;
5029 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5030 STp->ps[i].rw = ST_IDLE;
5031 STp->ps[i].at_sm = 0;
5032 STp->ps[i].last_block_valid = 0;
5034 STp->partition = STp->new_partition = 0;
5035 STp->nbr_partitions = 1; /* Bad guess ?-) */
5036 STps->drv_block = STps->drv_file = 0;
5037 retval = 0;
5038 goto out;
5041 if (mtc.mt_op == MTSEEK) {
5042 if (STp->raw)
5043 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5044 else
5045 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5046 if (!STp->can_partitions)
5047 STp->ps[0].rw = ST_IDLE;
5048 retval = i;
5049 goto out;
5052 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5053 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5054 goto out;
5057 if (auto_weof)
5058 cross_eof(STp, &SRpnt, 0);
5060 if (mtc.mt_op == MTCOMPRESSION)
5061 retval = -EINVAL; /* OnStream drives don't have compression hardware */
5062 else
5063 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5064 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5065 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5066 goto out;
5069 if (!STm->defined) {
5070 retval = (-ENXIO);
5071 goto out;
5074 if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5075 retval = i;
5076 goto out;
5079 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5080 struct mtget mt_status;
5082 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5083 retval = (-EINVAL);
5084 goto out;
5087 mt_status.mt_type = MT_ISONSTREAM_SC;
5088 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5089 mt_status.mt_dsreg =
5090 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5091 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5092 mt_status.mt_blkno = STps->drv_block;
5093 mt_status.mt_fileno = STps->drv_file;
5094 if (STp->block_size != 0) {
5095 if (STps->rw == ST_WRITING)
5096 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5097 else if (STps->rw == ST_READING)
5098 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5099 STp->block_size - 1) / STp->block_size;
5102 mt_status.mt_gstat = 0;
5103 if (STp->drv_write_prot)
5104 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5105 if (mt_status.mt_blkno == 0) {
5106 if (mt_status.mt_fileno == 0)
5107 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5108 else
5109 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5111 mt_status.mt_resid = STp->partition;
5112 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5113 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5114 else if (STps->eof >= ST_EOM_OK)
5115 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5116 if (STp->density == 1)
5117 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5118 else if (STp->density == 2)
5119 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5120 else if (STp->density == 3)
5121 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5122 if (STp->ready == ST_READY)
5123 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5124 if (STp->ready == ST_NO_TAPE)
5125 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5126 if (STps->at_sm)
5127 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5128 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5129 STp->drv_buffer != 0)
5130 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5132 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5133 if (i) {
5134 retval = (-EFAULT);
5135 goto out;
5138 STp->recover_erreg = 0; /* Clear after read */
5139 retval = 0;
5140 goto out;
5141 } /* End of MTIOCGET */
5143 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5144 struct mtpos mt_pos;
5146 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5147 retval = (-EINVAL);
5148 goto out;
5150 if (STp->raw)
5151 blk = osst_get_frame_position(STp, &SRpnt);
5152 else
5153 blk = osst_get_sector(STp, &SRpnt);
5154 if (blk < 0) {
5155 retval = blk;
5156 goto out;
5158 mt_pos.mt_blkno = blk;
5159 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5160 if (i)
5161 retval = -EFAULT;
5162 goto out;
5164 if (SRpnt) osst_release_request(SRpnt);
5166 mutex_unlock(&STp->lock);
5168 return scsi_ioctl(STp->device, cmd_in, p);
5170 out:
5171 if (SRpnt) osst_release_request(SRpnt);
5173 mutex_unlock(&STp->lock);
5175 return retval;
5178 #ifdef CONFIG_COMPAT
5179 static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5181 struct osst_tape *STp = file->private_data;
5182 struct scsi_device *sdev = STp->device;
5183 int ret = -ENOIOCTLCMD;
5184 if (sdev->host->hostt->compat_ioctl) {
5186 ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5189 return ret;
5191 #endif
5195 /* Memory handling routines */
5197 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5198 static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5200 int i;
5201 gfp_t priority;
5202 struct osst_buffer *tb;
5204 if (from_initialization)
5205 priority = GFP_ATOMIC;
5206 else
5207 priority = GFP_KERNEL;
5209 i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5210 tb = kzalloc(i, priority);
5211 if (!tb) {
5212 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5213 return NULL;
5216 tb->sg_segs = tb->orig_sg_segs = 0;
5217 tb->use_sg = max_sg;
5218 tb->in_use = 1;
5219 tb->dma = need_dma;
5220 tb->buffer_size = 0;
5221 #if DEBUG
5222 if (debugging)
5223 printk(OSST_DEB_MSG
5224 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5225 i, max_sg, need_dma);
5226 #endif
5227 return tb;
5230 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5231 static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5233 int segs, nbr, max_segs, b_size, order, got;
5234 gfp_t priority;
5236 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5237 return 1;
5239 if (STbuffer->sg_segs) {
5240 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5241 normalize_buffer(STbuffer);
5243 /* See how many segments we can use -- need at least two */
5244 nbr = max_segs = STbuffer->use_sg;
5245 if (nbr <= 2)
5246 return 0;
5248 priority = GFP_KERNEL /* | __GFP_NOWARN */;
5249 if (need_dma)
5250 priority |= GFP_DMA;
5252 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5253 big enough to reach the goal (code assumes no segments in place) */
5254 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5255 STbuffer->sg[0].page = alloc_pages(priority, order);
5256 STbuffer->sg[0].offset = 0;
5257 if (STbuffer->sg[0].page != NULL) {
5258 STbuffer->sg[0].length = b_size;
5259 STbuffer->b_data = page_address(STbuffer->sg[0].page);
5260 break;
5263 if (STbuffer->sg[0].page == NULL) {
5264 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5265 return 0;
5267 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5268 for (segs=STbuffer->sg_segs=1, got=b_size;
5269 segs < max_segs && got < OS_FRAME_SIZE; ) {
5270 STbuffer->sg[segs].page =
5271 alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5272 STbuffer->sg[segs].offset = 0;
5273 if (STbuffer->sg[segs].page == NULL) {
5274 if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
5275 b_size /= 2; /* Large enough for the rest of the buffers */
5276 order--;
5277 continue;
5279 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5280 OS_FRAME_SIZE);
5281 #if DEBUG
5282 STbuffer->buffer_size = got;
5283 #endif
5284 normalize_buffer(STbuffer);
5285 return 0;
5287 STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size;
5288 got += STbuffer->sg[segs].length;
5289 STbuffer->buffer_size = got;
5290 STbuffer->sg_segs = ++segs;
5292 #if DEBUG
5293 if (debugging) {
5294 printk(OSST_DEB_MSG
5295 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5296 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5297 printk(OSST_DEB_MSG
5298 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5299 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5300 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5302 #endif
5304 return 1;
5308 /* Release the segments */
5309 static void normalize_buffer(struct osst_buffer *STbuffer)
5311 int i, order, b_size;
5313 for (i=0; i < STbuffer->sg_segs; i++) {
5315 for (b_size = PAGE_SIZE, order = 0;
5316 b_size < STbuffer->sg[i].length;
5317 b_size *= 2, order++);
5319 __free_pages(STbuffer->sg[i].page, order);
5320 STbuffer->buffer_size -= STbuffer->sg[i].length;
5322 #if DEBUG
5323 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5324 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5325 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5326 #endif
5327 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5331 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5332 negative error code. */
5333 static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5335 int i, cnt, res, offset;
5337 for (i=0, offset=st_bp->buffer_bytes;
5338 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5339 offset -= st_bp->sg[i].length;
5340 if (i == st_bp->sg_segs) { /* Should never happen */
5341 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5342 return (-EIO);
5344 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5345 cnt = st_bp->sg[i].length - offset < do_count ?
5346 st_bp->sg[i].length - offset : do_count;
5347 res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
5348 if (res)
5349 return (-EFAULT);
5350 do_count -= cnt;
5351 st_bp->buffer_bytes += cnt;
5352 ubp += cnt;
5353 offset = 0;
5355 if (do_count) { /* Should never happen */
5356 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5357 do_count);
5358 return (-EIO);
5360 return 0;
5364 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5365 negative error code. */
5366 static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5368 int i, cnt, res, offset;
5370 for (i=0, offset=st_bp->read_pointer;
5371 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5372 offset -= st_bp->sg[i].length;
5373 if (i == st_bp->sg_segs) { /* Should never happen */
5374 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5375 return (-EIO);
5377 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5378 cnt = st_bp->sg[i].length - offset < do_count ?
5379 st_bp->sg[i].length - offset : do_count;
5380 res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
5381 if (res)
5382 return (-EFAULT);
5383 do_count -= cnt;
5384 st_bp->buffer_bytes -= cnt;
5385 st_bp->read_pointer += cnt;
5386 ubp += cnt;
5387 offset = 0;
5389 if (do_count) { /* Should never happen */
5390 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5391 return (-EIO);
5393 return 0;
5396 /* Sets the tail of the buffer after fill point to zero.
5397 Returns zero (success) or negative error code. */
5398 static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5400 int i, offset, do_count, cnt;
5402 for (i = 0, offset = st_bp->buffer_bytes;
5403 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5404 offset -= st_bp->sg[i].length;
5405 if (i == st_bp->sg_segs) { /* Should never happen */
5406 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5407 return (-EIO);
5409 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5410 i < st_bp->sg_segs && do_count > 0; i++) {
5411 cnt = st_bp->sg[i].length - offset < do_count ?
5412 st_bp->sg[i].length - offset : do_count ;
5413 memset(page_address(st_bp->sg[i].page) + offset, 0, cnt);
5414 do_count -= cnt;
5415 offset = 0;
5417 if (do_count) { /* Should never happen */
5418 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5419 return (-EIO);
5421 return 0;
5424 /* Copy a osst 32K chunk of memory into the buffer.
5425 Returns zero (success) or negative error code. */
5426 static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5428 int i, cnt, do_count = OS_DATA_SIZE;
5430 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5431 cnt = st_bp->sg[i].length < do_count ?
5432 st_bp->sg[i].length : do_count ;
5433 memcpy(page_address(st_bp->sg[i].page), ptr, cnt);
5434 do_count -= cnt;
5435 ptr += cnt;
5437 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5438 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5439 do_count, i);
5440 return (-EIO);
5442 return 0;
5445 /* Copy a osst 32K chunk of memory from the buffer.
5446 Returns zero (success) or negative error code. */
5447 static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5449 int i, cnt, do_count = OS_DATA_SIZE;
5451 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5452 cnt = st_bp->sg[i].length < do_count ?
5453 st_bp->sg[i].length : do_count ;
5454 memcpy(ptr, page_address(st_bp->sg[i].page), cnt);
5455 do_count -= cnt;
5456 ptr += cnt;
5458 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5459 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5460 do_count, i);
5461 return (-EIO);
5463 return 0;
5467 /* Module housekeeping */
5469 static void validate_options (void)
5471 if (max_dev > 0)
5472 osst_max_dev = max_dev;
5473 if (write_threshold_kbs > 0)
5474 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5475 if (osst_write_threshold > osst_buffer_size)
5476 osst_write_threshold = osst_buffer_size;
5477 if (max_sg_segs >= OSST_FIRST_SG)
5478 osst_max_sg_segs = max_sg_segs;
5479 #if DEBUG
5480 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5481 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5482 #endif
5485 #ifndef MODULE
5486 /* Set the boot options. Syntax: osst=xxx,yyy,...
5487 where xxx is write threshold in 1024 byte blocks,
5488 and yyy is number of s/g segments to use. */
5489 static int __init osst_setup (char *str)
5491 int i, ints[5];
5492 char *stp;
5494 stp = get_options(str, ARRAY_SIZE(ints), ints);
5496 if (ints[0] > 0) {
5497 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5498 *parms[i].val = ints[i + 1];
5499 } else {
5500 while (stp != NULL) {
5501 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5502 int len = strlen(parms[i].name);
5503 if (!strncmp(stp, parms[i].name, len) &&
5504 (*(stp + len) == ':' || *(stp + len) == '=')) {
5505 *parms[i].val =
5506 simple_strtoul(stp + len + 1, NULL, 0);
5507 break;
5510 if (i >= ARRAY_SIZE(parms))
5511 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5512 stp);
5513 stp = strchr(stp, ',');
5514 if (stp)
5515 stp++;
5519 return 1;
5522 __setup("osst=", osst_setup);
5524 #endif
5526 static const struct file_operations osst_fops = {
5527 .owner = THIS_MODULE,
5528 .read = osst_read,
5529 .write = osst_write,
5530 .ioctl = osst_ioctl,
5531 #ifdef CONFIG_COMPAT
5532 .compat_ioctl = osst_compat_ioctl,
5533 #endif
5534 .open = os_scsi_tape_open,
5535 .flush = os_scsi_tape_flush,
5536 .release = os_scsi_tape_close,
5539 static int osst_supports(struct scsi_device * SDp)
5541 struct osst_support_data {
5542 char *vendor;
5543 char *model;
5544 char *rev;
5545 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5548 static struct osst_support_data support_list[] = {
5549 /* {"XXX", "Yy-", "", NULL}, example */
5550 SIGS_FROM_OSST,
5551 {NULL, }};
5553 struct osst_support_data *rp;
5555 /* We are willing to drive OnStream SC-x0 as well as the
5556 * * IDE, ParPort, FireWire, USB variants, if accessible by
5557 * * emulation layer (ide-scsi, usb-storage, ...) */
5559 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5560 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5561 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5562 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5563 return 1;
5564 return 0;
5568 * sysfs support for osst driver parameter information
5571 static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5573 return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5576 static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5578 static int osst_create_sysfs_files(struct device_driver *sysfs)
5580 return driver_create_file(sysfs, &driver_attr_version);
5583 static void osst_remove_sysfs_files(struct device_driver *sysfs)
5585 driver_remove_file(sysfs, &driver_attr_version);
5589 * sysfs support for accessing ADR header information
5592 static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
5594 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5595 ssize_t l = 0;
5597 if (STp && STp->header_ok && STp->linux_media)
5598 l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5599 return l;
5602 CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5604 static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
5606 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5607 ssize_t l = 0;
5609 if (STp && STp->header_ok && STp->linux_media)
5610 l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5611 return l;
5614 CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5616 static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
5618 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5619 ssize_t l = 0;
5621 if (STp && STp->header_ok && STp->linux_media)
5622 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5623 return l;
5626 CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5628 static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
5630 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5631 ssize_t l = 0;
5633 if (STp && STp->header_ok && STp->linux_media)
5634 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5635 return l;
5638 CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5640 static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
5642 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5643 ssize_t l = 0;
5645 if (STp && STp->header_ok && STp->linux_media)
5646 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5647 return l;
5650 CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5652 static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
5654 struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
5655 ssize_t l = 0;
5657 if (STp && STp->header_ok && STp->linux_media)
5658 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5659 return l;
5662 CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5664 static struct class *osst_sysfs_class;
5666 static int osst_sysfs_init(void)
5668 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5669 if (IS_ERR(osst_sysfs_class)) {
5670 printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5671 return PTR_ERR(osst_sysfs_class);
5674 return 0;
5677 static void osst_sysfs_destroy(dev_t dev)
5679 class_device_destroy(osst_sysfs_class, dev);
5682 static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5684 struct class_device *osst_class_member;
5685 int err;
5687 osst_class_member = class_device_create(osst_sysfs_class, NULL, dev,
5688 device, "%s", name);
5689 if (IS_ERR(osst_class_member)) {
5690 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5691 return PTR_ERR(osst_class_member);
5694 class_set_devdata(osst_class_member, STp);
5695 err = class_device_create_file(osst_class_member,
5696 &class_device_attr_ADR_rev);
5697 if (err)
5698 goto err_out;
5699 err = class_device_create_file(osst_class_member,
5700 &class_device_attr_media_version);
5701 if (err)
5702 goto err_out;
5703 err = class_device_create_file(osst_class_member,
5704 &class_device_attr_capacity);
5705 if (err)
5706 goto err_out;
5707 err = class_device_create_file(osst_class_member,
5708 &class_device_attr_BOT_frame);
5709 if (err)
5710 goto err_out;
5711 err = class_device_create_file(osst_class_member,
5712 &class_device_attr_EOD_frame);
5713 if (err)
5714 goto err_out;
5715 err = class_device_create_file(osst_class_member,
5716 &class_device_attr_file_count);
5717 if (err)
5718 goto err_out;
5720 return 0;
5722 err_out:
5723 osst_sysfs_destroy(dev);
5724 return err;
5727 static void osst_sysfs_cleanup(void)
5729 class_destroy(osst_sysfs_class);
5733 * osst startup / cleanup code
5736 static int osst_probe(struct device *dev)
5738 struct scsi_device * SDp = to_scsi_device(dev);
5739 struct osst_tape * tpnt;
5740 struct st_modedef * STm;
5741 struct st_partstat * STps;
5742 struct osst_buffer * buffer;
5743 struct gendisk * drive;
5744 int i, dev_num, err = -ENODEV;
5746 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5747 return -ENODEV;
5749 drive = alloc_disk(1);
5750 if (!drive) {
5751 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5752 return -ENODEV;
5755 /* if this is the first attach, build the infrastructure */
5756 write_lock(&os_scsi_tapes_lock);
5757 if (os_scsi_tapes == NULL) {
5758 os_scsi_tapes =
5759 (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
5760 GFP_ATOMIC);
5761 if (os_scsi_tapes == NULL) {
5762 write_unlock(&os_scsi_tapes_lock);
5763 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5764 goto out_put_disk;
5766 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5769 if (osst_nr_dev >= osst_max_dev) {
5770 write_unlock(&os_scsi_tapes_lock);
5771 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5772 goto out_put_disk;
5775 /* find a free minor number */
5776 for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++);
5777 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5778 dev_num = i;
5780 /* allocate a struct osst_tape for this device */
5781 tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5782 if (!tpnt) {
5783 write_unlock(&os_scsi_tapes_lock);
5784 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5785 goto out_put_disk;
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 mutex_init(&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_sysfs_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_sysfs_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);