1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27static const char * osst_version = "0.99.4";
28
29
30#define OSST_FW_NEED_POLL_MIN 10601
31#define OSST_FW_NEED_POLL_MAX 10704
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)
33
34#include <linux/module.h>
35
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/slab.h>
42#include <linux/init.h>
43#include <linux/string.h>
44#include <linux/errno.h>
45#include <linux/mtio.h>
46#include <linux/ioctl.h>
47#include <linux/fcntl.h>
48#include <linux/spinlock.h>
49#include <linux/vmalloc.h>
50#include <linux/blkdev.h>
51#include <linux/moduleparam.h>
52#include <linux/delay.h>
53#include <linux/jiffies.h>
54#include <linux/mutex.h>
55#include <asm/uaccess.h>
56#include <asm/dma.h>
57
58
59
60#define DEBUG 0
61
62
63
64
65#define OSST_DEB_MSG KERN_NOTICE
66
67#include <scsi/scsi.h>
68#include <scsi/scsi_dbg.h>
69#include <scsi/scsi_device.h>
70#include <scsi/scsi_driver.h>
71#include <scsi/scsi_eh.h>
72#include <scsi/scsi_host.h>
73#include <scsi/scsi_ioctl.h>
74
75#define ST_KILOBYTE 1024
76
77#include "st.h"
78#include "osst.h"
79#include "osst_options.h"
80#include "osst_detect.h"
81
82static DEFINE_MUTEX(osst_int_mutex);
83static int max_dev = 0;
84static int write_threshold_kbs = 0;
85static int max_sg_segs = 0;
86
87#ifdef MODULE
88MODULE_AUTHOR("Willem Riede");
89MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
90MODULE_LICENSE("GPL");
91MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
92MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
93
94module_param(max_dev, int, 0444);
95MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
96
97module_param(write_threshold_kbs, int, 0644);
98MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
99
100module_param(max_sg_segs, int, 0644);
101MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
102#else
103static struct osst_dev_parm {
104 char *name;
105 int *val;
106} parms[] __initdata = {
107 { "max_dev", &max_dev },
108 { "write_threshold_kbs", &write_threshold_kbs },
109 { "max_sg_segs", &max_sg_segs }
110};
111#endif
112
113
114#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
115#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116
117
118
119#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
120#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
121#endif
122
123#if DEBUG
124static int debugging = 1;
125
126
127#endif
128
129
130
131#define MAX_RETRIES 0
132
133#define NO_TAPE NOT_READY
134
135#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
136#define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
137#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
138
139#define OSST_TIMEOUT (200 * HZ)
140#define OSST_LONG_TIMEOUT (1800 * HZ)
141
142#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
143#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
144#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
145#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
146
147
148
149#define SET_DENS_AND_BLK 0x10001
150
151static int osst_buffer_size = OSST_BUFFER_SIZE;
152static int osst_write_threshold = OSST_WRITE_THRESHOLD;
153static int osst_max_sg_segs = OSST_MAX_SG;
154static int osst_max_dev = OSST_MAX_TAPES;
155static int osst_nr_dev;
156
157static struct osst_tape **os_scsi_tapes = NULL;
158static DEFINE_RWLOCK(os_scsi_tapes_lock);
159
160static int modes_defined = 0;
161
162static struct osst_buffer *new_tape_buffer(int, int, int);
163static int enlarge_buffer(struct osst_buffer *, int);
164static void normalize_buffer(struct osst_buffer *);
165static int append_to_buffer(const char __user *, struct osst_buffer *, int);
166static int from_buffer(struct osst_buffer *, char __user *, int);
167static int osst_zero_buffer_tail(struct osst_buffer *);
168static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
169static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
170
171static int osst_probe(struct device *);
172static int osst_remove(struct device *);
173
174static struct scsi_driver osst_template = {
175 .owner = THIS_MODULE,
176 .gendrv = {
177 .name = "osst",
178 .probe = osst_probe,
179 .remove = osst_remove,
180 }
181};
182
183static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
184 unsigned int cmd_in, unsigned long arg);
185
186static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
187
188static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
189
190static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
191
192static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
193
194static inline char *tape_name(struct osst_tape *tape)
195{
196 return tape->drive->disk_name;
197}
198
199
200
201
202
203static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
204{
205 const u8 *ucp;
206 const u8 *sense = SRpnt->sense;
207
208 s->have_sense = scsi_normalize_sense(SRpnt->sense,
209 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
210 s->flags = 0;
211
212 if (s->have_sense) {
213 s->deferred = 0;
214 s->remainder_valid =
215 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
216 switch (sense[0] & 0x7f) {
217 case 0x71:
218 s->deferred = 1;
219 case 0x70:
220 s->fixed_format = 1;
221 s->flags = sense[2] & 0xe0;
222 break;
223 case 0x73:
224 s->deferred = 1;
225 case 0x72:
226 s->fixed_format = 0;
227 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
228 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
229 break;
230 }
231 }
232}
233
234
235static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
236{
237 char *name = tape_name(STp);
238 int result = SRpnt->result;
239 u8 * sense = SRpnt->sense, scode;
240#if DEBUG
241 const char *stp;
242#endif
243 struct st_cmdstatus *cmdstatp;
244
245 if (!result)
246 return 0;
247
248 cmdstatp = &STp->buffer->cmdstat;
249 osst_analyze_sense(SRpnt, cmdstatp);
250
251 if (cmdstatp->have_sense)
252 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
253 else
254 scode = 0;
255#if DEBUG
256 if (debugging) {
257 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
258 name, result,
259 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
260 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
261 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
262 name, scode, sense[12], sense[13]);
263 if (cmdstatp->have_sense)
264 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
265 }
266 else
267#endif
268 if (cmdstatp->have_sense && (
269 scode != NO_SENSE &&
270 scode != RECOVERED_ERROR &&
271
272 scode != BLANK_CHECK &&
273 scode != VOLUME_OVERFLOW &&
274 SRpnt->cmd[0] != MODE_SENSE &&
275 SRpnt->cmd[0] != TEST_UNIT_READY)) {
276 if (cmdstatp->have_sense) {
277 printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
278 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
279 }
280 else {
281 static int notyetprinted = 1;
282
283 printk(KERN_WARNING
284 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
285 name, result, driver_byte(result),
286 host_byte(result));
287 if (notyetprinted) {
288 notyetprinted = 0;
289 printk(KERN_INFO
290 "%s:I: This warning may be caused by your scsi controller,\n", name);
291 printk(KERN_INFO
292 "%s:I: it has been reported with some Buslogic cards.\n", name);
293 }
294 }
295 }
296 STp->pos_unknown |= STp->device->was_reset;
297
298 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
299 STp->recover_count++;
300 STp->recover_erreg++;
301#if DEBUG
302 if (debugging) {
303 if (SRpnt->cmd[0] == READ_6)
304 stp = "read";
305 else if (SRpnt->cmd[0] == WRITE_6)
306 stp = "write";
307 else
308 stp = "ioctl";
309 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
310 STp->recover_count);
311 }
312#endif
313 if ((sense[2] & 0xe0) == 0)
314 return 0;
315 }
316 return (-EIO);
317}
318
319
320
321static void osst_end_async(struct request *req, int update)
322{
323 struct osst_request *SRpnt = req->end_io_data;
324 struct osst_tape *STp = SRpnt->stp;
325 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
326
327 STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
328#if DEBUG
329 STp->write_pending = 0;
330#endif
331 if (SRpnt->waiting)
332 complete(SRpnt->waiting);
333
334 if (SRpnt->bio) {
335 kfree(mdata->pages);
336 blk_rq_unmap_user(SRpnt->bio);
337 }
338
339 __blk_put_request(req->q, req);
340}
341
342
343static struct osst_request *osst_allocate_request(void)
344{
345 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
346}
347
348static void osst_release_request(struct osst_request *streq)
349{
350 kfree(streq);
351}
352
353static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
354 int cmd_len, int data_direction, void *buffer, unsigned bufflen,
355 int use_sg, int timeout, int retries)
356{
357 struct request *req;
358 struct page **pages = NULL;
359 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
360
361 int err = 0;
362 int write = (data_direction == DMA_TO_DEVICE);
363
364 req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
365 if (!req)
366 return DRIVER_ERROR << 24;
367
368 req->cmd_type = REQ_TYPE_BLOCK_PC;
369 req->cmd_flags |= REQ_QUIET;
370
371 SRpnt->bio = NULL;
372
373 if (use_sg) {
374 struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
375 int i;
376
377 pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
378 if (!pages)
379 goto free_req;
380
381 for_each_sg(sgl, sg, use_sg, i)
382 pages[i] = sg_page(sg);
383
384 mdata->null_mapped = 1;
385
386 mdata->page_order = get_order(sgl[0].length);
387 mdata->nr_entries =
388 DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
389 mdata->offset = 0;
390
391 err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
392 if (err) {
393 kfree(pages);
394 goto free_req;
395 }
396 SRpnt->bio = req->bio;
397 mdata->pages = pages;
398
399 } else if (bufflen) {
400 err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
401 if (err)
402 goto free_req;
403 }
404
405 req->cmd_len = cmd_len;
406 memset(req->cmd, 0, BLK_MAX_CDB);
407 memcpy(req->cmd, cmd, req->cmd_len);
408 req->sense = SRpnt->sense;
409 req->sense_len = 0;
410 req->timeout = timeout;
411 req->retries = retries;
412 req->end_io_data = SRpnt;
413
414 blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
415 return 0;
416free_req:
417 blk_put_request(req);
418 return DRIVER_ERROR << 24;
419}
420
421
422
423
424static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
425 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
426{
427 unsigned char *bp;
428 unsigned short use_sg;
429#ifdef OSST_INJECT_ERRORS
430 static int inject = 0;
431 static int repeat = 0;
432#endif
433 struct completion *waiting;
434
435
436 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
437 printk(KERN_ERR "%s: Async command already active.\n",
438 tape_name(STp));
439 if (signal_pending(current))
440 (STp->buffer)->syscall_result = (-EINTR);
441 else
442 (STp->buffer)->syscall_result = (-EBUSY);
443 return NULL;
444 }
445
446 if (SRpnt == NULL) {
447 SRpnt = osst_allocate_request();
448 if (SRpnt == NULL) {
449 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
450 tape_name(STp));
451 if (signal_pending(current))
452 (STp->buffer)->syscall_result = (-EINTR);
453 else
454 (STp->buffer)->syscall_result = (-EBUSY);
455 return NULL;
456 }
457 SRpnt->stp = STp;
458 }
459
460
461
462 if (!do_wait)
463 (STp->buffer)->last_SRpnt = SRpnt;
464
465 waiting = &STp->wait;
466 init_completion(waiting);
467 SRpnt->waiting = waiting;
468
469 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
470 if (use_sg) {
471 bp = (char *)&(STp->buffer->sg[0]);
472 if (STp->buffer->sg_segs < use_sg)
473 use_sg = STp->buffer->sg_segs;
474 }
475 else
476 bp = (STp->buffer)->b_data;
477
478 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
479 STp->buffer->cmdstat.have_sense = 0;
480 STp->buffer->syscall_result = 0;
481
482 if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
483 use_sg, timeout, retries))
484
485 (STp->buffer)->syscall_result = (-EBUSY);
486 else if (do_wait) {
487 wait_for_completion(waiting);
488 SRpnt->waiting = NULL;
489 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
490#ifdef OSST_INJECT_ERRORS
491 if (STp->buffer->syscall_result == 0 &&
492 cmd[0] == READ_6 &&
493 cmd[4] &&
494 ( (++ inject % 83) == 29 ||
495 (STp->first_frame_position == 240
496 &&
497 ++repeat < 3))) {
498 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
499 STp->buffer->last_result_fatal = 1;
500 }
501#endif
502 }
503 return SRpnt;
504}
505
506
507
508static void osst_write_behind_check(struct osst_tape *STp)
509{
510 struct osst_buffer * STbuffer;
511
512 STbuffer = STp->buffer;
513
514#if DEBUG
515 if (STp->write_pending)
516 STp->nbr_waits++;
517 else
518 STp->nbr_finished++;
519#endif
520 wait_for_completion(&(STp->wait));
521 STp->buffer->last_SRpnt->waiting = NULL;
522
523 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
524
525 if (STp->buffer->syscall_result)
526 STp->buffer->syscall_result =
527 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
528 else
529 STp->first_frame_position++;
530
531 osst_release_request(STp->buffer->last_SRpnt);
532
533 if (STbuffer->writing < STbuffer->buffer_bytes)
534 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
535
536 STbuffer->last_SRpnt = NULL;
537 STbuffer->buffer_bytes -= STbuffer->writing;
538 STbuffer->writing = 0;
539
540 return;
541}
542
543
544
545
546
547
548
549static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
550 int logical_blk_num, int blk_sz, int blk_cnt)
551{
552 os_aux_t *aux = STp->buffer->aux;
553 os_partition_t *par = &aux->partition;
554 os_dat_t *dat = &aux->dat;
555
556 if (STp->raw) return;
557
558 memset(aux, 0, sizeof(*aux));
559 aux->format_id = htonl(0);
560 memcpy(aux->application_sig, "LIN4", 4);
561 aux->hdwr = htonl(0);
562 aux->frame_type = frame_type;
563
564 switch (frame_type) {
565 case OS_FRAME_TYPE_HEADER:
566 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
567 par->partition_num = OS_CONFIG_PARTITION;
568 par->par_desc_ver = OS_PARTITION_VERSION;
569 par->wrt_pass_cntr = htons(0xffff);
570
571 par->first_frame_ppos = htonl(0);
572 par->last_frame_ppos = htonl(0xbb7);
573 aux->frame_seq_num = htonl(0);
574 aux->logical_blk_num_high = htonl(0);
575 aux->logical_blk_num = htonl(0);
576 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
577 break;
578 case OS_FRAME_TYPE_DATA:
579 case OS_FRAME_TYPE_MARKER:
580 dat->dat_sz = 8;
581 dat->reserved1 = 0;
582 dat->entry_cnt = 1;
583 dat->reserved3 = 0;
584 dat->dat_list[0].blk_sz = htonl(blk_sz);
585 dat->dat_list[0].blk_cnt = htons(blk_cnt);
586 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
587 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
588 dat->dat_list[0].reserved = 0;
589 case OS_FRAME_TYPE_EOD:
590 aux->update_frame_cntr = htonl(0);
591 par->partition_num = OS_DATA_PARTITION;
592 par->par_desc_ver = OS_PARTITION_VERSION;
593 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
594 par->first_frame_ppos = htonl(STp->first_data_ppos);
595 par->last_frame_ppos = htonl(STp->capacity);
596 aux->frame_seq_num = htonl(frame_seq_number);
597 aux->logical_blk_num_high = htonl(0);
598 aux->logical_blk_num = htonl(logical_blk_num);
599 break;
600 default: ;
601 }
602 aux->filemark_cnt = htonl(STp->filemark_cnt);
603 aux->phys_fm = htonl(0xffffffff);
604 aux->last_mark_ppos = htonl(STp->last_mark_ppos);
605 aux->last_mark_lbn = htonl(STp->last_mark_lbn);
606}
607
608
609
610
611static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
612{
613 char * name = tape_name(STp);
614 os_aux_t * aux = STp->buffer->aux;
615 os_partition_t * par = &(aux->partition);
616 struct st_partstat * STps = &(STp->ps[STp->partition]);
617 int blk_cnt, blk_sz, i;
618
619 if (STp->raw) {
620 if (STp->buffer->syscall_result) {
621 for (i=0; i < STp->buffer->sg_segs; i++)
622 memset(page_address(sg_page(&STp->buffer->sg[i])),
623 0, STp->buffer->sg[i].length);
624 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
625 } else
626 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
627 return 1;
628 }
629 if (STp->buffer->syscall_result) {
630#if DEBUG
631 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
632#endif
633 return 0;
634 }
635 if (ntohl(aux->format_id) != 0) {
636#if DEBUG
637 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
638#endif
639 goto err_out;
640 }
641 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
642 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
643#if DEBUG
644 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
645#endif
646 goto err_out;
647 }
648 if (par->partition_num != OS_DATA_PARTITION) {
649 if (!STp->linux_media || STp->linux_media_version != 2) {
650#if DEBUG
651 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
652 name, par->partition_num);
653#endif
654 goto err_out;
655 }
656 }
657 if (par->par_desc_ver != OS_PARTITION_VERSION) {
658#if DEBUG
659 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
660#endif
661 goto err_out;
662 }
663 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
664#if DEBUG
665 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
666 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
667#endif
668 goto err_out;
669 }
670 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
671 aux->frame_type != OS_FRAME_TYPE_EOD &&
672 aux->frame_type != OS_FRAME_TYPE_MARKER) {
673 if (!quiet) {
674#if DEBUG
675 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
676#endif
677 }
678 goto err_out;
679 }
680 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
681 STp->first_frame_position < STp->eod_frame_ppos) {
682 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
683 STp->first_frame_position);
684 goto err_out;
685 }
686 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
687 if (!quiet) {
688#if DEBUG
689 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
690 name, ntohl(aux->frame_seq_num), frame_seq_number);
691#endif
692 }
693 goto err_out;
694 }
695 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
696 STps->eof = ST_FM_HIT;
697
698 i = ntohl(aux->filemark_cnt);
699 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
700 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
701#if DEBUG
702 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
703 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
704 i, STp->first_frame_position - 1);
705#endif
706 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
707 if (i >= STp->filemark_cnt)
708 STp->filemark_cnt = i+1;
709 }
710 }
711 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
712 STps->eof = ST_EOD_1;
713 STp->frame_in_buffer = 1;
714 }
715 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
716 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
717 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
718 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
719 STp->buffer->read_pointer = 0;
720 STp->frame_in_buffer = 1;
721
722
723 if (STp->block_size != blk_sz && blk_sz > 0) {
724 printk(KERN_INFO
725 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
726 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
727 STp->block_size<1024?STp->block_size:STp->block_size/1024,
728 STp->block_size<1024?'b':'k');
729 STp->block_size = blk_sz;
730 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
731 }
732 STps->eof = ST_NOEOF;
733 }
734 STp->frame_seq_number = ntohl(aux->frame_seq_num);
735 STp->logical_blk_num = ntohl(aux->logical_blk_num);
736 return 1;
737
738err_out:
739 if (STp->read_error_frame == 0)
740 STp->read_error_frame = STp->first_frame_position - 1;
741 return 0;
742}
743
744
745
746
747static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
748 unsigned timeout, int initial_delay)
749{
750 unsigned char cmd[MAX_COMMAND_SIZE];
751 struct osst_request * SRpnt;
752 unsigned long startwait = jiffies;
753#if DEBUG
754 int dbg = debugging;
755 char * name = tape_name(STp);
756
757 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
758#endif
759
760 if (initial_delay > 0)
761 msleep(jiffies_to_msecs(initial_delay));
762
763 memset(cmd, 0, MAX_COMMAND_SIZE);
764 cmd[0] = TEST_UNIT_READY;
765
766 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
767 *aSRpnt = SRpnt;
768 if (!SRpnt) return (-EBUSY);
769
770 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
771 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
772 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
773 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
774 SRpnt->sense[13] == 0 ) )) {
775#if DEBUG
776 if (debugging) {
777 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
778 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
779 debugging = 0;
780 }
781#endif
782 msleep(100);
783
784 memset(cmd, 0, MAX_COMMAND_SIZE);
785 cmd[0] = TEST_UNIT_READY;
786
787 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
788 }
789 *aSRpnt = SRpnt;
790#if DEBUG
791 debugging = dbg;
792#endif
793 if ( STp->buffer->syscall_result &&
794 osst_write_error_recovery(STp, aSRpnt, 0) ) {
795#if DEBUG
796 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
797 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
798 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
799 SRpnt->sense[12], SRpnt->sense[13]);
800#endif
801 return (-EIO);
802 }
803#if DEBUG
804 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
805#endif
806 return 0;
807}
808
809
810
811
812static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
813{
814 unsigned char cmd[MAX_COMMAND_SIZE];
815 struct osst_request * SRpnt;
816 unsigned long startwait = jiffies;
817#if DEBUG
818 int dbg = debugging;
819 char * name = tape_name(STp);
820
821 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
822#endif
823
824 memset(cmd, 0, MAX_COMMAND_SIZE);
825 cmd[0] = TEST_UNIT_READY;
826
827 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
828 *aSRpnt = SRpnt;
829 if (!SRpnt) return (-EBUSY);
830
831 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
832 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
833#if DEBUG
834 if (debugging) {
835 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
836 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
837 debugging = 0;
838 }
839#endif
840 msleep(100);
841
842 memset(cmd, 0, MAX_COMMAND_SIZE);
843 cmd[0] = TEST_UNIT_READY;
844
845 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
846 }
847 *aSRpnt = SRpnt;
848#if DEBUG
849 debugging = dbg;
850#endif
851 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
852 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
853#if DEBUG
854 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
855 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
856 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
857 SRpnt->sense[12], SRpnt->sense[13]);
858#endif
859 return 0;
860 }
861#if DEBUG
862 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
863#endif
864 return 1;
865}
866
867static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
868{
869 int retval;
870
871 osst_wait_ready(STp, aSRpnt, 15 * 60, 0);
872 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
873 if (retval) return (retval);
874 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
875 return (osst_get_frame_position(STp, aSRpnt));
876}
877
878
879
880
881static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
882{
883 unsigned char cmd[MAX_COMMAND_SIZE];
884 struct osst_request * SRpnt;
885 int result = 0;
886 int delay = OSST_WAIT_WRITE_COMPLETE;
887#if DEBUG
888 char * name = tape_name(STp);
889
890 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
891#endif
892
893 memset(cmd, 0, MAX_COMMAND_SIZE);
894 cmd[0] = WRITE_FILEMARKS;
895 cmd[1] = 1;
896
897 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
898 *aSRpnt = SRpnt;
899 if (!SRpnt) return (-EBUSY);
900 if (STp->buffer->syscall_result) {
901 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
902 if (SRpnt->sense[13] == 8) {
903 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
904 }
905 } else
906 result = osst_write_error_recovery(STp, aSRpnt, 0);
907 }
908 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
909 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
910
911 return (result);
912}
913
914#define OSST_POLL_PER_SEC 10
915static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
916{
917 unsigned long startwait = jiffies;
918 char * name = tape_name(STp);
919#if DEBUG
920 char notyetprinted = 1;
921#endif
922 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
923 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
924
925 while (time_before (jiffies, startwait + to*HZ))
926 {
927 int result;
928 result = osst_get_frame_position(STp, aSRpnt);
929 if (result == -EIO)
930 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
931 return 0;
932 if (result < 0) break;
933 if (STp->first_frame_position == curr &&
934 ((minlast < 0 &&
935 (signed)STp->last_frame_position > (signed)curr + minlast) ||
936 (minlast >= 0 && STp->cur_frames > minlast)
937 ) && result >= 0)
938 {
939#if DEBUG
940 if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
941 printk (OSST_DEB_MSG
942 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
943 name, curr, curr+minlast, STp->first_frame_position,
944 STp->last_frame_position, STp->cur_frames,
945 result, (jiffies-startwait)/HZ,
946 (((jiffies-startwait)%HZ)*10)/HZ);
947#endif
948 return 0;
949 }
950#if DEBUG
951 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
952 {
953 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
954 name, curr, curr+minlast, STp->first_frame_position,
955 STp->last_frame_position, STp->cur_frames, result);
956 notyetprinted--;
957 }
958#endif
959 msleep(1000 / OSST_POLL_PER_SEC);
960 }
961#if DEBUG
962 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
963 name, curr, curr+minlast, STp->first_frame_position,
964 STp->last_frame_position, STp->cur_frames,
965 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
966#endif
967 return -EBUSY;
968}
969
970static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
971{
972 struct osst_request * SRpnt;
973 unsigned char cmd[MAX_COMMAND_SIZE];
974 unsigned long startwait = jiffies;
975 int retval = 1;
976 char * name = tape_name(STp);
977
978 if (writing) {
979 char mybuf[24];
980 char * olddata = STp->buffer->b_data;
981 int oldsize = STp->buffer->buffer_size;
982
983
984
985 memset(cmd, 0, MAX_COMMAND_SIZE);
986 cmd[0] = WRITE_FILEMARKS;
987 cmd[1] = 1;
988 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
989 MAX_RETRIES, 1);
990
991 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
992
993 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
994
995
996 retval = osst_write_error_recovery(STp, aSRpnt, 0);
997 break;
998 }
999 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
1000
1001 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1002 memset(cmd, 0, MAX_COMMAND_SIZE);
1003 cmd[0] = READ_POSITION;
1004
1005 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1006 MAX_RETRIES, 1);
1007
1008 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1009 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1010 }
1011 if (retval)
1012 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1013 } else
1014
1015 if (STp->buffer->syscall_result)
1016 printk(KERN_WARNING
1017 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1018 (*aSRpnt)->sense[ 2] & 0x0f,
1019 (*aSRpnt)->sense[12],
1020 (*aSRpnt)->sense[13]);
1021
1022 return retval;
1023}
1024
1025
1026
1027
1028static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1029{
1030 unsigned char cmd[MAX_COMMAND_SIZE];
1031 struct osst_request * SRpnt;
1032 int retval = 0;
1033#if DEBUG
1034 os_aux_t * aux = STp->buffer->aux;
1035 char * name = tape_name(STp);
1036#endif
1037
1038 if (STp->poll)
1039 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1040 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1041
1042 memset(cmd, 0, MAX_COMMAND_SIZE);
1043 cmd[0] = READ_6;
1044 cmd[1] = 1;
1045 cmd[4] = 1;
1046
1047#if DEBUG
1048 if (debugging)
1049 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1050#endif
1051 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1052 STp->timeout, MAX_RETRIES, 1);
1053 *aSRpnt = SRpnt;
1054 if (!SRpnt)
1055 return (-EBUSY);
1056
1057 if ((STp->buffer)->syscall_result) {
1058 retval = 1;
1059 if (STp->read_error_frame == 0) {
1060 STp->read_error_frame = STp->first_frame_position;
1061#if DEBUG
1062 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1063#endif
1064 }
1065#if DEBUG
1066 if (debugging)
1067 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1068 name,
1069 SRpnt->sense[0], SRpnt->sense[1],
1070 SRpnt->sense[2], SRpnt->sense[3],
1071 SRpnt->sense[4], SRpnt->sense[5],
1072 SRpnt->sense[6], SRpnt->sense[7]);
1073#endif
1074 }
1075 else
1076 STp->first_frame_position++;
1077#if DEBUG
1078 if (debugging) {
1079 char sig[8]; int i;
1080 for (i=0;i<4;i++)
1081 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1082 sig[4] = '\0';
1083 printk(OSST_DEB_MSG
1084 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1085 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1086 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1087 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1088 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1089 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1090 if (aux->frame_type==2)
1091 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1092 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1093 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1094 }
1095#endif
1096 return (retval);
1097}
1098
1099static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1100{
1101 struct st_partstat * STps = &(STp->ps[STp->partition]);
1102 struct osst_request * SRpnt ;
1103 unsigned char cmd[MAX_COMMAND_SIZE];
1104 int retval = 0;
1105 char * name = tape_name(STp);
1106
1107 if (STps->rw != ST_READING) {
1108 if (STps->rw == ST_WRITING || STp->dirty) {
1109 STp->write_type = OS_WRITE_DATA;
1110 osst_flush_write_buffer(STp, aSRpnt);
1111 osst_flush_drive_buffer(STp, aSRpnt);
1112 }
1113 STps->rw = ST_READING;
1114 STp->frame_in_buffer = 0;
1115
1116
1117
1118
1119
1120 memset(cmd, 0, MAX_COMMAND_SIZE);
1121 cmd[0] = READ_6;
1122 cmd[1] = 1;
1123
1124#if DEBUG
1125 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1126#endif
1127 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1128 *aSRpnt = SRpnt;
1129 if ((retval = STp->buffer->syscall_result))
1130 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1131 }
1132
1133 return retval;
1134}
1135
1136static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1137 int frame_seq_number, int quiet)
1138{
1139 struct st_partstat * STps = &(STp->ps[STp->partition]);
1140 char * name = tape_name(STp);
1141 int cnt = 0,
1142 bad = 0,
1143 past = 0,
1144 x,
1145 position;
1146
1147
1148
1149
1150 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1151#if DEBUG
1152 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1153#endif
1154 return (STps->eof);
1155 }
1156
1157
1158
1159 while (1) {
1160 if (cnt++ > 400) {
1161 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1162 name, frame_seq_number);
1163 if (STp->read_error_frame) {
1164 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1165#if DEBUG
1166 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1167 name, STp->read_error_frame);
1168#endif
1169 STp->read_error_frame = 0;
1170 STp->abort_count++;
1171 }
1172 return (-EIO);
1173 }
1174#if DEBUG
1175 if (debugging)
1176 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1177 name, frame_seq_number, cnt);
1178#endif
1179 if ( osst_initiate_read(STp, aSRpnt)
1180 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1181 if (STp->raw)
1182 return (-EIO);
1183 position = osst_get_frame_position(STp, aSRpnt);
1184 if (position >= 0xbae && position < 0xbb8)
1185 position = 0xbb8;
1186 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1187 position = STp->read_error_frame - 1;
1188 bad = 0;
1189 }
1190 else {
1191 position += 29;
1192 cnt += 19;
1193 }
1194#if DEBUG
1195 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1196 name, position);
1197#endif
1198 osst_set_frame_position(STp, aSRpnt, position, 0);
1199 continue;
1200 }
1201 if (osst_verify_frame(STp, frame_seq_number, quiet))
1202 break;
1203 if (osst_verify_frame(STp, -1, quiet)) {
1204 x = ntohl(STp->buffer->aux->frame_seq_num);
1205 if (STp->fast_open) {
1206 printk(KERN_WARNING
1207 "%s:W: Found logical frame %d instead of %d after fast open\n",
1208 name, x, frame_seq_number);
1209 STp->header_ok = 0;
1210 STp->read_error_frame = 0;
1211 return (-EIO);
1212 }
1213 if (x > frame_seq_number) {
1214 if (++past > 3) {
1215
1216 position = STp->read_error_frame - 1;
1217 }
1218 else {
1219 position = osst_get_frame_position(STp, aSRpnt)
1220 + frame_seq_number - x - 1;
1221
1222 if (STp->first_frame_position >= 3000 && position < 3000)
1223 position -= 10;
1224 }
1225#if DEBUG
1226 printk(OSST_DEB_MSG
1227 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1228 name, x, frame_seq_number,
1229 STp->first_frame_position - position);
1230#endif
1231 osst_set_frame_position(STp, aSRpnt, position, 0);
1232 cnt += 10;
1233 }
1234 else
1235 past = 0;
1236 }
1237 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1238#if DEBUG
1239 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1240#endif
1241 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1242 cnt--;
1243 }
1244 STp->frame_in_buffer = 0;
1245 }
1246 if (cnt > 1) {
1247 STp->recover_count++;
1248 STp->recover_erreg++;
1249 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1250 name, STp->read_error_frame);
1251 }
1252 STp->read_count++;
1253
1254#if DEBUG
1255 if (debugging || STps->eof)
1256 printk(OSST_DEB_MSG
1257 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1258 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1259#endif
1260 STp->fast_open = 0;
1261 STp->read_error_frame = 0;
1262 return (STps->eof);
1263}
1264
1265static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1266{
1267 struct st_partstat * STps = &(STp->ps[STp->partition]);
1268 char * name = tape_name(STp);
1269 int retries = 0;
1270 int frame_seq_estimate, ppos_estimate, move;
1271
1272 if (logical_blk_num < 0) logical_blk_num = 0;
1273#if DEBUG
1274 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1275 name, logical_blk_num, STp->logical_blk_num,
1276 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1277 STp->block_size<1024?'b':'k');
1278#endif
1279
1280 if (STps->drv_block >= 0) {
1281 move = logical_blk_num - STp->logical_blk_num;
1282 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1283 move /= (OS_DATA_SIZE / STp->block_size);
1284 frame_seq_estimate = STp->frame_seq_number + move;
1285 } else
1286 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1287
1288 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1289 else ppos_estimate = frame_seq_estimate + 20;
1290 while (++retries < 10) {
1291 if (ppos_estimate > STp->eod_frame_ppos-2) {
1292 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1293 ppos_estimate = STp->eod_frame_ppos - 2;
1294 }
1295 if (frame_seq_estimate < 0) {
1296 frame_seq_estimate = 0;
1297 ppos_estimate = 10;
1298 }
1299 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1300 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1301
1302 if (logical_blk_num < STp->logical_blk_num ||
1303 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1304 if (STps->eof == ST_FM_HIT)
1305 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1306 else {
1307 move = logical_blk_num - STp->logical_blk_num;
1308 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1309 move /= (OS_DATA_SIZE / STp->block_size);
1310 }
1311 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1312#if DEBUG
1313 printk(OSST_DEB_MSG
1314 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1315 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1316 STp->logical_blk_num, logical_blk_num, move);
1317#endif
1318 frame_seq_estimate += move;
1319 ppos_estimate += move;
1320 continue;
1321 } else {
1322 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1323 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1324 STp->logical_blk_num = logical_blk_num;
1325#if DEBUG
1326 printk(OSST_DEB_MSG
1327 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1328 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1329 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1330 STp->block_size);
1331#endif
1332 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1333 if (STps->eof == ST_FM_HIT) {
1334 STps->drv_file++;
1335 STps->drv_block = 0;
1336 } else {
1337 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1338 STp->logical_blk_num -
1339 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1340 -1;
1341 }
1342 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1343 return 0;
1344 }
1345 }
1346 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1347 goto error;
1348
1349#if DEBUG
1350 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1351 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1352 STp->logical_blk_num, logical_blk_num);
1353#endif
1354 if (frame_seq_estimate != STp->frame_seq_number)
1355 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1356 else
1357 break;
1358 }
1359error:
1360 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1361 name, logical_blk_num, STp->logical_blk_num, retries);
1362 return (-EIO);
1363}
1364
1365
1366
1367
1368
1369
1370#define OSST_FRAME_SHIFT 6
1371#define OSST_SECTOR_SHIFT 9
1372#define OSST_SECTOR_MASK 0x03F
1373
1374static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1375{
1376 int sector;
1377#if DEBUG
1378 char * name = tape_name(STp);
1379
1380 printk(OSST_DEB_MSG
1381 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1382 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1383 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1384 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1385 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1386 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1387#endif
1388
1389 if (STp->ps[STp->partition].drv_block >= 0) {
1390 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1391 STp->first_frame_position) << OSST_FRAME_SHIFT;
1392 if (STp->ps[STp->partition].rw == ST_WRITING)
1393 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1394 else
1395 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1396 } else {
1397 sector = osst_get_frame_position(STp, aSRpnt);
1398 if (sector > 0)
1399 sector <<= OSST_FRAME_SHIFT;
1400 }
1401 return sector;
1402}
1403
1404static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1405{
1406 struct st_partstat * STps = &(STp->ps[STp->partition]);
1407 int frame = sector >> OSST_FRAME_SHIFT,
1408 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1409 r;
1410#if DEBUG
1411 char * name = tape_name(STp);
1412
1413 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1414 name, sector, frame, offset);
1415#endif
1416 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1417
1418 if (frame <= STp->first_data_ppos) {
1419 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1420 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1421 }
1422 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1423 if (r < 0) return r;
1424
1425 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1426 if (r < 0) return r;
1427
1428 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1429
1430 if (offset) {
1431 STp->logical_blk_num += offset / STp->block_size;
1432 STp->buffer->read_pointer = offset;
1433 STp->buffer->buffer_bytes -= offset;
1434 } else {
1435 STp->frame_seq_number++;
1436 STp->frame_in_buffer = 0;
1437 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1438 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1439 }
1440 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1441 if (STps->eof == ST_FM_HIT) {
1442 STps->drv_file++;
1443 STps->drv_block = 0;
1444 } else {
1445 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1446 STp->logical_blk_num -
1447 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1448 -1;
1449 }
1450 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1451#if DEBUG
1452 printk(OSST_DEB_MSG
1453 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1454 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1455 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1456#endif
1457 return 0;
1458}
1459
1460
1461
1462
1463
1464
1465
1466
1467static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1468 unsigned int frame, unsigned int skip, int pending)
1469{
1470 struct osst_request * SRpnt = * aSRpnt;
1471 unsigned char * buffer, * p;
1472 unsigned char cmd[MAX_COMMAND_SIZE];
1473 int flag, new_frame, i;
1474 int nframes = STp->cur_frames;
1475 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1476 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1477 - (nframes + pending - 1);
1478 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1479 - (nframes + pending - 1) * blks_per_frame;
1480 char * name = tape_name(STp);
1481 unsigned long startwait = jiffies;
1482#if DEBUG
1483 int dbg = debugging;
1484#endif
1485
1486 if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1487 return (-EIO);
1488
1489 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1490 name, nframes, pending?" and one that was pending":"");
1491
1492 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1493#if DEBUG
1494 if (pending && debugging)
1495 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1496 name, frame_seq_number + nframes,
1497 logical_blk_num + nframes * blks_per_frame,
1498 p[0], p[1], p[2], p[3]);
1499#endif
1500 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1501
1502 memset(cmd, 0, MAX_COMMAND_SIZE);
1503 cmd[0] = 0x3C;
1504 cmd[1] = 6;
1505 cmd[7] = 32768 >> 8;
1506 cmd[8] = 32768 & 0xff;
1507
1508 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1509 STp->timeout, MAX_RETRIES, 1);
1510
1511 if ((STp->buffer)->syscall_result || !SRpnt) {
1512 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1513 vfree(buffer);
1514 *aSRpnt = SRpnt;
1515 return (-EIO);
1516 }
1517 osst_copy_from_buffer(STp->buffer, p);
1518#if DEBUG
1519 if (debugging)
1520 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1521 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1522#endif
1523 }
1524 *aSRpnt = SRpnt;
1525 osst_get_frame_position(STp, aSRpnt);
1526
1527#if DEBUG
1528 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1529#endif
1530
1531
1532
1533 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1534
1535 if (flag) {
1536 if (STp->write_type == OS_WRITE_HEADER) {
1537 i += skip;
1538 p += skip * OS_DATA_SIZE;
1539 }
1540 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1541 new_frame = 3000-i;
1542 else
1543 new_frame += skip;
1544#if DEBUG
1545 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1546 name, new_frame+i, frame_seq_number+i);
1547#endif
1548 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1549 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1550 osst_get_frame_position(STp, aSRpnt);
1551 SRpnt = * aSRpnt;
1552
1553 if (new_frame > frame + 1000) {
1554 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1555 vfree(buffer);
1556 return (-EIO);
1557 }
1558 if ( i >= nframes + pending ) break;
1559 flag = 0;
1560 }
1561 osst_copy_to_buffer(STp->buffer, p);
1562
1563
1564
1565 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1566 logical_blk_num + i*blks_per_frame,
1567 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1568 memset(cmd, 0, MAX_COMMAND_SIZE);
1569 cmd[0] = WRITE_6;
1570 cmd[1] = 1;
1571 cmd[4] = 1;
1572
1573#if DEBUG
1574 if (debugging)
1575 printk(OSST_DEB_MSG
1576 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1577 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1578 p[0], p[1], p[2], p[3]);
1579#endif
1580 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1581 STp->timeout, MAX_RETRIES, 1);
1582
1583 if (STp->buffer->syscall_result)
1584 flag = 1;
1585 else {
1586 p += OS_DATA_SIZE; i++;
1587
1588
1589 if ( i == nframes + pending ) {
1590#if DEBUG
1591 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1592#endif
1593 memset(cmd, 0, MAX_COMMAND_SIZE);
1594 cmd[0] = WRITE_FILEMARKS;
1595 cmd[1] = 1;
1596 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1597 STp->timeout, MAX_RETRIES, 1);
1598#if DEBUG
1599 if (debugging) {
1600 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1601 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1602 debugging = 0;
1603 }
1604#endif
1605 flag = STp->buffer->syscall_result;
1606 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1607
1608 memset(cmd, 0, MAX_COMMAND_SIZE);
1609 cmd[0] = TEST_UNIT_READY;
1610
1611 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1612 MAX_RETRIES, 1);
1613
1614 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1615 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1616
1617 msleep(100);
1618 continue;
1619 }
1620 if (STp->buffer->syscall_result)
1621 flag = 1;
1622 break;
1623 }
1624#if DEBUG
1625 debugging = dbg;
1626 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1627#endif
1628 }
1629 }
1630 *aSRpnt = SRpnt;
1631 if (flag) {
1632 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1633 SRpnt->sense[12] == 0 &&
1634 SRpnt->sense[13] == 2) {
1635 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1636 vfree(buffer);
1637 return (-EIO);
1638 }
1639 i = ((SRpnt->sense[3] << 24) |
1640 (SRpnt->sense[4] << 16) |
1641 (SRpnt->sense[5] << 8) |
1642 SRpnt->sense[6] ) - new_frame;
1643 p = &buffer[i * OS_DATA_SIZE];
1644#if DEBUG
1645 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1646#endif
1647 osst_get_frame_position(STp, aSRpnt);
1648#if DEBUG
1649 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1650 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1651#endif
1652 }
1653 }
1654 if (flag) {
1655
1656 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1657 STp->write_type == OS_WRITE_HEADER?"header":"body");
1658 }
1659 if (!pending)
1660 osst_copy_to_buffer(STp->buffer, p);
1661 vfree(buffer);
1662 return 0;
1663}
1664
1665static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1666 unsigned int frame, unsigned int skip, int pending)
1667{
1668 unsigned char cmd[MAX_COMMAND_SIZE];
1669 struct osst_request * SRpnt;
1670 char * name = tape_name(STp);
1671 int expected = 0;
1672 int attempts = 1000 / skip;
1673 int flag = 1;
1674 unsigned long startwait = jiffies;
1675#if DEBUG
1676 int dbg = debugging;
1677#endif
1678
1679 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1680 if (flag) {
1681#if DEBUG
1682 debugging = dbg;
1683#endif
1684 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1685 frame = 3000-skip;
1686 expected = frame+skip+STp->cur_frames+pending;
1687#if DEBUG
1688 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1689 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1690#endif
1691 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1692 flag = 0;
1693 attempts--;
1694 schedule_timeout_interruptible(msecs_to_jiffies(100));
1695 }
1696 if (osst_get_frame_position(STp, aSRpnt) < 0) {
1697#if DEBUG
1698 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1699 name, STp->first_frame_position,
1700 STp->last_frame_position, STp->cur_frames);
1701#endif
1702 frame = STp->last_frame_position;
1703 flag = 1;
1704 continue;
1705 }
1706 if (pending && STp->cur_frames < 50) {
1707
1708 memset(cmd, 0, MAX_COMMAND_SIZE);
1709 cmd[0] = WRITE_6;
1710 cmd[1] = 1;
1711 cmd[4] = 1;
1712#if DEBUG
1713 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1714 name, STp->frame_seq_number-1, STp->first_frame_position);
1715#endif
1716 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1717 STp->timeout, MAX_RETRIES, 1);
1718 *aSRpnt = SRpnt;
1719
1720 if (STp->buffer->syscall_result) {
1721 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1722 SRpnt->sense[12] == 0 &&
1723 SRpnt->sense[13] == 2) {
1724 printk(KERN_ERR
1725 "%s:E: Volume overflow in write error recovery\n",
1726 name);
1727 break;
1728 }
1729 flag = 1;
1730 }
1731 else
1732 pending = 0;
1733
1734 continue;
1735 }
1736 if (STp->cur_frames == 0) {
1737#if DEBUG
1738 debugging = dbg;
1739 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1740#endif
1741 if (STp->first_frame_position != expected) {
1742 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1743 name, STp->first_frame_position, expected);
1744 return (-EIO);
1745 }
1746 return 0;
1747 }
1748#if DEBUG
1749 if (debugging) {
1750 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1751 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1752 debugging = 0;
1753 }
1754#endif
1755 schedule_timeout_interruptible(msecs_to_jiffies(100));
1756 }
1757 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1758#if DEBUG
1759 debugging = dbg;
1760#endif
1761 return (-EIO);
1762}
1763
1764
1765
1766
1767
1768static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1769{
1770 struct osst_request * SRpnt = * aSRpnt;
1771 struct st_partstat * STps = & STp->ps[STp->partition];
1772 char * name = tape_name(STp);
1773 int retval = 0;
1774 int rw_state;
1775 unsigned int frame, skip;
1776
1777 rw_state = STps->rw;
1778
1779 if ((SRpnt->sense[ 2] & 0x0f) != 3
1780 || SRpnt->sense[12] != 12
1781 || SRpnt->sense[13] != 0) {
1782#if DEBUG
1783 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1784 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1785#endif
1786 return (-EIO);
1787 }
1788 frame = (SRpnt->sense[3] << 24) |
1789 (SRpnt->sense[4] << 16) |
1790 (SRpnt->sense[5] << 8) |
1791 SRpnt->sense[6];
1792 skip = SRpnt->sense[9];
1793
1794#if DEBUG
1795 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1796#endif
1797 osst_get_frame_position(STp, aSRpnt);
1798#if DEBUG
1799 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1800 name, STp->first_frame_position, STp->last_frame_position);
1801#endif
1802 switch (STp->write_type) {
1803 case OS_WRITE_DATA:
1804 case OS_WRITE_EOD:
1805 case OS_WRITE_NEW_MARK:
1806 printk(KERN_WARNING
1807 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1808 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1809 if (STp->os_fw_rev >= 10600)
1810 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1811 else
1812 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1813 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1814 retval?"E" :"I",
1815 retval?"" :"Don't worry, ",
1816 retval?" not ":" ");
1817 break;
1818 case OS_WRITE_LAST_MARK:
1819 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1820 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1821 retval = -EIO;
1822 break;
1823 case OS_WRITE_HEADER:
1824 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1825 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1826 break;
1827 default:
1828 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1829 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1830 }
1831 osst_get_frame_position(STp, aSRpnt);
1832#if DEBUG
1833 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1834 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1835 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1836#endif
1837 if (retval == 0) {
1838 STp->recover_count++;
1839 STp->recover_erreg++;
1840 } else
1841 STp->abort_count++;
1842
1843 STps->rw = rw_state;
1844 return retval;
1845}
1846
1847static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1848 int mt_op, int mt_count)
1849{
1850 char * name = tape_name(STp);
1851 int cnt;
1852 int last_mark_ppos = -1;
1853
1854#if DEBUG
1855 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1856#endif
1857 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1858#if DEBUG
1859 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1860#endif
1861 return -EIO;
1862 }
1863 if (STp->linux_media_version >= 4) {
1864
1865
1866
1867 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1868 if (STp->header_ok &&
1869 STp->header_cache != NULL &&
1870 (cnt - mt_count) >= 0 &&
1871 (cnt - mt_count) < OS_FM_TAB_MAX &&
1872 (cnt - mt_count) < STp->filemark_cnt &&
1873 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1874
1875 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1876#if DEBUG
1877 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1878 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1879 STp->header_cache == NULL?"lack of header cache":"count out of range");
1880 else
1881 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1882 name, cnt,
1883 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1884 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1885 STp->buffer->aux->last_mark_ppos))?"match":"error",
1886 mt_count, last_mark_ppos);
1887#endif
1888 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1889 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1890 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1891#if DEBUG
1892 printk(OSST_DEB_MSG
1893 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1894#endif
1895 return (-EIO);
1896 }
1897 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1898 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1899 name, last_mark_ppos);
1900 return (-EIO);
1901 }
1902 goto found;
1903 }
1904#if DEBUG
1905 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1906#endif
1907 }
1908 cnt = 0;
1909 while (cnt != mt_count) {
1910 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1911 if (last_mark_ppos == -1)
1912 return (-EIO);
1913#if DEBUG
1914 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1915#endif
1916 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1917 cnt++;
1918 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1919#if DEBUG
1920 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1921#endif
1922 return (-EIO);
1923 }
1924 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1925 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1926 name, last_mark_ppos);
1927 return (-EIO);
1928 }
1929 }
1930found:
1931 if (mt_op == MTBSFM) {
1932 STp->frame_seq_number++;
1933 STp->frame_in_buffer = 0;
1934 STp->buffer->buffer_bytes = 0;
1935 STp->buffer->read_pointer = 0;
1936 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1937 }
1938 return 0;
1939}
1940
1941
1942
1943
1944
1945
1946static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1947 int mt_op, int mt_count)
1948{
1949 int cnt = 0;
1950#if DEBUG
1951 char * name = tape_name(STp);
1952
1953 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1954#endif
1955 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1956#if DEBUG
1957 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1958#endif
1959 return (-EIO);
1960 }
1961 while (1) {
1962 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1963#if DEBUG
1964 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1965#endif
1966 return (-EIO);
1967 }
1968 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1969 cnt++;
1970 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1971#if DEBUG
1972 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1973#endif
1974 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1975#if DEBUG
1976 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1977 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1978#endif
1979 STp->eod_frame_ppos = STp->first_frame_position-1;
1980 }
1981 return (-EIO);
1982 }
1983 if (cnt == mt_count)
1984 break;
1985 STp->frame_in_buffer = 0;
1986 }
1987 if (mt_op == MTFSF) {
1988 STp->frame_seq_number++;
1989 STp->frame_in_buffer = 0;
1990 STp->buffer->buffer_bytes = 0;
1991 STp->buffer->read_pointer = 0;
1992 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1993 }
1994 return 0;
1995}
1996
1997
1998
1999
2000static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
2001 int mt_op, int mt_count)
2002{
2003 char * name = tape_name(STp);
2004 int cnt = 0,
2005 next_mark_ppos = -1;
2006
2007#if DEBUG
2008 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
2009#endif
2010 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2011#if DEBUG
2012 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
2013#endif
2014 return (-EIO);
2015 }
2016
2017 if (STp->linux_media_version >= 4) {
2018
2019
2020
2021 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
2022 if (STp->header_ok &&
2023 STp->header_cache != NULL &&
2024 (cnt + mt_count) < OS_FM_TAB_MAX &&
2025 (cnt + mt_count) < STp->filemark_cnt &&
2026 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2027 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
2028
2029 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
2030#if DEBUG
2031 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
2032 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
2033 STp->header_cache == NULL?"lack of header cache":"count out of range");
2034 else
2035 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2036 name, cnt,
2037 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2038 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
2039 STp->buffer->aux->last_mark_ppos))?"match":"error",
2040 mt_count, next_mark_ppos);
2041#endif
2042 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
2043#if DEBUG
2044 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2045#endif
2046 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2047 } else {
2048 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2049 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2050#if DEBUG
2051 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2052 name);
2053#endif
2054 return (-EIO);
2055 }
2056 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2057 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2058 name, next_mark_ppos);
2059 return (-EIO);
2060 }
2061 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
2062 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
2063 name, cnt+mt_count, next_mark_ppos,
2064 ntohl(STp->buffer->aux->filemark_cnt));
2065 return (-EIO);
2066 }
2067 }
2068 } else {
2069
2070
2071
2072 while (1) {
2073 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
2074 break;
2075 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2076#if DEBUG
2077 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2078#endif
2079 return (-EIO);
2080 }
2081 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2082 if (STp->first_mark_ppos == -1) {
2083#if DEBUG
2084 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2085#endif
2086 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2087 }
2088 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2089 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2090#if DEBUG
2091 printk(OSST_DEB_MSG
2092 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2093 name);
2094#endif
2095 return (-EIO);
2096 }
2097 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2098 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2099 name, STp->first_mark_ppos);
2100 return (-EIO);
2101 }
2102 } else {
2103 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2104 return (-EIO);
2105 mt_count++;
2106 }
2107 }
2108 cnt++;
2109 while (cnt != mt_count) {
2110 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2111 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2112#if DEBUG
2113 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2114#endif
2115 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2116 }
2117#if DEBUG
2118 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2119#endif
2120 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2121 cnt++;
2122 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2123#if DEBUG
2124 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2125 name);
2126#endif
2127 return (-EIO);
2128 }
2129 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2130 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2131 name, next_mark_ppos);
2132 return (-EIO);
2133 }
2134 }
2135 }
2136 if (mt_op == MTFSF) {
2137 STp->frame_seq_number++;
2138 STp->frame_in_buffer = 0;
2139 STp->buffer->buffer_bytes = 0;
2140 STp->buffer->read_pointer = 0;
2141 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2142 }
2143 return 0;
2144}
2145
2146
2147
2148
2149
2150#if DEBUG
2151static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2152{
2153 unsigned char cmd[MAX_COMMAND_SIZE];
2154 struct osst_request * SRpnt = * aSRpnt;
2155 char * name = tape_name(STp);
2156
2157 memset(cmd, 0, MAX_COMMAND_SIZE);
2158 cmd[0] = MODE_SELECT;
2159 cmd[1] = 0x10;
2160 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2161
2162 (STp->buffer)->b_data[0] = cmd[4] - 1;
2163 (STp->buffer)->b_data[1] = 0;
2164 (STp->buffer)->b_data[2] = 0;
2165 (STp->buffer)->b_data[3] = 0;
2166 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2167 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2168 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2169 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2170
2171 if (debugging)
2172 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2173
2174 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2175 *aSRpnt = SRpnt;
2176
2177 if ((STp->buffer)->syscall_result)
2178 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2179}
2180#endif
2181
2182
2183static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2184{
2185 int result;
2186 int this_mark_ppos = STp->first_frame_position;
2187 int this_mark_lbn = STp->logical_blk_num;
2188#if DEBUG
2189 char * name = tape_name(STp);
2190#endif
2191
2192 if (STp->raw) return 0;
2193
2194 STp->write_type = OS_WRITE_NEW_MARK;
2195#if DEBUG
2196 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2197 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2198#endif
2199 STp->dirty = 1;
2200 result = osst_flush_write_buffer(STp, aSRpnt);
2201 result |= osst_flush_drive_buffer(STp, aSRpnt);
2202 STp->last_mark_ppos = this_mark_ppos;
2203 STp->last_mark_lbn = this_mark_lbn;
2204 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2205 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2206 if (STp->filemark_cnt++ == 0)
2207 STp->first_mark_ppos = this_mark_ppos;
2208 return result;
2209}
2210
2211static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2212{
2213 int result;
2214#if DEBUG
2215 char * name = tape_name(STp);
2216#endif
2217
2218 if (STp->raw) return 0;
2219
2220 STp->write_type = OS_WRITE_EOD;
2221 STp->eod_frame_ppos = STp->first_frame_position;
2222#if DEBUG
2223 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2224 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2225#endif
2226 STp->dirty = 1;
2227
2228 result = osst_flush_write_buffer(STp, aSRpnt);
2229 result |= osst_flush_drive_buffer(STp, aSRpnt);
2230 STp->eod_frame_lfa = --(STp->frame_seq_number);
2231 return result;
2232}
2233
2234static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2235{
2236 char * name = tape_name(STp);
2237
2238#if DEBUG
2239 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2240#endif
2241 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2242 osst_set_frame_position(STp, aSRpnt, where, 0);
2243 STp->write_type = OS_WRITE_FILLER;
2244 while (count--) {
2245 memcpy(STp->buffer->b_data, "Filler", 6);
2246 STp->buffer->buffer_bytes = 6;
2247 STp->dirty = 1;
2248 if (osst_flush_write_buffer(STp, aSRpnt)) {
2249 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2250 return (-EIO);
2251 }
2252 }
2253#if DEBUG
2254 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2255#endif
2256 return osst_flush_drive_buffer(STp, aSRpnt);
2257}
2258
2259static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2260{
2261 char * name = tape_name(STp);
2262 int result;
2263
2264#if DEBUG
2265 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2266#endif
2267 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2268 osst_set_frame_position(STp, aSRpnt, where, 0);
2269 STp->write_type = OS_WRITE_HEADER;
2270 while (count--) {
2271 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2272 STp->buffer->buffer_bytes = sizeof(os_header_t);
2273 STp->dirty = 1;
2274 if (osst_flush_write_buffer(STp, aSRpnt)) {
2275 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2276 return (-EIO);
2277 }
2278 }
2279 result = osst_flush_drive_buffer(STp, aSRpnt);
2280#if DEBUG
2281 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2282#endif
2283 return result;
2284}
2285
2286static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2287{
2288 os_header_t * header;
2289 int result;
2290 char * name = tape_name(STp);
2291
2292#if DEBUG
2293 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2294#endif
2295 if (STp->raw) return 0;
2296
2297 if (STp->header_cache == NULL) {
2298 if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2299 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2300 return (-ENOMEM);
2301 }
2302 memset(STp->header_cache, 0, sizeof(os_header_t));
2303#if DEBUG
2304 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2305#endif
2306 }
2307 if (STp->header_ok) STp->update_frame_cntr++;
2308 else STp->update_frame_cntr = 0;
2309
2310 header = STp->header_cache;
2311 strcpy(header->ident_str, "ADR_SEQ");
2312 header->major_rev = 1;
2313 header->minor_rev = 4;
2314 header->ext_trk_tb_off = htons(17192);
2315 header->pt_par_num = 1;
2316 header->partition[0].partition_num = OS_DATA_PARTITION;
2317 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2318 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2319 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2320 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2321 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2322 header->cfg_col_width = htonl(20);
2323 header->dat_col_width = htonl(1500);
2324 header->qfa_col_width = htonl(0);
2325 header->ext_track_tb.nr_stream_part = 1;
2326 header->ext_track_tb.et_ent_sz = 32;
2327 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2328 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2329 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2330 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2331 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2332 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2333 header->dat_fm_tab.fm_part_num = 0;
2334 header->dat_fm_tab.fm_tab_ent_sz = 4;
2335 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2336 STp->filemark_cnt:OS_FM_TAB_MAX);
2337
2338 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2339 if (STp->update_frame_cntr == 0)
2340 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2341 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2342
2343 if (locate_eod) {
2344#if DEBUG
2345 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2346#endif
2347 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2348 }
2349 if (result)
2350 printk(KERN_ERR "%s:E: Write header failed\n", name);
2351 else {
2352 memcpy(STp->application_sig, "LIN4", 4);
2353 STp->linux_media = 1;
2354 STp->linux_media_version = 4;
2355 STp->header_ok = 1;
2356 }
2357 return result;
2358}
2359
2360static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2361{
2362 if (STp->header_cache != NULL)
2363 memset(STp->header_cache, 0, sizeof(os_header_t));
2364
2365 STp->logical_blk_num = STp->frame_seq_number = 0;
2366 STp->frame_in_buffer = 0;
2367 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2368 STp->filemark_cnt = 0;
2369 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2370 return osst_write_header(STp, aSRpnt, 1);
2371}
2372
2373static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2374{
2375 char * name = tape_name(STp);
2376 os_header_t * header;
2377 os_aux_t * aux;
2378 char id_string[8];
2379 int linux_media_version,
2380 update_frame_cntr;
2381
2382 if (STp->raw)
2383 return 1;
2384
2385 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2386 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2387 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2388 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2389 if (osst_initiate_read (STp, aSRpnt)) {
2390 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2391 return 0;
2392 }
2393 }
2394 if (osst_read_frame(STp, aSRpnt, 180)) {
2395#if DEBUG
2396 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2397#endif
2398 return 0;
2399 }
2400 header = (os_header_t *) STp->buffer->b_data;
2401 aux = STp->buffer->aux;
2402 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2403#if DEBUG
2404 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2405#endif
2406 return 0;
2407 }
2408 if (ntohl(aux->frame_seq_num) != 0 ||
2409 ntohl(aux->logical_blk_num) != 0 ||
2410 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2411 ntohl(aux->partition.first_frame_ppos) != 0 ||
2412 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2413#if DEBUG
2414 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2415 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2416 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2417 ntohl(aux->partition.last_frame_ppos));
2418#endif
2419 return 0;
2420 }
2421 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2422 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2423 strlcpy(id_string, header->ident_str, 8);
2424#if DEBUG
2425 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2426#endif
2427 return 0;
2428 }
2429 update_frame_cntr = ntohl(aux->update_frame_cntr);
2430 if (update_frame_cntr < STp->update_frame_cntr) {
2431#if DEBUG
2432 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2433 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2434#endif
2435 return 0;
2436 }
2437 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2438#if DEBUG
2439 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2440 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2441 header->minor_rev > 4 )? "Invalid" : "Warning:",
2442 header->major_rev, header->minor_rev);
2443#endif
2444 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2445 return 0;
2446 }
2447#if DEBUG
2448 if (header->pt_par_num != 1)
2449 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2450 name, header->pt_par_num);
2451#endif
2452 memcpy(id_string, aux->application_sig, 4);
2453 id_string[4] = 0;
2454 if (memcmp(id_string, "LIN", 3) == 0) {
2455 STp->linux_media = 1;
2456 linux_media_version = id_string[3] - '0';
2457 if (linux_media_version != 4)
2458 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2459 name, linux_media_version);
2460 } else {
2461 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2462 return 0;
2463 }
2464 if (linux_media_version < STp->linux_media_version) {
2465#if DEBUG
2466 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2467 name, ppos, linux_media_version);
2468#endif
2469 return 0;
2470 }
2471 if (linux_media_version > STp->linux_media_version) {
2472#if DEBUG
2473 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2474 name, ppos, linux_media_version);
2475#endif
2476 memcpy(STp->application_sig, id_string, 5);
2477 STp->linux_media_version = linux_media_version;
2478 STp->update_frame_cntr = -1;
2479 }
2480 if (update_frame_cntr > STp->update_frame_cntr) {
2481#if DEBUG
2482 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2483 name, ppos, update_frame_cntr);
2484#endif
2485 if (STp->header_cache == NULL) {
2486 if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2487 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2488 return 0;
2489 }
2490#if DEBUG
2491 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2492#endif
2493 }
2494 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2495 header = STp->header_cache;
2496
2497 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2498 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2499 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2500 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2501 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2502 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2503 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2504 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2505 STp->update_frame_cntr = update_frame_cntr;
2506#if DEBUG
2507 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2508 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2509 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2510 STp->first_data_ppos,
2511 ntohl(header->partition[0].last_frame_ppos),
2512 ntohl(header->partition[0].eod_frame_ppos));
2513 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2514 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2515#endif
2516 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2517#if DEBUG
2518 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2519#endif
2520 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2521 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2522 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2523 }
2524 if (header->minor_rev == 4 &&
2525 (header->ext_trk_tb_off != htons(17192) ||
2526 header->partition[0].partition_num != OS_DATA_PARTITION ||
2527 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2528 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2529 header->cfg_col_width != htonl(20) ||
2530 header->dat_col_width != htonl(1500) ||
2531 header->qfa_col_width != htonl(0) ||
2532 header->ext_track_tb.nr_stream_part != 1 ||
2533 header->ext_track_tb.et_ent_sz != 32 ||
2534 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2535 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2536 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2537 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2538 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2539 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2540 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2541 header->dat_fm_tab.fm_tab_ent_cnt !=
2542 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2543 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2544
2545 }
2546
2547 return 1;
2548}
2549
2550static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2551{
2552 int position, ppos;
2553 int first, last;
2554 int valid = 0;
2555 char * name = tape_name(STp);
2556
2557 position = osst_get_frame_position(STp, aSRpnt);
2558
2559 if (STp->raw) {
2560 STp->header_ok = STp->linux_media = 1;
2561 STp->linux_media_version = 0;
2562 return 1;
2563 }
2564 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2565 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2566 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2567 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2568#if DEBUG
2569 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2570#endif
2571
2572
2573
2574
2575 first = position==10?0xbae: 5;
2576 last = position==10?0xbb3:10;
2577
2578 for (ppos = first; ppos < last; ppos++)
2579 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2580 valid = 1;
2581
2582 first = position==10? 5:0xbae;
2583 last = position==10?10:0xbb3;
2584
2585 for (ppos = first; ppos < last; ppos++)
2586 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2587 valid = 1;
2588
2589 if (!valid) {
2590 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2591 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2592 osst_set_frame_position(STp, aSRpnt, 10, 0);
2593 return 0;
2594 }
2595 if (position <= STp->first_data_ppos) {
2596 position = STp->first_data_ppos;
2597 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2598 }
2599 osst_set_frame_position(STp, aSRpnt, position, 0);
2600 STp->header_ok = 1;
2601
2602 return 1;
2603}
2604
2605static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2606{
2607 int frame_position = STp->first_frame_position;
2608 int frame_seq_numbr = STp->frame_seq_number;
2609 int logical_blk_num = STp->logical_blk_num;
2610 int halfway_frame = STp->frame_in_buffer;
2611 int read_pointer = STp->buffer->read_pointer;
2612 int prev_mark_ppos = -1;
2613 int actual_mark_ppos, i, n;
2614#if DEBUG
2615 char * name = tape_name(STp);
2616
2617 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2618#endif
2619 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2620 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2621#if DEBUG
2622 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2623#endif
2624 return (-EIO);
2625 }
2626 if (STp->linux_media_version >= 4) {
2627 for (i=0; i<STp->filemark_cnt; i++)
2628 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2629 prev_mark_ppos = n;
2630 } else
2631 prev_mark_ppos = frame_position - 1;
2632 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2633 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2634 if (frame_position != STp->first_frame_position ||
2635 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2636 prev_mark_ppos != actual_mark_ppos ) {
2637#if DEBUG
2638 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2639 STp->first_frame_position, frame_position,
2640 STp->frame_seq_number + (halfway_frame?0:1),
2641 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2642#endif
2643 return (-EIO);
2644 }
2645 if (halfway_frame) {
2646
2647 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2648 STp->buffer->buffer_bytes = read_pointer;
2649 STp->ps[STp->partition].rw = ST_WRITING;
2650 STp->dirty = 1;
2651 }
2652 STp->frame_in_buffer = halfway_frame;
2653 STp->frame_seq_number = frame_seq_numbr;
2654 STp->logical_blk_num = logical_blk_num;
2655 return 0;
2656}
2657
2658
2659
2660
2661
2662
2663
2664static unsigned int osst_parse_firmware_rev (const char * str)
2665{
2666 if (str[1] == '.') {
2667 return (str[0]-'0')*10000
2668 +(str[2]-'0')*1000
2669 +(str[3]-'0')*100;
2670 } else {
2671 return (str[0]-'0')*10000
2672 +(str[1]-'0')*1000
2673 +(str[2]-'0')*100 - 100
2674 +(str[3]-'@');
2675 }
2676}
2677
2678
2679
2680
2681static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2682{
2683 unsigned char cmd[MAX_COMMAND_SIZE];
2684 char * name = tape_name(STp);
2685 struct osst_request * SRpnt = * aSRpnt;
2686 osst_mode_parameter_header_t * header;
2687 osst_block_size_page_t * bs;
2688 osst_capabilities_page_t * cp;
2689 osst_tape_paramtr_page_t * prm;
2690 int drive_buffer_size;
2691
2692 if (STp->ready != ST_READY) {
2693#if DEBUG
2694 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2695#endif
2696 return (-EIO);
2697 }
2698
2699 if (STp->os_fw_rev < 10600) {
2700 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2701 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2702 }
2703
2704
2705
2706
2707
2708 memset(cmd, 0, MAX_COMMAND_SIZE);
2709 cmd[0] = MODE_SENSE;
2710 cmd[1] = 8;
2711 cmd[2] = BLOCK_SIZE_PAGE;
2712 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2713
2714 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2715 if (SRpnt == NULL) {
2716#if DEBUG
2717 printk(OSST_DEB_MSG "osst :D: Busy\n");
2718#endif
2719 return (-EBUSY);
2720 }
2721 *aSRpnt = SRpnt;
2722 if ((STp->buffer)->syscall_result != 0) {
2723 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2724 return (-EIO);
2725 }
2726
2727 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2728 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2729
2730#if DEBUG
2731 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2732 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2733 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2734 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2735#endif
2736
2737
2738
2739
2740 bs->one = 1;
2741 bs->play32 = 0;
2742 bs->play32_5 = 1;
2743 bs->record32 = 0;
2744 bs->record32_5 = 1;
2745
2746 memset(cmd, 0, MAX_COMMAND_SIZE);
2747 cmd[0] = MODE_SELECT;
2748 cmd[1] = 0x10;
2749 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2750
2751 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2752 *aSRpnt = SRpnt;
2753 if ((STp->buffer)->syscall_result != 0) {
2754 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2755 return (-EIO);
2756 }
2757
2758#if DEBUG
2759 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2760
2761
2762
2763
2764 osst_set_retries(STp, aSRpnt, 0);
2765 SRpnt = * aSRpnt;
2766#endif
2767
2768
2769
2770
2771
2772 memset(cmd, 0, MAX_COMMAND_SIZE);
2773 cmd[0] = MODE_SELECT;
2774 cmd[1] = 0x10;
2775 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2776
2777 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2778 header->medium_type = 0;
2779 header->dsp = 0;
2780 header->bdl = 0;
2781
2782 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2783 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2784 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2785 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2786 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2787 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2788 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2789 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2790
2791 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2792 *aSRpnt = SRpnt;
2793
2794 if ((STp->buffer)->syscall_result != 0) {
2795 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2796 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2797 return (-EIO);
2798 }
2799
2800 memset(cmd, 0, MAX_COMMAND_SIZE);
2801 cmd[0] = MODE_SENSE;
2802 cmd[1] = 8;
2803 cmd[2] = CAPABILITIES_PAGE;
2804 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2805
2806 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2807 *aSRpnt = SRpnt;
2808
2809 if ((STp->buffer)->syscall_result != 0) {
2810 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2811 return (-EIO);
2812 }
2813
2814 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2815 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2816 sizeof(osst_mode_parameter_header_t) + header->bdl);
2817
2818 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2819
2820 memset(cmd, 0, MAX_COMMAND_SIZE);
2821 cmd[0] = MODE_SENSE;
2822 cmd[1] = 8;
2823 cmd[2] = TAPE_PARAMTR_PAGE;
2824 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2825
2826 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2827 *aSRpnt = SRpnt;
2828
2829 if ((STp->buffer)->syscall_result != 0) {
2830 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2831 return (-EIO);
2832 }
2833
2834 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2835 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2836 sizeof(osst_mode_parameter_header_t) + header->bdl);
2837
2838 STp->density = prm->density;
2839 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2840#if DEBUG
2841 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2842 name, STp->density, STp->capacity / 32, drive_buffer_size);
2843#endif
2844
2845 return 0;
2846
2847}
2848
2849
2850
2851
2852static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2853{
2854 int result;
2855 char * name = tape_name(STp);
2856
2857#if DEBUG
2858 if (debugging)
2859 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2860 name, forward ? "forward" : "backward");
2861#endif
2862
2863 if (forward) {
2864
2865 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2866 }
2867 else
2868
2869 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2870
2871 if (result < 0)
2872 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2873 name, forward ? "forward" : "backward");
2874
2875 return result;
2876}
2877
2878
2879
2880
2881static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2882{
2883 unsigned char scmd[MAX_COMMAND_SIZE];
2884 struct osst_request * SRpnt;
2885 int result = 0;
2886 char * name = tape_name(STp);
2887
2888
2889
2890 char mybuf[24];
2891 char * olddata = STp->buffer->b_data;
2892 int oldsize = STp->buffer->buffer_size;
2893
2894 if (STp->ready != ST_READY) return (-EIO);
2895
2896 memset (scmd, 0, MAX_COMMAND_SIZE);
2897 scmd[0] = READ_POSITION;
2898
2899 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2900 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2901 STp->timeout, MAX_RETRIES, 1);
2902 if (!SRpnt) {
2903 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2904 return (-EBUSY);
2905 }
2906 *aSRpnt = SRpnt;
2907
2908 if (STp->buffer->syscall_result)
2909 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL;
2910
2911 if (result == -EINVAL)
2912 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2913 else {
2914 if (result == -EIO) {
2915 unsigned char mysense[16];
2916 memcpy (mysense, SRpnt->sense, 16);
2917 memset (scmd, 0, MAX_COMMAND_SIZE);
2918 scmd[0] = READ_POSITION;
2919 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2920 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2921 STp->timeout, MAX_RETRIES, 1);
2922#if DEBUG
2923 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2924 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2925 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2926#endif
2927 if (!STp->buffer->syscall_result)
2928 memcpy (SRpnt->sense, mysense, 16);
2929 else
2930 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2931 }
2932 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2933 + ((STp->buffer)->b_data[5] << 16)
2934 + ((STp->buffer)->b_data[6] << 8)
2935 + (STp->buffer)->b_data[7];
2936 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2937 + ((STp->buffer)->b_data[ 9] << 16)
2938 + ((STp->buffer)->b_data[10] << 8)
2939 + (STp->buffer)->b_data[11];
2940 STp->cur_frames = (STp->buffer)->b_data[15];
2941#if DEBUG
2942 if (debugging) {
2943 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2944 STp->first_frame_position, STp->last_frame_position,
2945 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2946 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2947 STp->cur_frames);
2948 }
2949#endif
2950 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2951#if DEBUG
2952 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2953 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2954#endif
2955 STp->first_frame_position = STp->last_frame_position;
2956 }
2957 }
2958 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2959
2960 return (result == 0 ? STp->first_frame_position : result);
2961}
2962
2963
2964
2965static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2966{
2967 unsigned char scmd[MAX_COMMAND_SIZE];
2968 struct osst_request * SRpnt;
2969 struct st_partstat * STps;
2970 int result = 0;
2971 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2972 char * name = tape_name(STp);
2973
2974 if (STp->ready != ST_READY) return (-EIO);
2975
2976 STps = &(STp->ps[STp->partition]);
2977
2978 if (ppos < 0 || ppos > STp->capacity) {
2979 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2980 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2981 result = (-EINVAL);
2982 }
2983
2984 do {
2985#if DEBUG
2986 if (debugging)
2987 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2988#endif
2989 memset (scmd, 0, MAX_COMMAND_SIZE);
2990 scmd[0] = SEEK_10;
2991 scmd[1] = 1;
2992 scmd[3] = (pp >> 24);
2993 scmd[4] = (pp >> 16);
2994 scmd[5] = (pp >> 8);
2995 scmd[6] = pp;
2996 if (skip)
2997 scmd[9] = 0x80;
2998
2999 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
3000 MAX_RETRIES, 1);
3001 if (!SRpnt)
3002 return (-EBUSY);
3003 *aSRpnt = SRpnt;
3004
3005 if ((STp->buffer)->syscall_result != 0) {
3006#if DEBUG
3007 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
3008 name, STp->first_frame_position, pp);
3009#endif
3010 result = (-EIO);
3011 }
3012 if (pp != ppos)
3013 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
3014 } while ((pp != ppos) && (pp = ppos));
3015 STp->first_frame_position = STp->last_frame_position = ppos;
3016 STps->eof = ST_NOEOF;
3017 STps->at_sm = 0;
3018 STps->rw = ST_IDLE;
3019 STp->frame_in_buffer = 0;
3020 return result;
3021}
3022
3023static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
3024{
3025 struct st_partstat * STps = &(STp->ps[STp->partition]);
3026 int result = 0;
3027
3028 if (STp->write_type != OS_WRITE_NEW_MARK) {
3029
3030 result = osst_flush_drive_buffer(STp, aSRpnt);
3031 if (result < 0) goto out;
3032 result = osst_write_filemark(STp, aSRpnt);
3033 if (result < 0) goto out;
3034
3035 if (STps->drv_file >= 0)
3036 STps->drv_file++ ;
3037 STps->drv_block = 0;
3038 }
3039 result = osst_write_eod(STp, aSRpnt);
3040 osst_write_header(STp, aSRpnt, leave_at_EOT);
3041
3042 STps->eof = ST_FM;
3043out:
3044 return result;
3045}
3046
3047
3048
3049
3050static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
3051{
3052 int offset, transfer, blks = 0;
3053 int result = 0;
3054 unsigned char cmd[MAX_COMMAND_SIZE];
3055 struct osst_request * SRpnt = *aSRpnt;
3056 struct st_partstat * STps;
3057 char * name = tape_name(STp);
3058
3059 if ((STp->buffer)->writing) {
3060 if (SRpnt == (STp->buffer)->last_SRpnt)
3061#if DEBUG
3062 { printk(OSST_DEB_MSG
3063 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
3064#endif
3065 *aSRpnt = SRpnt = NULL;
3066#if DEBUG
3067 } else if (SRpnt)
3068 printk(OSST_DEB_MSG
3069 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
3070#endif
3071 osst_write_behind_check(STp);
3072 if ((STp->buffer)->syscall_result) {
3073#if DEBUG
3074 if (debugging)
3075 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3076 name, (STp->buffer)->midlevel_result);
3077#endif
3078 if ((STp->buffer)->midlevel_result == INT_MAX)
3079 return (-ENOSPC);
3080 return (-EIO);
3081 }
3082 }
3083
3084 result = 0;
3085 if (STp->dirty == 1) {
3086
3087 STp->write_count++;
3088 STps = &(STp->ps[STp->partition]);
3089 STps->rw = ST_WRITING;
3090 offset = STp->buffer->buffer_bytes;
3091 blks = (offset + STp->block_size - 1) / STp->block_size;
3092 transfer = OS_FRAME_SIZE;
3093
3094 if (offset < OS_DATA_SIZE)
3095 osst_zero_buffer_tail(STp->buffer);
3096
3097 if (STp->poll)
3098 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3099 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3100
3101 memset(cmd, 0, MAX_COMMAND_SIZE);
3102 cmd[0] = WRITE_6;
3103 cmd[1] = 1;
3104 cmd[4] = 1;
3105
3106 switch (STp->write_type) {
3107 case OS_WRITE_DATA:
3108#if DEBUG
3109 if (debugging)
3110 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3111 name, blks, STp->frame_seq_number,
3112 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3113#endif
3114 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3115 STp->logical_blk_num - blks, STp->block_size, blks);
3116 break;
3117 case OS_WRITE_EOD:
3118 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3119 STp->logical_blk_num, 0, 0);
3120 break;
3121 case OS_WRITE_NEW_MARK:
3122 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3123 STp->logical_blk_num++, 0, blks=1);
3124 break;
3125 case OS_WRITE_HEADER:
3126 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3127 break;
3128 default:
3129 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3130 }
3131#if DEBUG
3132 if (debugging)
3133 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3134 name, offset, transfer, blks);
3135#endif
3136
3137 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3138 STp->timeout, MAX_RETRIES, 1);
3139 *aSRpnt = SRpnt;
3140 if (!SRpnt)
3141 return (-EBUSY);
3142
3143 if ((STp->buffer)->syscall_result != 0) {
3144#if DEBUG
3145 printk(OSST_DEB_MSG
3146 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3147 name, SRpnt->sense[0], SRpnt->sense[2],
3148 SRpnt->sense[12], SRpnt->sense[13]);
3149#endif
3150 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3151 (SRpnt->sense[2] & 0x40) &&
3152 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3153 STp->dirty = 0;
3154 (STp->buffer)->buffer_bytes = 0;
3155 result = (-ENOSPC);
3156 }
3157 else {
3158 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3159 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3160 result = (-EIO);
3161 }
3162 }
3163 STps->drv_block = (-1);
3164 }
3165 else {
3166 STp->first_frame_position++;
3167 STp->dirty = 0;
3168 (STp->buffer)->buffer_bytes = 0;
3169 }
3170 }
3171#if DEBUG
3172 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3173#endif
3174 return result;
3175}
3176
3177
3178
3179
3180static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3181{
3182 struct st_partstat * STps;
3183 int backspace = 0, result = 0;
3184#if DEBUG
3185 char * name = tape_name(STp);
3186#endif
3187
3188
3189
3190
3191
3192 if( STp->pos_unknown)
3193 return (-EIO);
3194
3195 if (STp->ready != ST_READY)
3196 return 0;
3197
3198 STps = &(STp->ps[STp->partition]);
3199 if (STps->rw == ST_WRITING || STp->dirty) {
3200 STp->write_type = OS_WRITE_DATA;
3201 return osst_flush_write_buffer(STp, aSRpnt);
3202 }
3203 if (STp->block_size == 0)
3204 return 0;
3205
3206#if DEBUG
3207 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3208#endif
3209
3210 if (!STp->can_bsr) {
3211 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3212 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3213 (STp->buffer)->buffer_bytes = 0;
3214 (STp->buffer)->read_pointer = 0;
3215 STp->frame_in_buffer = 0;
3216 }
3217
3218 if (!seek_next) {
3219 if (STps->eof == ST_FM_HIT) {
3220 result = cross_eof(STp, aSRpnt, 0);
3221 if (!result)
3222 STps->eof = ST_NOEOF;
3223 else {
3224 if (STps->drv_file >= 0)
3225 STps->drv_file++;
3226 STps->drv_block = 0;
3227 }
3228 }
3229 if (!result && backspace > 0)
3230 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3231 }
3232 else if (STps->eof == ST_FM_HIT) {
3233 if (STps->drv_file >= 0)
3234 STps->drv_file++;
3235 STps->drv_block = 0;
3236 STps->eof = ST_NOEOF;
3237 }
3238
3239 return result;
3240}
3241
3242static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3243{
3244 unsigned char cmd[MAX_COMMAND_SIZE];
3245 struct osst_request * SRpnt;
3246 int blks;
3247#if DEBUG
3248 char * name = tape_name(STp);
3249#endif
3250
3251 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) {
3252#if DEBUG
3253 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3254#endif
3255 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3256 return (-EIO);
3257 }
3258
3259 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3260#if DEBUG
3261 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3262#endif
3263 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3264 }
3265 }
3266
3267 if (STp->poll)
3268 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3269 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3270 return (-EIO);
3271
3272
3273
3274 STp->ps[STp->partition].rw = ST_WRITING;
3275 STp->write_type = OS_WRITE_DATA;
3276
3277 memset(cmd, 0, MAX_COMMAND_SIZE);
3278 cmd[0] = WRITE_6;
3279 cmd[1] = 1;
3280 cmd[4] = 1;
3281 blks = STp->buffer->buffer_bytes / STp->block_size;
3282#if DEBUG
3283 if (debugging)
3284 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3285 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3286#endif
3287 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3288 STp->logical_blk_num - blks, STp->block_size, blks);
3289
3290#if DEBUG
3291 if (!synchronous)
3292 STp->write_pending = 1;
3293#endif
3294 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3295 MAX_RETRIES, synchronous);
3296 if (!SRpnt)
3297 return (-EBUSY);
3298 *aSRpnt = SRpnt;
3299
3300 if (synchronous) {
3301 if (STp->buffer->syscall_result != 0) {
3302#if DEBUG
3303 if (debugging)
3304 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3305#endif
3306 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3307 (SRpnt->sense[2] & 0x40)) {
3308 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3309 return (-ENOSPC);
3310 }
3311 else {
3312 if (osst_write_error_recovery(STp, aSRpnt, 1))
3313 return (-EIO);
3314 }
3315 }
3316 else
3317 STp->first_frame_position++;
3318 }
3319
3320 STp->write_count++;
3321
3322 return 0;
3323}
3324
3325
3326static int do_door_lock(struct osst_tape * STp, int do_lock)
3327{
3328 int retval, cmd;
3329
3330 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3331#if DEBUG
3332 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3333#endif
3334 retval = scsi_ioctl(STp->device, cmd, NULL);
3335 if (!retval) {
3336 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3337 }
3338 else {
3339 STp->door_locked = ST_LOCK_FAILS;
3340 }
3341 return retval;
3342}
3343
3344
3345static void reset_state(struct osst_tape *STp)
3346{
3347 int i;
3348 struct st_partstat *STps;
3349
3350 STp->pos_unknown = 0;
3351 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3352 STps = &(STp->ps[i]);
3353 STps->rw = ST_IDLE;
3354 STps->eof = ST_NOEOF;
3355 STps->at_sm = 0;
3356 STps->last_block_valid = 0;
3357 STps->drv_block = -1;
3358 STps->drv_file = -1;
3359 }
3360}
3361
3362
3363
3364
3365
3366static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3367{
3368 ssize_t total, retval = 0;
3369 ssize_t i, do_count, blks, transfer;
3370 int write_threshold;
3371 int doing_write = 0;
3372 const char __user * b_point;
3373 struct osst_request * SRpnt = NULL;
3374 struct st_modedef * STm;
3375 struct st_partstat * STps;
3376 struct osst_tape * STp = filp->private_data;
3377 char * name = tape_name(STp);
3378
3379
3380 if (mutex_lock_interruptible(&STp->lock))
3381 return (-ERESTARTSYS);
3382
3383
3384
3385
3386
3387
3388
3389 if( !scsi_block_when_processing_errors(STp->device) ) {
3390 retval = (-ENXIO);
3391 goto out;
3392 }
3393
3394 if (STp->ready != ST_READY) {
3395 if (STp->ready == ST_NO_TAPE)
3396 retval = (-ENOMEDIUM);
3397 else
3398 retval = (-EIO);
3399 goto out;
3400 }
3401 STm = &(STp->modes[STp->current_mode]);
3402 if (!STm->defined) {
3403 retval = (-ENXIO);
3404 goto out;
3405 }
3406 if (count == 0)
3407 goto out;
3408
3409
3410
3411
3412
3413 if (STp->pos_unknown) {
3414 retval = (-EIO);
3415 goto out;
3416 }
3417
3418#if DEBUG
3419 if (!STp->in_use) {
3420 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3421 retval = (-EIO);
3422 goto out;
3423 }
3424#endif
3425
3426 if (STp->write_prot) {
3427 retval = (-EACCES);
3428 goto out;
3429 }
3430
3431
3432 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3433 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3434 name, count, STp->block_size<1024?
3435 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3436 retval = (-EINVAL);
3437 goto out;
3438 }
3439
3440 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3441 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3442 name, STp->first_frame_position);
3443 retval = (-ENOSPC);
3444 goto out;
3445 }
3446
3447 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3448 STp->door_locked = ST_LOCKED_AUTO;
3449
3450 STps = &(STp->ps[STp->partition]);
3451
3452 if (STps->rw == ST_READING) {
3453#if DEBUG
3454 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3455 STps->drv_file, STps->drv_block);
3456#endif
3457 retval = osst_flush_buffer(STp, &SRpnt, 0);
3458 if (retval)
3459 goto out;
3460 STps->rw = ST_IDLE;
3461 }
3462 if (STps->rw != ST_WRITING) {
3463
3464 if (!STp->header_ok ||
3465 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3466 (STps->drv_file == 0 && STps->drv_block == 0)) {
3467 STp->wrt_pass_cntr++;
3468#if DEBUG
3469 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3470 name, STp->wrt_pass_cntr);
3471#endif
3472 osst_reset_header(STp, &SRpnt);
3473 STps->drv_file = STps->drv_block = 0;
3474 }
3475
3476 else {
3477 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3478 STps->drv_file < 0 || STps->drv_block < 0) {
3479 if (STp->first_frame_position == STp->eod_frame_ppos) {
3480 STps->drv_file = STp->filemark_cnt;
3481 STps->drv_block = 0;
3482 }
3483 else {
3484
3485#if DEBUG
3486 printk(OSST_DEB_MSG
3487 "%s:D: Cannot write at indeterminate position.\n", name);
3488#endif
3489 retval = (-EIO);
3490 goto out;
3491 }
3492 }
3493 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3494 STp->filemark_cnt = STps->drv_file;
3495 STp->last_mark_ppos =
3496 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3497 printk(KERN_WARNING
3498 "%s:W: Overwriting file %d with old write pass counter %d\n",
3499 name, STps->drv_file, STp->wrt_pass_cntr);
3500 printk(KERN_WARNING
3501 "%s:W: may lead to stale data being accepted on reading back!\n",
3502 name);
3503#if DEBUG
3504 printk(OSST_DEB_MSG
3505 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3506 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3507#endif
3508 }
3509 }
3510 STp->fast_open = 0;
3511 }
3512 if (!STp->header_ok) {
3513#if DEBUG
3514 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3515#endif
3516 retval = (-EIO);
3517 goto out;
3518 }
3519
3520 if ((STp->buffer)->writing) {
3521if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3522 osst_write_behind_check(STp);
3523 if ((STp->buffer)->syscall_result) {
3524#if DEBUG
3525 if (debugging)
3526 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3527 (STp->buffer)->midlevel_result);
3528#endif
3529 if ((STp->buffer)->midlevel_result == INT_MAX)
3530 STps->eof = ST_EOM_OK;
3531 else
3532 STps->eof = ST_EOM_ERROR;
3533 }
3534 }
3535 if (STps->eof == ST_EOM_OK) {
3536 retval = (-ENOSPC);
3537 goto out;
3538 }
3539 else if (STps->eof == ST_EOM_ERROR) {
3540 retval = (-EIO);
3541 goto out;
3542 }
3543
3544
3545
3546 if ((copy_from_user(&i, buf, 1) != 0 ||
3547 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3548 retval = (-EFAULT);
3549 goto out;
3550 }
3551
3552 if (!STm->do_buffer_writes) {
3553 write_threshold = 1;
3554 }
3555 else
3556 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3557 if (!STm->do_async_writes)
3558 write_threshold--;
3559
3560 total = count;
3561#if DEBUG
3562 if (debugging)
3563 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3564 name, (int) count, STps->drv_file, STps->drv_block,
3565 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3566#endif
3567 b_point = buf;
3568 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3569 {
3570 doing_write = 1;
3571 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3572 (STp->buffer)->buffer_bytes;
3573 if (do_count > count)
3574 do_count = count;
3575
3576 i = append_to_buffer(b_point, STp->buffer, do_count);
3577 if (i) {
3578 retval = i;
3579 goto out;
3580 }
3581
3582 blks = do_count / STp->block_size;
3583 STp->logical_blk_num += blks;
3584
3585 i = osst_write_frame(STp, &SRpnt, 1);
3586
3587 if (i == (-ENOSPC)) {
3588 transfer = STp->buffer->writing;
3589 if (transfer <= do_count) {
3590 *ppos += do_count - transfer;
3591 count -= do_count - transfer;
3592 if (STps->drv_block >= 0) {
3593 STps->drv_block += (do_count - transfer) / STp->block_size;
3594 }
3595 STps->eof = ST_EOM_OK;
3596 retval = (-ENOSPC);
3597#if DEBUG
3598 if (debugging)
3599 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3600 name, (int) transfer);
3601#endif
3602 }
3603 else {
3604 STps->eof = ST_EOM_ERROR;
3605 STps->drv_block = (-1);
3606 retval = (-EIO);
3607#if DEBUG
3608 if (debugging)
3609 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3610#endif
3611 }
3612 }
3613 else
3614 retval = i;
3615
3616 if (retval < 0) {
3617 if (SRpnt != NULL) {
3618 osst_release_request(SRpnt);
3619 SRpnt = NULL;
3620 }
3621 STp->buffer->buffer_bytes = 0;
3622 STp->dirty = 0;
3623 if (count < total)
3624 retval = total - count;
3625 goto out;
3626 }
3627
3628 *ppos += do_count;
3629 b_point += do_count;
3630 count -= do_count;
3631 if (STps->drv_block >= 0) {
3632 STps->drv_block += blks;
3633 }
3634 STp->buffer->buffer_bytes = 0;
3635 STp->dirty = 0;
3636 }
3637
3638 if (count != 0) {
3639 STp->dirty = 1;
3640 i = append_to_buffer(b_point, STp->buffer, count);
3641 if (i) {
3642 retval = i;
3643 goto out;
3644 }
3645 blks = count / STp->block_size;
3646 STp->logical_blk_num += blks;
3647 if (STps->drv_block >= 0) {
3648 STps->drv_block += blks;
3649 }
3650 *ppos += count;
3651 count = 0;
3652 }
3653
3654 if (doing_write && (STp->buffer)->syscall_result != 0) {
3655 retval = (STp->buffer)->syscall_result;
3656 goto out;
3657 }
3658
3659 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3660
3661 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3662 STp->block_size) * STp->block_size;
3663 STp->dirty = !((STp->buffer)->writing ==
3664 (STp->buffer)->buffer_bytes);
3665
3666 i = osst_write_frame(STp, &SRpnt, 0);
3667 if (i < 0) {
3668 retval = (-EIO);
3669 goto out;
3670 }
3671 SRpnt = NULL;
3672 }
3673 STps->at_sm &= (total == 0);
3674 if (total > 0)
3675 STps->eof = ST_NOEOF;
3676
3677 retval = total;
3678
3679out:
3680 if (SRpnt != NULL) osst_release_request(SRpnt);
3681
3682 mutex_unlock(&STp->lock);
3683
3684 return retval;
3685}
3686
3687
3688
3689static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3690{
3691 ssize_t total, retval = 0;
3692 ssize_t i, transfer;
3693 int special;
3694 struct st_modedef * STm;
3695 struct st_partstat * STps;
3696 struct osst_request * SRpnt = NULL;
3697 struct osst_tape * STp = filp->private_data;
3698 char * name = tape_name(STp);
3699
3700
3701 if (mutex_lock_interruptible(&STp->lock))
3702 return (-ERESTARTSYS);
3703
3704
3705
3706
3707
3708
3709
3710 if( !scsi_block_when_processing_errors(STp->device) ) {
3711 retval = (-ENXIO);
3712 goto out;
3713 }
3714
3715 if (STp->ready != ST_READY) {
3716 if (STp->ready == ST_NO_TAPE)
3717 retval = (-ENOMEDIUM);
3718 else
3719 retval = (-EIO);
3720 goto out;
3721 }
3722 STm = &(STp->modes[STp->current_mode]);
3723 if (!STm->defined) {
3724 retval = (-ENXIO);
3725 goto out;
3726 }
3727#if DEBUG
3728 if (!STp->in_use) {
3729 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3730 retval = (-EIO);
3731 goto out;
3732 }
3733#endif
3734
3735 if (!STp->header_ok) {
3736 retval = (-EIO);
3737 goto out;
3738 }
3739
3740 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3741 STp->door_locked = ST_LOCKED_AUTO;
3742
3743 STps = &(STp->ps[STp->partition]);
3744 if (STps->rw == ST_WRITING) {
3745 retval = osst_flush_buffer(STp, &SRpnt, 0);
3746 if (retval)
3747 goto out;
3748 STps->rw = ST_IDLE;
3749
3750 }
3751
3752 if ((count % STp->block_size) != 0) {
3753 printk(KERN_WARNING
3754 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3755 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3756 }
3757
3758#if DEBUG
3759 if (debugging && STps->eof != ST_NOEOF)
3760 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3761 STps->eof, (STp->buffer)->buffer_bytes);
3762#endif
3763 if ((STp->buffer)->buffer_bytes == 0 &&
3764 STps->eof >= ST_EOD_1) {
3765 if (STps->eof < ST_EOD) {
3766 STps->eof += 1;
3767 retval = 0;
3768 goto out;
3769 }
3770 retval = (-EIO);
3771 goto out;
3772 }
3773
3774
3775
3776 if (copy_from_user(&i, buf, 1) != 0 ||
3777 copy_to_user (buf, &i, 1) != 0 ||
3778 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3779 copy_to_user (buf + count - 1, &i, 1) != 0) {
3780 retval = (-EFAULT);
3781 goto out;
3782 }
3783
3784
3785 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3786
3787
3788 if ((STp->buffer)->buffer_bytes == 0) {
3789 if (STps->eof == ST_FM_HIT)
3790 break;
3791 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3792 if (special < 0) {
3793 STp->frame_in_buffer = 0;
3794 retval = special;
3795 goto out;
3796 }
3797 }
3798
3799
3800 if ((STp->buffer)->buffer_bytes > 0) {
3801#if DEBUG
3802 if (debugging && STps->eof != ST_NOEOF)
3803 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3804 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3805#endif
3806
3807 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3808 (STp->buffer)->buffer_bytes : count - total)/
3809 STp->block_size) * STp->block_size;
3810
3811 if (transfer == 0) {
3812 printk(KERN_WARNING
3813 "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n",
3814 name, count, STp->block_size < 1024?
3815 STp->block_size:STp->block_size/1024,
3816 STp->block_size<1024?'b':'k');
3817 break;
3818 }
3819 i = from_buffer(STp->buffer, buf, transfer);
3820 if (i) {
3821 retval = i;
3822 goto out;
3823 }
3824 STp->logical_blk_num += transfer / STp->block_size;
3825 STps->drv_block += transfer / STp->block_size;
3826 *ppos += transfer;
3827 buf += transfer;
3828 total += transfer;
3829 }
3830
3831 if ((STp->buffer)->buffer_bytes == 0) {
3832#if DEBUG
3833 if (debugging)
3834 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3835 name, STp->frame_seq_number);
3836#endif
3837 STp->frame_in_buffer = 0;
3838 STp->frame_seq_number++;
3839 }
3840 }
3841
3842
3843 if (total == 0) {
3844 if (STps->eof == ST_FM_HIT) {
3845 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3846 STps->drv_block = 0;
3847 if (STps->drv_file >= 0)
3848 STps->drv_file++;
3849 }
3850 else if (STps->eof == ST_EOD_1) {
3851 STps->eof = ST_EOD_2;
3852 if (STps->drv_block > 0 && STps->drv_file >= 0)
3853 STps->drv_file++;
3854 STps->drv_block = 0;
3855 }
3856 else if (STps->eof == ST_EOD_2)
3857 STps->eof = ST_EOD;
3858 }
3859 else if (STps->eof == ST_FM)
3860 STps->eof = ST_NOEOF;
3861
3862 retval = total;
3863
3864out:
3865 if (SRpnt != NULL) osst_release_request(SRpnt);
3866
3867 mutex_unlock(&STp->lock);
3868
3869 return retval;
3870}
3871
3872
3873
3874static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3875{
3876 printk(KERN_INFO
3877"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3878 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3879 STm->do_read_ahead);
3880 printk(KERN_INFO
3881"%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3882 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3883 printk(KERN_INFO
3884"%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3885 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3886 STp->scsi2_logical);
3887 printk(KERN_INFO
3888"%s:I: sysv: %d\n", name, STm->sysv);
3889#if DEBUG
3890 printk(KERN_INFO
3891 "%s:D: debugging: %d\n",
3892 name, debugging);
3893#endif
3894}
3895
3896
3897static int osst_set_options(struct osst_tape *STp, long options)
3898{
3899 int value;
3900 long code;
3901 struct st_modedef * STm;
3902 char * name = tape_name(STp);
3903
3904 STm = &(STp->modes[STp->current_mode]);
3905 if (!STm->defined) {
3906 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3907 modes_defined = 1;
3908#if DEBUG
3909 if (debugging)
3910 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3911 name, STp->current_mode);
3912#endif
3913 }
3914
3915 code = options & MT_ST_OPTIONS;
3916 if (code == MT_ST_BOOLEANS) {
3917 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3918 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3919 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3920 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3921 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3922 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3923 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3924 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3925 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3926 if ((STp->device)->scsi_level >= SCSI_2)
3927 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3928 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3929 STm->sysv = (options & MT_ST_SYSV) != 0;
3930#if DEBUG
3931 debugging = (options & MT_ST_DEBUGGING) != 0;
3932#endif
3933 osst_log_options(STp, STm, name);
3934 }
3935 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3936 value = (code == MT_ST_SETBOOLEANS);
3937 if ((options & MT_ST_BUFFER_WRITES) != 0)
3938 STm->do_buffer_writes = value;
3939 if ((options & MT_ST_ASYNC_WRITES) != 0)
3940 STm->do_async_writes = value;
3941 if ((options & MT_ST_DEF_WRITES) != 0)
3942 STm->defaults_for_writes = value;
3943 if ((options & MT_ST_READ_AHEAD) != 0)
3944 STm->do_read_ahead = value;
3945 if ((options & MT_ST_TWO_FM) != 0)
3946 STp->two_fm = value;
3947 if ((options & MT_ST_FAST_MTEOM) != 0)
3948 STp->fast_mteom = value;
3949 if ((options & MT_ST_AUTO_LOCK) != 0)
3950 STp->do_auto_lock = value;
3951 if ((options & MT_ST_CAN_BSR) != 0)
3952 STp->can_bsr = value;
3953 if ((options & MT_ST_NO_BLKLIMS) != 0)
3954 STp->omit_blklims = value;
3955 if ((STp->device)->scsi_level >= SCSI_2 &&
3956 (options & MT_ST_CAN_PARTITIONS) != 0)
3957 STp->can_partitions = value;
3958 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3959 STp->scsi2_logical = value;
3960 if ((options & MT_ST_SYSV) != 0)
3961 STm->sysv = value;
3962#if DEBUG
3963 if ((options & MT_ST_DEBUGGING) != 0)
3964 debugging = value;
3965#endif
3966 osst_log_options(STp, STm, name);
3967 }
3968 else if (code == MT_ST_WRITE_THRESHOLD) {
3969 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3970 if (value < 1 || value > osst_buffer_size) {
3971 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3972 name, value);
3973 return (-EIO);
3974 }
3975 STp->write_threshold = value;
3976 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3977 name, value);
3978 }
3979 else if (code == MT_ST_DEF_BLKSIZE) {
3980 value = (options & ~MT_ST_OPTIONS);
3981 if (value == ~MT_ST_OPTIONS) {
3982 STm->default_blksize = (-1);
3983 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3984 }
3985 else {
3986 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3987 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3988 name, value);
3989 return (-EINVAL);
3990 }
3991 STm->default_blksize = value;
3992 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3993 name, STm->default_blksize);
3994 }
3995 }
3996 else if (code == MT_ST_TIMEOUTS) {
3997 value = (options & ~MT_ST_OPTIONS);
3998 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3999 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
4000 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
4001 (value & ~MT_ST_SET_LONG_TIMEOUT));
4002 }
4003 else {
4004 STp->timeout = value * HZ;
4005 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
4006 }
4007 }
4008 else if (code == MT_ST_DEF_OPTIONS) {
4009 code = (options & ~MT_ST_CLEAR_DEFAULT);
4010 value = (options & MT_ST_CLEAR_DEFAULT);
4011 if (code == MT_ST_DEF_DENSITY) {
4012 if (value == MT_ST_CLEAR_DEFAULT) {
4013 STm->default_density = (-1);
4014 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
4015 }
4016 else {
4017 STm->default_density = value & 0xff;
4018 printk(KERN_INFO "%s:I: Density default set to %x\n",
4019 name, STm->default_density);
4020 }
4021 }
4022 else if (code == MT_ST_DEF_DRVBUFFER) {
4023 if (value == MT_ST_CLEAR_DEFAULT) {
4024 STp->default_drvbuffer = 0xff;
4025 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
4026 }
4027 else {
4028 STp->default_drvbuffer = value & 7;
4029 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
4030 name, STp->default_drvbuffer);
4031 }
4032 }
4033 else if (code == MT_ST_DEF_COMPRESSION) {
4034 if (value == MT_ST_CLEAR_DEFAULT) {
4035 STm->default_compression = ST_DONT_TOUCH;
4036 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
4037 }
4038 else {
4039 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
4040 printk(KERN_INFO "%s:I: Compression default set to %x\n",
4041 name, (value & 1));
4042 }
4043 }
4044 }
4045 else
4046 return (-EIO);
4047
4048 return 0;
4049}
4050
4051
4052
4053static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
4054 unsigned int cmd_in, unsigned long arg)
4055{
4056 int timeout;
4057 long ltmp;
4058 int i, ioctl_result;
4059 int chg_eof = 1;
4060 unsigned char cmd[MAX_COMMAND_SIZE];
4061 struct osst_request * SRpnt = * aSRpnt;
4062 struct st_partstat * STps;
4063 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
4064 int datalen = 0, direction = DMA_NONE;
4065 char * name = tape_name(STp);
4066
4067 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
4068 if (STp->ready == ST_NO_TAPE)
4069 return (-ENOMEDIUM);
4070 else
4071 return (-EIO);
4072 }
4073 timeout = STp->long_timeout;
4074 STps = &(STp->ps[STp->partition]);
4075 fileno = STps->drv_file;
4076 blkno = STps->drv_block;
4077 at_sm = STps->at_sm;
4078 frame_seq_numbr = STp->frame_seq_number;
4079 logical_blk_num = STp->logical_blk_num;
4080
4081 memset(cmd, 0, MAX_COMMAND_SIZE);
4082 switch (cmd_in) {
4083 case MTFSFM:
4084 chg_eof = 0;
4085 case MTFSF:
4086 if (STp->raw)
4087 return (-EIO);
4088 if (STp->linux_media)
4089 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4090 else
4091 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4092 if (fileno >= 0)
4093 fileno += arg;
4094 blkno = 0;
4095 at_sm &= (arg == 0);
4096 goto os_bypass;
4097
4098 case MTBSF:
4099 chg_eof = 0;
4100 case MTBSFM:
4101 if (STp->raw)
4102 return (-EIO);
4103 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4104 if (fileno >= 0)
4105 fileno -= arg;
4106 blkno = (-1);
4107 at_sm &= (arg == 0);
4108 goto os_bypass;
4109
4110 case MTFSR:
4111 case MTBSR:
4112#if DEBUG
4113 if (debugging)
4114 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4115 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4116#endif
4117 if (cmd_in == MTFSR) {
4118 logical_blk_num += arg;
4119 if (blkno >= 0) blkno += arg;
4120 }
4121 else {
4122 logical_blk_num -= arg;
4123 if (blkno >= 0) blkno -= arg;
4124 }
4125 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4126 fileno = STps->drv_file;
4127 blkno = STps->drv_block;
4128 at_sm &= (arg == 0);
4129 goto os_bypass;
4130
4131 case MTFSS:
4132 cmd[0] = SPACE;
4133 cmd[1] = 0x04;
4134 cmd[2] = (arg >> 16);
4135 cmd[3] = (arg >> 8);
4136 cmd[4] = arg;
4137#if DEBUG
4138 if (debugging)
4139 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4140 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4141#endif
4142 if (arg != 0) {
4143 blkno = fileno = (-1);
4144 at_sm = 1;
4145 }
4146 break;
4147 case MTBSS:
4148 cmd[0] = SPACE;
4149 cmd[1] = 0x04;
4150 ltmp = (-arg);
4151 cmd[2] = (ltmp >> 16);
4152 cmd[3] = (ltmp >> 8);
4153 cmd[4] = ltmp;
4154#if DEBUG
4155 if (debugging) {
4156 if (cmd[2] & 0x80)
4157 ltmp = 0xff000000;
4158 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4159 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4160 name, (-ltmp));
4161 }
4162#endif
4163 if (arg != 0) {
4164 blkno = fileno = (-1);
4165 at_sm = 1;
4166 }
4167 break;
4168 case MTWEOF:
4169 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4170 STp->write_type = OS_WRITE_DATA;
4171 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4172 } else
4173 ioctl_result = 0;
4174#if DEBUG
4175 if (debugging)
4176 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4177#endif
4178 for (i=0; i<arg; i++)
4179 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4180 if (fileno >= 0) fileno += arg;
4181 if (blkno >= 0) blkno = 0;
4182 goto os_bypass;
4183
4184 case MTWSM:
4185 if (STp->write_prot)
4186 return (-EACCES);
4187 if (!STp->raw)
4188 return 0;
4189 cmd[0] = WRITE_FILEMARKS;
4190 if (cmd_in == MTWSM)
4191 cmd[1] = 2;
4192 cmd[2] = (arg >> 16);
4193 cmd[3] = (arg >> 8);
4194 cmd[4] = arg;
4195 timeout = STp->timeout;
4196#if DEBUG
4197 if (debugging)
4198 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4199 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4200#endif
4201 if (fileno >= 0)
4202 fileno += arg;
4203 blkno = 0;
4204 at_sm = (cmd_in == MTWSM);
4205 break;
4206 case MTOFFL:
4207 case MTLOAD:
4208 case MTUNLOAD:
4209 case MTRETEN:
4210 cmd[0] = START_STOP;
4211 cmd[1] = 1;
4212 if (cmd_in == MTLOAD) {
4213 if (STp->ready == ST_NO_TAPE)
4214 cmd[4] = 4;
4215 else
4216 cmd[4] = 1;
4217 }
4218 if (cmd_in == MTRETEN)
4219 cmd[4] = 3;
4220 if (cmd_in == MTOFFL)
4221 cmd[4] = 4;
4222 timeout = STp->timeout;
4223#if DEBUG
4224 if (debugging) {
4225 switch (cmd_in) {
4226 case MTUNLOAD:
4227 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4228 break;
4229 case MTLOAD:
4230 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4231 break;
4232 case MTRETEN:
4233 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4234 break;
4235 case MTOFFL:
4236 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4237 break;
4238 }
4239 }
4240#endif
4241 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4242 break;
4243 case MTNOP:
4244#if DEBUG
4245 if (debugging)
4246 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4247#endif
4248 return 0;
4249 break;
4250 case MTEOM:
4251#if DEBUG
4252 if (debugging)
4253 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4254#endif
4255 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4256 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4257 ioctl_result = -EIO;
4258 goto os_bypass;
4259 }
4260 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4261#if DEBUG
4262 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4263#endif
4264 ioctl_result = -EIO;
4265 goto os_bypass;
4266 }
4267 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4268 fileno = STp->filemark_cnt;
4269 blkno = at_sm = 0;
4270 goto os_bypass;
4271
4272 case MTERASE:
4273 if (STp->write_prot)
4274 return (-EACCES);
4275 ioctl_result = osst_reset_header(STp, &SRpnt);
4276 i = osst_write_eod(STp, &SRpnt);
4277 if (i < ioctl_result) ioctl_result = i;
4278 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4279 if (i < ioctl_result) ioctl_result = i;
4280 fileno = blkno = at_sm = 0 ;
4281 goto os_bypass;
4282
4283 case MTREW:
4284 cmd[0] = REZERO_UNIT;
4285 cmd[1] = 1;
4286#if DEBUG
4287 if (debugging)
4288 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4289#endif
4290 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4291 break;
4292
4293 case MTSETBLK:
4294 if ((STps->drv_block == 0 ) &&
4295 !STp->dirty &&
4296 ((STp->buffer)->buffer_bytes == 0) &&
4297 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4298 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4299 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4300
4301
4302
4303
4304
4305
4306 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4307 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4308 name, STp->block_size);
4309 return 0;
4310 }
4311 case MTSETDENSITY:
4312 case MTSETDRVBUFFER:
4313 case SET_DENS_AND_BLK:
4314 chg_eof = 0;
4315 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4316 return (-EIO);
4317 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4318 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4319 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4320 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4321 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4322 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4323 return (-EINVAL);
4324 }
4325 return 0;
4326
4327 default:
4328 return (-ENOSYS);
4329 }
4330
4331 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4332
4333 ioctl_result = (STp->buffer)->syscall_result;
4334
4335 if (!SRpnt) {
4336#if DEBUG
4337 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4338#endif
4339 return ioctl_result;
4340 }
4341
4342 if (!ioctl_result) {
4343 STp->frame_seq_number = frame_seq_numbr;
4344 STp->logical_blk_num = logical_blk_num;
4345 }
4346
4347os_bypass:
4348#if DEBUG
4349 if (debugging)
4350 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4351#endif
4352
4353 if (!ioctl_result) {
4354
4355 if (cmd_in == MTFSFM) {
4356 fileno--;
4357 blkno--;
4358 }
4359 if (cmd_in == MTBSFM) {
4360 fileno++;
4361 blkno++;
4362 }
4363 STps->drv_block = blkno;
4364 STps->drv_file = fileno;
4365 STps->at_sm = at_sm;
4366
4367 if (cmd_in == MTEOM)
4368 STps->eof = ST_EOD;
4369 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4370 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4371 STps->drv_block++;
4372 STp->logical_blk_num++;
4373 STp->frame_seq_number++;
4374 STp->frame_in_buffer = 0;
4375 STp->buffer->read_pointer = 0;
4376 }
4377 else if (cmd_in == MTFSF)
4378 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4379 else if (chg_eof)
4380 STps->eof = ST_NOEOF;
4381
4382 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4383 STp->rew_at_close = 0;
4384 else if (cmd_in == MTLOAD) {
4385 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4386 STp->ps[i].rw = ST_IDLE;
4387 STp->ps[i].last_block_valid = 0;
4388 }
4389 STp->partition = 0;
4390 }
4391
4392 if (cmd_in == MTREW) {
4393 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4394 if (ioctl_result > 0)
4395 ioctl_result = 0;
4396 }
4397
4398 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4399 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4400 STps->drv_file = STps->drv_block = -1;
4401 else
4402 STps->drv_file = STps->drv_block = 0;
4403 STps->eof = ST_NOEOF;
4404 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4405 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4406 STps->drv_file = STps->drv_block = -1;
4407 else {
4408 STps->drv_file = STp->filemark_cnt;
4409 STps->drv_block = 0;
4410 }
4411 STps->eof = ST_EOD;
4412 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4413 STps->drv_file = STps->drv_block = (-1);
4414 STps->eof = ST_NOEOF;
4415 STp->header_ok = 0;
4416 } else if (cmd_in == MTERASE) {
4417 STp->header_ok = 0;
4418 } else if (SRpnt) {
4419 if (SRpnt->sense[2] & 0x40) {
4420 STps->eof = ST_EOM_OK;
4421 STps->drv_block = 0;
4422 }
4423 if (chg_eof)
4424 STps->eof = ST_NOEOF;
4425
4426 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4427 STps->eof = ST_EOD;
4428
4429 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4430 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4431 }
4432 *aSRpnt = SRpnt;
4433
4434 return ioctl_result;
4435}
4436
4437
4438
4439static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4440{
4441 unsigned short flags;
4442 int i, b_size, new_session = 0, retval = 0;
4443 unsigned char cmd[MAX_COMMAND_SIZE];
4444 struct osst_request * SRpnt = NULL;
4445 struct osst_tape * STp;
4446 struct st_modedef * STm;
4447 struct st_partstat * STps;
4448 char * name;
4449 int dev = TAPE_NR(inode);
4450 int mode = TAPE_MODE(inode);
4451
4452
4453
4454
4455
4456
4457 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4458
4459 write_lock(&os_scsi_tapes_lock);
4460 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4461 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4462 write_unlock(&os_scsi_tapes_lock);
4463 return (-ENXIO);
4464 }
4465
4466 name = tape_name(STp);
4467
4468 if (STp->in_use) {
4469 write_unlock(&os_scsi_tapes_lock);
4470#if DEBUG
4471 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4472#endif
4473 return (-EBUSY);
4474 }
4475 if (scsi_device_get(STp->device)) {
4476 write_unlock(&os_scsi_tapes_lock);
4477#if DEBUG
4478 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4479#endif
4480 return (-ENXIO);
4481 }
4482 filp->private_data = STp;
4483 STp->in_use = 1;
4484 write_unlock(&os_scsi_tapes_lock);
4485 STp->rew_at_close = TAPE_REWIND(inode);
4486
4487 if( !scsi_block_when_processing_errors(STp->device) ) {
4488 return -ENXIO;
4489 }
4490
4491 if (mode != STp->current_mode) {
4492#if DEBUG
4493 if (debugging)
4494 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4495 name, STp->current_mode, mode);
4496#endif
4497 new_session = 1;
4498 STp->current_mode = mode;
4499 }
4500 STm = &(STp->modes[STp->current_mode]);
4501
4502 flags = filp->f_flags;
4503 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4504
4505 STp->raw = TAPE_IS_RAW(inode);
4506 if (STp->raw)
4507 STp->header_ok = 0;
4508
4509
4510 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4511 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4512 retval = (-EOVERFLOW);
4513 goto err_out;
4514 }
4515 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4516 for (i = 0, b_size = 0;
4517 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4518 b_size += STp->buffer->sg[i++].length);
4519 STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4520#if DEBUG
4521 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4522 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4523 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4524 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4525#endif
4526 } else {
4527 STp->buffer->aux = NULL;
4528 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4529 retval = (-EIO);
4530 goto err_out;
4531 }
4532 STp->buffer->writing = 0;
4533 STp->buffer->syscall_result = 0;
4534 STp->dirty = 0;
4535 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4536 STps = &(STp->ps[i]);
4537 STps->rw = ST_IDLE;
4538 }
4539 STp->ready = ST_READY;
4540#if DEBUG
4541 STp->nbr_waits = STp->nbr_finished = 0;
4542#endif
4543
4544 memset (cmd, 0, MAX_COMMAND_SIZE);
4545 cmd[0] = TEST_UNIT_READY;
4546
4547 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4548 if (!SRpnt) {
4549 retval = (STp->buffer)->syscall_result;
4550 goto err_out;
4551 }
4552 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4553 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4554 SRpnt->sense[12] == 4 ) {
4555#if DEBUG
4556 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4557#endif
4558 if (filp->f_flags & O_NONBLOCK) {
4559 retval = -EAGAIN;
4560 goto err_out;
4561 }
4562 if (SRpnt->sense[13] == 2) {
4563 memset (cmd, 0, MAX_COMMAND_SIZE);
4564 cmd[0] = START_STOP;
4565 cmd[1] = 1;
4566 cmd[4] = 1;
4567 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4568 STp->timeout, MAX_RETRIES, 1);
4569 }
4570 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4571 }
4572 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4573 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4574#if DEBUG
4575 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4576#endif
4577 STp->header_ok = 0;
4578
4579 for (i=0; i < 10; i++) {
4580
4581 memset (cmd, 0, MAX_COMMAND_SIZE);
4582 cmd[0] = TEST_UNIT_READY;
4583
4584 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4585 STp->timeout, MAX_RETRIES, 1);
4586 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4587 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4588 break;
4589 }
4590
4591 STp->pos_unknown = 0;
4592 STp->partition = STp->new_partition = 0;
4593 if (STp->can_partitions)
4594 STp->nbr_partitions = 1;
4595 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4596 STps = &(STp->ps[i]);
4597 STps->rw = ST_IDLE;
4598 STps->eof = ST_NOEOF;
4599 STps->at_sm = 0;
4600 STps->last_block_valid = 0;
4601 STps->drv_block = 0;
4602 STps->drv_file = 0 ;
4603 }
4604 new_session = 1;
4605 STp->recover_count = 0;
4606 STp->abort_count = 0;
4607 }
4608
4609
4610
4611
4612 if (!STp->buffer->syscall_result && STp->header_ok &&
4613 !SRpnt->result && SRpnt->sense[0] == 0) {
4614
4615 memset(cmd, 0, MAX_COMMAND_SIZE);
4616 cmd[0] = MODE_SENSE;
4617 cmd[1] = 8;
4618 cmd[2] = VENDOR_IDENT_PAGE;
4619 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4620
4621 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4622
4623 if (STp->buffer->syscall_result ||
4624 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4625 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4626 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4627 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4628#if DEBUG
4629 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4630 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4631 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4632 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4633 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4634#endif
4635 STp->header_ok = 0;
4636 }
4637 i = STp->first_frame_position;
4638 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4639 if (STp->door_locked == ST_UNLOCKED) {
4640 if (do_door_lock(STp, 1))
4641 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4642 else
4643 STp->door_locked = ST_LOCKED_AUTO;
4644 }
4645 if (!STp->frame_in_buffer) {
4646 STp->block_size = (STm->default_blksize > 0) ?
4647 STm->default_blksize : OS_DATA_SIZE;
4648 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4649 }
4650 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4651 STp->fast_open = 1;
4652 osst_release_request(SRpnt);
4653 return 0;
4654 }
4655#if DEBUG
4656 if (i != STp->first_frame_position)
4657 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4658 name, i, STp->first_frame_position);
4659#endif
4660 STp->header_ok = 0;
4661 }
4662 STp->fast_open = 0;
4663
4664 if ((STp->buffer)->syscall_result != 0 &&
4665 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4666
4667 memset(cmd, 0, MAX_COMMAND_SIZE);
4668 cmd[0] = MODE_SELECT;
4669 cmd[1] = 0x10;
4670 cmd[4] = 4 + MODE_HEADER_LENGTH;
4671
4672 (STp->buffer)->b_data[0] = cmd[4] - 1;
4673 (STp->buffer)->b_data[1] = 0;
4674 (STp->buffer)->b_data[2] = 0;
4675 (STp->buffer)->b_data[3] = 0;
4676 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4677 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4678 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4679 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4680
4681#if DEBUG
4682 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4683#endif
4684 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4685
4686 STp->header_ok = 0;
4687
4688 for (i=0; i < 10; i++) {
4689
4690 memset (cmd, 0, MAX_COMMAND_SIZE);
4691 cmd[0] = TEST_UNIT_READY;
4692
4693 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4694 STp->timeout, MAX_RETRIES, 1);
4695 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4696 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4697 break;
4698
4699 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4700 int j;
4701
4702 STp->pos_unknown = 0;
4703 STp->partition = STp->new_partition = 0;
4704 if (STp->can_partitions)
4705 STp->nbr_partitions = 1;
4706 for (j = 0; j < ST_NBR_PARTITIONS; j++) {
4707 STps = &(STp->ps[j]);
4708 STps->rw = ST_IDLE;
4709 STps->eof = ST_NOEOF;
4710 STps->at_sm = 0;
4711 STps->last_block_valid = 0;
4712 STps->drv_block = 0;
4713 STps->drv_file = 0 ;
4714 }
4715 new_session = 1;
4716 }
4717 }
4718 }
4719
4720 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))
4721 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4722
4723 if ((STp->buffer)->syscall_result != 0) {
4724 if ((STp->device)->scsi_level >= SCSI_2 &&
4725 (SRpnt-&g