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#include <asm/system.h>
58
59
60
61#define DEBUG 0
62
63
64
65
66#define OSST_DEB_MSG KERN_NOTICE
67
68#include <scsi/scsi.h>
69#include <scsi/scsi_dbg.h>
70#include <scsi/scsi_device.h>
71#include <scsi/scsi_driver.h>
72#include <scsi/scsi_eh.h>
73#include <scsi/scsi_host.h>
74#include <scsi/scsi_ioctl.h>
75
76#define ST_KILOBYTE 1024
77
78#include "st.h"
79#include "osst.h"
80#include "osst_options.h"
81#include "osst_detect.h"
82
83static DEFINE_MUTEX(osst_int_mutex);
84static int max_dev = 0;
85static int write_threshold_kbs = 0;
86static int max_sg_segs = 0;
87
88#ifdef MODULE
89MODULE_AUTHOR("Willem Riede");
90MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
91MODULE_LICENSE("GPL");
92MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
93MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
94
95module_param(max_dev, int, 0444);
96MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
97
98module_param(write_threshold_kbs, int, 0644);
99MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
100
101module_param(max_sg_segs, int, 0644);
102MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
103#else
104static struct osst_dev_parm {
105 char *name;
106 int *val;
107} parms[] __initdata = {
108 { "max_dev", &max_dev },
109 { "write_threshold_kbs", &write_threshold_kbs },
110 { "max_sg_segs", &max_sg_segs }
111};
112#endif
113
114
115#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
116#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
117
118
119
120#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
121#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
122#endif
123
124#if DEBUG
125static int debugging = 1;
126
127
128#endif
129
130
131
132#define MAX_RETRIES 0
133
134#define NO_TAPE NOT_READY
135
136#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
137#define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
138#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
139
140#define OSST_TIMEOUT (200 * HZ)
141#define OSST_LONG_TIMEOUT (1800 * HZ)
142
143#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
144#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
145#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
146#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
147
148
149
150#define SET_DENS_AND_BLK 0x10001
151
152static int osst_buffer_size = OSST_BUFFER_SIZE;
153static int osst_write_threshold = OSST_WRITE_THRESHOLD;
154static int osst_max_sg_segs = OSST_MAX_SG;
155static int osst_max_dev = OSST_MAX_TAPES;
156static int osst_nr_dev;
157
158static struct osst_tape **os_scsi_tapes = NULL;
159static DEFINE_RWLOCK(os_scsi_tapes_lock);
160
161static int modes_defined = 0;
162
163static struct osst_buffer *new_tape_buffer(int, int, int);
164static int enlarge_buffer(struct osst_buffer *, int);
165static void normalize_buffer(struct osst_buffer *);
166static int append_to_buffer(const char __user *, struct osst_buffer *, int);
167static int from_buffer(struct osst_buffer *, char __user *, int);
168static int osst_zero_buffer_tail(struct osst_buffer *);
169static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
170static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
171
172static int osst_probe(struct device *);
173static int osst_remove(struct device *);
174
175static struct scsi_driver osst_template = {
176 .owner = THIS_MODULE,
177 .gendrv = {
178 .name = "osst",
179 .probe = osst_probe,
180 .remove = osst_remove,
181 }
182};
183
184static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
185 unsigned int cmd_in, unsigned long arg);
186
187static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
188
189static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
190
191static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
192
193static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
194
195static inline char *tape_name(struct osst_tape *tape)
196{
197 return tape->drive->disk_name;
198}
199
200
201
202
203
204static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
205{
206 const u8 *ucp;
207 const u8 *sense = SRpnt->sense;
208
209 s->have_sense = scsi_normalize_sense(SRpnt->sense,
210 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
211 s->flags = 0;
212
213 if (s->have_sense) {
214 s->deferred = 0;
215 s->remainder_valid =
216 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
217 switch (sense[0] & 0x7f) {
218 case 0x71:
219 s->deferred = 1;
220 case 0x70:
221 s->fixed_format = 1;
222 s->flags = sense[2] & 0xe0;
223 break;
224 case 0x73:
225 s->deferred = 1;
226 case 0x72:
227 s->fixed_format = 0;
228 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
229 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
230 break;
231 }
232 }
233}
234
235
236static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
237{
238 char *name = tape_name(STp);
239 int result = SRpnt->result;
240 u8 * sense = SRpnt->sense, scode;
241#if DEBUG
242 const char *stp;
243#endif
244 struct st_cmdstatus *cmdstatp;
245
246 if (!result)
247 return 0;
248
249 cmdstatp = &STp->buffer->cmdstat;
250 osst_analyze_sense(SRpnt, cmdstatp);
251
252 if (cmdstatp->have_sense)
253 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
254 else
255 scode = 0;
256#if DEBUG
257 if (debugging) {
258 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
259 name, result,
260 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
261 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
262 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
263 name, scode, sense[12], sense[13]);
264 if (cmdstatp->have_sense)
265 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
266 }
267 else
268#endif
269 if (cmdstatp->have_sense && (
270 scode != NO_SENSE &&
271 scode != RECOVERED_ERROR &&
272
273 scode != BLANK_CHECK &&
274 scode != VOLUME_OVERFLOW &&
275 SRpnt->cmd[0] != MODE_SENSE &&
276 SRpnt->cmd[0] != TEST_UNIT_READY)) {
277 if (cmdstatp->have_sense) {
278 printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
279 __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
280 }
281 else {
282 static int notyetprinted = 1;
283
284 printk(KERN_WARNING
285 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
286 name, result, driver_byte(result),
287 host_byte(result));
288 if (notyetprinted) {
289 notyetprinted = 0;
290 printk(KERN_INFO
291 "%s:I: This warning may be caused by your scsi controller,\n", name);
292 printk(KERN_INFO
293 "%s:I: it has been reported with some Buslogic cards.\n", name);
294 }
295 }
296 }
297 STp->pos_unknown |= STp->device->was_reset;
298
299 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
300 STp->recover_count++;
301 STp->recover_erreg++;
302#if DEBUG
303 if (debugging) {
304 if (SRpnt->cmd[0] == READ_6)
305 stp = "read";
306 else if (SRpnt->cmd[0] == WRITE_6)
307 stp = "write";
308 else
309 stp = "ioctl";
310 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
311 STp->recover_count);
312 }
313#endif
314 if ((sense[2] & 0xe0) == 0)
315 return 0;
316 }
317 return (-EIO);
318}
319
320
321
322static void osst_end_async(struct request *req, int update)
323{
324 struct osst_request *SRpnt = req->end_io_data;
325 struct osst_tape *STp = SRpnt->stp;
326 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
327
328 STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
329#if DEBUG
330 STp->write_pending = 0;
331#endif
332 if (SRpnt->waiting)
333 complete(SRpnt->waiting);
334
335 if (SRpnt->bio) {
336 kfree(mdata->pages);
337 blk_rq_unmap_user(SRpnt->bio);
338 }
339
340 __blk_put_request(req->q, req);
341}
342
343
344static struct osst_request *osst_allocate_request(void)
345{
346 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
347}
348
349static void osst_release_request(struct osst_request *streq)
350{
351 kfree(streq);
352}
353
354static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
355 int cmd_len, int data_direction, void *buffer, unsigned bufflen,
356 int use_sg, int timeout, int retries)
357{
358 struct request *req;
359 struct page **pages = NULL;
360 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
361
362 int err = 0;
363 int write = (data_direction == DMA_TO_DEVICE);
364
365 req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
366 if (!req)
367 return DRIVER_ERROR << 24;
368
369 req->cmd_type = REQ_TYPE_BLOCK_PC;
370 req->cmd_flags |= REQ_QUIET;
371
372 SRpnt->bio = NULL;
373
374 if (use_sg) {
375 struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
376 int i;
377
378 pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
379 if (!pages)
380 goto free_req;
381
382 for_each_sg(sgl, sg, use_sg, i)
383 pages[i] = sg_page(sg);
384
385 mdata->null_mapped = 1;
386
387 mdata->page_order = get_order(sgl[0].length);
388 mdata->nr_entries =
389 DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
390 mdata->offset = 0;
391
392 err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
393 if (err) {
394 kfree(pages);
395 goto free_req;
396 }
397 SRpnt->bio = req->bio;
398 mdata->pages = pages;
399
400 } else if (bufflen) {
401 err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
402 if (err)
403 goto free_req;
404 }
405
406 req->cmd_len = cmd_len;
407 memset(req->cmd, 0, BLK_MAX_CDB);
408 memcpy(req->cmd, cmd, req->cmd_len);
409 req->sense = SRpnt->sense;
410 req->sense_len = 0;
411 req->timeout = timeout;
412 req->retries = retries;
413 req->end_io_data = SRpnt;
414
415 blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
416 return 0;
417free_req:
418 blk_put_request(req);
419 return DRIVER_ERROR << 24;
420}
421
422
423
424
425static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
426 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
427{
428 unsigned char *bp;
429 unsigned short use_sg;
430#ifdef OSST_INJECT_ERRORS
431 static int inject = 0;
432 static int repeat = 0;
433#endif
434 struct completion *waiting;
435
436
437 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
438 printk(KERN_ERR "%s: Async command already active.\n",
439 tape_name(STp));
440 if (signal_pending(current))
441 (STp->buffer)->syscall_result = (-EINTR);
442 else
443 (STp->buffer)->syscall_result = (-EBUSY);
444 return NULL;
445 }
446
447 if (SRpnt == NULL) {
448 SRpnt = osst_allocate_request();
449 if (SRpnt == NULL) {
450 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
451 tape_name(STp));
452 if (signal_pending(current))
453 (STp->buffer)->syscall_result = (-EINTR);
454 else
455 (STp->buffer)->syscall_result = (-EBUSY);
456 return NULL;
457 }
458 SRpnt->stp = STp;
459 }
460
461
462
463 if (!do_wait)
464 (STp->buffer)->last_SRpnt = SRpnt;
465
466 waiting = &STp->wait;
467 init_completion(waiting);
468 SRpnt->waiting = waiting;
469
470 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
471 if (use_sg) {
472 bp = (char *)&(STp->buffer->sg[0]);
473 if (STp->buffer->sg_segs < use_sg)
474 use_sg = STp->buffer->sg_segs;
475 }
476 else
477 bp = (STp->buffer)->b_data;
478
479 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
480 STp->buffer->cmdstat.have_sense = 0;
481 STp->buffer->syscall_result = 0;
482
483 if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
484 use_sg, timeout, retries))
485
486 (STp->buffer)->syscall_result = (-EBUSY);
487 else if (do_wait) {
488 wait_for_completion(waiting);
489 SRpnt->waiting = NULL;
490 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
491#ifdef OSST_INJECT_ERRORS
492 if (STp->buffer->syscall_result == 0 &&
493 cmd[0] == READ_6 &&
494 cmd[4] &&
495 ( (++ inject % 83) == 29 ||
496 (STp->first_frame_position == 240
497 &&
498 ++repeat < 3))) {
499 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
500 STp->buffer->last_result_fatal = 1;
501 }
502#endif
503 }
504 return SRpnt;
505}
506
507
508
509static void osst_write_behind_check(struct osst_tape *STp)
510{
511 struct osst_buffer * STbuffer;
512
513 STbuffer = STp->buffer;
514
515#if DEBUG
516 if (STp->write_pending)
517 STp->nbr_waits++;
518 else
519 STp->nbr_finished++;
520#endif
521 wait_for_completion(&(STp->wait));
522 STp->buffer->last_SRpnt->waiting = NULL;
523
524 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
525
526 if (STp->buffer->syscall_result)
527 STp->buffer->syscall_result =
528 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
529 else
530 STp->first_frame_position++;
531
532 osst_release_request(STp->buffer->last_SRpnt);
533
534 if (STbuffer->writing < STbuffer->buffer_bytes)
535 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
536
537 STbuffer->last_SRpnt = NULL;
538 STbuffer->buffer_bytes -= STbuffer->writing;
539 STbuffer->writing = 0;
540
541 return;
542}
543
544
545
546
547
548
549
550static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
551 int logical_blk_num, int blk_sz, int blk_cnt)
552{
553 os_aux_t *aux = STp->buffer->aux;
554 os_partition_t *par = &aux->partition;
555 os_dat_t *dat = &aux->dat;
556
557 if (STp->raw) return;
558
559 memset(aux, 0, sizeof(*aux));
560 aux->format_id = htonl(0);
561 memcpy(aux->application_sig, "LIN4", 4);
562 aux->hdwr = htonl(0);
563 aux->frame_type = frame_type;
564
565 switch (frame_type) {
566 case OS_FRAME_TYPE_HEADER:
567 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
568 par->partition_num = OS_CONFIG_PARTITION;
569 par->par_desc_ver = OS_PARTITION_VERSION;
570 par->wrt_pass_cntr = htons(0xffff);
571
572 par->first_frame_ppos = htonl(0);
573 par->last_frame_ppos = htonl(0xbb7);
574 aux->frame_seq_num = htonl(0);
575 aux->logical_blk_num_high = htonl(0);
576 aux->logical_blk_num = htonl(0);
577 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
578 break;
579 case OS_FRAME_TYPE_DATA:
580 case OS_FRAME_TYPE_MARKER:
581 dat->dat_sz = 8;
582 dat->reserved1 = 0;
583 dat->entry_cnt = 1;
584 dat->reserved3 = 0;
585 dat->dat_list[0].blk_sz = htonl(blk_sz);
586 dat->dat_list[0].blk_cnt = htons(blk_cnt);
587 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
588 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
589 dat->dat_list[0].reserved = 0;
590 case OS_FRAME_TYPE_EOD:
591 aux->update_frame_cntr = htonl(0);
592 par->partition_num = OS_DATA_PARTITION;
593 par->par_desc_ver = OS_PARTITION_VERSION;
594 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
595 par->first_frame_ppos = htonl(STp->first_data_ppos);
596 par->last_frame_ppos = htonl(STp->capacity);
597 aux->frame_seq_num = htonl(frame_seq_number);
598 aux->logical_blk_num_high = htonl(0);
599 aux->logical_blk_num = htonl(logical_blk_num);
600 break;
601 default: ;
602 }
603 aux->filemark_cnt = htonl(STp->filemark_cnt);
604 aux->phys_fm = htonl(0xffffffff);
605 aux->last_mark_ppos = htonl(STp->last_mark_ppos);
606 aux->last_mark_lbn = htonl(STp->last_mark_lbn);
607}
608
609
610
611
612static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
613{
614 char * name = tape_name(STp);
615 os_aux_t * aux = STp->buffer->aux;
616 os_partition_t * par = &(aux->partition);
617 struct st_partstat * STps = &(STp->ps[STp->partition]);
618 int blk_cnt, blk_sz, i;
619
620 if (STp->raw) {
621 if (STp->buffer->syscall_result) {
622 for (i=0; i < STp->buffer->sg_segs; i++)
623 memset(page_address(sg_page(&STp->buffer->sg[i])),
624 0, STp->buffer->sg[i].length);
625 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
626 } else
627 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
628 return 1;
629 }
630 if (STp->buffer->syscall_result) {
631#if DEBUG
632 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
633#endif
634 return 0;
635 }
636 if (ntohl(aux->format_id) != 0) {
637#if DEBUG
638 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
639#endif
640 goto err_out;
641 }
642 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
643 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
644#if DEBUG
645 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
646#endif
647 goto err_out;
648 }
649 if (par->partition_num != OS_DATA_PARTITION) {
650 if (!STp->linux_media || STp->linux_media_version != 2) {
651#if DEBUG
652 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
653 name, par->partition_num);
654#endif
655 goto err_out;
656 }
657 }
658 if (par->par_desc_ver != OS_PARTITION_VERSION) {
659#if DEBUG
660 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
661#endif
662 goto err_out;
663 }
664 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
665#if DEBUG
666 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
667 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
668#endif
669 goto err_out;
670 }
671 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
672 aux->frame_type != OS_FRAME_TYPE_EOD &&
673 aux->frame_type != OS_FRAME_TYPE_MARKER) {
674 if (!quiet) {
675#if DEBUG
676 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
677#endif
678 }
679 goto err_out;
680 }
681 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
682 STp->first_frame_position < STp->eod_frame_ppos) {
683 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
684 STp->first_frame_position);
685 goto err_out;
686 }
687 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
688 if (!quiet) {
689#if DEBUG
690 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
691 name, ntohl(aux->frame_seq_num), frame_seq_number);
692#endif
693 }
694 goto err_out;
695 }
696 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
697 STps->eof = ST_FM_HIT;
698
699 i = ntohl(aux->filemark_cnt);
700 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
701 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
702#if DEBUG
703 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
704 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
705 i, STp->first_frame_position - 1);
706#endif
707 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
708 if (i >= STp->filemark_cnt)
709 STp->filemark_cnt = i+1;
710 }
711 }
712 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
713 STps->eof = ST_EOD_1;
714 STp->frame_in_buffer = 1;
715 }
716 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
717 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
718 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
719 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
720 STp->buffer->read_pointer = 0;
721 STp->frame_in_buffer = 1;
722
723
724 if (STp->block_size != blk_sz && blk_sz > 0) {
725 printk(KERN_INFO
726 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
727 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
728 STp->block_size<1024?STp->block_size:STp->block_size/1024,
729 STp->block_size<1024?'b':'k');
730 STp->block_size = blk_sz;
731 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
732 }
733 STps->eof = ST_NOEOF;
734 }
735 STp->frame_seq_number = ntohl(aux->frame_seq_num);
736 STp->logical_blk_num = ntohl(aux->logical_blk_num);
737 return 1;
738
739err_out:
740 if (STp->read_error_frame == 0)
741 STp->read_error_frame = STp->first_frame_position - 1;
742 return 0;
743}
744
745
746
747
748static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
749 unsigned timeout, int initial_delay)
750{
751 unsigned char cmd[MAX_COMMAND_SIZE];
752 struct osst_request * SRpnt;
753 unsigned long startwait = jiffies;
754#if DEBUG
755 int dbg = debugging;
756 char * name = tape_name(STp);
757
758 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
759#endif
760
761 if (initial_delay > 0)
762 msleep(jiffies_to_msecs(initial_delay));
763
764 memset(cmd, 0, MAX_COMMAND_SIZE);
765 cmd[0] = TEST_UNIT_READY;
766
767 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
768 *aSRpnt = SRpnt;
769 if (!SRpnt) return (-EBUSY);
770
771 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
772 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
773 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
774 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
775 SRpnt->sense[13] == 0 ) )) {
776#if DEBUG
777 if (debugging) {
778 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
779 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
780 debugging = 0;
781 }
782#endif
783 msleep(100);
784
785 memset(cmd, 0, MAX_COMMAND_SIZE);
786 cmd[0] = TEST_UNIT_READY;
787
788 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
789 }
790 *aSRpnt = SRpnt;
791#if DEBUG
792 debugging = dbg;
793#endif
794 if ( STp->buffer->syscall_result &&
795 osst_write_error_recovery(STp, aSRpnt, 0) ) {
796#if DEBUG
797 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
798 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
799 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
800 SRpnt->sense[12], SRpnt->sense[13]);
801#endif
802 return (-EIO);
803 }
804#if DEBUG
805 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
806#endif
807 return 0;
808}
809
810
811
812
813static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
814{
815 unsigned char cmd[MAX_COMMAND_SIZE];
816 struct osst_request * SRpnt;
817 unsigned long startwait = jiffies;
818#if DEBUG
819 int dbg = debugging;
820 char * name = tape_name(STp);
821
822 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
823#endif
824
825 memset(cmd, 0, MAX_COMMAND_SIZE);
826 cmd[0] = TEST_UNIT_READY;
827
828 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
829 *aSRpnt = SRpnt;
830 if (!SRpnt) return (-EBUSY);
831
832 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
833 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
834#if DEBUG
835 if (debugging) {
836 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
837 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
838 debugging = 0;
839 }
840#endif
841 msleep(100);
842
843 memset(cmd, 0, MAX_COMMAND_SIZE);
844 cmd[0] = TEST_UNIT_READY;
845
846 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
847 }
848 *aSRpnt = SRpnt;
849#if DEBUG
850 debugging = dbg;
851#endif
852 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
853 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
854#if DEBUG
855 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
856 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
857 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
858 SRpnt->sense[12], SRpnt->sense[13]);
859#endif
860 return 0;
861 }
862#if DEBUG
863 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
864#endif
865 return 1;
866}
867
868static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
869{
870 int retval;
871
872 osst_wait_ready(STp, aSRpnt, 15 * 60, 0);
873 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
874 if (retval) return (retval);
875 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
876 return (osst_get_frame_position(STp, aSRpnt));
877}
878
879
880
881
882static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
883{
884 unsigned char cmd[MAX_COMMAND_SIZE];
885 struct osst_request * SRpnt;
886 int result = 0;
887 int delay = OSST_WAIT_WRITE_COMPLETE;
888#if DEBUG
889 char * name = tape_name(STp);
890
891 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
892#endif
893
894 memset(cmd, 0, MAX_COMMAND_SIZE);
895 cmd[0] = WRITE_FILEMARKS;
896 cmd[1] = 1;
897
898 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
899 *aSRpnt = SRpnt;
900 if (!SRpnt) return (-EBUSY);
901 if (STp->buffer->syscall_result) {
902 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
903 if (SRpnt->sense[13] == 8) {
904 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
905 }
906 } else
907 result = osst_write_error_recovery(STp, aSRpnt, 0);
908 }
909 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
910 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
911
912 return (result);
913}
914
915#define OSST_POLL_PER_SEC 10
916static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
917{
918 unsigned long startwait = jiffies;
919 char * name = tape_name(STp);
920#if DEBUG
921 char notyetprinted = 1;
922#endif
923 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
924 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
925
926 while (time_before (jiffies, startwait + to*HZ))
927 {
928 int result;
929 result = osst_get_frame_position(STp, aSRpnt);
930 if (result == -EIO)
931 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
932 return 0;
933 if (result < 0) break;
934 if (STp->first_frame_position == curr &&
935 ((minlast < 0 &&
936 (signed)STp->last_frame_position > (signed)curr + minlast) ||
937 (minlast >= 0 && STp->cur_frames > minlast)
938 ) && result >= 0)
939 {
940#if DEBUG
941 if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
942 printk (OSST_DEB_MSG
943 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
944 name, curr, curr+minlast, STp->first_frame_position,
945 STp->last_frame_position, STp->cur_frames,
946 result, (jiffies-startwait)/HZ,
947 (((jiffies-startwait)%HZ)*10)/HZ);
948#endif
949 return 0;
950 }
951#if DEBUG
952 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
953 {
954 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
955 name, curr, curr+minlast, STp->first_frame_position,
956 STp->last_frame_position, STp->cur_frames, result);
957 notyetprinted--;
958 }
959#endif
960 msleep(1000 / OSST_POLL_PER_SEC);
961 }
962#if DEBUG
963 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
964 name, curr, curr+minlast, STp->first_frame_position,
965 STp->last_frame_position, STp->cur_frames,
966 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
967#endif
968 return -EBUSY;
969}
970
971static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
972{
973 struct osst_request * SRpnt;
974 unsigned char cmd[MAX_COMMAND_SIZE];
975 unsigned long startwait = jiffies;
976 int retval = 1;
977 char * name = tape_name(STp);
978
979 if (writing) {
980 char mybuf[24];
981 char * olddata = STp->buffer->b_data;
982 int oldsize = STp->buffer->buffer_size;
983
984
985
986 memset(cmd, 0, MAX_COMMAND_SIZE);
987 cmd[0] = WRITE_FILEMARKS;
988 cmd[1] = 1;
989 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
990 MAX_RETRIES, 1);
991
992 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
993
994 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
995
996
997 retval = osst_write_error_recovery(STp, aSRpnt, 0);
998 break;
999 }
1000 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
1001
1002 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1003 memset(cmd, 0, MAX_COMMAND_SIZE);
1004 cmd[0] = READ_POSITION;
1005
1006 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1007 MAX_RETRIES, 1);
1008
1009 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1010 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1011 }
1012 if (retval)
1013 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1014 } else
1015
1016 if (STp->buffer->syscall_result)
1017 printk(KERN_WARNING
1018 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1019 (*aSRpnt)->sense[ 2] & 0x0f,
1020 (*aSRpnt)->sense[12],
1021 (*aSRpnt)->sense[13]);
1022
1023 return retval;
1024}
1025
1026
1027
1028
1029static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1030{
1031 unsigned char cmd[MAX_COMMAND_SIZE];
1032 struct osst_request * SRpnt;
1033 int retval = 0;
1034#if DEBUG
1035 os_aux_t * aux = STp->buffer->aux;
1036 char * name = tape_name(STp);
1037#endif
1038
1039 if (STp->poll)
1040 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1041 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1042
1043 memset(cmd, 0, MAX_COMMAND_SIZE);
1044 cmd[0] = READ_6;
1045 cmd[1] = 1;
1046 cmd[4] = 1;
1047
1048#if DEBUG
1049 if (debugging)
1050 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1051#endif
1052 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1053 STp->timeout, MAX_RETRIES, 1);
1054 *aSRpnt = SRpnt;
1055 if (!SRpnt)
1056 return (-EBUSY);
1057
1058 if ((STp->buffer)->syscall_result) {
1059 retval = 1;
1060 if (STp->read_error_frame == 0) {
1061 STp->read_error_frame = STp->first_frame_position;
1062#if DEBUG
1063 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1064#endif
1065 }
1066#if DEBUG
1067 if (debugging)
1068 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1069 name,
1070 SRpnt->sense[0], SRpnt->sense[1],
1071 SRpnt->sense[2], SRpnt->sense[3],
1072 SRpnt->sense[4], SRpnt->sense[5],
1073 SRpnt->sense[6], SRpnt->sense[7]);
1074#endif
1075 }
1076 else
1077 STp->first_frame_position++;
1078#if DEBUG
1079 if (debugging) {
1080 char sig[8]; int i;
1081 for (i=0;i<4;i++)
1082 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1083 sig[4] = '\0';
1084 printk(OSST_DEB_MSG
1085 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1086 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1087 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1088 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1089 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1090 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1091 if (aux->frame_type==2)
1092 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1093 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1094 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1095 }
1096#endif
1097 return (retval);
1098}
1099
1100static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1101{
1102 struct st_partstat * STps = &(STp->ps[STp->partition]);
1103 struct osst_request * SRpnt ;
1104 unsigned char cmd[MAX_COMMAND_SIZE];
1105 int retval = 0;
1106 char * name = tape_name(STp);
1107
1108 if (STps->rw != ST_READING) {
1109 if (STps->rw == ST_WRITING || STp->dirty) {
1110 STp->write_type = OS_WRITE_DATA;
1111 osst_flush_write_buffer(STp, aSRpnt);
1112 osst_flush_drive_buffer(STp, aSRpnt);
1113 }
1114 STps->rw = ST_READING;
1115 STp->frame_in_buffer = 0;
1116
1117
1118
1119
1120
1121 memset(cmd, 0, MAX_COMMAND_SIZE);
1122 cmd[0] = READ_6;
1123 cmd[1] = 1;
1124
1125#if DEBUG
1126 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1127#endif
1128 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1129 *aSRpnt = SRpnt;
1130 if ((retval = STp->buffer->syscall_result))
1131 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1132 }
1133
1134 return retval;
1135}
1136
1137static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1138 int frame_seq_number, int quiet)
1139{
1140 struct st_partstat * STps = &(STp->ps[STp->partition]);
1141 char * name = tape_name(STp);
1142 int cnt = 0,
1143 bad = 0,
1144 past = 0,
1145 x,
1146 position;
1147
1148
1149
1150
1151 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1152#if DEBUG
1153 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1154#endif
1155 return (STps->eof);
1156 }
1157
1158
1159
1160 while (1) {
1161 if (cnt++ > 400) {
1162 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1163 name, frame_seq_number);
1164 if (STp->read_error_frame) {
1165 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1166#if DEBUG
1167 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1168 name, STp->read_error_frame);
1169#endif
1170 STp->read_error_frame = 0;
1171 STp->abort_count++;
1172 }
1173 return (-EIO);
1174 }
1175#if DEBUG
1176 if (debugging)
1177 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1178 name, frame_seq_number, cnt);
1179#endif
1180 if ( osst_initiate_read(STp, aSRpnt)
1181 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1182 if (STp->raw)
1183 return (-EIO);
1184 position = osst_get_frame_position(STp, aSRpnt);
1185 if (position >= 0xbae && position < 0xbb8)
1186 position = 0xbb8;
1187 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1188 position = STp->read_error_frame - 1;
1189 bad = 0;
1190 }
1191 else {
1192 position += 29;
1193 cnt += 19;
1194 }
1195#if DEBUG
1196 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1197 name, position);
1198#endif
1199 osst_set_frame_position(STp, aSRpnt, position, 0);
1200 continue;
1201 }
1202 if (osst_verify_frame(STp, frame_seq_number, quiet))
1203 break;
1204 if (osst_verify_frame(STp, -1, quiet)) {
1205 x = ntohl(STp->buffer->aux->frame_seq_num);
1206 if (STp->fast_open) {
1207 printk(KERN_WARNING
1208 "%s:W: Found logical frame %d instead of %d after fast open\n",
1209 name, x, frame_seq_number);
1210 STp->header_ok = 0;
1211 STp->read_error_frame = 0;
1212 return (-EIO);
1213 }
1214 if (x > frame_seq_number) {
1215 if (++past > 3) {
1216
1217 position = STp->read_error_frame - 1;
1218 }
1219 else {
1220 position = osst_get_frame_position(STp, aSRpnt)
1221 + frame_seq_number - x - 1;
1222
1223 if (STp->first_frame_position >= 3000 && position < 3000)
1224 position -= 10;
1225 }
1226#if DEBUG
1227 printk(OSST_DEB_MSG
1228 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1229 name, x, frame_seq_number,
1230 STp->first_frame_position - position);
1231#endif
1232 osst_set_frame_position(STp, aSRpnt, position, 0);
1233 cnt += 10;
1234 }
1235 else
1236 past = 0;
1237 }
1238 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1239#if DEBUG
1240 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1241#endif
1242 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1243 cnt--;
1244 }
1245 STp->frame_in_buffer = 0;
1246 }
1247 if (cnt > 1) {
1248 STp->recover_count++;
1249 STp->recover_erreg++;
1250 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1251 name, STp->read_error_frame);
1252 }
1253 STp->read_count++;
1254
1255#if DEBUG
1256 if (debugging || STps->eof)
1257 printk(OSST_DEB_MSG
1258 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1259 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1260#endif
1261 STp->fast_open = 0;
1262 STp->read_error_frame = 0;
1263 return (STps->eof);
1264}
1265
1266static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1267{
1268 struct st_partstat * STps = &(STp->ps[STp->partition]);
1269 char * name = tape_name(STp);
1270 int retries = 0;
1271 int frame_seq_estimate, ppos_estimate, move;
1272
1273 if (logical_blk_num < 0) logical_blk_num = 0;
1274#if DEBUG
1275 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1276 name, logical_blk_num, STp->logical_blk_num,
1277 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1278 STp->block_size<1024?'b':'k');
1279#endif
1280
1281 if (STps->drv_block >= 0) {
1282 move = logical_blk_num - STp->logical_blk_num;
1283 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1284 move /= (OS_DATA_SIZE / STp->block_size);
1285 frame_seq_estimate = STp->frame_seq_number + move;
1286 } else
1287 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1288
1289 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1290 else ppos_estimate = frame_seq_estimate + 20;
1291 while (++retries < 10) {
1292 if (ppos_estimate > STp->eod_frame_ppos-2) {
1293 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1294 ppos_estimate = STp->eod_frame_ppos - 2;
1295 }
1296 if (frame_seq_estimate < 0) {
1297 frame_seq_estimate = 0;
1298 ppos_estimate = 10;
1299 }
1300 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1301 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1302
1303 if (logical_blk_num < STp->logical_blk_num ||
1304 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1305 if (STps->eof == ST_FM_HIT)
1306 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1307 else {
1308 move = logical_blk_num - STp->logical_blk_num;
1309 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1310 move /= (OS_DATA_SIZE / STp->block_size);
1311 }
1312 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1313#if DEBUG
1314 printk(OSST_DEB_MSG
1315 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1316 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1317 STp->logical_blk_num, logical_blk_num, move);
1318#endif
1319 frame_seq_estimate += move;
1320 ppos_estimate += move;
1321 continue;
1322 } else {
1323 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1324 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1325 STp->logical_blk_num = logical_blk_num;
1326#if DEBUG
1327 printk(OSST_DEB_MSG
1328 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1329 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1330 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1331 STp->block_size);
1332#endif
1333 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1334 if (STps->eof == ST_FM_HIT) {
1335 STps->drv_file++;
1336 STps->drv_block = 0;
1337 } else {
1338 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1339 STp->logical_blk_num -
1340 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1341 -1;
1342 }
1343 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1344 return 0;
1345 }
1346 }
1347 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1348 goto error;
1349
1350#if DEBUG
1351 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1352 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1353 STp->logical_blk_num, logical_blk_num);
1354#endif
1355 if (frame_seq_estimate != STp->frame_seq_number)
1356 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1357 else
1358 break;
1359 }
1360error:
1361 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1362 name, logical_blk_num, STp->logical_blk_num, retries);
1363 return (-EIO);
1364}
1365
1366
1367
1368
1369
1370
1371#define OSST_FRAME_SHIFT 6
1372#define OSST_SECTOR_SHIFT 9
1373#define OSST_SECTOR_MASK 0x03F
1374
1375static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1376{
1377 int sector;
1378#if DEBUG
1379 char * name = tape_name(STp);
1380
1381 printk(OSST_DEB_MSG
1382 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1383 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1384 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1385 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1386 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1387 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1388#endif
1389
1390 if (STp->ps[STp->partition].drv_block >= 0) {
1391 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1392 STp->first_frame_position) << OSST_FRAME_SHIFT;
1393 if (STp->ps[STp->partition].rw == ST_WRITING)
1394 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1395 else
1396 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1397 } else {
1398 sector = osst_get_frame_position(STp, aSRpnt);
1399 if (sector > 0)
1400 sector <<= OSST_FRAME_SHIFT;
1401 }
1402 return sector;
1403}
1404
1405static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1406{
1407 struct st_partstat * STps = &(STp->ps[STp->partition]);
1408 int frame = sector >> OSST_FRAME_SHIFT,
1409 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1410 r;
1411#if DEBUG
1412 char * name = tape_name(STp);
1413
1414 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1415 name, sector, frame, offset);
1416#endif
1417 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1418
1419 if (frame <= STp->first_data_ppos) {
1420 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1421 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1422 }
1423 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1424 if (r < 0) return r;
1425
1426 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1427 if (r < 0) return r;
1428
1429 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1430
1431 if (offset) {
1432 STp->logical_blk_num += offset / STp->block_size;
1433 STp->buffer->read_pointer = offset;
1434 STp->buffer->buffer_bytes -= offset;
1435 } else {
1436 STp->frame_seq_number++;
1437 STp->frame_in_buffer = 0;
1438 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1439 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1440 }
1441 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1442 if (STps->eof == ST_FM_HIT) {
1443 STps->drv_file++;
1444 STps->drv_block = 0;
1445 } else {
1446 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1447 STp->logical_blk_num -
1448 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1449 -1;
1450 }
1451 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1452#if DEBUG
1453 printk(OSST_DEB_MSG
1454 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1455 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1456 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1457#endif
1458 return 0;
1459}
1460
1461
1462
1463
1464
1465
1466
1467
1468static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1469 unsigned int frame, unsigned int skip, int pending)
1470{
1471 struct osst_request * SRpnt = * aSRpnt;
1472 unsigned char * buffer, * p;
1473 unsigned char cmd[MAX_COMMAND_SIZE];
1474 int flag, new_frame, i;
1475 int nframes = STp->cur_frames;
1476 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1477 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1478 - (nframes + pending - 1);
1479 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1480 - (nframes + pending - 1) * blks_per_frame;
1481 char * name = tape_name(STp);
1482 unsigned long startwait = jiffies;
1483#if DEBUG
1484 int dbg = debugging;
1485#endif
1486
1487 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1488 return (-EIO);
1489
1490 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1491 name, nframes, pending?" and one that was pending":"");
1492
1493 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1494#if DEBUG
1495 if (pending && debugging)
1496 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1497 name, frame_seq_number + nframes,
1498 logical_blk_num + nframes * blks_per_frame,
1499 p[0], p[1], p[2], p[3]);
1500#endif
1501 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1502
1503 memset(cmd, 0, MAX_COMMAND_SIZE);
1504 cmd[0] = 0x3C;
1505 cmd[1] = 6;
1506 cmd[7] = 32768 >> 8;
1507 cmd[8] = 32768 & 0xff;
1508
1509 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1510 STp->timeout, MAX_RETRIES, 1);
1511
1512 if ((STp->buffer)->syscall_result || !SRpnt) {
1513 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1514 vfree(buffer);
1515 *aSRpnt = SRpnt;
1516 return (-EIO);
1517 }
1518 osst_copy_from_buffer(STp->buffer, p);
1519#if DEBUG
1520 if (debugging)
1521 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1522 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1523#endif
1524 }
1525 *aSRpnt = SRpnt;
1526 osst_get_frame_position(STp, aSRpnt);
1527
1528#if DEBUG
1529 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1530#endif
1531
1532
1533
1534 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1535
1536 if (flag) {
1537 if (STp->write_type == OS_WRITE_HEADER) {
1538 i += skip;
1539 p += skip * OS_DATA_SIZE;
1540 }
1541 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1542 new_frame = 3000-i;
1543 else
1544 new_frame += skip;
1545#if DEBUG
1546 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1547 name, new_frame+i, frame_seq_number+i);
1548#endif
1549 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1550 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1551 osst_get_frame_position(STp, aSRpnt);
1552 SRpnt = * aSRpnt;
1553
1554 if (new_frame > frame + 1000) {
1555 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1556 vfree(buffer);
1557 return (-EIO);
1558 }
1559 if ( i >= nframes + pending ) break;
1560 flag = 0;
1561 }
1562 osst_copy_to_buffer(STp->buffer, p);
1563
1564
1565
1566 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1567 logical_blk_num + i*blks_per_frame,
1568 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1569 memset(cmd, 0, MAX_COMMAND_SIZE);
1570 cmd[0] = WRITE_6;
1571 cmd[1] = 1;
1572 cmd[4] = 1;
1573
1574#if DEBUG
1575 if (debugging)
1576 printk(OSST_DEB_MSG
1577 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1578 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1579 p[0], p[1], p[2], p[3]);
1580#endif
1581 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1582 STp->timeout, MAX_RETRIES, 1);
1583
1584 if (STp->buffer->syscall_result)
1585 flag = 1;
1586 else {
1587 p += OS_DATA_SIZE; i++;
1588
1589
1590 if ( i == nframes + pending ) {
1591#if DEBUG
1592 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1593#endif
1594 memset(cmd, 0, MAX_COMMAND_SIZE);
1595 cmd[0] = WRITE_FILEMARKS;
1596 cmd[1] = 1;
1597 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1598 STp->timeout, MAX_RETRIES, 1);
1599#if DEBUG
1600 if (debugging) {
1601 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1602 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1603 debugging = 0;
1604 }
1605#endif
1606 flag = STp->buffer->syscall_result;
1607 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1608
1609 memset(cmd, 0, MAX_COMMAND_SIZE);
1610 cmd[0] = TEST_UNIT_READY;
1611
1612 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1613 MAX_RETRIES, 1);
1614
1615 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1616 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1617
1618 msleep(100);
1619 continue;
1620 }
1621 if (STp->buffer->syscall_result)
1622 flag = 1;
1623 break;
1624 }
1625#if DEBUG
1626 debugging = dbg;
1627 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1628#endif
1629 }
1630 }
1631 *aSRpnt = SRpnt;
1632 if (flag) {
1633 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1634 SRpnt->sense[12] == 0 &&
1635 SRpnt->sense[13] == 2) {
1636 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1637 vfree(buffer);
1638 return (-EIO);
1639 }
1640 i = ((SRpnt->sense[3] << 24) |
1641 (SRpnt->sense[4] << 16) |
1642 (SRpnt->sense[5] << 8) |
1643 SRpnt->sense[6] ) - new_frame;
1644 p = &buffer[i * OS_DATA_SIZE];
1645#if DEBUG
1646 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1647#endif
1648 osst_get_frame_position(STp, aSRpnt);
1649#if DEBUG
1650 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1651 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1652#endif
1653 }
1654 }
1655 if (flag) {
1656
1657 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1658 STp->write_type == OS_WRITE_HEADER?"header":"body");
1659 }
1660 if (!pending)
1661 osst_copy_to_buffer(STp->buffer, p);
1662 vfree(buffer);
1663 return 0;
1664}
1665
1666static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1667 unsigned int frame, unsigned int skip, int pending)
1668{
1669 unsigned char cmd[MAX_COMMAND_SIZE];
1670 struct osst_request * SRpnt;
1671 char * name = tape_name(STp);
1672 int expected = 0;
1673 int attempts = 1000 / skip;
1674 int flag = 1;
1675 unsigned long startwait = jiffies;
1676#if DEBUG
1677 int dbg = debugging;
1678#endif
1679
1680 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1681 if (flag) {
1682#if DEBUG
1683 debugging = dbg;
1684#endif
1685 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1686 frame = 3000-skip;
1687 expected = frame+skip+STp->cur_frames+pending;
1688#if DEBUG
1689 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1690 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1691#endif
1692 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1693 flag = 0;
1694 attempts--;
1695 schedule_timeout_interruptible(msecs_to_jiffies(100));
1696 }
1697 if (osst_get_frame_position(STp, aSRpnt) < 0) {
1698#if DEBUG
1699 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1700 name, STp->first_frame_position,
1701 STp->last_frame_position, STp->cur_frames);
1702#endif
1703 frame = STp->last_frame_position;
1704 flag = 1;
1705 continue;
1706 }
1707 if (pending && STp->cur_frames < 50) {
1708
1709 memset(cmd, 0, MAX_COMMAND_SIZE);
1710 cmd[0] = WRITE_6;
1711 cmd[1] = 1;
1712 cmd[4] = 1;
1713#if DEBUG
1714 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1715 name, STp->frame_seq_number-1, STp->first_frame_position);
1716#endif
1717 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1718 STp->timeout, MAX_RETRIES, 1);
1719 *aSRpnt = SRpnt;
1720
1721 if (STp->buffer->syscall_result) {
1722 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1723 SRpnt->sense[12] == 0 &&
1724 SRpnt->sense[13] == 2) {
1725 printk(KERN_ERR
1726 "%s:E: Volume overflow in write error recovery\n",
1727 name);
1728 break;
1729 }
1730 flag = 1;
1731 }
1732 else
1733 pending = 0;
1734
1735 continue;
1736 }
1737 if (STp->cur_frames == 0) {
1738#if DEBUG
1739 debugging = dbg;
1740 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1741#endif
1742 if (STp->first_frame_position != expected) {
1743 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1744 name, STp->first_frame_position, expected);
1745 return (-EIO);
1746 }
1747 return 0;
1748 }
1749#if DEBUG
1750 if (debugging) {
1751 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1752 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1753 debugging = 0;
1754 }
1755#endif
1756 schedule_timeout_interruptible(msecs_to_jiffies(100));
1757 }
1758 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1759#if DEBUG
1760 debugging = dbg;
1761#endif
1762 return (-EIO);
1763}
1764
1765
1766
1767
1768
1769static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1770{
1771 struct osst_request * SRpnt = * aSRpnt;
1772 struct st_partstat * STps = & STp->ps[STp->partition];
1773 char * name = tape_name(STp);
1774 int retval = 0;
1775 int rw_state;
1776 unsigned int frame, skip;
1777
1778 rw_state = STps->rw;
1779
1780 if ((SRpnt->sense[ 2] & 0x0f) != 3
1781 || SRpnt->sense[12] != 12
1782 || SRpnt->sense[13] != 0) {
1783#if DEBUG
1784 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1785 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1786#endif
1787 return (-EIO);
1788 }
1789 frame = (SRpnt->sense[3] << 24) |
1790 (SRpnt->sense[4] << 16) |
1791 (SRpnt->sense[5] << 8) |
1792 SRpnt->sense[6];
1793 skip = SRpnt->sense[9];
1794
1795#if DEBUG
1796 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1797#endif
1798 osst_get_frame_position(STp, aSRpnt);
1799#if DEBUG
1800 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1801 name, STp->first_frame_position, STp->last_frame_position);
1802#endif
1803 switch (STp->write_type) {
1804 case OS_WRITE_DATA:
1805 case OS_WRITE_EOD:
1806 case OS_WRITE_NEW_MARK:
1807 printk(KERN_WARNING
1808 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1809 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1810 if (STp->os_fw_rev >= 10600)
1811 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1812 else
1813 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1814 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1815 retval?"E" :"I",
1816 retval?"" :"Don't worry, ",
1817 retval?" not ":" ");
1818 break;
1819 case OS_WRITE_LAST_MARK:
1820 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1821 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1822 retval = -EIO;
1823 break;
1824 case OS_WRITE_HEADER:
1825 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1826 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1827 break;
1828 default:
1829 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1830 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1831 }
1832 osst_get_frame_position(STp, aSRpnt);
1833#if DEBUG
1834 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1835 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1836 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1837#endif
1838 if (retval == 0) {
1839 STp->recover_count++;
1840 STp->recover_erreg++;
1841 } else
1842 STp->abort_count++;
1843
1844 STps->rw = rw_state;
1845 return retval;
1846}
1847
1848static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1849 int mt_op, int mt_count)
1850{
1851 char * name = tape_name(STp);
1852 int cnt;
1853 int last_mark_ppos = -1;
1854
1855#if DEBUG
1856 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1857#endif
1858 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1859#if DEBUG
1860 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1861#endif
1862 return -EIO;
1863 }
1864 if (STp->linux_media_version >= 4) {
1865
1866
1867
1868 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1869 if (STp->header_ok &&
1870 STp->header_cache != NULL &&
1871 (cnt - mt_count) >= 0 &&
1872 (cnt - mt_count) < OS_FM_TAB_MAX &&
1873 (cnt - mt_count) < STp->filemark_cnt &&
1874 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1875
1876 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1877#if DEBUG
1878 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1879 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1880 STp->header_cache == NULL?"lack of header cache":"count out of range");
1881 else
1882 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1883 name, cnt,
1884 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1885 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1886 STp->buffer->aux->last_mark_ppos))?"match":"error",
1887 mt_count, last_mark_ppos);
1888#endif
1889 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1890 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1891 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1892#if DEBUG
1893 printk(OSST_DEB_MSG
1894 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1895#endif
1896 return (-EIO);
1897 }
1898 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1899 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1900 name, last_mark_ppos);
1901 return (-EIO);
1902 }
1903 goto found;
1904 }
1905#if DEBUG
1906 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1907#endif
1908 }
1909 cnt = 0;
1910 while (cnt != mt_count) {
1911 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1912 if (last_mark_ppos == -1)
1913 return (-EIO);
1914#if DEBUG
1915 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1916#endif
1917 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1918 cnt++;
1919 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1920#if DEBUG
1921 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1922#endif
1923 return (-EIO);
1924 }
1925 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1926 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1927 name, last_mark_ppos);
1928 return (-EIO);
1929 }
1930 }
1931found:
1932 if (mt_op == MTBSFM) {
1933 STp->frame_seq_number++;
1934 STp->frame_in_buffer = 0;
1935 STp->buffer->buffer_bytes = 0;
1936 STp->buffer->read_pointer = 0;
1937 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1938 }
1939 return 0;
1940}
1941
1942
1943
1944
1945
1946
1947static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1948 int mt_op, int mt_count)
1949{
1950 int cnt = 0;
1951#if DEBUG
1952 char * name = tape_name(STp);
1953
1954 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1955#endif
1956 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1957#if DEBUG
1958 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1959#endif
1960 return (-EIO);
1961 }
1962 while (1) {
1963 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1964#if DEBUG
1965 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1966#endif
1967 return (-EIO);
1968 }
1969 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1970 cnt++;
1971 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1972#if DEBUG
1973 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1974#endif
1975 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1976#if DEBUG
1977 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1978 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1979#endif
1980 STp->eod_frame_ppos = STp->first_frame_position-1;
1981 }
1982 return (-EIO);
1983 }
1984 if (cnt == mt_count)
1985 break;
1986 STp->frame_in_buffer = 0;
1987 }
1988 if (mt_op == MTFSF) {
1989 STp->frame_seq_number++;
1990 STp->frame_in_buffer = 0;
1991 STp->buffer->buffer_bytes = 0;
1992 STp->buffer->read_pointer = 0;
1993 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1994 }
1995 return 0;
1996}
1997
1998
1999
2000
2001static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
2002 int mt_op, int mt_count)
2003{
2004 char * name = tape_name(STp);
2005 int cnt = 0,
2006 next_mark_ppos = -1;
2007
2008#if DEBUG
2009 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
2010#endif
2011 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2012#if DEBUG
2013 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
2014#endif
2015 return (-EIO);
2016 }
2017
2018 if (STp->linux_media_version >= 4) {
2019
2020
2021
2022 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
2023 if (STp->header_ok &&
2024 STp->header_cache != NULL &&
2025 (cnt + mt_count) < OS_FM_TAB_MAX &&
2026 (cnt + mt_count) < STp->filemark_cnt &&
2027 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2028 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
2029
2030 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
2031#if DEBUG
2032 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
2033 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
2034 STp->header_cache == NULL?"lack of header cache":"count out of range");
2035 else
2036 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2037 name, cnt,
2038 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2039 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
2040 STp->buffer->aux->last_mark_ppos))?"match":"error",
2041 mt_count, next_mark_ppos);
2042#endif
2043 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
2044#if DEBUG
2045 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2046#endif
2047 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2048 } else {
2049 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2050 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2051#if DEBUG
2052 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2053 name);
2054#endif
2055 return (-EIO);
2056 }
2057 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2058 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2059 name, next_mark_ppos);
2060 return (-EIO);
2061 }
2062 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
2063 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
2064 name, cnt+mt_count, next_mark_ppos,
2065 ntohl(STp->buffer->aux->filemark_cnt));
2066 return (-EIO);
2067 }
2068 }
2069 } else {
2070
2071
2072
2073 while (1) {
2074 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
2075 break;
2076 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2077#if DEBUG
2078 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2079#endif
2080 return (-EIO);
2081 }
2082 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2083 if (STp->first_mark_ppos == -1) {
2084#if DEBUG
2085 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2086#endif
2087 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2088 }
2089 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2090 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2091#if DEBUG
2092 printk(OSST_DEB_MSG
2093 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2094 name);
2095#endif
2096 return (-EIO);
2097 }
2098 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2099 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2100 name, STp->first_mark_ppos);
2101 return (-EIO);
2102 }
2103 } else {
2104 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2105 return (-EIO);
2106 mt_count++;
2107 }
2108 }
2109 cnt++;
2110 while (cnt != mt_count) {
2111 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2112 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2113#if DEBUG
2114 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2115#endif
2116 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2117 }
2118#if DEBUG
2119 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2120#endif
2121 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2122 cnt++;
2123 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2124#if DEBUG
2125 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2126 name);
2127#endif
2128 return (-EIO);
2129 }
2130 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2131 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2132 name, next_mark_ppos);
2133 return (-EIO);
2134 }
2135 }
2136 }
2137 if (mt_op == MTFSF) {
2138 STp->frame_seq_number++;
2139 STp->frame_in_buffer = 0;
2140 STp->buffer->buffer_bytes = 0;
2141 STp->buffer->read_pointer = 0;
2142 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2143 }
2144 return 0;
2145}
2146
2147
2148
2149
2150
2151#if DEBUG
2152static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2153{
2154 unsigned char cmd[MAX_COMMAND_SIZE];
2155 struct osst_request * SRpnt = * aSRpnt;
2156 char * name = tape_name(STp);
2157
2158 memset(cmd, 0, MAX_COMMAND_SIZE);
2159 cmd[0] = MODE_SELECT;
2160 cmd[1] = 0x10;
2161 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2162
2163 (STp->buffer)->b_data[0] = cmd[4] - 1;
2164 (STp->buffer)->b_data[1] = 0;
2165 (STp->buffer)->b_data[2] = 0;
2166 (STp->buffer)->b_data[3] = 0;
2167 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2168 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2169 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2170 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2171
2172 if (debugging)
2173 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2174
2175 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2176 *aSRpnt = SRpnt;
2177
2178 if ((STp->buffer)->syscall_result)
2179 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2180}
2181#endif
2182
2183
2184static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2185{
2186 int result;
2187 int this_mark_ppos = STp->first_frame_position;
2188 int this_mark_lbn = STp->logical_blk_num;
2189#if DEBUG
2190 char * name = tape_name(STp);
2191#endif
2192
2193 if (STp->raw) return 0;
2194
2195 STp->write_type = OS_WRITE_NEW_MARK;
2196#if DEBUG
2197 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2198 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2199#endif
2200 STp->dirty = 1;
2201 result = osst_flush_write_buffer(STp, aSRpnt);
2202 result |= osst_flush_drive_buffer(STp, aSRpnt);
2203 STp->last_mark_ppos = this_mark_ppos;
2204 STp->last_mark_lbn = this_mark_lbn;
2205 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2206 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2207 if (STp->filemark_cnt++ == 0)
2208 STp->first_mark_ppos = this_mark_ppos;
2209 return result;
2210}
2211
2212static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2213{
2214 int result;
2215#if DEBUG
2216 char * name = tape_name(STp);
2217#endif
2218
2219 if (STp->raw) return 0;
2220
2221 STp->write_type = OS_WRITE_EOD;
2222 STp->eod_frame_ppos = STp->first_frame_position;
2223#if DEBUG
2224 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2225 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2226#endif
2227 STp->dirty = 1;
2228
2229 result = osst_flush_write_buffer(STp, aSRpnt);
2230 result |= osst_flush_drive_buffer(STp, aSRpnt);
2231 STp->eod_frame_lfa = --(STp->frame_seq_number);
2232 return result;
2233}
2234
2235static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2236{
2237 char * name = tape_name(STp);
2238
2239#if DEBUG
2240 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2241#endif
2242 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2243 osst_set_frame_position(STp, aSRpnt, where, 0);
2244 STp->write_type = OS_WRITE_FILLER;
2245 while (count--) {
2246 memcpy(STp->buffer->b_data, "Filler", 6);
2247 STp->buffer->buffer_bytes = 6;
2248 STp->dirty = 1;
2249 if (osst_flush_write_buffer(STp, aSRpnt)) {
2250 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2251 return (-EIO);
2252 }
2253 }
2254#if DEBUG
2255 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2256#endif
2257 return osst_flush_drive_buffer(STp, aSRpnt);
2258}
2259
2260static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2261{
2262 char * name = tape_name(STp);
2263 int result;
2264
2265#if DEBUG
2266 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2267#endif
2268 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2269 osst_set_frame_position(STp, aSRpnt, where, 0);
2270 STp->write_type = OS_WRITE_HEADER;
2271 while (count--) {
2272 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2273 STp->buffer->buffer_bytes = sizeof(os_header_t);
2274 STp->dirty = 1;
2275 if (osst_flush_write_buffer(STp, aSRpnt)) {
2276 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2277 return (-EIO);
2278 }
2279 }
2280 result = osst_flush_drive_buffer(STp, aSRpnt);
2281#if DEBUG
2282 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2283#endif
2284 return result;
2285}
2286
2287static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2288{
2289 os_header_t * header;
2290 int result;
2291 char * name = tape_name(STp);
2292
2293#if DEBUG
2294 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2295#endif
2296 if (STp->raw) return 0;
2297
2298 if (STp->header_cache == NULL) {
2299 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2300 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2301 return (-ENOMEM);
2302 }
2303 memset(STp->header_cache, 0, sizeof(os_header_t));
2304#if DEBUG
2305 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2306#endif
2307 }
2308 if (STp->header_ok) STp->update_frame_cntr++;
2309 else STp->update_frame_cntr = 0;
2310
2311 header = STp->header_cache;
2312 strcpy(header->ident_str, "ADR_SEQ");
2313 header->major_rev = 1;
2314 header->minor_rev = 4;
2315 header->ext_trk_tb_off = htons(17192);
2316 header->pt_par_num = 1;
2317 header->partition[0].partition_num = OS_DATA_PARTITION;
2318 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2319 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2320 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2321 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2322 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2323 header->cfg_col_width = htonl(20);
2324 header->dat_col_width = htonl(1500);
2325 header->qfa_col_width = htonl(0);
2326 header->ext_track_tb.nr_stream_part = 1;
2327 header->ext_track_tb.et_ent_sz = 32;
2328 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2329 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2330 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2331 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2332 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2333 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2334 header->dat_fm_tab.fm_part_num = 0;
2335 header->dat_fm_tab.fm_tab_ent_sz = 4;
2336 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2337 STp->filemark_cnt:OS_FM_TAB_MAX);
2338
2339 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2340 if (STp->update_frame_cntr == 0)
2341 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2342 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2343
2344 if (locate_eod) {
2345#if DEBUG
2346 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2347#endif
2348 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2349 }
2350 if (result)
2351 printk(KERN_ERR "%s:E: Write header failed\n", name);
2352 else {
2353 memcpy(STp->application_sig, "LIN4", 4);
2354 STp->linux_media = 1;
2355 STp->linux_media_version = 4;
2356 STp->header_ok = 1;
2357 }
2358 return result;
2359}
2360
2361static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2362{
2363 if (STp->header_cache != NULL)
2364 memset(STp->header_cache, 0, sizeof(os_header_t));
2365
2366 STp->logical_blk_num = STp->frame_seq_number = 0;
2367 STp->frame_in_buffer = 0;
2368 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2369 STp->filemark_cnt = 0;
2370 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2371 return osst_write_header(STp, aSRpnt, 1);
2372}
2373
2374static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2375{
2376 char * name = tape_name(STp);
2377 os_header_t * header;
2378 os_aux_t * aux;
2379 char id_string[8];
2380 int linux_media_version,
2381 update_frame_cntr;
2382
2383 if (STp->raw)
2384 return 1;
2385
2386 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2387 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2388 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2389 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2390 if (osst_initiate_read (STp, aSRpnt)) {
2391 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2392 return 0;
2393 }
2394 }
2395 if (osst_read_frame(STp, aSRpnt, 180)) {
2396#if DEBUG
2397 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2398#endif
2399 return 0;
2400 }
2401 header = (os_header_t *) STp->buffer->b_data;
2402 aux = STp->buffer->aux;
2403 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2404#if DEBUG
2405 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2406#endif
2407 return 0;
2408 }
2409 if (ntohl(aux->frame_seq_num) != 0 ||
2410 ntohl(aux->logical_blk_num) != 0 ||
2411 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2412 ntohl(aux->partition.first_frame_ppos) != 0 ||
2413 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2414#if DEBUG
2415 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2416 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2417 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2418 ntohl(aux->partition.last_frame_ppos));
2419#endif
2420 return 0;
2421 }
2422 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2423 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2424 strlcpy(id_string, header->ident_str, 8);
2425#if DEBUG
2426 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2427#endif
2428 return 0;
2429 }
2430 update_frame_cntr = ntohl(aux->update_frame_cntr);
2431 if (update_frame_cntr < STp->update_frame_cntr) {
2432#if DEBUG
2433 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2434 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2435#endif
2436 return 0;
2437 }
2438 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2439#if DEBUG
2440 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2441 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2442 header->minor_rev > 4 )? "Invalid" : "Warning:",
2443 header->major_rev, header->minor_rev);
2444#endif
2445 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2446 return 0;
2447 }
2448#if DEBUG
2449 if (header->pt_par_num != 1)
2450 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2451 name, header->pt_par_num);
2452#endif
2453 memcpy(id_string, aux->application_sig, 4);
2454 id_string[4] = 0;
2455 if (memcmp(id_string, "LIN", 3) == 0) {
2456 STp->linux_media = 1;
2457 linux_media_version = id_string[3] - '0';
2458 if (linux_media_version != 4)
2459 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2460 name, linux_media_version);
2461 } else {
2462 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2463 return 0;
2464 }
2465 if (linux_media_version < STp->linux_media_version) {
2466#if DEBUG
2467 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2468 name, ppos, linux_media_version);
2469#endif
2470 return 0;
2471 }
2472 if (linux_media_version > STp->linux_media_version) {
2473#if DEBUG
2474 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2475 name, ppos, linux_media_version);
2476#endif
2477 memcpy(STp->application_sig, id_string, 5);
2478 STp->linux_media_version = linux_media_version;
2479 STp->update_frame_cntr = -1;
2480 }
2481 if (update_frame_cntr > STp->update_frame_cntr) {
2482#if DEBUG
2483 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2484 name, ppos, update_frame_cntr);
2485#endif
2486 if (STp->header_cache == NULL) {
2487 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2488 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2489 return 0;
2490 }
2491#if DEBUG
2492 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2493#endif
2494 }
2495 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2496 header = STp->header_cache;
2497
2498 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2499 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2500 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2501 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2502 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2503 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2504 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2505 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2506 STp->update_frame_cntr = update_frame_cntr;
2507#if DEBUG
2508 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2509 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2510 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2511 STp->first_data_ppos,
2512 ntohl(header->partition[0].last_frame_ppos),
2513 ntohl(header->partition[0].eod_frame_ppos));
2514 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2515 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2516#endif
2517 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2518#if DEBUG
2519 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2520#endif
2521 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2522 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2523 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2524 }
2525 if (header->minor_rev == 4 &&
2526 (header->ext_trk_tb_off != htons(17192) ||
2527 header->partition[0].partition_num != OS_DATA_PARTITION ||
2528 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2529 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2530 header->cfg_col_width != htonl(20) ||
2531 header->dat_col_width != htonl(1500) ||
2532 header->qfa_col_width != htonl(0) ||
2533 header->ext_track_tb.nr_stream_part != 1 ||
2534 header->ext_track_tb.et_ent_sz != 32 ||
2535 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2536 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2537 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2538 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2539 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2540 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2541 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2542 header->dat_fm_tab.fm_tab_ent_cnt !=
2543 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2544 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2545
2546 }
2547
2548 return 1;
2549}
2550
2551static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2552{
2553 int position, ppos;
2554 int first, last;
2555 int valid = 0;
2556 char * name = tape_name(STp);
2557
2558 position = osst_get_frame_position(STp, aSRpnt);
2559
2560 if (STp->raw) {
2561 STp->header_ok = STp->linux_media = 1;
2562 STp->linux_media_version = 0;
2563 return 1;
2564 }
2565 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2566 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2567 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2568 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2569#if DEBUG
2570 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2571#endif
2572
2573
2574
2575
2576 first = position==10?0xbae: 5;
2577 last = position==10?0xbb3:10;
2578
2579 for (ppos = first; ppos < last; ppos++)
2580 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2581 valid = 1;
2582
2583 first = position==10? 5:0xbae;
2584 last = position==10?10:0xbb3;
2585
2586 for (ppos = first; ppos < last; ppos++)
2587 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2588 valid = 1;
2589
2590 if (!valid) {
2591 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2592 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2593 osst_set_frame_position(STp, aSRpnt, 10, 0);
2594 return 0;
2595 }
2596 if (position <= STp->first_data_ppos) {
2597 position = STp->first_data_ppos;
2598 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2599 }
2600 osst_set_frame_position(STp, aSRpnt, position, 0);
2601 STp->header_ok = 1;
2602
2603 return 1;
2604}
2605
2606static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2607{
2608 int frame_position = STp->first_frame_position;
2609 int frame_seq_numbr = STp->frame_seq_number;
2610 int logical_blk_num = STp->logical_blk_num;
2611 int halfway_frame = STp->frame_in_buffer;
2612 int read_pointer = STp->buffer->read_pointer;
2613 int prev_mark_ppos = -1;
2614 int actual_mark_ppos, i, n;
2615#if DEBUG
2616 char * name = tape_name(STp);
2617
2618 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2619#endif
2620 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2621 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2622#if DEBUG
2623 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2624#endif
2625 return (-EIO);
2626 }
2627 if (STp->linux_media_version >= 4) {
2628 for (i=0; i<STp->filemark_cnt; i++)
2629 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2630 prev_mark_ppos = n;
2631 } else
2632 prev_mark_ppos = frame_position - 1;
2633 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2634 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2635 if (frame_position != STp->first_frame_position ||
2636 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2637 prev_mark_ppos != actual_mark_ppos ) {
2638#if DEBUG
2639 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2640 STp->first_frame_position, frame_position,
2641 STp->frame_seq_number + (halfway_frame?0:1),
2642 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2643#endif
2644 return (-EIO);
2645 }
2646 if (halfway_frame) {
2647
2648 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2649 STp->buffer->buffer_bytes = read_pointer;
2650 STp->ps[STp->partition].rw = ST_WRITING;
2651 STp->dirty = 1;
2652 }
2653 STp->frame_in_buffer = halfway_frame;
2654 STp->frame_seq_number = frame_seq_numbr;
2655 STp->logical_blk_num = logical_blk_num;
2656 return 0;
2657}
2658
2659
2660
2661
2662
2663
2664
2665static unsigned int osst_parse_firmware_rev (const char * str)
2666{
2667 if (str[1] == '.') {
2668 return (str[0]-'0')*10000
2669 +(str[2]-'0')*1000
2670 +(str[3]-'0')*100;
2671 } else {
2672 return (str[0]-'0')*10000
2673 +(str[1]-'0')*1000
2674 +(str[2]-'0')*100 - 100
2675 +(str[3]-'@');
2676 }
2677}
2678
2679
2680
2681
2682static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2683{
2684 unsigned char cmd[MAX_COMMAND_SIZE];
2685 char * name = tape_name(STp);
2686 struct osst_request * SRpnt = * aSRpnt;
2687 osst_mode_parameter_header_t * header;
2688 osst_block_size_page_t * bs;
2689 osst_capabilities_page_t * cp;
2690 osst_tape_paramtr_page_t * prm;
2691 int drive_buffer_size;
2692
2693 if (STp->ready != ST_READY) {
2694#if DEBUG
2695 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2696#endif
2697 return (-EIO);
2698 }
2699
2700 if (STp->os_fw_rev < 10600) {
2701 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2702 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2703 }
2704
2705
2706
2707
2708
2709 memset(cmd, 0, MAX_COMMAND_SIZE);
2710 cmd[0] = MODE_SENSE;
2711 cmd[1] = 8;
2712 cmd[2] = BLOCK_SIZE_PAGE;
2713 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2714
2715 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2716 if (SRpnt == NULL) {
2717#if DEBUG
2718 printk(OSST_DEB_MSG "osst :D: Busy\n");
2719#endif
2720 return (-EBUSY);
2721 }
2722 *aSRpnt = SRpnt;
2723 if ((STp->buffer)->syscall_result != 0) {
2724 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2725 return (-EIO);
2726 }
2727
2728 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2729 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2730
2731#if DEBUG
2732 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2733 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2734 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2735 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2736#endif
2737
2738
2739
2740
2741 bs->one = 1;
2742 bs->play32 = 0;
2743 bs->play32_5 = 1;
2744 bs->record32 = 0;
2745 bs->record32_5 = 1;
2746
2747 memset(cmd, 0, MAX_COMMAND_SIZE);
2748 cmd[0] = MODE_SELECT;
2749 cmd[1] = 0x10;
2750 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2751
2752 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2753 *aSRpnt = SRpnt;
2754 if ((STp->buffer)->syscall_result != 0) {
2755 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2756 return (-EIO);
2757 }
2758
2759#if DEBUG
2760 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2761
2762
2763
2764
2765 osst_set_retries(STp, aSRpnt, 0);
2766 SRpnt = * aSRpnt;
2767#endif
2768
2769
2770
2771
2772
2773 memset(cmd, 0, MAX_COMMAND_SIZE);
2774 cmd[0] = MODE_SELECT;
2775 cmd[1] = 0x10;
2776 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2777
2778 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2779 header->medium_type = 0;
2780 header->dsp = 0;
2781 header->bdl = 0;
2782
2783 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2784 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2785 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2786 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2787 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2788 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2789 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2790 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2791
2792 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2793 *aSRpnt = SRpnt;
2794
2795 if ((STp->buffer)->syscall_result != 0) {
2796 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2797 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2798 return (-EIO);
2799 }
2800
2801 memset(cmd, 0, MAX_COMMAND_SIZE);
2802 cmd[0] = MODE_SENSE;
2803 cmd[1] = 8;
2804 cmd[2] = CAPABILITIES_PAGE;
2805 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2806
2807 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2808 *aSRpnt = SRpnt;
2809
2810 if ((STp->buffer)->syscall_result != 0) {
2811 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2812 return (-EIO);
2813 }
2814
2815 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2816 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2817 sizeof(osst_mode_parameter_header_t) + header->bdl);
2818
2819 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2820
2821 memset(cmd, 0, MAX_COMMAND_SIZE);
2822 cmd[0] = MODE_SENSE;
2823 cmd[1] = 8;
2824 cmd[2] = TAPE_PARAMTR_PAGE;
2825 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2826
2827 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2828 *aSRpnt = SRpnt;
2829
2830 if ((STp->buffer)->syscall_result != 0) {
2831 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2832 return (-EIO);
2833 }
2834
2835 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2836 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2837 sizeof(osst_mode_parameter_header_t) + header->bdl);
2838
2839 STp->density = prm->density;
2840 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2841#if DEBUG
2842 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2843 name, STp->density, STp->capacity / 32, drive_buffer_size);
2844#endif
2845
2846 return 0;
2847
2848}
2849
2850
2851
2852
2853static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2854{
2855 int result;
2856 char * name = tape_name(STp);
2857
2858#if DEBUG
2859 if (debugging)
2860 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2861 name, forward ? "forward" : "backward");
2862#endif
2863
2864 if (forward) {
2865
2866 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2867 }
2868 else
2869
2870 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2871
2872 if (result < 0)
2873 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2874 name, forward ? "forward" : "backward");
2875
2876 return result;
2877}
2878
2879
2880
2881
2882static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2883{
2884 unsigned char scmd[MAX_COMMAND_SIZE];
2885 struct osst_request * SRpnt;
2886 int result = 0;
2887 char * name = tape_name(STp);
2888
2889
2890
2891 char mybuf[24];
2892 char * olddata = STp->buffer->b_data;
2893 int oldsize = STp->buffer->buffer_size;
2894
2895 if (STp->ready != ST_READY) return (-EIO);
2896
2897 memset (scmd, 0, MAX_COMMAND_SIZE);
2898 scmd[0] = READ_POSITION;
2899
2900 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2901 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2902 STp->timeout, MAX_RETRIES, 1);
2903 if (!SRpnt) {
2904 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2905 return (-EBUSY);
2906 }
2907 *aSRpnt = SRpnt;
2908
2909 if (STp->buffer->syscall_result)
2910 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL;
2911
2912 if (result == -EINVAL)
2913 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2914 else {
2915 if (result == -EIO) {
2916 unsigned char mysense[16];
2917 memcpy (mysense, SRpnt->sense, 16);
2918 memset (scmd, 0, MAX_COMMAND_SIZE);
2919 scmd[0] = READ_POSITION;
2920 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2921 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2922 STp->timeout, MAX_RETRIES, 1);
2923#if DEBUG
2924 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2925 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2926 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2927#endif
2928 if (!STp->buffer->syscall_result)
2929 memcpy (SRpnt->sense, mysense, 16);
2930 else
2931 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2932 }
2933 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2934 + ((STp->buffer)->b_data[5] << 16)
2935 + ((STp->buffer)->b_data[6] << 8)
2936 + (STp->buffer)->b_data[7];
2937 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2938 + ((STp->buffer)->b_data[ 9] << 16)
2939 + ((STp->buffer)->b_data[10] << 8)
2940 + (STp->buffer)->b_data[11];
2941 STp->cur_frames = (STp->buffer)->b_data[15];
2942#if DEBUG
2943 if (debugging) {
2944 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2945 STp->first_frame_position, STp->last_frame_position,
2946 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2947 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2948 STp->cur_frames);
2949 }
2950#endif
2951 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2952#if DEBUG
2953 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2954 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2955#endif
2956 STp->first_frame_position = STp->last_frame_position;
2957 }
2958 }
2959 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2960
2961 return (result == 0 ? STp->first_frame_position : result);
2962}
2963
2964
2965
2966static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2967{
2968 unsigned char scmd[MAX_COMMAND_SIZE];
2969 struct osst_request * SRpnt;
2970 struct st_partstat * STps;
2971 int result = 0;
2972 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2973 char * name = tape_name(STp);
2974
2975 if (STp->ready != ST_READY) return (-EIO);
2976
2977 STps = &(STp->ps[STp->partition]);
2978
2979 if (ppos < 0 || ppos > STp->capacity) {
2980 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2981 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2982 result = (-EINVAL);
2983 }
2984
2985 do {
2986#if DEBUG
2987 if (debugging)
2988 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2989#endif
2990 memset (scmd, 0, MAX_COMMAND_SIZE);
2991 scmd[0] = SEEK_10;
2992 scmd[1] = 1;
2993 scmd[3] = (pp >> 24);
2994 scmd[4] = (pp >> 16);
2995 scmd[5] = (pp >> 8);
2996 scmd[6] = pp;
2997 if (skip)
2998 scmd[9] = 0x80;
2999
3000 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
3001 MAX_RETRIES, 1);
3002 if (!SRpnt)
3003 return (-EBUSY);
3004 *aSRpnt = SRpnt;
3005
3006 if ((STp->buffer)->syscall_result != 0) {
3007#if DEBUG
3008 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
3009 name, STp->first_frame_position, pp);
3010#endif
3011 result = (-EIO);
3012 }
3013 if (pp != ppos)
3014 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
3015 } while ((pp != ppos) && (pp = ppos));
3016 STp->first_frame_position = STp->last_frame_position = ppos;
3017 STps->eof = ST_NOEOF;
3018 STps->at_sm = 0;
3019 STps->rw = ST_IDLE;
3020 STp->frame_in_buffer = 0;
3021 return result;
3022}
3023
3024static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
3025{
3026 struct st_partstat * STps = &(STp->ps[STp->partition]);
3027 int result = 0;
3028
3029 if (STp->write_type != OS_WRITE_NEW_MARK) {
3030
3031 result = osst_flush_drive_buffer(STp, aSRpnt);
3032 if (result < 0) goto out;
3033 result = osst_write_filemark(STp, aSRpnt);
3034 if (result < 0) goto out;
3035
3036 if (STps->drv_file >= 0)
3037 STps->drv_file++ ;
3038 STps->drv_block = 0;
3039 }
3040 result = osst_write_eod(STp, aSRpnt);
3041 osst_write_header(STp, aSRpnt, leave_at_EOT);
3042
3043 STps->eof = ST_FM;
3044out:
3045 return result;
3046}
3047
3048
3049
3050
3051static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
3052{
3053 int offset, transfer, blks = 0;
3054 int result = 0;
3055 unsigned char cmd[MAX_COMMAND_SIZE];
3056 struct osst_request * SRpnt = *aSRpnt;
3057 struct st_partstat * STps;
3058 char * name = tape_name(STp);
3059
3060 if ((STp->buffer)->writing) {
3061 if (SRpnt == (STp->buffer)->last_SRpnt)
3062#if DEBUG
3063 { printk(OSST_DEB_MSG
3064 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
3065#endif
3066 *aSRpnt = SRpnt = NULL;
3067#if DEBUG
3068 } else if (SRpnt)
3069 printk(OSST_DEB_MSG
3070 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
3071#endif
3072 osst_write_behind_check(STp);
3073 if ((STp->buffer)->syscall_result) {
3074#if DEBUG
3075 if (debugging)
3076 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3077 name, (STp->buffer)->midlevel_result);
3078#endif
3079 if ((STp->buffer)->midlevel_result == INT_MAX)
3080 return (-ENOSPC);
3081 return (-EIO);
3082 }
3083 }
3084
3085 result = 0;
3086 if (STp->dirty == 1) {
3087
3088 STp->write_count++;
3089 STps = &(STp->ps[STp->partition]);
3090 STps->rw = ST_WRITING;
3091 offset = STp->buffer->buffer_bytes;
3092 blks = (offset + STp->block_size - 1) / STp->block_size;
3093 transfer = OS_FRAME_SIZE;
3094
3095 if (offset < OS_DATA_SIZE)
3096 osst_zero_buffer_tail(STp->buffer);
3097
3098 if (STp->poll)
3099 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3100 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3101
3102 memset(cmd, 0, MAX_COMMAND_SIZE);
3103 cmd[0] = WRITE_6;
3104 cmd[1] = 1;
3105 cmd[4] = 1;
3106
3107 switch (STp->write_type) {
3108 case OS_WRITE_DATA:
3109#if DEBUG
3110 if (debugging)
3111 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3112 name, blks, STp->frame_seq_number,
3113 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3114#endif
3115 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3116 STp->logical_blk_num - blks, STp->block_size, blks);
3117 break;
3118 case OS_WRITE_EOD:
3119 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3120 STp->logical_blk_num, 0, 0);
3121 break;
3122 case OS_WRITE_NEW_MARK:
3123 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3124 STp->logical_blk_num++, 0, blks=1);
3125 break;
3126 case OS_WRITE_HEADER:
3127 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3128 break;
3129 default:
3130 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3131 }
3132#if DEBUG
3133 if (debugging)
3134 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3135 name, offset, transfer, blks);
3136#endif
3137
3138 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3139 STp->timeout, MAX_RETRIES, 1);
3140 *aSRpnt = SRpnt;
3141 if (!SRpnt)
3142 return (-EBUSY);
3143
3144 if ((STp->buffer)->syscall_result != 0) {
3145#if DEBUG
3146 printk(OSST_DEB_MSG
3147 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3148 name, SRpnt->sense[0], SRpnt->sense[2],
3149 SRpnt->sense[12], SRpnt->sense[13]);
3150#endif
3151 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3152 (SRpnt->sense[2] & 0x40) &&
3153 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3154 STp->dirty = 0;
3155 (STp->buffer)->buffer_bytes = 0;
3156 result = (-ENOSPC);
3157 }
3158 else {
3159 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3160 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3161 result = (-EIO);
3162 }
3163 }
3164 STps->drv_block = (-1);
3165 }
3166 else {
3167 STp->first_frame_position++;
3168 STp->dirty = 0;
3169 (STp->buffer)->buffer_bytes = 0;
3170 }
3171 }
3172#if DEBUG
3173 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3174#endif
3175 return result;
3176}
3177
3178
3179
3180
3181static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3182{
3183 struct st_partstat * STps;
3184 int backspace = 0, result = 0;
3185#if DEBUG
3186 char * name = tape_name(STp);
3187#endif
3188
3189
3190
3191
3192
3193 if( STp->pos_unknown)
3194 return (-EIO);
3195
3196 if (STp->ready != ST_READY)
3197 return 0;
3198
3199 STps = &(STp->ps[STp->partition]);
3200 if (STps->rw == ST_WRITING || STp->dirty) {
3201 STp->write_type = OS_WRITE_DATA;
3202 return osst_flush_write_buffer(STp, aSRpnt);
3203 }
3204 if (STp->block_size == 0)
3205 return 0;
3206
3207#if DEBUG
3208 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3209#endif
3210
3211 if (!STp->can_bsr) {
3212 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3213 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3214 (STp->buffer)->buffer_bytes = 0;
3215 (STp->buffer)->read_pointer = 0;
3216 STp->frame_in_buffer = 0;
3217 }
3218
3219 if (!seek_next) {
3220 if (STps->eof == ST_FM_HIT) {
3221 result = cross_eof(STp, aSRpnt, 0);
3222 if (!result)
3223 STps->eof = ST_NOEOF;
3224 else {
3225 if (STps->drv_file >= 0)
3226 STps->drv_file++;
3227 STps->drv_block = 0;
3228 }
3229 }
3230 if (!result && backspace > 0)
3231 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3232 }
3233 else if (STps->eof == ST_FM_HIT) {
3234 if (STps->drv_file >= 0)
3235 STps->drv_file++;
3236 STps->drv_block = 0;
3237 STps->eof = ST_NOEOF;
3238 }
3239
3240 return result;
3241}
3242
3243static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3244{
3245 unsigned char cmd[MAX_COMMAND_SIZE];
3246 struct osst_request * SRpnt;
3247 int blks;
3248#if DEBUG
3249 char * name = tape_name(STp);
3250#endif
3251
3252 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) {
3253#if DEBUG
3254 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3255#endif
3256 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3257 return (-EIO);
3258 }
3259
3260 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3261#if DEBUG
3262 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3263#endif
3264 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3265 }
3266 }
3267
3268 if (STp->poll)
3269 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3270 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3271 return (-EIO);
3272
3273
3274
3275 STp->ps[STp->partition].rw = ST_WRITING;
3276 STp->write_type = OS_WRITE_DATA;
3277
3278 memset(cmd, 0, MAX_COMMAND_SIZE);
3279 cmd[0] = WRITE_6;
3280 cmd[1] = 1;
3281 cmd[4] = 1;
3282 blks = STp->buffer->buffer_bytes / STp->block_size;
3283#if DEBUG
3284 if (debugging)
3285 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3286 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3287#endif
3288 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3289 STp->logical_blk_num - blks, STp->block_size, blks);
3290
3291#if DEBUG
3292 if (!synchronous)
3293 STp->write_pending = 1;
3294#endif
3295 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3296 MAX_RETRIES, synchronous);
3297 if (!SRpnt)
3298 return (-EBUSY);
3299 *aSRpnt = SRpnt;
3300
3301 if (synchronous) {
3302 if (STp->buffer->syscall_result != 0) {
3303#if DEBUG
3304 if (debugging)
3305 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3306#endif
3307 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3308 (SRpnt->sense[2] & 0x40)) {
3309 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3310 return (-ENOSPC);
3311 }
3312 else {
3313 if (osst_write_error_recovery(STp, aSRpnt, 1))
3314 return (-EIO);
3315 }
3316 }
3317 else
3318 STp->first_frame_position++;
3319 }
3320
3321 STp->write_count++;
3322
3323 return 0;
3324}
3325
3326
3327static int do_door_lock(struct osst_tape * STp, int do_lock)
3328{
3329 int retval, cmd;
3330
3331 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3332#if DEBUG
3333 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3334#endif
3335 retval = scsi_ioctl(STp->device, cmd, NULL);
3336 if (!retval) {
3337 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3338 }
3339 else {
3340 STp->door_locked = ST_LOCK_FAILS;
3341 }
3342 return retval;
3343}
3344
3345
3346static void reset_state(struct osst_tape *STp)
3347{
3348 int i;
3349 struct st_partstat *STps;
3350
3351 STp->pos_unknown = 0;
3352 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3353 STps = &(STp->ps[i]);
3354 STps->rw = ST_IDLE;
3355 STps->eof = ST_NOEOF;
3356 STps->at_sm = 0;
3357 STps->last_block_valid = 0;
3358 STps->drv_block = -1;
3359 STps->drv_file = -1;
3360 }
3361}
3362
3363
3364
3365
3366
3367static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3368{
3369 ssize_t total, retval = 0;
3370 ssize_t i, do_count, blks, transfer;
3371 int write_threshold;
3372 int doing_write = 0;
3373 const char __user * b_point;
3374 struct osst_request * SRpnt = NULL;
3375 struct st_modedef * STm;
3376 struct st_partstat * STps;
3377 struct osst_tape * STp = filp->private_data;
3378 char * name = tape_name(STp);
3379
3380
3381 if (mutex_lock_interruptible(&STp->lock))
3382 return (-ERESTARTSYS);
3383
3384
3385
3386
3387
3388
3389
3390 if( !scsi_block_when_processing_errors(STp->device) ) {
3391 retval = (-ENXIO);
3392 goto out;
3393 }
3394
3395 if (STp->ready != ST_READY) {
3396 if (STp->ready == ST_NO_TAPE)
3397 retval = (-ENOMEDIUM);
3398 else
3399 retval = (-EIO);
3400 goto out;
3401 }
3402 STm = &(STp->modes[STp->current_mode]);
3403 if (!STm->defined) {
3404 retval = (-ENXIO);
3405 goto out;
3406 }
3407 if (count == 0)
3408 goto out;
3409
3410
3411
3412
3413
3414 if (STp->pos_unknown) {
3415 retval = (-EIO);
3416 goto out;
3417 }
3418
3419#if DEBUG
3420 if (!STp->in_use) {
3421 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3422 retval = (-EIO);
3423 goto out;
3424 }
3425#endif
3426
3427 if (STp->write_prot) {
3428 retval = (-EACCES);
3429 goto out;
3430 }
3431
3432
3433 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3434 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3435 name, count, STp->block_size<1024?
3436 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3437 retval = (-EINVAL);
3438 goto out;
3439 }
3440
3441 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3442 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3443 name, STp->first_frame_position);
3444 retval = (-ENOSPC);
3445 goto out;
3446 }
3447
3448 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3449 STp->door_locked = ST_LOCKED_AUTO;
3450
3451 STps = &(STp->ps[STp->partition]);
3452
3453 if (STps->rw == ST_READING) {
3454#if DEBUG
3455 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3456 STps->drv_file, STps->drv_block);
3457#endif
3458 retval = osst_flush_buffer(STp, &SRpnt, 0);
3459 if (retval)
3460 goto out;
3461 STps->rw = ST_IDLE;
3462 }
3463 if (STps->rw != ST_WRITING) {
3464
3465 if (!STp->header_ok ||
3466 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3467 (STps->drv_file == 0 && STps->drv_block == 0)) {
3468 STp->wrt_pass_cntr++;
3469#if DEBUG
3470 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3471 name, STp->wrt_pass_cntr);
3472#endif
3473 osst_reset_header(STp, &SRpnt);
3474 STps->drv_file = STps->drv_block = 0;
3475 }
3476
3477 else {
3478 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3479 STps->drv_file < 0 || STps->drv_block < 0) {
3480 if (STp->first_frame_position == STp->eod_frame_ppos) {
3481 STps->drv_file = STp->filemark_cnt;
3482 STps->drv_block = 0;
3483 }
3484 else {
3485
3486#if DEBUG
3487 printk(OSST_DEB_MSG
3488 "%s:D: Cannot write at indeterminate position.\n", name);
3489#endif
3490 retval = (-EIO);
3491 goto out;
3492 }
3493 }
3494 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3495 STp->filemark_cnt = STps->drv_file;
3496 STp->last_mark_ppos =
3497 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3498 printk(KERN_WARNING
3499 "%s:W: Overwriting file %d with old write pass counter %d\n",
3500 name, STps->drv_file, STp->wrt_pass_cntr);
3501 printk(KERN_WARNING
3502 "%s:W: may lead to stale data being accepted on reading back!\n",
3503 name);
3504#if DEBUG
3505 printk(OSST_DEB_MSG
3506 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3507 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3508#endif
3509 }
3510 }
3511 STp->fast_open = 0;
3512 }
3513 if (!STp->header_ok) {
3514#if DEBUG
3515 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3516#endif
3517 retval = (-EIO);
3518 goto out;
3519 }
3520
3521 if ((STp->buffer)->writing) {
3522if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3523 osst_write_behind_check(STp);
3524 if ((STp->buffer)->syscall_result) {
3525#if DEBUG
3526 if (debugging)
3527 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3528 (STp->buffer)->midlevel_result);
3529#endif
3530 if ((STp->buffer)->midlevel_result == INT_MAX)
3531 STps->eof = ST_EOM_OK;
3532 else
3533 STps->eof = ST_EOM_ERROR;
3534 }
3535 }
3536 if (STps->eof == ST_EOM_OK) {
3537 retval = (-ENOSPC);
3538 goto out;
3539 }
3540 else if (STps->eof == ST_EOM_ERROR) {
3541 retval = (-EIO);
3542 goto out;
3543 }
3544
3545
3546
3547 if ((copy_from_user(&i, buf, 1) != 0 ||
3548 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3549 retval = (-EFAULT);
3550 goto out;
3551 }
3552
3553 if (!STm->do_buffer_writes) {
3554 write_threshold = 1;
3555 }
3556 else
3557 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3558 if (!STm->do_async_writes)
3559 write_threshold--;
3560
3561 total = count;
3562#if DEBUG
3563 if (debugging)
3564 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3565 name, (int) count, STps->drv_file, STps->drv_block,
3566 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3567#endif
3568 b_point = buf;
3569 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3570 {
3571 doing_write = 1;
3572 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3573 (STp->buffer)->buffer_bytes;
3574 if (do_count > count)
3575 do_count = count;
3576
3577 i = append_to_buffer(b_point, STp->buffer, do_count);
3578 if (i) {
3579 retval = i;
3580 goto out;
3581 }
3582
3583 blks = do_count / STp->block_size;
3584 STp->logical_blk_num += blks;
3585
3586 i = osst_write_frame(STp, &SRpnt, 1);
3587
3588 if (i == (-ENOSPC)) {
3589 transfer = STp->buffer->writing;
3590 if (transfer <= do_count) {
3591 *ppos += do_count - transfer;
3592 count -= do_count - transfer;
3593 if (STps->drv_block >= 0) {
3594 STps->drv_block += (do_count - transfer) / STp->block_size;
3595 }
3596 STps->eof = ST_EOM_OK;
3597 retval = (-ENOSPC);
3598#if DEBUG
3599 if (debugging)
3600 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3601 name, (int) transfer);
3602#endif
3603 }
3604 else {
3605 STps->eof = ST_EOM_ERROR;
3606 STps->drv_block = (-1);
3607 retval = (-EIO);
3608#if DEBUG
3609 if (debugging)
3610 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3611#endif
3612 }
3613 }
3614 else
3615 retval = i;
3616
3617 if (retval < 0) {
3618 if (SRpnt != NULL) {
3619 osst_release_request(SRpnt);
3620 SRpnt = NULL;
3621 }
3622 STp->buffer->buffer_bytes = 0;
3623 STp->dirty = 0;
3624 if (count < total)
3625 retval = total - count;
3626 goto out;
3627 }
3628
3629 *ppos += do_count;
3630 b_point += do_count;
3631 count -= do_count;
3632 if (STps->drv_block >= 0) {
3633 STps->drv_block += blks;
3634 }
3635 STp->buffer->buffer_bytes = 0;
3636 STp->dirty = 0;
3637 }
3638
3639 if (count != 0) {
3640 STp->dirty = 1;
3641 i = append_to_buffer(b_point, STp->buffer, count);
3642 if (i) {
3643 retval = i;
3644 goto out;
3645 }
3646 blks = count / STp->block_size;
3647 STp->logical_blk_num += blks;
3648 if (STps->drv_block >= 0) {
3649 STps->drv_block += blks;
3650 }
3651 *ppos += count;
3652 count = 0;
3653 }
3654
3655 if (doing_write && (STp->buffer)->syscall_result != 0) {
3656 retval = (STp->buffer)->syscall_result;
3657 goto out;
3658 }
3659
3660 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3661
3662 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3663 STp->block_size) * STp->block_size;
3664 STp->dirty = !((STp->buffer)->writing ==
3665 (STp->buffer)->buffer_bytes);
3666
3667 i = osst_write_frame(STp, &SRpnt, 0);
3668 if (i < 0) {
3669 retval = (-EIO);
3670 goto out;
3671 }
3672 SRpnt = NULL;
3673 }
3674 STps->at_sm &= (total == 0);
3675 if (total > 0)
3676 STps->eof = ST_NOEOF;
3677
3678 retval = total;
3679
3680out:
3681 if (SRpnt != NULL) osst_release_request(SRpnt);
3682
3683 mutex_unlock(&STp->lock);
3684
3685 return retval;
3686}
3687
3688
3689
3690static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3691{
3692 ssize_t total, retval = 0;
3693 ssize_t i, transfer;
3694 int special;
3695 struct st_modedef * STm;
3696 struct st_partstat * STps;
3697 struct osst_request * SRpnt = NULL;
3698 struct osst_tape * STp = filp->private_data;
3699 char * name = tape_name(STp);
3700
3701
3702 if (mutex_lock_interruptible(&STp->lock))
3703 return (-ERESTARTSYS);
3704
3705
3706
3707
3708
3709
3710
3711 if( !scsi_block_when_processing_errors(STp->device) ) {
3712 retval = (-ENXIO);
3713 goto out;
3714 }
3715
3716 if (STp->ready != ST_READY) {
3717 if (STp->ready == ST_NO_TAPE)
3718 retval = (-ENOMEDIUM);
3719 else
3720 retval = (-EIO);
3721 goto out;
3722 }
3723 STm = &(STp->modes[STp->current_mode]);
3724 if (!STm->defined) {
3725 retval = (-ENXIO);
3726 goto out;
3727 }
3728#if DEBUG
3729 if (!STp->in_use) {
3730 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3731 retval = (-EIO);
3732 goto out;
3733 }
3734#endif
3735
3736 if (!STp->header_ok) {
3737 retval = (-EIO);
3738 goto out;
3739 }
3740
3741 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3742 STp->door_locked = ST_LOCKED_AUTO;
3743
3744 STps = &(STp->ps[STp->partition]);
3745 if (STps->rw == ST_WRITING) {
3746 retval = osst_flush_buffer(STp, &SRpnt, 0);
3747 if (retval)
3748 goto out;
3749 STps->rw = ST_IDLE;
3750
3751 }
3752
3753 if ((count % STp->block_size) != 0) {
3754 printk(KERN_WARNING
3755 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3756 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3757 }
3758
3759#if DEBUG
3760 if (debugging && STps->eof != ST_NOEOF)
3761 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3762 STps->eof, (STp->buffer)->buffer_bytes);
3763#endif
3764 if ((STp->buffer)->buffer_bytes == 0 &&
3765 STps->eof >= ST_EOD_1) {
3766 if (STps->eof < ST_EOD) {
3767 STps->eof += 1;
3768 retval = 0;
3769 goto out;
3770 }
3771 retval = (-EIO);
3772 goto out;
3773 }
3774
3775
3776
3777 if (copy_from_user(&i, buf, 1) != 0 ||
3778 copy_to_user (buf, &i, 1) != 0 ||
3779 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3780 copy_to_user (buf + count - 1, &i, 1) != 0) {
3781 retval = (-EFAULT);
3782 goto out;
3783 }
3784
3785
3786 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3787
3788
3789 if ((STp->buffer)->buffer_bytes == 0) {
3790 if (STps->eof == ST_FM_HIT)
3791 break;
3792 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3793 if (special < 0) {
3794 STp->frame_in_buffer = 0;
3795 retval = special;
3796 goto out;
3797 }
3798 }
3799
3800
3801 if ((STp->buffer)->buffer_bytes > 0) {
3802#if DEBUG
3803 if (debugging && STps->eof != ST_NOEOF)
3804 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3805 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3806#endif
3807
3808 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3809 (STp->buffer)->buffer_bytes : count - total)/
3810 STp->block_size) * STp->block_size;
3811
3812 if (transfer == 0) {
3813 printk(KERN_WARNING
3814 "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3815 name, count, STp->block_size < 1024?
3816 STp->block_size:STp->block_size/1024,
3817 STp->block_size<1024?'b':'k');
3818 break;
3819 }
3820 i = from_buffer(STp->buffer, buf, transfer);
3821 if (i) {
3822 retval = i;
3823 goto out;
3824 }
3825 STp->logical_blk_num += transfer / STp->block_size;
3826 STps->drv_block += transfer / STp->block_size;
3827 *ppos += transfer;
3828 buf += transfer;
3829 total += transfer;
3830 }
3831
3832 if ((STp->buffer)->buffer_bytes == 0) {
3833#if DEBUG
3834 if (debugging)
3835 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3836 name, STp->frame_seq_number);
3837#endif
3838 STp->frame_in_buffer = 0;
3839 STp->frame_seq_number++;
3840 }
3841 }
3842
3843
3844 if (total == 0) {
3845 if (STps->eof == ST_FM_HIT) {
3846 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3847 STps->drv_block = 0;
3848 if (STps->drv_file >= 0)
3849 STps->drv_file++;
3850 }
3851 else if (STps->eof == ST_EOD_1) {
3852 STps->eof = ST_EOD_2;
3853 if (STps->drv_block > 0 && STps->drv_file >= 0)
3854 STps->drv_file++;
3855 STps->drv_block = 0;
3856 }
3857 else if (STps->eof == ST_EOD_2)
3858 STps->eof = ST_EOD;
3859 }
3860 else if (STps->eof == ST_FM)
3861 STps->eof = ST_NOEOF;
3862
3863 retval = total;
3864
3865out:
3866 if (SRpnt != NULL) osst_release_request(SRpnt);
3867
3868 mutex_unlock(&STp->lock);
3869
3870 return retval;
3871}
3872
3873
3874
3875static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3876{
3877 printk(KERN_INFO
3878"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3879 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3880 STm->do_read_ahead);
3881 printk(KERN_INFO
3882"%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3883 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3884 printk(KERN_INFO
3885"%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3886 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3887 STp->scsi2_logical);
3888 printk(KERN_INFO
3889"%s:I: sysv: %d\n", name, STm->sysv);
3890#if DEBUG
3891 printk(KERN_INFO
3892 "%s:D: debugging: %d\n",
3893 name, debugging);
3894#endif
3895}
3896
3897
3898static int osst_set_options(struct osst_tape *STp, long options)
3899{
3900 int value;
3901 long code;
3902 struct st_modedef * STm;
3903 char * name = tape_name(STp);
3904
3905 STm = &(STp->modes[STp->current_mode]);
3906 if (!STm->defined) {
3907 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3908 modes_defined = 1;
3909#if DEBUG
3910 if (debugging)
3911 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3912 name, STp->current_mode);
3913#endif
3914 }
3915
3916 code = options & MT_ST_OPTIONS;
3917 if (code == MT_ST_BOOLEANS) {
3918 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3919 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3920 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3921 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3922 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3923 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3924 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3925 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3926 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3927 if ((STp->device)->scsi_level >= SCSI_2)
3928 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3929 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3930 STm->sysv = (options & MT_ST_SYSV) != 0;
3931#if DEBUG
3932 debugging = (options & MT_ST_DEBUGGING) != 0;
3933#endif
3934 osst_log_options(STp, STm, name);
3935 }
3936 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3937 value = (code == MT_ST_SETBOOLEANS);
3938 if ((options & MT_ST_BUFFER_WRITES) != 0)
3939 STm->do_buffer_writes = value;
3940 if ((options & MT_ST_ASYNC_WRITES) != 0)
3941 STm->do_async_writes = value;
3942 if ((options & MT_ST_DEF_WRITES) != 0)
3943 STm->defaults_for_writes = value;
3944 if ((options & MT_ST_READ_AHEAD) != 0)
3945 STm->do_read_ahead = value;
3946 if ((options & MT_ST_TWO_FM) != 0)
3947 STp->two_fm = value;
3948 if ((options & MT_ST_FAST_MTEOM) != 0)
3949 STp->fast_mteom = value;
3950 if ((options & MT_ST_AUTO_LOCK) != 0)
3951 STp->do_auto_lock = value;
3952 if ((options & MT_ST_CAN_BSR) != 0)
3953 STp->can_bsr = value;
3954 if ((options & MT_ST_NO_BLKLIMS) != 0)
3955 STp->omit_blklims = value;
3956 if ((STp->device)->scsi_level >= SCSI_2 &&
3957 (options & MT_ST_CAN_PARTITIONS) != 0)
3958 STp->can_partitions = value;
3959 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3960 STp->scsi2_logical = value;
3961 if ((options & MT_ST_SYSV) != 0)
3962 STm->sysv = value;
3963#if DEBUG
3964 if ((options & MT_ST_DEBUGGING) != 0)
3965 debugging = value;
3966#endif
3967 osst_log_options(STp, STm, name);
3968 }
3969 else if (code == MT_ST_WRITE_THRESHOLD) {
3970 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3971 if (value < 1 || value > osst_buffer_size) {
3972 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3973 name, value);
3974 return (-EIO);
3975 }
3976 STp->write_threshold = value;
3977 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3978 name, value);
3979 }
3980 else if (code == MT_ST_DEF_BLKSIZE) {
3981 value = (options & ~MT_ST_OPTIONS);
3982 if (value == ~MT_ST_OPTIONS) {
3983 STm->default_blksize = (-1);
3984 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3985 }
3986 else {
3987 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3988 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3989 name, value);
3990 return (-EINVAL);
3991 }
3992 STm->default_blksize = value;
3993 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3994 name, STm->default_blksize);
3995 }
3996 }
3997 else if (code == MT_ST_TIMEOUTS) {
3998 value = (options & ~MT_ST_OPTIONS);
3999 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
4000 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
4001 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
4002 (value & ~MT_ST_SET_LONG_TIMEOUT));
4003 }
4004 else {
4005 STp->timeout = value * HZ;
4006 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
4007 }
4008 }
4009 else if (code == MT_ST_DEF_OPTIONS) {
4010 code = (options & ~MT_ST_CLEAR_DEFAULT);
4011 value = (options & MT_ST_CLEAR_DEFAULT);
4012 if (code == MT_ST_DEF_DENSITY) {
4013 if (value == MT_ST_CLEAR_DEFAULT) {
4014 STm->default_density = (-1);
4015 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
4016 }
4017 else {
4018 STm->default_density = value & 0xff;
4019 printk(KERN_INFO "%s:I: Density default set to %x\n",
4020 name, STm->default_density);
4021 }
4022 }
4023 else if (code == MT_ST_DEF_DRVBUFFER) {
4024 if (value == MT_ST_CLEAR_DEFAULT) {
4025 STp->default_drvbuffer = 0xff;
4026 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
4027 }
4028 else {
4029 STp->default_drvbuffer = value & 7;
4030 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
4031 name, STp->default_drvbuffer);
4032 }
4033 }
4034 else if (code == MT_ST_DEF_COMPRESSION) {
4035 if (value == MT_ST_CLEAR_DEFAULT) {
4036 STm->default_compression = ST_DONT_TOUCH;
4037 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
4038 }
4039 else {
4040 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
4041 printk(KERN_INFO "%s:I: Compression default set to %x\n",
4042 name, (value & 1));
4043 }
4044 }
4045 }
4046 else
4047 return (-EIO);
4048
4049 return 0;
4050}
4051
4052
4053
4054static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
4055 unsigned int cmd_in, unsigned long arg)
4056{
4057 int timeout;
4058 long ltmp;
4059 int i, ioctl_result;
4060 int chg_eof = 1;
4061 unsigned char cmd[MAX_COMMAND_SIZE];
4062 struct osst_request * SRpnt = * aSRpnt;
4063 struct st_partstat * STps;
4064 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
4065 int datalen = 0, direction = DMA_NONE;
4066 char * name = tape_name(STp);
4067
4068 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
4069 if (STp->ready == ST_NO_TAPE)
4070 return (-ENOMEDIUM);
4071 else
4072 return (-EIO);
4073 }
4074 timeout = STp->long_timeout;
4075 STps = &(STp->ps[STp->partition]);
4076 fileno = STps->drv_file;
4077 blkno = STps->drv_block;
4078 at_sm = STps->at_sm;
4079 frame_seq_numbr = STp->frame_seq_number;
4080 logical_blk_num = STp->logical_blk_num;
4081
4082 memset(cmd, 0, MAX_COMMAND_SIZE);
4083 switch (cmd_in) {
4084 case MTFSFM:
4085 chg_eof = 0;
4086 case MTFSF:
4087 if (STp->raw)
4088 return (-EIO);
4089 if (STp->linux_media)
4090 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4091 else
4092 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4093 if (fileno >= 0)
4094 fileno += arg;
4095 blkno = 0;
4096 at_sm &= (arg == 0);
4097 goto os_bypass;
4098
4099 case MTBSF:
4100 chg_eof = 0;
4101 case MTBSFM:
4102 if (STp->raw)
4103 return (-EIO);
4104 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4105 if (fileno >= 0)
4106 fileno -= arg;
4107 blkno = (-1);
4108 at_sm &= (arg == 0);
4109 goto os_bypass;
4110
4111 case MTFSR:
4112 case MTBSR:
4113#if DEBUG
4114 if (debugging)
4115 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4116 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4117#endif
4118 if (cmd_in == MTFSR) {
4119 logical_blk_num += arg;
4120 if (blkno >= 0) blkno += arg;
4121 }
4122 else {
4123 logical_blk_num -= arg;
4124 if (blkno >= 0) blkno -= arg;
4125 }
4126 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4127 fileno = STps->drv_file;
4128 blkno = STps->drv_block;
4129 at_sm &= (arg == 0);
4130 goto os_bypass;
4131
4132 case MTFSS:
4133 cmd[0] = SPACE;
4134 cmd[1] = 0x04;
4135 cmd[2] = (arg >> 16);
4136 cmd[3] = (arg >> 8);
4137 cmd[4] = arg;
4138#if DEBUG
4139 if (debugging)
4140 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4141 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4142#endif
4143 if (arg != 0) {
4144 blkno = fileno = (-1);
4145 at_sm = 1;
4146 }
4147 break;
4148 case MTBSS:
4149 cmd[0] = SPACE;
4150 cmd[1] = 0x04;
4151 ltmp = (-arg);
4152 cmd[2] = (ltmp >> 16);
4153 cmd[3] = (ltmp >> 8);
4154 cmd[4] = ltmp;
4155#if DEBUG
4156 if (debugging) {
4157 if (cmd[2] & 0x80)
4158 ltmp = 0xff000000;
4159 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4160 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4161 name, (-ltmp));
4162 }
4163#endif
4164 if (arg != 0) {
4165 blkno = fileno = (-1);
4166 at_sm = 1;
4167 }
4168 break;
4169 case MTWEOF:
4170 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4171 STp->write_type = OS_WRITE_DATA;
4172 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4173 } else
4174 ioctl_result = 0;
4175#if DEBUG
4176 if (debugging)
4177 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4178#endif
4179 for (i=0; i<arg; i++)
4180 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4181 if (fileno >= 0) fileno += arg;
4182 if (blkno >= 0) blkno = 0;
4183 goto os_bypass;
4184
4185 case MTWSM:
4186 if (STp->write_prot)
4187 return (-EACCES);
4188 if (!STp->raw)
4189 return 0;
4190 cmd[0] = WRITE_FILEMARKS;
4191 if (cmd_in == MTWSM)
4192 cmd[1] = 2;
4193 cmd[2] = (arg >> 16);
4194 cmd[3] = (arg >> 8);
4195 cmd[4] = arg;
4196 timeout = STp->timeout;
4197#if DEBUG
4198 if (debugging)
4199 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4200 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4201#endif
4202 if (fileno >= 0)
4203 fileno += arg;
4204 blkno = 0;
4205 at_sm = (cmd_in == MTWSM);
4206 break;
4207 case MTOFFL:
4208 case MTLOAD:
4209 case MTUNLOAD:
4210 case MTRETEN:
4211 cmd[0] = START_STOP;
4212 cmd[1] = 1;
4213 if (cmd_in == MTLOAD) {
4214 if (STp->ready == ST_NO_TAPE)
4215 cmd[4] = 4;
4216 else
4217 cmd[4] = 1;
4218 }
4219 if (cmd_in == MTRETEN)
4220 cmd[4] = 3;
4221 if (cmd_in == MTOFFL)
4222 cmd[4] = 4;
4223 timeout = STp->timeout;
4224#if DEBUG
4225 if (debugging) {
4226 switch (cmd_in) {
4227 case MTUNLOAD:
4228 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4229 break;
4230 case MTLOAD:
4231 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4232 break;
4233 case MTRETEN:
4234 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4235 break;
4236 case MTOFFL:
4237 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4238 break;
4239 }
4240 }
4241#endif
4242 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4243 break;
4244 case MTNOP:
4245#if DEBUG
4246 if (debugging)
4247 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4248#endif
4249 return 0;
4250 break;
4251 case MTEOM:
4252#if DEBUG
4253 if (debugging)
4254 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4255#endif
4256 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4257 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4258 ioctl_result = -EIO;
4259 goto os_bypass;
4260 }
4261 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4262#if DEBUG
4263 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4264#endif
4265 ioctl_result = -EIO;
4266 goto os_bypass;
4267 }
4268 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4269 fileno = STp->filemark_cnt;
4270 blkno = at_sm = 0;
4271 goto os_bypass;
4272
4273 case MTERASE:
4274 if (STp->write_prot)
4275 return (-EACCES);
4276 ioctl_result = osst_reset_header(STp, &SRpnt);
4277 i = osst_write_eod(STp, &SRpnt);
4278 if (i < ioctl_result) ioctl_result = i;
4279 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4280 if (i < ioctl_result) ioctl_result = i;
4281 fileno = blkno = at_sm = 0 ;
4282 goto os_bypass;
4283
4284 case MTREW:
4285 cmd[0] = REZERO_UNIT;
4286 cmd[1] = 1;
4287#if DEBUG
4288 if (debugging)
4289 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4290#endif
4291 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4292 break;
4293
4294 case MTSETBLK:
4295 if ((STps->drv_block == 0 ) &&
4296 !STp->dirty &&
4297 ((STp->buffer)->buffer_bytes == 0) &&
4298 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4299 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4300 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4301
4302
4303
4304
4305
4306
4307 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4308 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4309 name, STp->block_size);
4310 return 0;
4311 }
4312 case MTSETDENSITY:
4313 case MTSETDRVBUFFER:
4314 case SET_DENS_AND_BLK:
4315 chg_eof = 0;
4316 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4317 return (-EIO);
4318 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4319 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4320 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4321 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4322 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4323 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4324 return (-EINVAL);
4325 }
4326 return 0;
4327
4328 default:
4329 return (-ENOSYS);
4330 }
4331
4332 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4333
4334 ioctl_result = (STp->buffer)->syscall_result;
4335
4336 if (!SRpnt) {
4337#if DEBUG
4338 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4339#endif
4340 return ioctl_result;
4341 }
4342
4343 if (!ioctl_result) {
4344 STp->frame_seq_number = frame_seq_numbr;
4345 STp->logical_blk_num = logical_blk_num;
4346 }
4347
4348os_bypass:
4349#if DEBUG
4350 if (debugging)
4351 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4352#endif
4353
4354 if (!ioctl_result) {
4355
4356 if (cmd_in == MTFSFM) {
4357 fileno--;
4358 blkno--;
4359 }
4360 if (cmd_in == MTBSFM) {
4361 fileno++;
4362 blkno++;
4363 }
4364 STps->drv_block = blkno;
4365 STps->drv_file = fileno;
4366 STps->at_sm = at_sm;
4367
4368 if (cmd_in == MTEOM)
4369 STps->eof = ST_EOD;
4370 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4371 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4372 STps->drv_block++;
4373 STp->logical_blk_num++;
4374 STp->frame_seq_number++;
4375 STp->frame_in_buffer = 0;
4376 STp->buffer->read_pointer = 0;
4377 }
4378 else if (cmd_in == MTFSF)
4379 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4380 else if (chg_eof)
4381 STps->eof = ST_NOEOF;
4382
4383 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4384 STp->rew_at_close = 0;
4385 else if (cmd_in == MTLOAD) {
4386 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4387 STp->ps[i].rw = ST_IDLE;
4388 STp->ps[i].last_block_valid = 0;
4389 }
4390 STp->partition = 0;
4391 }
4392
4393 if (cmd_in == MTREW) {
4394 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4395 if (ioctl_result > 0)
4396 ioctl_result = 0;
4397 }
4398
4399 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4400 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4401 STps->drv_file = STps->drv_block = -1;
4402 else
4403 STps->drv_file = STps->drv_block = 0;
4404 STps->eof = ST_NOEOF;
4405 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4406 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4407 STps->drv_file = STps->drv_block = -1;
4408 else {
4409 STps->drv_file = STp->filemark_cnt;
4410 STps->drv_block = 0;
4411 }
4412 STps->eof = ST_EOD;
4413 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4414 STps->drv_file = STps->drv_block = (-1);
4415 STps->eof = ST_NOEOF;
4416 STp->header_ok = 0;
4417 } else if (cmd_in == MTERASE) {
4418 STp->header_ok = 0;
4419 } else if (SRpnt) {
4420 if (SRpnt->sense[2] & 0x40) {
4421 STps->eof = ST_EOM_OK;
4422 STps->drv_block = 0;
4423 }
4424 if (chg_eof)
4425 STps->eof = ST_NOEOF;
4426
4427 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4428 STps->eof = ST_EOD;
4429
4430 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4431 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4432 }
4433 *aSRpnt = SRpnt;
4434
4435 return ioctl_result;
4436}
4437
4438
4439
4440static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4441{
4442 unsigned short flags;
4443 int i, b_size, new_session = 0, retval = 0;
4444 unsigned char cmd[MAX_COMMAND_SIZE];
4445 struct osst_request * SRpnt = NULL;
4446 struct osst_tape * STp;
4447 struct st_modedef * STm;
4448 struct st_partstat * STps;
4449 char * name;
4450 int dev = TAPE_NR(inode);
4451 int mode = TAPE_MODE(inode);
4452
4453
4454
4455
4456
4457
4458 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4459
4460 write_lock(&os_scsi_tapes_lock);
4461 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4462 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4463 write_unlock(&os_scsi_tapes_lock);
4464 return (-ENXIO);
4465 }
4466
4467 name = tape_name(STp);
4468
4469 if (STp->in_use) {
4470 write_unlock(&os_scsi_tapes_lock);
4471#if DEBUG
4472 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4473#endif
4474 return (-EBUSY);
4475 }
4476 if (scsi_device_get(STp->device)) {
4477 write_unlock(&os_scsi_tapes_lock);
4478#if DEBUG
4479 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4480#endif
4481 return (-ENXIO);
4482 }
4483 filp->private_data = STp;
4484 STp->in_use = 1;
4485 write_unlock(&os_scsi_tapes_lock);
4486 STp->rew_at_close = TAPE_REWIND(inode);
4487
4488 if( !scsi_block_when_processing_errors(STp->device) ) {
4489 return -ENXIO;
4490 }
4491
4492 if (mode != STp->current_mode) {
4493#if DEBUG
4494 if (debugging)
4495 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4496 name, STp->current_mode, mode);
4497#endif
4498 new_session = 1;
4499 STp->current_mode = mode;
4500 }
4501 STm = &(STp->modes[STp->current_mode]);
4502
4503 flags = filp->f_flags;
4504 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4505
4506 STp->raw = TAPE_IS_RAW(inode);
4507 if (STp->raw)
4508 STp->header_ok = 0;
4509
4510
4511 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4512 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4513 retval = (-EOVERFLOW);
4514 goto err_out;
4515 }
4516 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4517 for (i = 0, b_size = 0;
4518 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4519 b_size += STp->buffer->sg[i++].length);
4520 STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4521#if DEBUG
4522 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4523 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4524 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4525 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4526#endif
4527 } else {
4528 STp->buffer->aux = NULL;
4529 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4530 retval = (-EIO);
4531 goto err_out;
4532 }
4533 STp->buffer->writing = 0;
4534 STp->buffer->syscall_result = 0;
4535 STp->dirty = 0;
4536 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4537 STps = &(STp->ps[i]);
4538 STps->rw = ST_IDLE;
4539 }
4540 STp->ready = ST_READY;
4541#if DEBUG
4542 STp->nbr_waits = STp->nbr_finished = 0;
4543#endif
4544
4545 memset (cmd, 0, MAX_COMMAND_SIZE);
4546 cmd[0] = TEST_UNIT_READY;
4547
4548 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4549 if (!SRpnt) {
4550 retval = (STp->buffer)->syscall_result;
4551 goto err_out;
4552 }
4553 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4554 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4555 SRpnt->sense[12] == 4 ) {
4556#if DEBUG
4557 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4558#endif
4559 if (filp->f_flags & O_NONBLOCK) {
4560 retval = -EAGAIN;
4561 goto err_out;
4562 }
4563 if (SRpnt->sense[13] == 2) {
4564 memset (cmd, 0, MAX_COMMAND_SIZE);
4565 cmd[0] = START_STOP;
4566 cmd[1] = 1;
4567 cmd[4] = 1;
4568 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4569 STp->timeout, MAX_RETRIES, 1);
4570 }
4571 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4572 }
4573 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4574 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4575#if DEBUG
4576 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4577#endif
4578 STp->header_ok = 0;
4579
4580 for (i=0; i < 10; i++) {
4581
4582 memset (cmd, 0, MAX_COMMAND_SIZE);
4583 cmd[0] = TEST_UNIT_READY;
4584
4585 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4586 STp->timeout, MAX_RETRIES, 1);
4587 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4588 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4589 break;
4590 }
4591
4592 STp->pos_unknown = 0;
4593 STp->partition = STp->new_partition = 0;
4594 if (STp->can_partitions)
4595 STp->nbr_partitions = 1;
4596 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4597 STps = &(STp->ps[i]);
4598 STps->rw = ST_IDLE;
4599 STps->eof = ST_NOEOF;
4600 STps->at_sm = 0;
4601 STps->last_block_valid = 0;
4602 STps->drv_block = 0;
4603 STps->drv_file = 0 ;
4604 }
4605 new_session = 1;
4606 STp->recover_count = 0;
4607 STp->abort_count = 0;
4608 }
4609
4610
4611
4612
4613 if (!STp->buffer->syscall_result && STp->header_ok &&
4614 !SRpnt->result && SRpnt->sense[0] == 0) {
4615
4616 memset(cmd, 0, MAX_COMMAND_SIZE);
4617 cmd[0] = MODE_SENSE;
4618 cmd[1] = 8;
4619 cmd[2] = VENDOR_IDENT_PAGE;
4620 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4621
4622 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4623
4624 if (STp->buffer->syscall_result ||
4625 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4626 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4627 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4628 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4629#if DEBUG
4630 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4631 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4632 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4633 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4634 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4635#endif
4636 STp->header_ok = 0;
4637 }
4638 i = STp->first_frame_position;
4639 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4640 if (STp->door_locked == ST_UNLOCKED) {
4641 if (do_door_lock(STp, 1))
4642 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4643 else
4644 STp->door_locked = ST_LOCKED_AUTO;
4645 }
4646 if (!STp->frame_in_buffer) {
4647 STp->block_size = (STm->default_blksize > 0) ?
4648 STm->default_blksize : OS_DATA_SIZE;
4649 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4650 }
4651 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4652 STp->fast_open = 1;
4653 osst_release_request(SRpnt);
4654 return 0;
4655 }
4656#if DEBUG
4657 if (i != STp->first_frame_position)
4658 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4659 name, i, STp->first_frame_position);
4660#endif
4661 STp->header_ok = 0;
4662 }
4663 STp->fast_open = 0;
4664
4665 if ((STp->buffer)->syscall_result != 0 &&
4666 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4667
4668 memset(cmd, 0, MAX_COMMAND_SIZE);
4669 cmd[0] = MODE_SELECT;
4670 cmd[1] = 0x10;
4671 cmd[4] = 4 + MODE_HEADER_LENGTH;
4672
4673 (STp->buffer)->b_data[0] = cmd[4] - 1;
4674 (STp->buffer)->b_data[1] = 0;
4675 (STp->buffer)->b_data[2] = 0;
4676 (STp->buffer)->b_data[3] = 0;
4677 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4678 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4679 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4680 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4681
4682#if DEBUG
4683 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4684#endif
4685 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4686
4687 STp->header_ok = 0;
4688
4689 for (i=0; i < 10; i++) {
4690
4691 memset (cmd, 0, MAX_COMMAND_SIZE);
4692 cmd[0] = TEST_UNIT_READY;
4693
4694 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4695 STp->timeout, MAX_RETRIES, 1);
4696 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4697 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4698 break;
4699
4700 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4701 STp->pos_unknown = 0;
4702 STp->partition = STp->new_partition = 0;
4703 if (STp->can_partitions)
4704 STp->nbr_partitions = 1;
4705 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4706 STps = &(STp->ps[i]);
4707 STps->rw = ST_IDLE;
4708 STps->eof = ST_NOEOF;
4709 STps->at_sm = 0;
4710 STps->last_block_valid = 0;
4711 STps->drv_block = 0;
4712 STps->drv_file = 0 ;
4713 }
4714 new_session = 1;
4715 }
4716 }
4717 }
4718
4719 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))
4720 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4721
4722 if ((STp->buffer)->syscall_result != 0) {
4723 if ((STp->device)->scsi_level >= SCSI_2 &&
4724 (SRpnt->sense[0] & 0x70) == 0x70 &&
4725 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4726 SRpnt->sense[12] == 0x3a) {
4727 STp->ready = ST_NO_TAPE;
4728 } else
4729 STp->ready = ST_NOT_READY;
4730 osst_release_request(SRpnt);
4731 SRpnt = NULL;
4732 STp->density = 0;
4733 STp->write_prot = 0;
4734 STp->block_size = 0;
4735 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4736 STp->partition = STp->new_partition = 0;
4737 STp->door_locked = ST_UNLOCKED;
4738 return 0;
4739 }
4740
4741 osst_configure_onstream(STp, &SRpnt);
4742
4743 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4744 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4745 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4746 STp->buffer->buffer_bytes =
4747 STp->buffer->read_pointer =
4748 STp->frame_in_buffer = 0;
4749
4750#if DEBUG
4751 if (debugging)
4752 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4753 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4754 (STp->buffer)->buffer_blocks);
4755#endif
4756
4757 if (STp->drv_write_prot) {
4758 STp->write_prot = 1;
4759#if DEBUG
4760 if (debugging)
4761 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4762#endif
4763 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4764 retval = (-EROFS);
4765 goto err_out;
4766 }
4767 }
4768
4769 if (new_session) {
4770#if DEBUG
4771 if (debugging)
4772 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4773#endif
4774 STp->density_changed = STp->blksize_changed = 0;
4775 STp->compression_changed = 0;
4776 }
4777
4778
4779
4780
4781 if (STp->door_locked == ST_UNLOCKED) {
4782 if (do_door_lock(STp, 1))
4783 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4784 else
4785 STp->door_locked = ST_LOCKED_AUTO;
4786 }
4787
4788 osst_analyze_headers(STp, &SRpnt);
4789
4790 osst_release_request(SRpnt);
4791 SRpnt = NULL;
4792
4793 return 0;
4794
4795err_out:
4796 if (SRpnt != NULL)
4797 osst_release_request(SRpnt);
4798 normalize_buffer(STp->buffer);
4799 STp->header_ok = 0;
4800 STp->in_use = 0;
4801 scsi_device_put(STp->device);
4802
4803 return retval;
4804}
4805
4806
4807static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4808{
4809 int ret;
4810
4811 mutex_lock(&osst_int_mutex);
4812 ret = __os_scsi_tape_open(inode, filp);
4813 mutex_unlock(&osst_int_mutex);
4814 return ret;
4815}
4816
4817
4818
4819
4820static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4821{
4822 int result = 0, result2;
4823 struct osst_tape * STp = filp->private_data;
4824 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4825 struct st_partstat * STps = &(STp->ps[STp->partition]);
4826 struct osst_request * SRpnt = NULL;
4827 char * name = tape_name(STp);
4828
4829 if (file_count(filp) > 1)
4830 return 0;
4831
4832 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4833 STp->write_type = OS_WRITE_DATA;
4834 result = osst_flush_write_buffer(STp, &SRpnt);
4835 if (result != 0 && result != (-ENOSPC))
4836 goto out;
4837 }
4838 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4839
4840#if DEBUG
4841 if (debugging) {
4842 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4843 name, (long)(filp->f_pos));
4844 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4845 name, STp->nbr_waits, STp->nbr_finished);
4846 }
4847#endif
4848 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4849#if DEBUG
4850 if (debugging)
4851 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4852 name, 1+STp->two_fm);
4853#endif
4854 }
4855 else if (!STp->rew_at_close) {
4856 STps = &(STp->ps[STp->partition]);
4857 if (!STm->sysv || STps->rw != ST_READING) {
4858 if (STp->can_bsr)
4859 result = osst_flush_buffer(STp, &SRpnt, 0);
4860 else if (STps->eof == ST_FM_HIT) {
4861 result = cross_eof(STp, &SRpnt, 0);
4862 if (result) {
4863 if (STps->drv_file >= 0)
4864 STps->drv_file++;
4865 STps->drv_block = 0;
4866 STps->eof = ST_FM;
4867 }
4868 else
4869 STps->eof = ST_NOEOF;
4870 }
4871 }
4872 else if ((STps->eof == ST_NOEOF &&
4873 !(result = cross_eof(STp, &SRpnt, 1))) ||
4874 STps->eof == ST_FM_HIT) {
4875 if (STps->drv_file >= 0)
4876 STps->drv_file++;
4877 STps->drv_block = 0;
4878 STps->eof = ST_FM;
4879 }
4880 }
4881
4882out:
4883 if (STp->rew_at_close) {
4884 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4885 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4886 if (result == 0 && result2 < 0)
4887 result = result2;
4888 }
4889 if (SRpnt) osst_release_request(SRpnt);
4890
4891 if (STp->abort_count || STp->recover_count) {
4892 printk(KERN_INFO "%s:I:", name);
4893 if (STp->abort_count)
4894 printk(" %d unrecovered errors", STp->abort_count);
4895 if (STp->recover_count)
4896 printk(" %d recovered errors", STp->recover_count);
4897 if (STp->write_count)
4898 printk(" in %d frames written", STp->write_count);
4899 if (STp->read_count)
4900 printk(" in %d frames read", STp->read_count);
4901 printk("\n");
4902 STp->recover_count = 0;
4903 STp->abort_count = 0;
4904 }
4905 STp->write_count = 0;
4906 STp->read_count = 0;
4907
4908 return result;
4909}
4910
4911
4912
4913static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4914{
4915 int result = 0;
4916 struct osst_tape * STp = filp->private_data;
4917
4918 if (STp->door_locked == ST_LOCKED_AUTO)
4919 do_door_lock(STp, 0);
4920
4921 if (STp->raw)
4922 STp->header_ok = 0;
4923
4924 normalize_buffer(STp->buffer);
4925 write_lock(&os_scsi_tapes_lock);
4926 STp->in_use = 0;
4927 write_unlock(&os_scsi_tapes_lock);
4928
4929 scsi_device_put(STp->device);
4930
4931 return result;
4932}
4933
4934
4935
4936static long osst_ioctl(struct file * file,
4937 unsigned int cmd_in, unsigned long arg)
4938{
4939 int i, cmd_nr, cmd_type, blk, retval = 0;
4940 struct st_modedef * STm;
4941 struct st_partstat * STps;
4942 struct osst_request * SRpnt = NULL;
4943 struct osst_tape * STp = file->private_data;
4944 char * name = tape_name(STp);
4945 void __user * p = (void __user *)arg;
4946
4947 mutex_lock(&osst_int_mutex);
4948 if (mutex_lock_interruptible(&STp->lock)) {
4949 mutex_unlock(&osst_int_mutex);
4950 return -ERESTARTSYS;
4951 }
4952
4953#if DEBUG
4954 if (debugging && !STp->in_use) {
4955 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4956 retval = (-EIO);
4957 goto out;
4958 }
4959#endif
4960 STm = &(STp->modes[STp->current_mode]);
4961 STps = &(STp->ps[STp->partition]);
4962
4963
4964
4965
4966
4967
4968
4969 if( !scsi_block_when_processing_errors(STp->device) ) {
4970 retval = (-ENXIO);
4971 goto out;
4972 }
4973
4974 cmd_type = _IOC_TYPE(cmd_in);
4975 cmd_nr = _IOC_NR(cmd_in);
4976#if DEBUG
4977 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4978 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4979#endif
4980 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4981 struct mtop mtc;
4982 int auto_weof = 0;
4983
4984 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4985 retval = (-EINVAL);
4986 goto out;
4987 }
4988
4989 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4990 if (i) {
4991 retval = (-EFAULT);
4992 goto out;
4993 }
4994
4995 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4996 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4997 retval = (-EPERM);
4998 goto out;
4999 }
5000
5001 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
5002 retval = (-ENXIO);
5003 goto out;
5004 }
5005
5006 if (!STp->pos_unknown) {
5007
5008 if (STps->eof == ST_FM_HIT) {
5009 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
5010 mtc.mt_count -= 1;
5011 if (STps->drv_file >= 0)
5012 STps->drv_file += 1;
5013 }
5014 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
5015 mtc.mt_count += 1;
5016 if (STps->drv_file >= 0)
5017 STps->drv_file += 1;
5018 }
5019 }
5020
5021 if (mtc.mt_op == MTSEEK) {
5022
5023 i = !STp->can_partitions || (STp->new_partition != STp->partition);
5024 }
5025 else {
5026 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
5027 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
5028 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
5029 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
5030 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
5031 mtc.mt_op == MTCOMPRESSION;
5032 }
5033 i = osst_flush_buffer(STp, &SRpnt, i);
5034 if (i < 0) {
5035 retval = i;
5036 goto out;
5037 }
5038 }
5039 else {
5040
5041
5042
5043
5044
5045 if(mtc.mt_op != MTREW &&
5046 mtc.mt_op != MTOFFL &&
5047 mtc.mt_op != MTRETEN &&
5048 mtc.mt_op != MTERASE &&
5049 mtc.mt_op != MTSEEK &&
5050 mtc.mt_op != MTEOM) {
5051 retval = (-EIO);
5052 goto out;
5053 }
5054 reset_state(STp);
5055
5056 STp->device->was_reset = 0;
5057 }
5058
5059 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
5060 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
5061 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
5062 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
5063 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
5064
5065
5066
5067
5068
5069
5070
5071#if DEBUG
5072 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
5073 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
5074 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
5075 STp->logical_blk_num, STps->drv_file, STps->drv_block );
5076#endif
5077 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
5078 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
5079 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5080 i = osst_write_trailer(STp, &SRpnt,
5081 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5082#if DEBUG
5083 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5084 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5085 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5086#endif
5087 if (i < 0) {
5088 retval = i;
5089 goto out;
5090 }
5091 }
5092 STps->rw = ST_IDLE;
5093 }
5094
5095 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5096 do_door_lock(STp, 0);
5097
5098 if (mtc.mt_op == MTSETDRVBUFFER &&
5099 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5100 retval = osst_set_options(STp, mtc.mt_count);
5101 goto out;
5102 }
5103
5104 if (mtc.mt_op == MTSETPART) {
5105 if (mtc.mt_count >= STp->nbr_partitions)
5106 retval = -EINVAL;
5107 else {
5108 STp->new_partition = mtc.mt_count;
5109 retval = 0;
5110 }
5111 goto out;
5112 }
5113
5114 if (mtc.mt_op == MTMKPART) {
5115 if (!STp->can_partitions) {
5116 retval = (-EINVAL);
5117 goto out;
5118 }
5119 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0
5120) {
5121 retval = i;
5122 goto out;
5123 }
5124 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5125 STp->ps[i].rw = ST_IDLE;
5126 STp->ps[i].at_sm = 0;
5127 STp->ps[i].last_block_valid = 0;
5128 }
5129 STp->partition = STp->new_partition = 0;
5130 STp->nbr_partitions = 1;
5131 STps->drv_block = STps->drv_file = 0;
5132 retval = 0;
5133 goto out;
5134 }
5135
5136 if (mtc.mt_op == MTSEEK) {
5137 if (STp->raw)
5138 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5139 else
5140 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5141 if (!STp->can_partitions)
5142 STp->ps[0].rw = ST_IDLE;
5143 retval = i;
5144 goto out;
5145 }
5146
5147 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5148 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5149 goto out;
5150 }
5151
5152 if (auto_weof)
5153 cross_eof(STp, &SRpnt, 0);
5154
5155 if (mtc.mt_op == MTCOMPRESSION)
5156 retval = -EINVAL;
5157 else
5158
5159
5160 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5161 goto out;
5162 }
5163
5164 if (!STm->defined) {
5165 retval = (-ENXIO);
5166 goto out;
5167 }
5168
5169 if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5170 retval = i;
5171 goto out;
5172 }
5173
5174 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5175 struct mtget mt_status;
5176
5177 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5178 retval = (-EINVAL);
5179 goto out;
5180 }
5181
5182 mt_status.mt_type = MT_ISONSTREAM_SC;
5183 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5184 mt_status.mt_dsreg =
5185 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5186 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5187 mt_status.mt_blkno = STps->drv_block;
5188 mt_status.mt_fileno = STps->drv_file;
5189 if (STp->block_size != 0) {
5190 if (STps->rw == ST_WRITING)
5191 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5192 else if (STps->rw == ST_READING)
5193 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5194 STp->block_size - 1) / STp->block_size;
5195 }
5196
5197 mt_status.mt_gstat = 0;
5198 if (STp->drv_write_prot)
5199 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5200 if (mt_status.mt_blkno == 0) {
5201 if (mt_status.mt_fileno == 0)
5202 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5203 else
5204 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5205 }
5206 mt_status.mt_resid = STp->partition;
5207 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5208 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5209 else if (STps->eof >= ST_EOM_OK)
5210 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5211 if (STp->density == 1)
5212 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5213 else if (STp->density == 2)
5214 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5215 else if (STp->density == 3)
5216 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5217 if (STp->ready == ST_READY)
5218 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5219 if (STp->ready == ST_NO_TAPE)
5220 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5221 if (STps->at_sm)
5222 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5223 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5224 STp->drv_buffer != 0)
5225 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5226
5227 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5228 if (i) {
5229 retval = (-EFAULT);
5230 goto out;
5231 }
5232
5233 STp->recover_erreg = 0;
5234 retval = 0;
5235 goto out;
5236 }
5237
5238 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5239 struct mtpos mt_pos;
5240
5241 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5242 retval = (-EINVAL);
5243 goto out;
5244 }
5245 if (STp->raw)
5246 blk = osst_get_frame_position(STp, &SRpnt);
5247 else
5248 blk = osst_get_sector(STp, &SRpnt);
5249 if (blk < 0) {
5250 retval = blk;
5251 goto out;
5252 }
5253 mt_pos.mt_blkno = blk;
5254 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5255 if (i)
5256 retval = -EFAULT;
5257 goto out;
5258 }
5259 if (SRpnt) osst_release_request(SRpnt);
5260
5261 mutex_unlock(&STp->lock);
5262
5263 retval = scsi_ioctl(STp->device, cmd_in, p);
5264 mutex_unlock(&osst_int_mutex);
5265 return retval;
5266
5267out:
5268 if (SRpnt) osst_release_request(SRpnt);
5269
5270 mutex_unlock(&STp->lock);
5271 mutex_unlock(&osst_int_mutex);
5272
5273 return retval;
5274}
5275
5276#ifdef CONFIG_COMPAT
5277static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5278{
5279 struct osst_tape *STp = file->private_data;
5280 struct scsi_device *sdev = STp->device;
5281 int ret = -ENOIOCTLCMD;
5282 if (sdev->host->hostt->compat_ioctl) {
5283
5284 ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5285
5286 }
5287 return ret;
5288}
5289#endif
5290
5291
5292
5293
5294
5295
5296static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5297{
5298 int i;
5299 gfp_t priority;
5300 struct osst_buffer *tb;
5301
5302 if (from_initialization)
5303 priority = GFP_ATOMIC;
5304 else
5305 priority = GFP_KERNEL;
5306
5307 i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5308 tb = kzalloc(i, priority);
5309 if (!tb) {
5310 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5311 return NULL;
5312 }
5313
5314 tb->sg_segs = tb->orig_sg_segs = 0;
5315 tb->use_sg = max_sg;
5316 tb->in_use = 1;
5317 tb->dma = need_dma;
5318 tb->buffer_size = 0;
5319#if DEBUG
5320 if (debugging)
5321 printk(OSST_DEB_MSG
5322 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5323 i, max_sg, need_dma);
5324#endif
5325 return tb;
5326}
5327
5328
5329static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5330{
5331 int segs, nbr, max_segs, b_size, order, got;
5332 gfp_t priority;
5333
5334 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5335 return 1;
5336
5337 if (STbuffer->sg_segs) {
5338 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5339 normalize_buffer(STbuffer);
5340 }
5341
5342 nbr = max_segs = STbuffer->use_sg;
5343 if (nbr <= 2)
5344 return 0;
5345
5346 priority = GFP_KERNEL ;
5347 if (need_dma)
5348 priority |= GFP_DMA;
5349
5350
5351
5352 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5353 struct page *page = alloc_pages(priority, order);
5354
5355 STbuffer->sg[0].offset = 0;
5356 if (page != NULL) {
5357 sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5358 STbuffer->b_data = page_address(page);
5359 break;
5360 }
5361 }
5362 if (sg_page(&STbuffer->sg[0]) == NULL) {
5363 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5364 return 0;
5365 }
5366
5367 for (segs=STbuffer->sg_segs=1, got=b_size;
5368 segs < max_segs && got < OS_FRAME_SIZE; ) {
5369 struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5370 STbuffer->sg[segs].offset = 0;
5371 if (page == NULL) {
5372 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5373 OS_FRAME_SIZE);
5374#if DEBUG
5375 STbuffer->buffer_size = got;
5376#endif
5377 normalize_buffer(STbuffer);
5378 return 0;
5379 }
5380 sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5381 got += STbuffer->sg[segs].length;
5382 STbuffer->buffer_size = got;
5383 STbuffer->sg_segs = ++segs;
5384 }
5385#if DEBUG
5386 if (debugging) {
5387 printk(OSST_DEB_MSG
5388 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5389 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5390 printk(OSST_DEB_MSG
5391 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5392 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5393 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5394 }
5395#endif
5396
5397 return 1;
5398}
5399
5400
5401
5402static void normalize_buffer(struct osst_buffer *STbuffer)
5403{
5404 int i, order, b_size;
5405
5406 for (i=0; i < STbuffer->sg_segs; i++) {
5407
5408 for (b_size = PAGE_SIZE, order = 0;
5409 b_size < STbuffer->sg[i].length;
5410 b_size *= 2, order++);
5411
5412 __free_pages(sg_page(&STbuffer->sg[i]), order);
5413 STbuffer->buffer_size -= STbuffer->sg[i].length;
5414 }
5415#if DEBUG
5416 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5417 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5418 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5419#endif
5420 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5421}
5422
5423
5424
5425
5426static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5427{
5428 int i, cnt, res, offset;
5429
5430 for (i=0, offset=st_bp->buffer_bytes;
5431 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5432 offset -= st_bp->sg[i].length;
5433 if (i == st_bp->sg_segs) {
5434 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5435 return (-EIO);
5436 }
5437 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5438 cnt = st_bp->sg[i].length - offset < do_count ?
5439 st_bp->sg[i].length - offset : do_count;
5440 res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5441 if (res)
5442 return (-EFAULT);
5443 do_count -= cnt;
5444 st_bp->buffer_bytes += cnt;
5445 ubp += cnt;
5446 offset = 0;
5447 }
5448 if (do_count) {
5449 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5450 do_count);
5451 return (-EIO);
5452 }
5453 return 0;
5454}
5455
5456
5457
5458
5459static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5460{
5461 int i, cnt, res, offset;
5462
5463 for (i=0, offset=st_bp->read_pointer;
5464 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5465 offset -= st_bp->sg[i].length;
5466 if (i == st_bp->sg_segs) {
5467 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5468 return (-EIO);
5469 }
5470 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5471 cnt = st_bp->sg[i].length - offset < do_count ?
5472 st_bp->sg[i].length - offset : do_count;
5473 res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5474 if (res)
5475 return (-EFAULT);
5476 do_count -= cnt;
5477 st_bp->buffer_bytes -= cnt;
5478 st_bp->read_pointer += cnt;
5479 ubp += cnt;
5480 offset = 0;
5481 }
5482 if (do_count) {
5483 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5484 return (-EIO);
5485 }
5486 return 0;
5487}
5488
5489
5490
5491static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5492{
5493 int i, offset, do_count, cnt;
5494
5495 for (i = 0, offset = st_bp->buffer_bytes;
5496 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5497 offset -= st_bp->sg[i].length;
5498 if (i == st_bp->sg_segs) {
5499 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5500 return (-EIO);
5501 }
5502 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5503 i < st_bp->sg_segs && do_count > 0; i++) {
5504 cnt = st_bp->sg[i].length - offset < do_count ?
5505 st_bp->sg[i].length - offset : do_count ;
5506 memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5507 do_count -= cnt;
5508 offset = 0;
5509 }
5510 if (do_count) {
5511 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5512 return (-EIO);
5513 }
5514 return 0;
5515}
5516
5517
5518
5519static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5520{
5521 int i, cnt, do_count = OS_DATA_SIZE;
5522
5523 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5524 cnt = st_bp->sg[i].length < do_count ?
5525 st_bp->sg[i].length : do_count ;
5526 memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5527 do_count -= cnt;
5528 ptr += cnt;
5529 }
5530 if (do_count || i != st_bp->sg_segs-1) {
5531 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5532 do_count, i);
5533 return (-EIO);
5534 }
5535 return 0;
5536}
5537
5538
5539
5540static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5541{
5542 int i, cnt, do_count = OS_DATA_SIZE;
5543
5544 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5545 cnt = st_bp->sg[i].length < do_count ?
5546 st_bp->sg[i].length : do_count ;
5547 memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5548 do_count -= cnt;
5549 ptr += cnt;
5550 }
5551 if (do_count || i != st_bp->sg_segs-1) {
5552 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5553 do_count, i);
5554 return (-EIO);
5555 }
5556 return 0;
5557}
5558
5559
5560
5561
5562static void validate_options (void)
5563{
5564 if (max_dev > 0)
5565 osst_max_dev = max_dev;
5566 if (write_threshold_kbs > 0)
5567 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5568 if (osst_write_threshold > osst_buffer_size)
5569 osst_write_threshold = osst_buffer_size;
5570 if (max_sg_segs >= OSST_FIRST_SG)
5571 osst_max_sg_segs = max_sg_segs;
5572#if DEBUG
5573 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5574 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5575#endif
5576}
5577
5578#ifndef MODULE
5579
5580
5581
5582static int __init osst_setup (char *str)
5583{
5584 int i, ints[5];
5585 char *stp;
5586
5587 stp = get_options(str, ARRAY_SIZE(ints), ints);
5588
5589 if (ints[0] > 0) {
5590 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5591 *parms[i].val = ints[i + 1];
5592 } else {
5593 while (stp != NULL) {
5594 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5595 int len = strlen(parms[i].name);
5596 if (!strncmp(stp, parms[i].name, len) &&
5597 (*(stp + len) == ':' || *(stp + len) == '=')) {
5598 *parms[i].val =
5599 simple_strtoul(stp + len + 1, NULL, 0);
5600 break;
5601 }
5602 }
5603 if (i >= ARRAY_SIZE(parms))
5604 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5605 stp);
5606 stp = strchr(stp, ',');
5607 if (stp)
5608 stp++;
5609 }
5610 }
5611
5612 return 1;
5613}
5614
5615__setup("osst=", osst_setup);
5616
5617#endif
5618
5619static const struct file_operations osst_fops = {
5620 .owner = THIS_MODULE,
5621 .read = osst_read,
5622 .write = osst_write,
5623 .unlocked_ioctl = osst_ioctl,
5624#ifdef CONFIG_COMPAT
5625 .compat_ioctl = osst_compat_ioctl,
5626#endif
5627 .open = os_scsi_tape_open,
5628 .flush = os_scsi_tape_flush,
5629 .release = os_scsi_tape_close,
5630 .llseek = noop_llseek,
5631};
5632
5633static int osst_supports(struct scsi_device * SDp)
5634{
5635 struct osst_support_data {
5636 char *vendor;
5637 char *model;
5638 char *rev;
5639 char *driver_hint;
5640 };
5641
5642static struct osst_support_data support_list[] = {
5643
5644 SIGS_FROM_OSST,
5645 {NULL, }};
5646
5647 struct osst_support_data *rp;
5648
5649
5650
5651
5652
5653 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5654 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5655 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5656 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5657 return 1;
5658 return 0;
5659}
5660
5661
5662
5663
5664
5665static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5666{
5667 return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5668}
5669
5670static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5671
5672static int osst_create_sysfs_files(struct device_driver *sysfs)
5673{
5674 return driver_create_file(sysfs, &driver_attr_version);
5675}
5676
5677static void osst_remove_sysfs_files(struct device_driver *sysfs)
5678{
5679 driver_remove_file(sysfs, &driver_attr_version);
5680}
5681
5682
5683
5684
5685
5686static ssize_t osst_adr_rev_show(struct device *dev,
5687 struct device_attribute *attr, char *buf)
5688{
5689 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5690 ssize_t l = 0;
5691
5692 if (STp && STp->header_ok && STp->linux_media)
5693 l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5694 return l;
5695}
5696
5697DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5698
5699static ssize_t osst_linux_media_version_show(struct device *dev,
5700 struct device_attribute *attr,
5701 char *buf)
5702{
5703 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5704 ssize_t l = 0;
5705
5706 if (STp && STp->header_ok && STp->linux_media)
5707 l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5708 return l;
5709}
5710
5711DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5712
5713static ssize_t osst_capacity_show(struct device *dev,
5714 struct device_attribute *attr, char *buf)
5715{
5716 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5717 ssize_t l = 0;
5718
5719 if (STp && STp->header_ok && STp->linux_media)
5720 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5721 return l;
5722}
5723
5724DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5725
5726static ssize_t osst_first_data_ppos_show(struct device *dev,
5727 struct device_attribute *attr,
5728 char *buf)
5729{
5730 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5731 ssize_t l = 0;
5732
5733 if (STp && STp->header_ok && STp->linux_media)
5734 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5735 return l;
5736}
5737
5738DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5739
5740static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5741 struct device_attribute *attr,
5742 char *buf)
5743{
5744 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5745 ssize_t l = 0;
5746
5747 if (STp && STp->header_ok && STp->linux_media)
5748 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5749 return l;
5750}
5751
5752DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5753
5754static ssize_t osst_filemark_cnt_show(struct device *dev,
5755 struct device_attribute *attr, char *buf)
5756{
5757 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5758 ssize_t l = 0;
5759
5760 if (STp && STp->header_ok && STp->linux_media)
5761 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5762 return l;
5763}
5764
5765DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5766
5767static struct class *osst_sysfs_class;
5768
5769static int osst_sysfs_init(void)
5770{
5771 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5772 if (IS_ERR(osst_sysfs_class)) {
5773 printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5774 return PTR_ERR(osst_sysfs_class);
5775 }
5776
5777 return 0;
5778}
5779
5780static void osst_sysfs_destroy(dev_t dev)
5781{
5782 device_destroy(osst_sysfs_class, dev);
5783}
5784
5785static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5786{
5787 struct device *osst_member;
5788 int err;
5789
5790 osst_member = device_create(osst_sysfs_class, device, dev, STp,
5791 "%s", name);
5792 if (IS_ERR(osst_member)) {
5793 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5794 return PTR_ERR(osst_member);
5795 }
5796
5797 err = device_create_file(osst_member, &dev_attr_ADR_rev);
5798 if (err)
5799 goto err_out;
5800 err = device_create_file(osst_member, &dev_attr_media_version);
5801 if (err)
5802 goto err_out;
5803 err = device_create_file(osst_member, &dev_attr_capacity);
5804 if (err)
5805 goto err_out;
5806 err = device_create_file(osst_member, &dev_attr_BOT_frame);
5807 if (err)
5808 goto err_out;
5809 err = device_create_file(osst_member, &dev_attr_EOD_frame);
5810 if (err)
5811 goto err_out;
5812 err = device_create_file(osst_member, &dev_attr_file_count);
5813 if (err)
5814 goto err_out;
5815
5816 return 0;
5817
5818err_out:
5819 osst_sysfs_destroy(dev);
5820 return err;
5821}
5822
5823static void osst_sysfs_cleanup(void)
5824{
5825 class_destroy(osst_sysfs_class);
5826}
5827
5828
5829
5830
5831
5832static int osst_probe(struct device *dev)
5833{
5834 struct scsi_device * SDp = to_scsi_device(dev);
5835 struct osst_tape * tpnt;
5836 struct st_modedef * STm;
5837 struct st_partstat * STps;
5838 struct osst_buffer * buffer;
5839 struct gendisk * drive;
5840 int i, dev_num, err = -ENODEV;
5841
5842 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5843 return -ENODEV;
5844
5845 drive = alloc_disk(1);
5846 if (!drive) {
5847 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5848 return -ENODEV;
5849 }
5850
5851
5852 write_lock(&os_scsi_tapes_lock);
5853 if (os_scsi_tapes == NULL) {
5854 os_scsi_tapes =
5855 (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
5856 GFP_ATOMIC);
5857 if (os_scsi_tapes == NULL) {
5858 write_unlock(&os_scsi_tapes_lock);
5859 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5860 goto out_put_disk;
5861 }
5862 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5863 }
5864
5865 if (osst_nr_dev >= osst_max_dev) {
5866 write_unlock(&os_scsi_tapes_lock);
5867 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5868 goto out_put_disk;
5869 }
5870
5871
5872 for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++)
5873 ;
5874 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5875 dev_num = i;
5876
5877
5878 tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5879 if (!tpnt) {
5880 write_unlock(&os_scsi_tapes_lock);
5881 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5882 goto out_put_disk;
5883 }
5884
5885
5886 i = SDp->host->sg_tablesize;
5887 if (osst_max_sg_segs < i)
5888 i = osst_max_sg_segs;
5889 buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5890 if (buffer == NULL) {
5891 write_unlock(&os_scsi_tapes_lock);
5892 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5893 kfree(tpnt);
5894 goto out_put_disk;
5895 }
5896 os_scsi_tapes[dev_num] = tpnt;
5897 tpnt->buffer = buffer;
5898 tpnt->device = SDp;
5899 drive->private_data = &tpnt->driver;
5900 sprintf(drive->disk_name, "osst%d", dev_num);
5901 tpnt->driver = &osst_template;
5902 tpnt->drive = drive;
5903 tpnt->in_use = 0;
5904 tpnt->capacity = 0xfffff;
5905 tpnt->dirty = 0;
5906 tpnt->drv_buffer = 1;
5907 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5908 tpnt->density = 0;
5909 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5910 tpnt->can_bsr = OSST_IN_FILE_POS;
5911 tpnt->can_partitions = 0;
5912 tpnt->two_fm = OSST_TWO_FM;
5913 tpnt->fast_mteom = OSST_FAST_MTEOM;
5914 tpnt->scsi2_logical = OSST_SCSI2LOGICAL;
5915 tpnt->write_threshold = osst_write_threshold;
5916 tpnt->default_drvbuffer = 0xff;
5917 tpnt->partition = 0;
5918 tpnt->new_partition = 0;
5919 tpnt->nbr_partitions = 0;
5920 tpnt->min_block = 512;
5921 tpnt->max_block = OS_DATA_SIZE;
5922 tpnt->timeout = OSST_TIMEOUT;
5923 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5924
5925
5926
5927 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5928 tpnt->omit_blklims = 1;
5929
5930 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5931 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5932 tpnt->frame_in_buffer = 0;
5933 tpnt->header_ok = 0;
5934 tpnt->linux_media = 0;
5935 tpnt->header_cache = NULL;
5936
5937 for (i=0; i < ST_NBR_MODES; i++) {
5938 STm = &(tpnt->modes[i]);
5939 STm->defined = 0;
5940 STm->sysv = OSST_SYSV;
5941 STm->defaults_for_writes = 0;
5942 STm->do_async_writes = OSST_ASYNC_WRITES;
5943 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5944 STm->do_read_ahead = OSST_READ_AHEAD;
5945 STm->default_compression = ST_DONT_TOUCH;
5946 STm->default_blksize = 512;
5947 STm->default_density = (-1);
5948 }
5949
5950 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5951 STps = &(tpnt->ps[i]);
5952 STps->rw = ST_IDLE;
5953 STps->eof = ST_NOEOF;
5954 STps->at_sm = 0;
5955 STps->last_block_valid = 0;
5956 STps->drv_block = (-1);
5957 STps->drv_file = (-1);
5958 }
5959
5960 tpnt->current_mode = 0;
5961 tpnt->modes[0].defined = 1;
5962 tpnt->modes[2].defined = 1;
5963 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5964
5965 mutex_init(&tpnt->lock);
5966 osst_nr_dev++;
5967 write_unlock(&os_scsi_tapes_lock);
5968
5969 {
5970 char name[8];
5971
5972
5973 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5974 if (err)
5975 goto out_free_buffer;
5976
5977
5978 snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5979 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5980 if (err)
5981 goto out_free_sysfs1;
5982 }
5983
5984 sdev_printk(KERN_INFO, SDp,
5985 "osst :I: Attached OnStream %.5s tape as %s\n",
5986 SDp->model, tape_name(tpnt));
5987
5988 return 0;
5989
5990out_free_sysfs1:
5991 osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5992out_free_buffer:
5993 kfree(buffer);
5994out_put_disk:
5995 put_disk(drive);
5996 return err;
5997};
5998
5999static int osst_remove(struct device *dev)
6000{
6001 struct scsi_device * SDp = to_scsi_device(dev);
6002 struct osst_tape * tpnt;
6003 int i;
6004
6005 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
6006 return 0;
6007
6008 write_lock(&os_scsi_tapes_lock);
6009 for(i=0; i < osst_max_dev; i++) {
6010 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
6011 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
6012 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
6013 tpnt->device = NULL;
6014 put_disk(tpnt->drive);
6015 os_scsi_tapes[i] = NULL;
6016 osst_nr_dev--;
6017 write_unlock(&os_scsi_tapes_lock);
6018 vfree(tpnt->header_cache);
6019 if (tpnt->buffer) {
6020 normalize_buffer(tpnt->buffer);
6021 kfree(tpnt->buffer);
6022 }
6023 kfree(tpnt);
6024 return 0;
6025 }
6026 }
6027 write_unlock(&os_scsi_tapes_lock);
6028 return 0;
6029}
6030
6031static int __init init_osst(void)
6032{
6033 int err;
6034
6035 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
6036
6037 validate_options();
6038
6039 err = osst_sysfs_init();
6040 if (err)
6041 return err;
6042
6043 err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
6044 if (err < 0) {
6045 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
6046 goto err_out;
6047 }
6048
6049 err = scsi_register_driver(&osst_template.gendrv);
6050 if (err)
6051 goto err_out_chrdev;
6052
6053 err = osst_create_sysfs_files(&osst_template.gendrv);
6054 if (err)
6055 goto err_out_scsidrv;
6056
6057 return 0;
6058
6059err_out_scsidrv:
6060 scsi_unregister_driver(&osst_template.gendrv);
6061err_out_chrdev:
6062 unregister_chrdev(OSST_MAJOR, "osst");
6063err_out:
6064 osst_sysfs_cleanup();
6065 return err;
6066}
6067
6068static void __exit exit_osst (void)
6069{
6070 int i;
6071 struct osst_tape * STp;
6072
6073 osst_remove_sysfs_files(&osst_template.gendrv);
6074 scsi_unregister_driver(&osst_template.gendrv);
6075 unregister_chrdev(OSST_MAJOR, "osst");
6076 osst_sysfs_cleanup();
6077
6078 if (os_scsi_tapes) {
6079 for (i=0; i < osst_max_dev; ++i) {
6080 if (!(STp = os_scsi_tapes[i])) continue;
6081
6082 vfree(STp->header_cache);
6083 if (STp->buffer) {
6084 normalize_buffer(STp->buffer);
6085 kfree(STp->buffer);
6086 }
6087 put_disk(STp->drive);
6088 kfree(STp);
6089 }
6090 kfree(os_scsi_tapes);
6091 }
6092 printk(KERN_INFO "osst :I: Unloaded.\n");
6093}
6094
6095module_init(init_osst);
6096module_exit(exit_osst);
6097