1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27static const char * osst_version = "0.99.4";
28
29
30#define OSST_FW_NEED_POLL_MIN 10601
31#define OSST_FW_NEED_POLL_MAX 10704
32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
33
34#include <linux/module.h>
35
36#include <linux/fs.h>
37#include <linux/kernel.h>
38#include <linux/sched.h>
39#include <linux/proc_fs.h>
40#include <linux/mm.h>
41#include <linux/slab.h>
42#include <linux/init.h>
43#include <linux/string.h>
44#include <linux/errno.h>
45#include <linux/mtio.h>
46#include <linux/ioctl.h>
47#include <linux/fcntl.h>
48#include <linux/spinlock.h>
49#include <linux/vmalloc.h>
50#include <linux/blkdev.h>
51#include <linux/moduleparam.h>
52#include <linux/delay.h>
53#include <linux/jiffies.h>
54#include <linux/mutex.h>
55#include <asm/uaccess.h>
56#include <asm/dma.h>
57
58
59
60#define DEBUG 0
61
62
63
64
65#define OSST_DEB_MSG KERN_NOTICE
66
67#include <scsi/scsi.h>
68#include <scsi/scsi_dbg.h>
69#include <scsi/scsi_device.h>
70#include <scsi/scsi_driver.h>
71#include <scsi/scsi_eh.h>
72#include <scsi/scsi_host.h>
73#include <scsi/scsi_ioctl.h>
74
75#define ST_KILOBYTE 1024
76
77#include "st.h"
78#include "osst.h"
79#include "osst_options.h"
80#include "osst_detect.h"
81
82static DEFINE_MUTEX(osst_int_mutex);
83static int max_dev = 0;
84static int write_threshold_kbs = 0;
85static int max_sg_segs = 0;
86
87#ifdef MODULE
88MODULE_AUTHOR("Willem Riede");
89MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
90MODULE_LICENSE("GPL");
91MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
92MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
93
94module_param(max_dev, int, 0444);
95MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
96
97module_param(write_threshold_kbs, int, 0644);
98MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
99
100module_param(max_sg_segs, int, 0644);
101MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
102#else
103static struct osst_dev_parm {
104 char *name;
105 int *val;
106} parms[] __initdata = {
107 { "max_dev", &max_dev },
108 { "write_threshold_kbs", &write_threshold_kbs },
109 { "max_sg_segs", &max_sg_segs }
110};
111#endif
112
113
114#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
115#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116
117
118
119#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
120#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
121#endif
122
123#if DEBUG
124static int debugging = 1;
125
126
127#endif
128
129
130
131#define MAX_RETRIES 0
132
133#define NO_TAPE NOT_READY
134
135#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
136#define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
137#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
138
139#define OSST_TIMEOUT (200 * HZ)
140#define OSST_LONG_TIMEOUT (1800 * HZ)
141
142#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
143#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
144#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
145#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
146
147
148
149#define SET_DENS_AND_BLK 0x10001
150
151static int osst_buffer_size = OSST_BUFFER_SIZE;
152static int osst_write_threshold = OSST_WRITE_THRESHOLD;
153static int osst_max_sg_segs = OSST_MAX_SG;
154static int osst_max_dev = OSST_MAX_TAPES;
155static int osst_nr_dev;
156
157static struct osst_tape **os_scsi_tapes = NULL;
158static DEFINE_RWLOCK(os_scsi_tapes_lock);
159
160static int modes_defined = 0;
161
162static struct osst_buffer *new_tape_buffer(int, int, int);
163static int enlarge_buffer(struct osst_buffer *, int);
164static void normalize_buffer(struct osst_buffer *);
165static int append_to_buffer(const char __user *, struct osst_buffer *, int);
166static int from_buffer(struct osst_buffer *, char __user *, int);
167static int osst_zero_buffer_tail(struct osst_buffer *);
168static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
169static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
170
171static int osst_probe(struct device *);
172static int osst_remove(struct device *);
173
174static struct scsi_driver osst_template = {
175 .gendrv = {
176 .name = "osst",
177 .owner = THIS_MODULE,
178 .probe = osst_probe,
179 .remove = osst_remove,
180 }
181};
182
183static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
184 unsigned int cmd_in, unsigned long arg);
185
186static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
187
188static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
189
190static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
191
192static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
193
194static inline char *tape_name(struct osst_tape *tape)
195{
196 return tape->drive->disk_name;
197}
198
199
200
201
202
203static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
204{
205 const u8 *ucp;
206 const u8 *sense = SRpnt->sense;
207
208 s->have_sense = scsi_normalize_sense(SRpnt->sense,
209 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
210 s->flags = 0;
211
212 if (s->have_sense) {
213 s->deferred = 0;
214 s->remainder_valid =
215 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
216 switch (sense[0] & 0x7f) {
217 case 0x71:
218 s->deferred = 1;
219 case 0x70:
220 s->fixed_format = 1;
221 s->flags = sense[2] & 0xe0;
222 break;
223 case 0x73:
224 s->deferred = 1;
225 case 0x72:
226 s->fixed_format = 0;
227 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
228 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
229 break;
230 }
231 }
232}
233
234
235static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
236{
237 char *name = tape_name(STp);
238 int result = SRpnt->result;
239 u8 * sense = SRpnt->sense, scode;
240#if DEBUG
241 const char *stp;
242#endif
243 struct st_cmdstatus *cmdstatp;
244
245 if (!result)
246 return 0;
247
248 cmdstatp = &STp->buffer->cmdstat;
249 osst_analyze_sense(SRpnt, cmdstatp);
250
251 if (cmdstatp->have_sense)
252 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
253 else
254 scode = 0;
255#if DEBUG
256 if (debugging) {
257 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
258 name, result,
259 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
260 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
261 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
262 name, scode, sense[12], sense[13]);
263 if (cmdstatp->have_sense)
264 __scsi_print_sense(STp->device, name,
265 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(STp->device, name,
280 SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
281 }
282 else {
283 static int notyetprinted = 1;
284
285 printk(KERN_WARNING
286 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
287 name, result, driver_byte(result),
288 host_byte(result));
289 if (notyetprinted) {
290 notyetprinted = 0;
291 printk(KERN_INFO
292 "%s:I: This warning may be caused by your scsi controller,\n", name);
293 printk(KERN_INFO
294 "%s:I: it has been reported with some Buslogic cards.\n", name);
295 }
296 }
297 }
298 STp->pos_unknown |= STp->device->was_reset;
299
300 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
301 STp->recover_count++;
302 STp->recover_erreg++;
303#if DEBUG
304 if (debugging) {
305 if (SRpnt->cmd[0] == READ_6)
306 stp = "read";
307 else if (SRpnt->cmd[0] == WRITE_6)
308 stp = "write";
309 else
310 stp = "ioctl";
311 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
312 STp->recover_count);
313 }
314#endif
315 if ((sense[2] & 0xe0) == 0)
316 return 0;
317 }
318 return (-EIO);
319}
320
321
322
323static void osst_end_async(struct request *req, int update)
324{
325 struct osst_request *SRpnt = req->end_io_data;
326 struct osst_tape *STp = SRpnt->stp;
327 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
328
329 STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
330#if DEBUG
331 STp->write_pending = 0;
332#endif
333 if (SRpnt->waiting)
334 complete(SRpnt->waiting);
335
336 if (SRpnt->bio) {
337 kfree(mdata->pages);
338 blk_rq_unmap_user(SRpnt->bio);
339 }
340
341 __blk_put_request(req->q, req);
342}
343
344
345static struct osst_request *osst_allocate_request(void)
346{
347 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
348}
349
350static void osst_release_request(struct osst_request *streq)
351{
352 kfree(streq);
353}
354
355static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
356 int cmd_len, int data_direction, void *buffer, unsigned bufflen,
357 int use_sg, int timeout, int retries)
358{
359 struct request *req;
360 struct page **pages = NULL;
361 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
362
363 int err = 0;
364 int write = (data_direction == DMA_TO_DEVICE);
365
366 req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
367 if (IS_ERR(req))
368 return DRIVER_ERROR << 24;
369
370 blk_rq_set_block_pc(req);
371 req->cmd_flags |= REQ_QUIET;
372
373 SRpnt->bio = NULL;
374
375 if (use_sg) {
376 struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
377 int i;
378
379 pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
380 if (!pages)
381 goto free_req;
382
383 for_each_sg(sgl, sg, use_sg, i)
384 pages[i] = sg_page(sg);
385
386 mdata->null_mapped = 1;
387
388 mdata->page_order = get_order(sgl[0].length);
389 mdata->nr_entries =
390 DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
391 mdata->offset = 0;
392
393 err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
394 if (err) {
395 kfree(pages);
396 goto free_req;
397 }
398 SRpnt->bio = req->bio;
399 mdata->pages = pages;
400
401 } else if (bufflen) {
402 err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
403 if (err)
404 goto free_req;
405 }
406
407 req->cmd_len = cmd_len;
408 memset(req->cmd, 0, BLK_MAX_CDB);
409 memcpy(req->cmd, cmd, req->cmd_len);
410 req->sense = SRpnt->sense;
411 req->sense_len = 0;
412 req->timeout = timeout;
413 req->retries = retries;
414 req->end_io_data = SRpnt;
415
416 blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
417 return 0;
418free_req:
419 blk_put_request(req);
420 return DRIVER_ERROR << 24;
421}
422
423
424
425
426static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
427 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
428{
429 unsigned char *bp;
430 unsigned short use_sg;
431#ifdef OSST_INJECT_ERRORS
432 static int inject = 0;
433 static int repeat = 0;
434#endif
435 struct completion *waiting;
436
437
438 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
439 printk(KERN_ERR "%s: Async command already active.\n",
440 tape_name(STp));
441 if (signal_pending(current))
442 (STp->buffer)->syscall_result = (-EINTR);
443 else
444 (STp->buffer)->syscall_result = (-EBUSY);
445 return NULL;
446 }
447
448 if (SRpnt == NULL) {
449 SRpnt = osst_allocate_request();
450 if (SRpnt == NULL) {
451 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
452 tape_name(STp));
453 if (signal_pending(current))
454 (STp->buffer)->syscall_result = (-EINTR);
455 else
456 (STp->buffer)->syscall_result = (-EBUSY);
457 return NULL;
458 }
459 SRpnt->stp = STp;
460 }
461
462
463
464 if (!do_wait)
465 (STp->buffer)->last_SRpnt = SRpnt;
466
467 waiting = &STp->wait;
468 init_completion(waiting);
469 SRpnt->waiting = waiting;
470
471 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
472 if (use_sg) {
473 bp = (char *)&(STp->buffer->sg[0]);
474 if (STp->buffer->sg_segs < use_sg)
475 use_sg = STp->buffer->sg_segs;
476 }
477 else
478 bp = (STp->buffer)->b_data;
479
480 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
481 STp->buffer->cmdstat.have_sense = 0;
482 STp->buffer->syscall_result = 0;
483
484 if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
485 use_sg, timeout, retries))
486
487 (STp->buffer)->syscall_result = (-EBUSY);
488 else if (do_wait) {
489 wait_for_completion(waiting);
490 SRpnt->waiting = NULL;
491 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
492#ifdef OSST_INJECT_ERRORS
493 if (STp->buffer->syscall_result == 0 &&
494 cmd[0] == READ_6 &&
495 cmd[4] &&
496 ( (++ inject % 83) == 29 ||
497 (STp->first_frame_position == 240
498 &&
499 ++repeat < 3))) {
500 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
501 STp->buffer->last_result_fatal = 1;
502 }
503#endif
504 }
505 return SRpnt;
506}
507
508
509
510static void osst_write_behind_check(struct osst_tape *STp)
511{
512 struct osst_buffer * STbuffer;
513
514 STbuffer = STp->buffer;
515
516#if DEBUG
517 if (STp->write_pending)
518 STp->nbr_waits++;
519 else
520 STp->nbr_finished++;
521#endif
522 wait_for_completion(&(STp->wait));
523 STp->buffer->last_SRpnt->waiting = NULL;
524
525 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
526
527 if (STp->buffer->syscall_result)
528 STp->buffer->syscall_result =
529 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
530 else
531 STp->first_frame_position++;
532
533 osst_release_request(STp->buffer->last_SRpnt);
534
535 if (STbuffer->writing < STbuffer->buffer_bytes)
536 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
537
538 STbuffer->last_SRpnt = NULL;
539 STbuffer->buffer_bytes -= STbuffer->writing;
540 STbuffer->writing = 0;
541
542 return;
543}
544
545
546
547
548
549
550
551static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
552 int logical_blk_num, int blk_sz, int blk_cnt)
553{
554 os_aux_t *aux = STp->buffer->aux;
555 os_partition_t *par = &aux->partition;
556 os_dat_t *dat = &aux->dat;
557
558 if (STp->raw) return;
559
560 memset(aux, 0, sizeof(*aux));
561 aux->format_id = htonl(0);
562 memcpy(aux->application_sig, "LIN4", 4);
563 aux->hdwr = htonl(0);
564 aux->frame_type = frame_type;
565
566 switch (frame_type) {
567 case OS_FRAME_TYPE_HEADER:
568 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
569 par->partition_num = OS_CONFIG_PARTITION;
570 par->par_desc_ver = OS_PARTITION_VERSION;
571 par->wrt_pass_cntr = htons(0xffff);
572
573 par->first_frame_ppos = htonl(0);
574 par->last_frame_ppos = htonl(0xbb7);
575 aux->frame_seq_num = htonl(0);
576 aux->logical_blk_num_high = htonl(0);
577 aux->logical_blk_num = htonl(0);
578 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
579 break;
580 case OS_FRAME_TYPE_DATA:
581 case OS_FRAME_TYPE_MARKER:
582 dat->dat_sz = 8;
583 dat->reserved1 = 0;
584 dat->entry_cnt = 1;
585 dat->reserved3 = 0;
586 dat->dat_list[0].blk_sz = htonl(blk_sz);
587 dat->dat_list[0].blk_cnt = htons(blk_cnt);
588 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
589 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
590 dat->dat_list[0].reserved = 0;
591 case OS_FRAME_TYPE_EOD:
592 aux->update_frame_cntr = htonl(0);
593 par->partition_num = OS_DATA_PARTITION;
594 par->par_desc_ver = OS_PARTITION_VERSION;
595 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
596 par->first_frame_ppos = htonl(STp->first_data_ppos);
597 par->last_frame_ppos = htonl(STp->capacity);
598 aux->frame_seq_num = htonl(frame_seq_number);
599 aux->logical_blk_num_high = htonl(0);
600 aux->logical_blk_num = htonl(logical_blk_num);
601 break;
602 default: ;
603 }
604 aux->filemark_cnt = htonl(STp->filemark_cnt);
605 aux->phys_fm = htonl(0xffffffff);
606 aux->last_mark_ppos = htonl(STp->last_mark_ppos);
607 aux->last_mark_lbn = htonl(STp->last_mark_lbn);
608}
609
610
611
612
613static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
614{
615 char * name = tape_name(STp);
616 os_aux_t * aux = STp->buffer->aux;
617 os_partition_t * par = &(aux->partition);
618 struct st_partstat * STps = &(STp->ps[STp->partition]);
619 int blk_cnt, blk_sz, i;
620
621 if (STp->raw) {
622 if (STp->buffer->syscall_result) {
623 for (i=0; i < STp->buffer->sg_segs; i++)
624 memset(page_address(sg_page(&STp->buffer->sg[i])),
625 0, STp->buffer->sg[i].length);
626 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
627 } else
628 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
629 return 1;
630 }
631 if (STp->buffer->syscall_result) {
632#if DEBUG
633 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
634#endif
635 return 0;
636 }
637 if (ntohl(aux->format_id) != 0) {
638#if DEBUG
639 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
640#endif
641 goto err_out;
642 }
643 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
644 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
645#if DEBUG
646 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
647#endif
648 goto err_out;
649 }
650 if (par->partition_num != OS_DATA_PARTITION) {
651 if (!STp->linux_media || STp->linux_media_version != 2) {
652#if DEBUG
653 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
654 name, par->partition_num);
655#endif
656 goto err_out;
657 }
658 }
659 if (par->par_desc_ver != OS_PARTITION_VERSION) {
660#if DEBUG
661 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
662#endif
663 goto err_out;
664 }
665 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
666#if DEBUG
667 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
668 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
669#endif
670 goto err_out;
671 }
672 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
673 aux->frame_type != OS_FRAME_TYPE_EOD &&
674 aux->frame_type != OS_FRAME_TYPE_MARKER) {
675 if (!quiet) {
676#if DEBUG
677 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
678#endif
679 }
680 goto err_out;
681 }
682 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
683 STp->first_frame_position < STp->eod_frame_ppos) {
684 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
685 STp->first_frame_position);
686 goto err_out;
687 }
688 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
689 if (!quiet) {
690#if DEBUG
691 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
692 name, ntohl(aux->frame_seq_num), frame_seq_number);
693#endif
694 }
695 goto err_out;
696 }
697 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
698 STps->eof = ST_FM_HIT;
699
700 i = ntohl(aux->filemark_cnt);
701 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
702 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
703#if DEBUG
704 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
705 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
706 i, STp->first_frame_position - 1);
707#endif
708 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
709 if (i >= STp->filemark_cnt)
710 STp->filemark_cnt = i+1;
711 }
712 }
713 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
714 STps->eof = ST_EOD_1;
715 STp->frame_in_buffer = 1;
716 }
717 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
718 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
719 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
720 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
721 STp->buffer->read_pointer = 0;
722 STp->frame_in_buffer = 1;
723
724
725 if (STp->block_size != blk_sz && blk_sz > 0) {
726 printk(KERN_INFO
727 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
728 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
729 STp->block_size<1024?STp->block_size:STp->block_size/1024,
730 STp->block_size<1024?'b':'k');
731 STp->block_size = blk_sz;
732 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
733 }
734 STps->eof = ST_NOEOF;
735 }
736 STp->frame_seq_number = ntohl(aux->frame_seq_num);
737 STp->logical_blk_num = ntohl(aux->logical_blk_num);
738 return 1;
739
740err_out:
741 if (STp->read_error_frame == 0)
742 STp->read_error_frame = STp->first_frame_position - 1;
743 return 0;
744}
745
746
747
748
749static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
750 unsigned timeout, int initial_delay)
751{
752 unsigned char cmd[MAX_COMMAND_SIZE];
753 struct osst_request * SRpnt;
754 unsigned long startwait = jiffies;
755#if DEBUG
756 int dbg = debugging;
757 char * name = tape_name(STp);
758
759 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
760#endif
761
762 if (initial_delay > 0)
763 msleep(jiffies_to_msecs(initial_delay));
764
765 memset(cmd, 0, MAX_COMMAND_SIZE);
766 cmd[0] = TEST_UNIT_READY;
767
768 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
769 *aSRpnt = SRpnt;
770 if (!SRpnt) return (-EBUSY);
771
772 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
773 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
774 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
775 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
776 SRpnt->sense[13] == 0 ) )) {
777#if DEBUG
778 if (debugging) {
779 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
780 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
781 debugging = 0;
782 }
783#endif
784 msleep(100);
785
786 memset(cmd, 0, MAX_COMMAND_SIZE);
787 cmd[0] = TEST_UNIT_READY;
788
789 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
790 }
791 *aSRpnt = SRpnt;
792#if DEBUG
793 debugging = dbg;
794#endif
795 if ( STp->buffer->syscall_result &&
796 osst_write_error_recovery(STp, aSRpnt, 0) ) {
797#if DEBUG
798 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
799 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
800 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
801 SRpnt->sense[12], SRpnt->sense[13]);
802#endif
803 return (-EIO);
804 }
805#if DEBUG
806 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
807#endif
808 return 0;
809}
810
811
812
813
814static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
815{
816 unsigned char cmd[MAX_COMMAND_SIZE];
817 struct osst_request * SRpnt;
818 unsigned long startwait = jiffies;
819#if DEBUG
820 int dbg = debugging;
821 char * name = tape_name(STp);
822
823 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
824#endif
825
826 memset(cmd, 0, MAX_COMMAND_SIZE);
827 cmd[0] = TEST_UNIT_READY;
828
829 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
830 *aSRpnt = SRpnt;
831 if (!SRpnt) return (-EBUSY);
832
833 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
834 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
835#if DEBUG
836 if (debugging) {
837 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
838 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
839 debugging = 0;
840 }
841#endif
842 msleep(100);
843
844 memset(cmd, 0, MAX_COMMAND_SIZE);
845 cmd[0] = TEST_UNIT_READY;
846
847 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
848 }
849 *aSRpnt = SRpnt;
850#if DEBUG
851 debugging = dbg;
852#endif
853 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
854 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
855#if DEBUG
856 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
857 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
858 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
859 SRpnt->sense[12], SRpnt->sense[13]);
860#endif
861 return 0;
862 }
863#if DEBUG
864 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
865#endif
866 return 1;
867}
868
869static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
870{
871 int retval;
872
873 osst_wait_ready(STp, aSRpnt, 15 * 60, 0);
874 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
875 if (retval) return (retval);
876 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
877 return (osst_get_frame_position(STp, aSRpnt));
878}
879
880
881
882
883static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
884{
885 unsigned char cmd[MAX_COMMAND_SIZE];
886 struct osst_request * SRpnt;
887 int result = 0;
888 int delay = OSST_WAIT_WRITE_COMPLETE;
889#if DEBUG
890 char * name = tape_name(STp);
891
892 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
893#endif
894
895 memset(cmd, 0, MAX_COMMAND_SIZE);
896 cmd[0] = WRITE_FILEMARKS;
897 cmd[1] = 1;
898
899 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
900 *aSRpnt = SRpnt;
901 if (!SRpnt) return (-EBUSY);
902 if (STp->buffer->syscall_result) {
903 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
904 if (SRpnt->sense[13] == 8) {
905 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
906 }
907 } else
908 result = osst_write_error_recovery(STp, aSRpnt, 0);
909 }
910 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
911 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
912
913 return (result);
914}
915
916#define OSST_POLL_PER_SEC 10
917static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
918{
919 unsigned long startwait = jiffies;
920 char * name = tape_name(STp);
921#if DEBUG
922 char notyetprinted = 1;
923#endif
924 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
925 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
926
927 while (time_before (jiffies, startwait + to*HZ))
928 {
929 int result;
930 result = osst_get_frame_position(STp, aSRpnt);
931 if (result == -EIO)
932 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
933 return 0;
934 if (result < 0) break;
935 if (STp->first_frame_position == curr &&
936 ((minlast < 0 &&
937 (signed)STp->last_frame_position > (signed)curr + minlast) ||
938 (minlast >= 0 && STp->cur_frames > minlast)
939 ) && result >= 0)
940 {
941#if DEBUG
942 if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
943 printk (OSST_DEB_MSG
944 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
945 name, curr, curr+minlast, STp->first_frame_position,
946 STp->last_frame_position, STp->cur_frames,
947 result, (jiffies-startwait)/HZ,
948 (((jiffies-startwait)%HZ)*10)/HZ);
949#endif
950 return 0;
951 }
952#if DEBUG
953 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
954 {
955 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
956 name, curr, curr+minlast, STp->first_frame_position,
957 STp->last_frame_position, STp->cur_frames, result);
958 notyetprinted--;
959 }
960#endif
961 msleep(1000 / OSST_POLL_PER_SEC);
962 }
963#if DEBUG
964 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
965 name, curr, curr+minlast, STp->first_frame_position,
966 STp->last_frame_position, STp->cur_frames,
967 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
968#endif
969 return -EBUSY;
970}
971
972static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
973{
974 struct osst_request * SRpnt;
975 unsigned char cmd[MAX_COMMAND_SIZE];
976 unsigned long startwait = jiffies;
977 int retval = 1;
978 char * name = tape_name(STp);
979
980 if (writing) {
981 char mybuf[24];
982 char * olddata = STp->buffer->b_data;
983 int oldsize = STp->buffer->buffer_size;
984
985
986
987 memset(cmd, 0, MAX_COMMAND_SIZE);
988 cmd[0] = WRITE_FILEMARKS;
989 cmd[1] = 1;
990 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
991 MAX_RETRIES, 1);
992
993 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
994
995 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
996
997
998 retval = osst_write_error_recovery(STp, aSRpnt, 0);
999 break;
1000 }
1001 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
1002
1003 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1004 memset(cmd, 0, MAX_COMMAND_SIZE);
1005 cmd[0] = READ_POSITION;
1006
1007 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1008 MAX_RETRIES, 1);
1009
1010 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1011 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1012 }
1013 if (retval)
1014 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1015 } else
1016
1017 if (STp->buffer->syscall_result)
1018 printk(KERN_WARNING
1019 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1020 (*aSRpnt)->sense[ 2] & 0x0f,
1021 (*aSRpnt)->sense[12],
1022 (*aSRpnt)->sense[13]);
1023
1024 return retval;
1025}
1026
1027
1028
1029
1030static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1031{
1032 unsigned char cmd[MAX_COMMAND_SIZE];
1033 struct osst_request * SRpnt;
1034 int retval = 0;
1035#if DEBUG
1036 os_aux_t * aux = STp->buffer->aux;
1037 char * name = tape_name(STp);
1038#endif
1039
1040 if (STp->poll)
1041 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1042 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1043
1044 memset(cmd, 0, MAX_COMMAND_SIZE);
1045 cmd[0] = READ_6;
1046 cmd[1] = 1;
1047 cmd[4] = 1;
1048
1049#if DEBUG
1050 if (debugging)
1051 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1052#endif
1053 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1054 STp->timeout, MAX_RETRIES, 1);
1055 *aSRpnt = SRpnt;
1056 if (!SRpnt)
1057 return (-EBUSY);
1058
1059 if ((STp->buffer)->syscall_result) {
1060 retval = 1;
1061 if (STp->read_error_frame == 0) {
1062 STp->read_error_frame = STp->first_frame_position;
1063#if DEBUG
1064 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1065#endif
1066 }
1067#if DEBUG
1068 if (debugging)
1069 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1070 name,
1071 SRpnt->sense[0], SRpnt->sense[1],
1072 SRpnt->sense[2], SRpnt->sense[3],
1073 SRpnt->sense[4], SRpnt->sense[5],
1074 SRpnt->sense[6], SRpnt->sense[7]);
1075#endif
1076 }
1077 else
1078 STp->first_frame_position++;
1079#if DEBUG
1080 if (debugging) {
1081 char sig[8]; int i;
1082 for (i=0;i<4;i++)
1083 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1084 sig[4] = '\0';
1085 printk(OSST_DEB_MSG
1086 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1087 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1088 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1089 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1090 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1091 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1092 if (aux->frame_type==2)
1093 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1094 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1095 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1096 }
1097#endif
1098 return (retval);
1099}
1100
1101static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1102{
1103 struct st_partstat * STps = &(STp->ps[STp->partition]);
1104 struct osst_request * SRpnt ;
1105 unsigned char cmd[MAX_COMMAND_SIZE];
1106 int retval = 0;
1107 char * name = tape_name(STp);
1108
1109 if (STps->rw != ST_READING) {
1110 if (STps->rw == ST_WRITING || STp->dirty) {
1111 STp->write_type = OS_WRITE_DATA;
1112 osst_flush_write_buffer(STp, aSRpnt);
1113 osst_flush_drive_buffer(STp, aSRpnt);
1114 }
1115 STps->rw = ST_READING;
1116 STp->frame_in_buffer = 0;
1117
1118
1119
1120
1121
1122 memset(cmd, 0, MAX_COMMAND_SIZE);
1123 cmd[0] = READ_6;
1124 cmd[1] = 1;
1125
1126#if DEBUG
1127 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1128#endif
1129 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1130 *aSRpnt = SRpnt;
1131 if ((retval = STp->buffer->syscall_result))
1132 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1133 }
1134
1135 return retval;
1136}
1137
1138static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1139 int frame_seq_number, int quiet)
1140{
1141 struct st_partstat * STps = &(STp->ps[STp->partition]);
1142 char * name = tape_name(STp);
1143 int cnt = 0,
1144 bad = 0,
1145 past = 0,
1146 x,
1147 position;
1148
1149
1150
1151
1152 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1153#if DEBUG
1154 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1155#endif
1156 return (STps->eof);
1157 }
1158
1159
1160
1161 while (1) {
1162 if (cnt++ > 400) {
1163 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1164 name, frame_seq_number);
1165 if (STp->read_error_frame) {
1166 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1167#if DEBUG
1168 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1169 name, STp->read_error_frame);
1170#endif
1171 STp->read_error_frame = 0;
1172 STp->abort_count++;
1173 }
1174 return (-EIO);
1175 }
1176#if DEBUG
1177 if (debugging)
1178 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1179 name, frame_seq_number, cnt);
1180#endif
1181 if ( osst_initiate_read(STp, aSRpnt)
1182 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1183 if (STp->raw)
1184 return (-EIO);
1185 position = osst_get_frame_position(STp, aSRpnt);
1186 if (position >= 0xbae && position < 0xbb8)
1187 position = 0xbb8;
1188 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1189 position = STp->read_error_frame - 1;
1190 bad = 0;
1191 }
1192 else {
1193 position += 29;
1194 cnt += 19;
1195 }
1196#if DEBUG
1197 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1198 name, position);
1199#endif
1200 osst_set_frame_position(STp, aSRpnt, position, 0);
1201 continue;
1202 }
1203 if (osst_verify_frame(STp, frame_seq_number, quiet))
1204 break;
1205 if (osst_verify_frame(STp, -1, quiet)) {
1206 x = ntohl(STp->buffer->aux->frame_seq_num);
1207 if (STp->fast_open) {
1208 printk(KERN_WARNING
1209 "%s:W: Found logical frame %d instead of %d after fast open\n",
1210 name, x, frame_seq_number);
1211 STp->header_ok = 0;
1212 STp->read_error_frame = 0;
1213 return (-EIO);
1214 }
1215 if (x > frame_seq_number) {
1216 if (++past > 3) {
1217
1218 position = STp->read_error_frame - 1;
1219 }
1220 else {
1221 position = osst_get_frame_position(STp, aSRpnt)
1222 + frame_seq_number - x - 1;
1223
1224 if (STp->first_frame_position >= 3000 && position < 3000)
1225 position -= 10;
1226 }
1227#if DEBUG
1228 printk(OSST_DEB_MSG
1229 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1230 name, x, frame_seq_number,
1231 STp->first_frame_position - position);
1232#endif
1233 osst_set_frame_position(STp, aSRpnt, position, 0);
1234 cnt += 10;
1235 }
1236 else
1237 past = 0;
1238 }
1239 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1240#if DEBUG
1241 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1242#endif
1243 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1244 cnt--;
1245 }
1246 STp->frame_in_buffer = 0;
1247 }
1248 if (cnt > 1) {
1249 STp->recover_count++;
1250 STp->recover_erreg++;
1251 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1252 name, STp->read_error_frame);
1253 }
1254 STp->read_count++;
1255
1256#if DEBUG
1257 if (debugging || STps->eof)
1258 printk(OSST_DEB_MSG
1259 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1260 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1261#endif
1262 STp->fast_open = 0;
1263 STp->read_error_frame = 0;
1264 return (STps->eof);
1265}
1266
1267static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1268{
1269 struct st_partstat * STps = &(STp->ps[STp->partition]);
1270 char * name = tape_name(STp);
1271 int retries = 0;
1272 int frame_seq_estimate, ppos_estimate, move;
1273
1274 if (logical_blk_num < 0) logical_blk_num = 0;
1275#if DEBUG
1276 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1277 name, logical_blk_num, STp->logical_blk_num,
1278 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1279 STp->block_size<1024?'b':'k');
1280#endif
1281
1282 if (STps->drv_block >= 0) {
1283 move = logical_blk_num - STp->logical_blk_num;
1284 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1285 move /= (OS_DATA_SIZE / STp->block_size);
1286 frame_seq_estimate = STp->frame_seq_number + move;
1287 } else
1288 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1289
1290 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1291 else ppos_estimate = frame_seq_estimate + 20;
1292 while (++retries < 10) {
1293 if (ppos_estimate > STp->eod_frame_ppos-2) {
1294 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1295 ppos_estimate = STp->eod_frame_ppos - 2;
1296 }
1297 if (frame_seq_estimate < 0) {
1298 frame_seq_estimate = 0;
1299 ppos_estimate = 10;
1300 }
1301 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1302 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1303
1304 if (logical_blk_num < STp->logical_blk_num ||
1305 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1306 if (STps->eof == ST_FM_HIT)
1307 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1308 else {
1309 move = logical_blk_num - STp->logical_blk_num;
1310 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1311 move /= (OS_DATA_SIZE / STp->block_size);
1312 }
1313 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1314#if DEBUG
1315 printk(OSST_DEB_MSG
1316 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1317 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1318 STp->logical_blk_num, logical_blk_num, move);
1319#endif
1320 frame_seq_estimate += move;
1321 ppos_estimate += move;
1322 continue;
1323 } else {
1324 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1325 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1326 STp->logical_blk_num = logical_blk_num;
1327#if DEBUG
1328 printk(OSST_DEB_MSG
1329 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1330 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1331 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1332 STp->block_size);
1333#endif
1334 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1335 if (STps->eof == ST_FM_HIT) {
1336 STps->drv_file++;
1337 STps->drv_block = 0;
1338 } else {
1339 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1340 STp->logical_blk_num -
1341 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1342 -1;
1343 }
1344 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1345 return 0;
1346 }
1347 }
1348 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1349 goto error;
1350
1351#if DEBUG
1352 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1353 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1354 STp->logical_blk_num, logical_blk_num);
1355#endif
1356 if (frame_seq_estimate != STp->frame_seq_number)
1357 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1358 else
1359 break;
1360 }
1361error:
1362 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1363 name, logical_blk_num, STp->logical_blk_num, retries);
1364 return (-EIO);
1365}
1366
1367
1368
1369
1370
1371
1372#define OSST_FRAME_SHIFT 6
1373#define OSST_SECTOR_SHIFT 9
1374#define OSST_SECTOR_MASK 0x03F
1375
1376static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1377{
1378 int sector;
1379#if DEBUG
1380 char * name = tape_name(STp);
1381
1382 printk(OSST_DEB_MSG
1383 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1384 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1385 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1386 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1387 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1388 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1389#endif
1390
1391 if (STp->ps[STp->partition].drv_block >= 0) {
1392 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1393 STp->first_frame_position) << OSST_FRAME_SHIFT;
1394 if (STp->ps[STp->partition].rw == ST_WRITING)
1395 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1396 else
1397 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1398 } else {
1399 sector = osst_get_frame_position(STp, aSRpnt);
1400 if (sector > 0)
1401 sector <<= OSST_FRAME_SHIFT;
1402 }
1403 return sector;
1404}
1405
1406static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1407{
1408 struct st_partstat * STps = &(STp->ps[STp->partition]);
1409 int frame = sector >> OSST_FRAME_SHIFT,
1410 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1411 r;
1412#if DEBUG
1413 char * name = tape_name(STp);
1414
1415 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1416 name, sector, frame, offset);
1417#endif
1418 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1419
1420 if (frame <= STp->first_data_ppos) {
1421 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1422 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1423 }
1424 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1425 if (r < 0) return r;
1426
1427 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1428 if (r < 0) return r;
1429
1430 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1431
1432 if (offset) {
1433 STp->logical_blk_num += offset / STp->block_size;
1434 STp->buffer->read_pointer = offset;
1435 STp->buffer->buffer_bytes -= offset;
1436 } else {
1437 STp->frame_seq_number++;
1438 STp->frame_in_buffer = 0;
1439 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1440 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1441 }
1442 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1443 if (STps->eof == ST_FM_HIT) {
1444 STps->drv_file++;
1445 STps->drv_block = 0;
1446 } else {
1447 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1448 STp->logical_blk_num -
1449 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1450 -1;
1451 }
1452 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1453#if DEBUG
1454 printk(OSST_DEB_MSG
1455 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1456 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1457 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1458#endif
1459 return 0;
1460}
1461
1462
1463
1464
1465
1466
1467
1468
1469static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1470 unsigned int frame, unsigned int skip, int pending)
1471{
1472 struct osst_request * SRpnt = * aSRpnt;
1473 unsigned char * buffer, * p;
1474 unsigned char cmd[MAX_COMMAND_SIZE];
1475 int flag, new_frame, i;
1476 int nframes = STp->cur_frames;
1477 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1478 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1479 - (nframes + pending - 1);
1480 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1481 - (nframes + pending - 1) * blks_per_frame;
1482 char * name = tape_name(STp);
1483 unsigned long startwait = jiffies;
1484#if DEBUG
1485 int dbg = debugging;
1486#endif
1487
1488 if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1489 return (-EIO);
1490
1491 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1492 name, nframes, pending?" and one that was pending":"");
1493
1494 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1495#if DEBUG
1496 if (pending && debugging)
1497 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1498 name, frame_seq_number + nframes,
1499 logical_blk_num + nframes * blks_per_frame,
1500 p[0], p[1], p[2], p[3]);
1501#endif
1502 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1503
1504 memset(cmd, 0, MAX_COMMAND_SIZE);
1505 cmd[0] = 0x3C;
1506 cmd[1] = 6;
1507 cmd[7] = 32768 >> 8;
1508 cmd[8] = 32768 & 0xff;
1509
1510 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1511 STp->timeout, MAX_RETRIES, 1);
1512
1513 if ((STp->buffer)->syscall_result || !SRpnt) {
1514 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1515 vfree(buffer);
1516 *aSRpnt = SRpnt;
1517 return (-EIO);
1518 }
1519 osst_copy_from_buffer(STp->buffer, p);
1520#if DEBUG
1521 if (debugging)
1522 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1523 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1524#endif
1525 }
1526 *aSRpnt = SRpnt;
1527 osst_get_frame_position(STp, aSRpnt);
1528
1529#if DEBUG
1530 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1531#endif
1532
1533
1534
1535 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1536
1537 if (flag) {
1538 if (STp->write_type == OS_WRITE_HEADER) {
1539 i += skip;
1540 p += skip * OS_DATA_SIZE;
1541 }
1542 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1543 new_frame = 3000-i;
1544 else
1545 new_frame += skip;
1546#if DEBUG
1547 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1548 name, new_frame+i, frame_seq_number+i);
1549#endif
1550 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1551 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1552 osst_get_frame_position(STp, aSRpnt);
1553 SRpnt = * aSRpnt;
1554
1555 if (new_frame > frame + 1000) {
1556 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1557 vfree(buffer);
1558 return (-EIO);
1559 }
1560 if ( i >= nframes + pending ) break;
1561 flag = 0;
1562 }
1563 osst_copy_to_buffer(STp->buffer, p);
1564
1565
1566
1567 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1568 logical_blk_num + i*blks_per_frame,
1569 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1570 memset(cmd, 0, MAX_COMMAND_SIZE);
1571 cmd[0] = WRITE_6;
1572 cmd[1] = 1;
1573 cmd[4] = 1;
1574
1575#if DEBUG
1576 if (debugging)
1577 printk(OSST_DEB_MSG
1578 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1579 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1580 p[0], p[1], p[2], p[3]);
1581#endif
1582 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1583 STp->timeout, MAX_RETRIES, 1);
1584
1585 if (STp->buffer->syscall_result)
1586 flag = 1;
1587 else {
1588 p += OS_DATA_SIZE; i++;
1589
1590
1591 if ( i == nframes + pending ) {
1592#if DEBUG
1593 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1594#endif
1595 memset(cmd, 0, MAX_COMMAND_SIZE);
1596 cmd[0] = WRITE_FILEMARKS;
1597 cmd[1] = 1;
1598 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1599 STp->timeout, MAX_RETRIES, 1);
1600#if DEBUG
1601 if (debugging) {
1602 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1603 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1604 debugging = 0;
1605 }
1606#endif
1607 flag = STp->buffer->syscall_result;
1608 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1609
1610 memset(cmd, 0, MAX_COMMAND_SIZE);
1611 cmd[0] = TEST_UNIT_READY;
1612
1613 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1614 MAX_RETRIES, 1);
1615
1616 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1617 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1618
1619 msleep(100);
1620 continue;
1621 }
1622 if (STp->buffer->syscall_result)
1623 flag = 1;
1624 break;
1625 }
1626#if DEBUG
1627 debugging = dbg;
1628 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1629#endif
1630 }
1631 }
1632 *aSRpnt = SRpnt;
1633 if (flag) {
1634 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1635 SRpnt->sense[12] == 0 &&
1636 SRpnt->sense[13] == 2) {
1637 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1638 vfree(buffer);
1639 return (-EIO);
1640 }
1641 i = ((SRpnt->sense[3] << 24) |
1642 (SRpnt->sense[4] << 16) |
1643 (SRpnt->sense[5] << 8) |
1644 SRpnt->sense[6] ) - new_frame;
1645 p = &buffer[i * OS_DATA_SIZE];
1646#if DEBUG
1647 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1648#endif
1649 osst_get_frame_position(STp, aSRpnt);
1650#if DEBUG
1651 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1652 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1653#endif
1654 }
1655 }
1656 if (flag) {
1657
1658 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1659 STp->write_type == OS_WRITE_HEADER?"header":"body");
1660 }
1661 if (!pending)
1662 osst_copy_to_buffer(STp->buffer, p);
1663 vfree(buffer);
1664 return 0;
1665}
1666
1667static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1668 unsigned int frame, unsigned int skip, int pending)
1669{
1670 unsigned char cmd[MAX_COMMAND_SIZE];
1671 struct osst_request * SRpnt;
1672 char * name = tape_name(STp);
1673 int expected = 0;
1674 int attempts = 1000 / skip;
1675 int flag = 1;
1676 unsigned long startwait = jiffies;
1677#if DEBUG
1678 int dbg = debugging;
1679#endif
1680
1681 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1682 if (flag) {
1683#if DEBUG
1684 debugging = dbg;
1685#endif
1686 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1687 frame = 3000-skip;
1688 expected = frame+skip+STp->cur_frames+pending;
1689#if DEBUG
1690 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1691 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1692#endif
1693 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1694 flag = 0;
1695 attempts--;
1696 schedule_timeout_interruptible(msecs_to_jiffies(100));
1697 }
1698 if (osst_get_frame_position(STp, aSRpnt) < 0) {
1699#if DEBUG
1700 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1701 name, STp->first_frame_position,
1702 STp->last_frame_position, STp->cur_frames);
1703#endif
1704 frame = STp->last_frame_position;
1705 flag = 1;
1706 continue;
1707 }
1708 if (pending && STp->cur_frames < 50) {
1709
1710 memset(cmd, 0, MAX_COMMAND_SIZE);
1711 cmd[0] = WRITE_6;
1712 cmd[1] = 1;
1713 cmd[4] = 1;
1714#if DEBUG
1715 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1716 name, STp->frame_seq_number-1, STp->first_frame_position);
1717#endif
1718 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1719 STp->timeout, MAX_RETRIES, 1);
1720 *aSRpnt = SRpnt;
1721
1722 if (STp->buffer->syscall_result) {
1723 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1724 SRpnt->sense[12] == 0 &&
1725 SRpnt->sense[13] == 2) {
1726 printk(KERN_ERR
1727 "%s:E: Volume overflow in write error recovery\n",
1728 name);
1729 break;
1730 }
1731 flag = 1;
1732 }
1733 else
1734 pending = 0;
1735
1736 continue;
1737 }
1738 if (STp->cur_frames == 0) {
1739#if DEBUG
1740 debugging = dbg;
1741 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1742#endif
1743 if (STp->first_frame_position != expected) {
1744 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1745 name, STp->first_frame_position, expected);
1746 return (-EIO);
1747 }
1748 return 0;
1749 }
1750#if DEBUG
1751 if (debugging) {
1752 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1753 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1754 debugging = 0;
1755 }
1756#endif
1757 schedule_timeout_interruptible(msecs_to_jiffies(100));
1758 }
1759 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1760#if DEBUG
1761 debugging = dbg;
1762#endif
1763 return (-EIO);
1764}
1765
1766
1767
1768
1769
1770static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1771{
1772 struct osst_request * SRpnt = * aSRpnt;
1773 struct st_partstat * STps = & STp->ps[STp->partition];
1774 char * name = tape_name(STp);
1775 int retval = 0;
1776 int rw_state;
1777 unsigned int frame, skip;
1778
1779 rw_state = STps->rw;
1780
1781 if ((SRpnt->sense[ 2] & 0x0f) != 3
1782 || SRpnt->sense[12] != 12
1783 || SRpnt->sense[13] != 0) {
1784#if DEBUG
1785 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1786 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1787#endif
1788 return (-EIO);
1789 }
1790 frame = (SRpnt->sense[3] << 24) |
1791 (SRpnt->sense[4] << 16) |
1792 (SRpnt->sense[5] << 8) |
1793 SRpnt->sense[6];
1794 skip = SRpnt->sense[9];
1795
1796#if DEBUG
1797 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1798#endif
1799 osst_get_frame_position(STp, aSRpnt);
1800#if DEBUG
1801 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1802 name, STp->first_frame_position, STp->last_frame_position);
1803#endif
1804 switch (STp->write_type) {
1805 case OS_WRITE_DATA:
1806 case OS_WRITE_EOD:
1807 case OS_WRITE_NEW_MARK:
1808 printk(KERN_WARNING
1809 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1810 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1811 if (STp->os_fw_rev >= 10600)
1812 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1813 else
1814 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1815 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1816 retval?"E" :"I",
1817 retval?"" :"Don't worry, ",
1818 retval?" not ":" ");
1819 break;
1820 case OS_WRITE_LAST_MARK:
1821 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1822 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1823 retval = -EIO;
1824 break;
1825 case OS_WRITE_HEADER:
1826 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1827 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1828 break;
1829 default:
1830 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1831 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1832 }
1833 osst_get_frame_position(STp, aSRpnt);
1834#if DEBUG
1835 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1836 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1837 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1838#endif
1839 if (retval == 0) {
1840 STp->recover_count++;
1841 STp->recover_erreg++;
1842 } else
1843 STp->abort_count++;
1844
1845 STps->rw = rw_state;
1846 return retval;
1847}
1848
1849static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1850 int mt_op, int mt_count)
1851{
1852 char * name = tape_name(STp);
1853 int cnt;
1854 int last_mark_ppos = -1;
1855
1856#if DEBUG
1857 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1858#endif
1859 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1860#if DEBUG
1861 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1862#endif
1863 return -EIO;
1864 }
1865 if (STp->linux_media_version >= 4) {
1866
1867
1868
1869 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1870 if (STp->header_ok &&
1871 STp->header_cache != NULL &&
1872 (cnt - mt_count) >= 0 &&
1873 (cnt - mt_count) < OS_FM_TAB_MAX &&
1874 (cnt - mt_count) < STp->filemark_cnt &&
1875 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1876
1877 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1878#if DEBUG
1879 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1880 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1881 STp->header_cache == NULL?"lack of header cache":"count out of range");
1882 else
1883 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1884 name, cnt,
1885 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1886 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1887 STp->buffer->aux->last_mark_ppos))?"match":"error",
1888 mt_count, last_mark_ppos);
1889#endif
1890 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1891 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1892 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1893#if DEBUG
1894 printk(OSST_DEB_MSG
1895 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1896#endif
1897 return (-EIO);
1898 }
1899 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1900 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1901 name, last_mark_ppos);
1902 return (-EIO);
1903 }
1904 goto found;
1905 }
1906#if DEBUG
1907 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1908#endif
1909 }
1910 cnt = 0;
1911 while (cnt != mt_count) {
1912 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1913 if (last_mark_ppos == -1)
1914 return (-EIO);
1915#if DEBUG
1916 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1917#endif
1918 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1919 cnt++;
1920 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1921#if DEBUG
1922 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1923#endif
1924 return (-EIO);
1925 }
1926 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1927 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1928 name, last_mark_ppos);
1929 return (-EIO);
1930 }
1931 }
1932found:
1933 if (mt_op == MTBSFM) {
1934 STp->frame_seq_number++;
1935 STp->frame_in_buffer = 0;
1936 STp->buffer->buffer_bytes = 0;
1937 STp->buffer->read_pointer = 0;
1938 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1939 }
1940 return 0;
1941}
1942
1943
1944
1945
1946
1947
1948static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1949 int mt_op, int mt_count)
1950{
1951 int cnt = 0;
1952#if DEBUG
1953 char * name = tape_name(STp);
1954
1955 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1956#endif
1957 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1958#if DEBUG
1959 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1960#endif
1961 return (-EIO);
1962 }
1963 while (1) {
1964 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1965#if DEBUG
1966 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1967#endif
1968 return (-EIO);
1969 }
1970 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1971 cnt++;
1972 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1973#if DEBUG
1974 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1975#endif
1976 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1977#if DEBUG
1978 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1979 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1980#endif
1981 STp->eod_frame_ppos = STp->first_frame_position-1;
1982 }
1983 return (-EIO);
1984 }
1985 if (cnt == mt_count)
1986 break;
1987 STp->frame_in_buffer = 0;
1988 }
1989 if (mt_op == MTFSF) {
1990 STp->frame_seq_number++;
1991 STp->frame_in_buffer = 0;
1992 STp->buffer->buffer_bytes = 0;
1993 STp->buffer->read_pointer = 0;
1994 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1995 }
1996 return 0;
1997}
1998
1999
2000
2001
2002static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
2003 int mt_op, int mt_count)
2004{
2005 char * name = tape_name(STp);
2006 int cnt = 0,
2007 next_mark_ppos = -1;
2008
2009#if DEBUG
2010 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
2011#endif
2012 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2013#if DEBUG
2014 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
2015#endif
2016 return (-EIO);
2017 }
2018
2019 if (STp->linux_media_version >= 4) {
2020
2021
2022
2023 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
2024 if (STp->header_ok &&
2025 STp->header_cache != NULL &&
2026 (cnt + mt_count) < OS_FM_TAB_MAX &&
2027 (cnt + mt_count) < STp->filemark_cnt &&
2028 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2029 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
2030
2031 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
2032#if DEBUG
2033 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
2034 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
2035 STp->header_cache == NULL?"lack of header cache":"count out of range");
2036 else
2037 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2038 name, cnt,
2039 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2040 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
2041 STp->buffer->aux->last_mark_ppos))?"match":"error",
2042 mt_count, next_mark_ppos);
2043#endif
2044 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
2045#if DEBUG
2046 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2047#endif
2048 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2049 } else {
2050 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2051 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2052#if DEBUG
2053 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2054 name);
2055#endif
2056 return (-EIO);
2057 }
2058 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2059 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2060 name, next_mark_ppos);
2061 return (-EIO);
2062 }
2063 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
2064 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
2065 name, cnt+mt_count, next_mark_ppos,
2066 ntohl(STp->buffer->aux->filemark_cnt));
2067 return (-EIO);
2068 }
2069 }
2070 } else {
2071
2072
2073
2074 while (1) {
2075 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
2076 break;
2077 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2078#if DEBUG
2079 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2080#endif
2081 return (-EIO);
2082 }
2083 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2084 if (STp->first_mark_ppos == -1) {
2085#if DEBUG
2086 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2087#endif
2088 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2089 }
2090 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2091 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2092#if DEBUG
2093 printk(OSST_DEB_MSG
2094 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2095 name);
2096#endif
2097 return (-EIO);
2098 }
2099 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2100 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2101 name, STp->first_mark_ppos);
2102 return (-EIO);
2103 }
2104 } else {
2105 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2106 return (-EIO);
2107 mt_count++;
2108 }
2109 }
2110 cnt++;
2111 while (cnt != mt_count) {
2112 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2113 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2114#if DEBUG
2115 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2116#endif
2117 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2118 }
2119#if DEBUG
2120 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2121#endif
2122 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2123 cnt++;
2124 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2125#if DEBUG
2126 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2127 name);
2128#endif
2129 return (-EIO);
2130 }
2131 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2132 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2133 name, next_mark_ppos);
2134 return (-EIO);
2135 }
2136 }
2137 }
2138 if (mt_op == MTFSF) {
2139 STp->frame_seq_number++;
2140 STp->frame_in_buffer = 0;
2141 STp->buffer->buffer_bytes = 0;
2142 STp->buffer->read_pointer = 0;
2143 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2144 }
2145 return 0;
2146}
2147
2148
2149
2150
2151
2152#if DEBUG
2153static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2154{
2155 unsigned char cmd[MAX_COMMAND_SIZE];
2156 struct osst_request * SRpnt = * aSRpnt;
2157 char * name = tape_name(STp);
2158
2159 memset(cmd, 0, MAX_COMMAND_SIZE);
2160 cmd[0] = MODE_SELECT;
2161 cmd[1] = 0x10;
2162 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2163
2164 (STp->buffer)->b_data[0] = cmd[4] - 1;
2165 (STp->buffer)->b_data[1] = 0;
2166 (STp->buffer)->b_data[2] = 0;
2167 (STp->buffer)->b_data[3] = 0;
2168 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2169 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2170 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2171 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2172
2173 if (debugging)
2174 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2175
2176 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2177 *aSRpnt = SRpnt;
2178
2179 if ((STp->buffer)->syscall_result)
2180 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2181}
2182#endif
2183
2184
2185static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2186{
2187 int result;
2188 int this_mark_ppos = STp->first_frame_position;
2189 int this_mark_lbn = STp->logical_blk_num;
2190#if DEBUG
2191 char * name = tape_name(STp);
2192#endif
2193
2194 if (STp->raw) return 0;
2195
2196 STp->write_type = OS_WRITE_NEW_MARK;
2197#if DEBUG
2198 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2199 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2200#endif
2201 STp->dirty = 1;
2202 result = osst_flush_write_buffer(STp, aSRpnt);
2203 result |= osst_flush_drive_buffer(STp, aSRpnt);
2204 STp->last_mark_ppos = this_mark_ppos;
2205 STp->last_mark_lbn = this_mark_lbn;
2206 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2207 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2208 if (STp->filemark_cnt++ == 0)
2209 STp->first_mark_ppos = this_mark_ppos;
2210 return result;
2211}
2212
2213static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2214{
2215 int result;
2216#if DEBUG
2217 char * name = tape_name(STp);
2218#endif
2219
2220 if (STp->raw) return 0;
2221
2222 STp->write_type = OS_WRITE_EOD;
2223 STp->eod_frame_ppos = STp->first_frame_position;
2224#if DEBUG
2225 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2226 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2227#endif
2228 STp->dirty = 1;
2229
2230 result = osst_flush_write_buffer(STp, aSRpnt);
2231 result |= osst_flush_drive_buffer(STp, aSRpnt);
2232 STp->eod_frame_lfa = --(STp->frame_seq_number);
2233 return result;
2234}
2235
2236static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2237{
2238 char * name = tape_name(STp);
2239
2240#if DEBUG
2241 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2242#endif
2243 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2244 osst_set_frame_position(STp, aSRpnt, where, 0);
2245 STp->write_type = OS_WRITE_FILLER;
2246 while (count--) {
2247 memcpy(STp->buffer->b_data, "Filler", 6);
2248 STp->buffer->buffer_bytes = 6;
2249 STp->dirty = 1;
2250 if (osst_flush_write_buffer(STp, aSRpnt)) {
2251 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2252 return (-EIO);
2253 }
2254 }
2255#if DEBUG
2256 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2257#endif
2258 return osst_flush_drive_buffer(STp, aSRpnt);
2259}
2260
2261static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2262{
2263 char * name = tape_name(STp);
2264 int result;
2265
2266#if DEBUG
2267 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2268#endif
2269 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2270 osst_set_frame_position(STp, aSRpnt, where, 0);
2271 STp->write_type = OS_WRITE_HEADER;
2272 while (count--) {
2273 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2274 STp->buffer->buffer_bytes = sizeof(os_header_t);
2275 STp->dirty = 1;
2276 if (osst_flush_write_buffer(STp, aSRpnt)) {
2277 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2278 return (-EIO);
2279 }
2280 }
2281 result = osst_flush_drive_buffer(STp, aSRpnt);
2282#if DEBUG
2283 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2284#endif
2285 return result;
2286}
2287
2288static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2289{
2290 os_header_t * header;
2291 int result;
2292 char * name = tape_name(STp);
2293
2294#if DEBUG
2295 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2296#endif
2297 if (STp->raw) return 0;
2298
2299 if (STp->header_cache == NULL) {
2300 if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2301 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2302 return (-ENOMEM);
2303 }
2304 memset(STp->header_cache, 0, sizeof(os_header_t));
2305#if DEBUG
2306 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2307#endif
2308 }
2309 if (STp->header_ok) STp->update_frame_cntr++;
2310 else STp->update_frame_cntr = 0;
2311
2312 header = STp->header_cache;
2313 strcpy(header->ident_str, "ADR_SEQ");
2314 header->major_rev = 1;
2315 header->minor_rev = 4;
2316 header->ext_trk_tb_off = htons(17192);
2317 header->pt_par_num = 1;
2318 header->partition[0].partition_num = OS_DATA_PARTITION;
2319 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2320 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2321 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2322 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2323 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2324 header->cfg_col_width = htonl(20);
2325 header->dat_col_width = htonl(1500);
2326 header->qfa_col_width = htonl(0);
2327 header->ext_track_tb.nr_stream_part = 1;
2328 header->ext_track_tb.et_ent_sz = 32;
2329 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2330 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2331 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2332 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2333 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2334 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2335 header->dat_fm_tab.fm_part_num = 0;
2336 header->dat_fm_tab.fm_tab_ent_sz = 4;
2337 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2338 STp->filemark_cnt:OS_FM_TAB_MAX);
2339
2340 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2341 if (STp->update_frame_cntr == 0)
2342 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2343 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2344
2345 if (locate_eod) {
2346#if DEBUG
2347 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2348#endif
2349 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2350 }
2351 if (result)
2352 printk(KERN_ERR "%s:E: Write header failed\n", name);
2353 else {
2354 memcpy(STp->application_sig, "LIN4", 4);
2355 STp->linux_media = 1;
2356 STp->linux_media_version = 4;
2357 STp->header_ok = 1;
2358 }
2359 return result;
2360}
2361
2362static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2363{
2364 if (STp->header_cache != NULL)
2365 memset(STp->header_cache, 0, sizeof(os_header_t));
2366
2367 STp->logical_blk_num = STp->frame_seq_number = 0;
2368 STp->frame_in_buffer = 0;
2369 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2370 STp->filemark_cnt = 0;
2371 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2372 return osst_write_header(STp, aSRpnt, 1);
2373}
2374
2375static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2376{
2377 char * name = tape_name(STp);
2378 os_header_t * header;
2379 os_aux_t * aux;
2380 char id_string[8];
2381 int linux_media_version,
2382 update_frame_cntr;
2383
2384 if (STp->raw)
2385 return 1;
2386
2387 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2388 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2389 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2390 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2391 if (osst_initiate_read (STp, aSRpnt)) {
2392 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2393 return 0;
2394 }
2395 }
2396 if (osst_read_frame(STp, aSRpnt, 180)) {
2397#if DEBUG
2398 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2399#endif
2400 return 0;
2401 }
2402 header = (os_header_t *) STp->buffer->b_data;
2403 aux = STp->buffer->aux;
2404 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2405#if DEBUG
2406 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2407#endif
2408 return 0;
2409 }
2410 if (ntohl(aux->frame_seq_num) != 0 ||
2411 ntohl(aux->logical_blk_num) != 0 ||
2412 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2413 ntohl(aux->partition.first_frame_ppos) != 0 ||
2414 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2415#if DEBUG
2416 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2417 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2418 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2419 ntohl(aux->partition.last_frame_ppos));
2420#endif
2421 return 0;
2422 }
2423 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2424 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2425 strlcpy(id_string, header->ident_str, 8);
2426#if DEBUG
2427 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2428#endif
2429 return 0;
2430 }
2431 update_frame_cntr = ntohl(aux->update_frame_cntr);
2432 if (update_frame_cntr < STp->update_frame_cntr) {
2433#if DEBUG
2434 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2435 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2436#endif
2437 return 0;
2438 }
2439 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2440#if DEBUG
2441 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2442 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2443 header->minor_rev > 4 )? "Invalid" : "Warning:",
2444 header->major_rev, header->minor_rev);
2445#endif
2446 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2447 return 0;
2448 }
2449#if DEBUG
2450 if (header->pt_par_num != 1)
2451 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2452 name, header->pt_par_num);
2453#endif
2454 memcpy(id_string, aux->application_sig, 4);
2455 id_string[4] = 0;
2456 if (memcmp(id_string, "LIN", 3) == 0) {
2457 STp->linux_media = 1;
2458 linux_media_version = id_string[3] - '0';
2459 if (linux_media_version != 4)
2460 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2461 name, linux_media_version);
2462 } else {
2463 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2464 return 0;
2465 }
2466 if (linux_media_version < STp->linux_media_version) {
2467#if DEBUG
2468 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2469 name, ppos, linux_media_version);
2470#endif
2471 return 0;
2472 }
2473 if (linux_media_version > STp->linux_media_version) {
2474#if DEBUG
2475 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2476 name, ppos, linux_media_version);
2477#endif
2478 memcpy(STp->application_sig, id_string, 5);
2479 STp->linux_media_version = linux_media_version;
2480 STp->update_frame_cntr = -1;
2481 }
2482 if (update_frame_cntr > STp->update_frame_cntr) {
2483#if DEBUG
2484 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2485 name, ppos, update_frame_cntr);
2486#endif
2487 if (STp->header_cache == NULL) {
2488 if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2489 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2490 return 0;
2491 }
2492#if DEBUG
2493 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2494#endif
2495 }
2496 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2497 header = STp->header_cache;
2498
2499 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2500 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2501 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2502 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2503 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2504 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2505 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2506 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2507 STp->update_frame_cntr = update_frame_cntr;
2508#if DEBUG
2509 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2510 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2511 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2512 STp->first_data_ppos,
2513 ntohl(header->partition[0].last_frame_ppos),
2514 ntohl(header->partition[0].eod_frame_ppos));
2515 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2516 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2517#endif
2518 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2519#if DEBUG
2520 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2521#endif
2522 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2523 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2524 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2525 }
2526 if (header->minor_rev == 4 &&
2527 (header->ext_trk_tb_off != htons(17192) ||
2528 header->partition[0].partition_num != OS_DATA_PARTITION ||
2529 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2530 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2531 header->cfg_col_width != htonl(20) ||
2532 header->dat_col_width != htonl(1500) ||
2533 header->qfa_col_width != htonl(0) ||
2534 header->ext_track_tb.nr_stream_part != 1 ||
2535 header->ext_track_tb.et_ent_sz != 32 ||
2536 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2537 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2538 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2539 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2540 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2541 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2542 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2543 header->dat_fm_tab.fm_tab_ent_cnt !=
2544 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2545 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2546
2547 }
2548
2549 return 1;
2550}
2551
2552static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2553{
2554 int position, ppos;
2555 int first, last;
2556 int valid = 0;
2557 char * name = tape_name(STp);
2558
2559 position = osst_get_frame_position(STp, aSRpnt);
2560
2561 if (STp->raw) {
2562 STp->header_ok = STp->linux_media = 1;
2563 STp->linux_media_version = 0;
2564 return 1;
2565 }
2566 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2567 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2568 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2569 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2570#if DEBUG
2571 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2572#endif
2573
2574
2575
2576
2577 first = position==10?0xbae: 5;
2578 last = position==10?0xbb3:10;
2579
2580 for (ppos = first; ppos < last; ppos++)
2581 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2582 valid = 1;
2583
2584 first = position==10? 5:0xbae;
2585 last = position==10?10:0xbb3;
2586
2587 for (ppos = first; ppos < last; ppos++)
2588 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2589 valid = 1;
2590
2591 if (!valid) {
2592 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2593 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2594 osst_set_frame_position(STp, aSRpnt, 10, 0);
2595 return 0;
2596 }
2597 if (position <= STp->first_data_ppos) {
2598 position = STp->first_data_ppos;
2599 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2600 }
2601 osst_set_frame_position(STp, aSRpnt, position, 0);
2602 STp->header_ok = 1;
2603
2604 return 1;
2605}
2606
2607static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2608{
2609 int frame_position = STp->first_frame_position;
2610 int frame_seq_numbr = STp->frame_seq_number;
2611 int logical_blk_num = STp->logical_blk_num;
2612 int halfway_frame = STp->frame_in_buffer;
2613 int read_pointer = STp->buffer->read_pointer;
2614 int prev_mark_ppos = -1;
2615 int actual_mark_ppos, i, n;
2616#if DEBUG
2617 char * name = tape_name(STp);
2618
2619 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2620#endif
2621 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2622 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2623#if DEBUG
2624 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2625#endif
2626 return (-EIO);
2627 }
2628 if (STp->linux_media_version >= 4) {
2629 for (i=0; i<STp->filemark_cnt; i++)
2630 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2631 prev_mark_ppos = n;
2632 } else
2633 prev_mark_ppos = frame_position - 1;
2634 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2635 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2636 if (frame_position != STp->first_frame_position ||
2637 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2638 prev_mark_ppos != actual_mark_ppos ) {
2639#if DEBUG
2640 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2641 STp->first_frame_position, frame_position,
2642 STp->frame_seq_number + (halfway_frame?0:1),
2643 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2644#endif
2645 return (-EIO);
2646 }
2647 if (halfway_frame) {
2648
2649 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2650 STp->buffer->buffer_bytes = read_pointer;
2651 STp->ps[STp->partition].rw = ST_WRITING;
2652 STp->dirty = 1;
2653 }
2654 STp->frame_in_buffer = halfway_frame;
2655 STp->frame_seq_number = frame_seq_numbr;
2656 STp->logical_blk_num = logical_blk_num;
2657 return 0;
2658}
2659
2660
2661
2662
2663
2664
2665
2666static unsigned int osst_parse_firmware_rev (const char * str)
2667{
2668 if (str[1] == '.') {
2669 return (str[0]-'0')*10000
2670 +(str[2]-'0')*1000
2671 +(str[3]-'0')*100;
2672 } else {
2673 return (str[0]-'0')*10000
2674 +(str[1]-'0')*1000
2675 +(str[2]-'0')*100 - 100
2676 +(str[3]-'@');
2677 }
2678}
2679
2680
2681
2682
2683static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2684{
2685 unsigned char cmd[MAX_COMMAND_SIZE];
2686 char * name = tape_name(STp);
2687 struct osst_request * SRpnt = * aSRpnt;
2688 osst_mode_parameter_header_t * header;
2689 osst_block_size_page_t * bs;
2690 osst_capabilities_page_t * cp;
2691 osst_tape_paramtr_page_t * prm;
2692 int drive_buffer_size;
2693
2694 if (STp->ready != ST_READY) {
2695#if DEBUG
2696 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2697#endif
2698 return (-EIO);
2699 }
2700
2701 if (STp->os_fw_rev < 10600) {
2702 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2703 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2704 }
2705
2706
2707
2708
2709
2710 memset(cmd, 0, MAX_COMMAND_SIZE);
2711 cmd[0] = MODE_SENSE;
2712 cmd[1] = 8;
2713 cmd[2] = BLOCK_SIZE_PAGE;
2714 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2715
2716 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2717 if (SRpnt == NULL) {
2718#if DEBUG
2719 printk(OSST_DEB_MSG "osst :D: Busy\n");
2720#endif
2721 return (-EBUSY);
2722 }
2723 *aSRpnt = SRpnt;
2724 if ((STp->buffer)->syscall_result != 0) {
2725 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2726 return (-EIO);
2727 }
2728
2729 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2730 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2731
2732#if DEBUG
2733 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2734 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2735 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2736 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2737#endif
2738
2739
2740
2741
2742 bs->one = 1;
2743 bs->play32 = 0;
2744 bs->play32_5 = 1;
2745 bs->record32 = 0;
2746 bs->record32_5 = 1;
2747
2748 memset(cmd, 0, MAX_COMMAND_SIZE);
2749 cmd[0] = MODE_SELECT;
2750 cmd[1] = 0x10;
2751 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2752
2753 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2754 *aSRpnt = SRpnt;
2755 if ((STp->buffer)->syscall_result != 0) {
2756 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2757 return (-EIO);
2758 }
2759
2760#if DEBUG
2761 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2762
2763
2764
2765
2766 osst_set_retries(STp, aSRpnt, 0);
2767 SRpnt = * aSRpnt;
2768#endif
2769
2770
2771
2772
2773
2774 memset(cmd, 0, MAX_COMMAND_SIZE);
2775 cmd[0] = MODE_SELECT;
2776 cmd[1] = 0x10;
2777 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2778
2779 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2780 header->medium_type = 0;
2781 header->dsp = 0;
2782 header->bdl = 0;
2783
2784 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2785 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2786 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2787 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2788 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2789 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2790 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2791 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2792
2793 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2794 *aSRpnt = SRpnt;
2795
2796 if ((STp->buffer)->syscall_result != 0) {
2797 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2798 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2799 return (-EIO);
2800 }
2801
2802 memset(cmd, 0, MAX_COMMAND_SIZE);
2803 cmd[0] = MODE_SENSE;
2804 cmd[1] = 8;
2805 cmd[2] = CAPABILITIES_PAGE;
2806 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2807
2808 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2809 *aSRpnt = SRpnt;
2810
2811 if ((STp->buffer)->syscall_result != 0) {
2812 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2813 return (-EIO);
2814 }
2815
2816 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2817 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2818 sizeof(osst_mode_parameter_header_t) + header->bdl);
2819
2820 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2821
2822 memset(cmd, 0, MAX_COMMAND_SIZE);
2823 cmd[0] = MODE_SENSE;
2824 cmd[1] = 8;
2825 cmd[2] = TAPE_PARAMTR_PAGE;
2826 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2827
2828 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2829 *aSRpnt = SRpnt;
2830
2831 if ((STp->buffer)->syscall_result != 0) {
2832 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2833 return (-EIO);
2834 }
2835
2836 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2837 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2838 sizeof(osst_mode_parameter_header_t) + header->bdl);
2839
2840 STp->density = prm->density;
2841 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2842#if DEBUG
2843 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2844 name, STp->density, STp->capacity / 32, drive_buffer_size);
2845#endif
2846
2847 return 0;
2848
2849}
2850
2851
2852
2853
2854static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2855{
2856 int result;
2857 char * name = tape_name(STp);
2858
2859#if DEBUG
2860 if (debugging)
2861 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2862 name, forward ? "forward" : "backward");
2863#endif
2864
2865 if (forward) {
2866
2867 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2868 }
2869 else
2870
2871 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2872
2873 if (result < 0)
2874 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2875 name, forward ? "forward" : "backward");
2876
2877 return result;
2878}
2879
2880
2881
2882
2883static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2884{
2885 unsigned char scmd[MAX_COMMAND_SIZE];
2886 struct osst_request * SRpnt;
2887 int result = 0;
2888 char * name = tape_name(STp);
2889
2890
2891
2892 char mybuf[24];
2893 char * olddata = STp->buffer->b_data;
2894 int oldsize = STp->buffer->buffer_size;
2895
2896 if (STp->ready != ST_READY) return (-EIO);
2897
2898 memset (scmd, 0, MAX_COMMAND_SIZE);
2899 scmd[0] = READ_POSITION;
2900
2901 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2902 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2903 STp->timeout, MAX_RETRIES, 1);
2904 if (!SRpnt) {
2905 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2906 return (-EBUSY);
2907 }
2908 *aSRpnt = SRpnt;
2909
2910 if (STp->buffer->syscall_result)
2911 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL;
2912
2913 if (result == -EINVAL)
2914 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2915 else {
2916 if (result == -EIO) {
2917 unsigned char mysense[16];
2918 memcpy (mysense, SRpnt->sense, 16);
2919 memset (scmd, 0, MAX_COMMAND_SIZE);
2920 scmd[0] = READ_POSITION;
2921 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2922 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2923 STp->timeout, MAX_RETRIES, 1);
2924#if DEBUG
2925 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2926 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2927 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2928#endif
2929 if (!STp->buffer->syscall_result)
2930 memcpy (SRpnt->sense, mysense, 16);
2931 else
2932 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2933 }
2934 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2935 + ((STp->buffer)->b_data[5] << 16)
2936 + ((STp->buffer)->b_data[6] << 8)
2937 + (STp->buffer)->b_data[7];
2938 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2939 + ((STp->buffer)->b_data[ 9] << 16)
2940 + ((STp->buffer)->b_data[10] << 8)
2941 + (STp->buffer)->b_data[11];
2942 STp->cur_frames = (STp->buffer)->b_data[15];
2943#if DEBUG
2944 if (debugging) {
2945 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2946 STp->first_frame_position, STp->last_frame_position,
2947 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2948 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2949 STp->cur_frames);
2950 }
2951#endif
2952 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2953#if DEBUG
2954 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2955 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2956#endif
2957 STp->first_frame_position = STp->last_frame_position;
2958 }
2959 }
2960 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2961
2962 return (result == 0 ? STp->first_frame_position : result);
2963}
2964
2965
2966
2967static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2968{
2969 unsigned char scmd[MAX_COMMAND_SIZE];
2970 struct osst_request * SRpnt;
2971 struct st_partstat * STps;
2972 int result = 0;
2973 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2974 char * name = tape_name(STp);
2975
2976 if (STp->ready != ST_READY) return (-EIO);
2977
2978 STps = &(STp->ps[STp->partition]);
2979
2980 if (ppos < 0 || ppos > STp->capacity) {
2981 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2982 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2983 result = (-EINVAL);
2984 }
2985
2986 do {
2987#if DEBUG
2988 if (debugging)
2989 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2990#endif
2991 memset (scmd, 0, MAX_COMMAND_SIZE);
2992 scmd[0] = SEEK_10;
2993 scmd[1] = 1;
2994 scmd[3] = (pp >> 24);
2995 scmd[4] = (pp >> 16);
2996 scmd[5] = (pp >> 8);
2997 scmd[6] = pp;
2998 if (skip)
2999 scmd[9] = 0x80;
3000
3001 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
3002 MAX_RETRIES, 1);
3003 if (!SRpnt)
3004 return (-EBUSY);
3005 *aSRpnt = SRpnt;
3006
3007 if ((STp->buffer)->syscall_result != 0) {
3008#if DEBUG
3009 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
3010 name, STp->first_frame_position, pp);
3011#endif
3012 result = (-EIO);
3013 }
3014 if (pp != ppos)
3015 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
3016 } while ((pp != ppos) && (pp = ppos));
3017 STp->first_frame_position = STp->last_frame_position = ppos;
3018 STps->eof = ST_NOEOF;
3019 STps->at_sm = 0;
3020 STps->rw = ST_IDLE;
3021 STp->frame_in_buffer = 0;
3022 return result;
3023}
3024
3025static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
3026{
3027 struct st_partstat * STps = &(STp->ps[STp->partition]);
3028 int result = 0;
3029
3030 if (STp->write_type != OS_WRITE_NEW_MARK) {
3031
3032 result = osst_flush_drive_buffer(STp, aSRpnt);
3033 if (result < 0) goto out;
3034 result = osst_write_filemark(STp, aSRpnt);
3035 if (result < 0) goto out;
3036
3037 if (STps->drv_file >= 0)
3038 STps->drv_file++ ;
3039 STps->drv_block = 0;
3040 }
3041 result = osst_write_eod(STp, aSRpnt);
3042 osst_write_header(STp, aSRpnt, leave_at_EOT);
3043
3044 STps->eof = ST_FM;
3045out:
3046 return result;
3047}
3048
3049
3050
3051
3052static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
3053{
3054 int offset, transfer, blks = 0;
3055 int result = 0;
3056 unsigned char cmd[MAX_COMMAND_SIZE];
3057 struct osst_request * SRpnt = *aSRpnt;
3058 struct st_partstat * STps;
3059 char * name = tape_name(STp);
3060
3061 if ((STp->buffer)->writing) {
3062 if (SRpnt == (STp->buffer)->last_SRpnt)
3063#if DEBUG
3064 { printk(OSST_DEB_MSG
3065 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
3066#endif
3067 *aSRpnt = SRpnt = NULL;
3068#if DEBUG
3069 } else if (SRpnt)
3070 printk(OSST_DEB_MSG
3071 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
3072#endif
3073 osst_write_behind_check(STp);
3074 if ((STp->buffer)->syscall_result) {
3075#if DEBUG
3076 if (debugging)
3077 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3078 name, (STp->buffer)->midlevel_result);
3079#endif
3080 if ((STp->buffer)->midlevel_result == INT_MAX)
3081 return (-ENOSPC);
3082 return (-EIO);
3083 }
3084 }
3085
3086 result = 0;
3087 if (STp->dirty == 1) {
3088
3089 STp->write_count++;
3090 STps = &(STp->ps[STp->partition]);
3091 STps->rw = ST_WRITING;
3092 offset = STp->buffer->buffer_bytes;
3093 blks = (offset + STp->block_size - 1) / STp->block_size;
3094 transfer = OS_FRAME_SIZE;
3095
3096 if (offset < OS_DATA_SIZE)
3097 osst_zero_buffer_tail(STp->buffer);
3098
3099 if (STp->poll)
3100 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3101 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3102
3103 memset(cmd, 0, MAX_COMMAND_SIZE);
3104 cmd[0] = WRITE_6;
3105 cmd[1] = 1;
3106 cmd[4] = 1;
3107
3108 switch (STp->write_type) {
3109 case OS_WRITE_DATA:
3110#if DEBUG
3111 if (debugging)
3112 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3113 name, blks, STp->frame_seq_number,
3114 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3115#endif
3116 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3117 STp->logical_blk_num - blks, STp->block_size, blks);
3118 break;
3119 case OS_WRITE_EOD:
3120 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3121 STp->logical_blk_num, 0, 0);
3122 break;
3123 case OS_WRITE_NEW_MARK:
3124 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3125 STp->logical_blk_num++, 0, blks=1);
3126 break;
3127 case OS_WRITE_HEADER:
3128 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3129 break;
3130 default:
3131 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3132 }
3133#if DEBUG
3134 if (debugging)
3135 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3136 name, offset, transfer, blks);
3137#endif
3138
3139 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3140 STp->timeout, MAX_RETRIES, 1);
3141 *aSRpnt = SRpnt;
3142 if (!SRpnt)
3143 return (-EBUSY);
3144
3145 if ((STp->buffer)->syscall_result != 0) {
3146#if DEBUG
3147 printk(OSST_DEB_MSG
3148 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3149 name, SRpnt->sense[0], SRpnt->sense[2],
3150 SRpnt->sense[12], SRpnt->sense[13]);
3151#endif
3152 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3153 (SRpnt->sense[2] & 0x40) &&
3154 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3155 STp->dirty = 0;
3156 (STp->buffer)->buffer_bytes = 0;
3157 result = (-ENOSPC);
3158 }
3159 else {
3160 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3161 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3162 result = (-EIO);
3163 }
3164 }
3165 STps->drv_block = (-1);
3166 }
3167 else {
3168 STp->first_frame_position++;
3169 STp->dirty = 0;
3170 (STp->buffer)->buffer_bytes = 0;
3171 }
3172 }
3173#if DEBUG
3174 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3175#endif
3176 return result;
3177}
3178
3179
3180
3181
3182static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3183{
3184 struct st_partstat * STps;
3185 int backspace = 0, result = 0;
3186#if DEBUG
3187 char * name = tape_name(STp);
3188#endif
3189
3190
3191
3192
3193
3194 if( STp->pos_unknown)
3195 return (-EIO);
3196
3197 if (STp->ready != ST_READY)
3198 return 0;
3199
3200 STps = &(STp->ps[STp->partition]);
3201 if (STps->rw == ST_WRITING || STp->dirty) {
3202 STp->write_type = OS_WRITE_DATA;
3203 return osst_flush_write_buffer(STp, aSRpnt);
3204 }
3205 if (STp->block_size == 0)
3206 return 0;
3207
3208#if DEBUG
3209 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3210#endif
3211
3212 if (!STp->can_bsr) {
3213 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3214 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3215 (STp->buffer)->buffer_bytes = 0;
3216 (STp->buffer)->read_pointer = 0;
3217 STp->frame_in_buffer = 0;
3218 }
3219
3220 if (!seek_next) {
3221 if (STps->eof == ST_FM_HIT) {
3222 result = cross_eof(STp, aSRpnt, 0);
3223 if (!result)
3224 STps->eof = ST_NOEOF;
3225 else {
3226 if (STps->drv_file >= 0)
3227 STps->drv_file++;
3228 STps->drv_block = 0;
3229 }
3230 }
3231 if (!result && backspace > 0)
3232 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3233 }
3234 else if (STps->eof == ST_FM_HIT) {
3235 if (STps->drv_file >= 0)
3236 STps->drv_file++;
3237 STps->drv_block = 0;
3238 STps->eof = ST_NOEOF;
3239 }
3240
3241 return result;
3242}
3243
3244static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3245{
3246 unsigned char cmd[MAX_COMMAND_SIZE];
3247 struct osst_request * SRpnt;
3248 int blks;
3249#if DEBUG
3250 char * name = tape_name(STp);
3251#endif
3252
3253 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) {
3254#if DEBUG
3255 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3256#endif
3257 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3258 return (-EIO);
3259 }
3260
3261 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3262#if DEBUG
3263 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3264#endif
3265 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3266 }
3267 }
3268
3269 if (STp->poll)
3270 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3271 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3272 return (-EIO);
3273
3274
3275
3276 STp->ps[STp->partition].rw = ST_WRITING;
3277 STp->write_type = OS_WRITE_DATA;
3278
3279 memset(cmd, 0, MAX_COMMAND_SIZE);
3280 cmd[0] = WRITE_6;
3281 cmd[1] = 1;
3282 cmd[4] = 1;
3283 blks = STp->buffer->buffer_bytes / STp->block_size;
3284#if DEBUG
3285 if (debugging)
3286 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3287 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3288#endif
3289 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3290 STp->logical_blk_num - blks, STp->block_size, blks);
3291
3292#if DEBUG
3293 if (!synchronous)
3294 STp->write_pending = 1;
3295#endif
3296 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3297 MAX_RETRIES, synchronous);
3298 if (!SRpnt)
3299 return (-EBUSY);
3300 *aSRpnt = SRpnt;
3301
3302 if (synchronous) {
3303 if (STp->buffer->syscall_result != 0) {
3304#if DEBUG
3305 if (debugging)
3306 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3307#endif
3308 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3309 (SRpnt->sense[2] & 0x40)) {
3310 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3311 return (-ENOSPC);
3312 }
3313 else {
3314 if (osst_write_error_recovery(STp, aSRpnt, 1))
3315 return (-EIO);
3316 }
3317 }
3318 else
3319 STp->first_frame_position++;
3320 }
3321
3322 STp->write_count++;
3323
3324 return 0;
3325}
3326
3327
3328static int do_door_lock(struct osst_tape * STp, int do_lock)
3329{
3330 int retval;
3331
3332#if DEBUG
3333 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3334#endif
3335
3336 retval = scsi_set_medium_removal(STp->device,
3337 do_lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
3338 if (!retval)
3339 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3340 else
3341 STp->door_locked = ST_LOCK_FAILS;
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 transferred, 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 int j;
4702
4703 STp->pos_unknown = 0;
4704 STp->partition = STp->new_partition = 0;
4705 if (STp->can_partitions)
4706 STp->nbr_partitions = 1;
4707 for (j = 0; j < ST_NBR_PARTITIONS; j++) {
4708 STps = &(STp->ps[j]);
4709 STps->rw = ST_IDLE;
4710 STps->eof = ST_NOEOF;
4711 STps->at_sm = 0;
4712 STps->last_block_valid = 0;
4713 STps->drv_block = 0;
4714 STps->drv_file = 0 ;
4715 }
4716 new_session = 1;
4717 }
4718 }
4719 }
4720
4721 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))
4722 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4723
4724 if ((STp->buffer)->syscall_result != 0) {
4725 if ((STp->device)->scsi_level >= SCSI_2 &&
4726 (SRpnt->sense[0] & 0x70) == 0x70 &&
4727 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4728 SRpnt->sense[12] == 0x3a) {
4729 STp->ready = ST_NO_TAPE;
4730 } else
4731 STp->ready = ST_NOT_READY;
4732 osst_release_request(SRpnt);
4733 SRpnt = NULL;
4734 STp->density = 0;
4735 STp->write_prot = 0;
4736 STp->block_size = 0;
4737 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4738 STp->partition = STp->new_partition = 0;
4739 STp->door_locked = ST_UNLOCKED;
4740 return 0;
4741 }
4742
4743 osst_configure_onstream(STp, &SRpnt);
4744
4745 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4746 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4747 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4748 STp->buffer->buffer_bytes =
4749 STp->buffer->read_pointer =
4750 STp->frame_in_buffer = 0;
4751
4752#if DEBUG
4753 if (debugging)
4754 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4755 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4756 (STp->buffer)->buffer_blocks);
4757#endif
4758
4759 if (STp->drv_write_prot) {
4760 STp->write_prot = 1;
4761#if DEBUG
4762 if (debugging)
4763 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4764#endif
4765 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4766 retval = (-EROFS);
4767 goto err_out;
4768 }
4769 }
4770
4771 if (new_session) {
4772#if DEBUG
4773 if (debugging)
4774 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4775#endif
4776 STp->density_changed = STp->blksize_changed = 0;
4777 STp->compression_changed = 0;
4778 }
4779
4780
4781
4782
4783 if (STp->door_locked == ST_UNLOCKED) {
4784 if (do_door_lock(STp, 1))
4785 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4786 else
4787 STp->door_locked = ST_LOCKED_AUTO;
4788 }
4789
4790 osst_analyze_headers(STp, &SRpnt);
4791
4792 osst_release_request(SRpnt);
4793 SRpnt = NULL;
4794
4795 return 0;
4796
4797err_out:
4798 if (SRpnt != NULL)
4799 osst_release_request(SRpnt);
4800 normalize_buffer(STp->buffer);
4801 STp->header_ok = 0;
4802 STp->in_use = 0;
4803 scsi_device_put(STp->device);
4804
4805 return retval;
4806}
4807
4808
4809static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4810{
4811 int ret;
4812
4813 mutex_lock(&osst_int_mutex);
4814 ret = __os_scsi_tape_open(inode, filp);
4815 mutex_unlock(&osst_int_mutex);
4816 return ret;
4817}
4818
4819
4820
4821
4822static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4823{
4824 int result = 0, result2;
4825 struct osst_tape * STp = filp->private_data;
4826 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4827 struct st_partstat * STps = &(STp->ps[STp->partition]);
4828 struct osst_request * SRpnt = NULL;
4829 char * name = tape_name(STp);
4830
4831 if (file_count(filp) > 1)
4832 return 0;
4833
4834 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4835 STp->write_type = OS_WRITE_DATA;
4836 result = osst_flush_write_buffer(STp, &SRpnt);
4837 if (result != 0 && result != (-ENOSPC))
4838 goto out;
4839 }
4840 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4841
4842#if DEBUG
4843 if (debugging) {
4844 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4845 name, (long)(filp->f_pos));
4846 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4847 name, STp->nbr_waits, STp->nbr_finished);
4848 }
4849#endif
4850 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4851#if DEBUG
4852 if (debugging)
4853 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4854 name, 1+STp->two_fm);
4855#endif
4856 }
4857 else if (!STp->rew_at_close) {
4858 STps = &(STp->ps[STp->partition]);
4859 if (!STm->sysv || STps->rw != ST_READING) {
4860 if (STp->can_bsr)
4861 result = osst_flush_buffer(STp, &SRpnt, 0);
4862 else if (STps->eof == ST_FM_HIT) {
4863 result = cross_eof(STp, &SRpnt, 0);
4864 if (result) {
4865 if (STps->drv_file >= 0)
4866 STps->drv_file++;
4867 STps->drv_block = 0;
4868 STps->eof = ST_FM;
4869 }
4870 else
4871 STps->eof = ST_NOEOF;
4872 }
4873 }
4874 else if ((STps->eof == ST_NOEOF &&
4875 !(result = cross_eof(STp, &SRpnt, 1))) ||
4876 STps->eof == ST_FM_HIT) {
4877 if (STps->drv_file >= 0)
4878 STps->drv_file++;
4879 STps->drv_block = 0;
4880 STps->eof = ST_FM;
4881 }
4882 }
4883
4884out:
4885 if (STp->rew_at_close) {
4886 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4887 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4888 if (result == 0 && result2 < 0)
4889 result = result2;
4890 }
4891 if (SRpnt) osst_release_request(SRpnt);
4892
4893 if (STp->abort_count || STp->recover_count) {
4894 printk(KERN_INFO "%s:I:", name);
4895 if (STp->abort_count)
4896 printk(" %d unrecovered errors", STp->abort_count);
4897 if (STp->recover_count)
4898 printk(" %d recovered errors", STp->recover_count);
4899 if (STp->write_count)
4900 printk(" in %d frames written", STp->write_count);
4901 if (STp->read_count)
4902 printk(" in %d frames read", STp->read_count);
4903 printk("\n");
4904 STp->recover_count = 0;
4905 STp->abort_count = 0;
4906 }
4907 STp->write_count = 0;
4908 STp->read_count = 0;
4909
4910 return result;
4911}
4912
4913
4914
4915static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4916{
4917 int result = 0;
4918 struct osst_tape * STp = filp->private_data;
4919
4920 if (STp->door_locked == ST_LOCKED_AUTO)
4921 do_door_lock(STp, 0);
4922
4923 if (STp->raw)
4924 STp->header_ok = 0;
4925
4926 normalize_buffer(STp->buffer);
4927 write_lock(&os_scsi_tapes_lock);
4928 STp->in_use = 0;
4929 write_unlock(&os_scsi_tapes_lock);
4930
4931 scsi_device_put(STp->device);
4932
4933 return result;
4934}
4935
4936
4937
4938static long osst_ioctl(struct file * file,
4939 unsigned int cmd_in, unsigned long arg)
4940{
4941 int i, cmd_nr, cmd_type, blk, retval = 0;
4942 struct st_modedef * STm;
4943 struct st_partstat * STps;
4944 struct osst_request * SRpnt = NULL;
4945 struct osst_tape * STp = file->private_data;
4946 char * name = tape_name(STp);
4947 void __user * p = (void __user *)arg;
4948
4949 mutex_lock(&osst_int_mutex);
4950 if (mutex_lock_interruptible(&STp->lock)) {
4951 mutex_unlock(&osst_int_mutex);
4952 return -ERESTARTSYS;
4953 }
4954
4955#if DEBUG
4956 if (debugging && !STp->in_use) {
4957 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4958 retval = (-EIO);
4959 goto out;
4960 }
4961#endif
4962 STm = &(STp->modes[STp->current_mode]);
4963 STps = &(STp->ps[STp->partition]);
4964
4965
4966
4967
4968
4969
4970
4971 retval = scsi_ioctl_block_when_processing_errors(STp->device, cmd_in,
4972 file->f_flags & O_NDELAY);
4973 if (retval)
4974 goto out;
4975
4976 cmd_type = _IOC_TYPE(cmd_in);
4977 cmd_nr = _IOC_NR(cmd_in);
4978#if DEBUG
4979 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4980 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4981#endif
4982 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4983 struct mtop mtc;
4984 int auto_weof = 0;
4985
4986 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4987 retval = (-EINVAL);
4988 goto out;
4989 }
4990
4991 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4992 if (i) {
4993 retval = (-EFAULT);
4994 goto out;
4995 }
4996
4997 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4998 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4999 retval = (-EPERM);
5000 goto out;
5001 }
5002
5003 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
5004 retval = (-ENXIO);
5005 goto out;
5006 }
5007
5008 if (!STp->pos_unknown) {
5009
5010 if (STps->eof == ST_FM_HIT) {
5011 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
5012 mtc.mt_count -= 1;
5013 if (STps->drv_file >= 0)
5014 STps->drv_file += 1;
5015 }
5016 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
5017 mtc.mt_count += 1;
5018 if (STps->drv_file >= 0)
5019 STps->drv_file += 1;
5020 }
5021 }
5022
5023 if (mtc.mt_op == MTSEEK) {
5024
5025 i = !STp->can_partitions || (STp->new_partition != STp->partition);
5026 }
5027 else {
5028 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
5029 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
5030 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
5031 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
5032 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
5033 mtc.mt_op == MTCOMPRESSION;
5034 }
5035 i = osst_flush_buffer(STp, &SRpnt, i);
5036 if (i < 0) {
5037 retval = i;
5038 goto out;
5039 }
5040 }
5041 else {
5042
5043
5044
5045
5046
5047 if(mtc.mt_op != MTREW &&
5048 mtc.mt_op != MTOFFL &&
5049 mtc.mt_op != MTRETEN &&
5050 mtc.mt_op != MTERASE &&
5051 mtc.mt_op != MTSEEK &&
5052 mtc.mt_op != MTEOM) {
5053 retval = (-EIO);
5054 goto out;
5055 }
5056 reset_state(STp);
5057
5058 STp->device->was_reset = 0;
5059 }
5060
5061 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
5062 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
5063 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
5064 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
5065 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
5066
5067
5068
5069
5070
5071
5072
5073#if DEBUG
5074 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
5075 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
5076 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
5077 STp->logical_blk_num, STps->drv_file, STps->drv_block );
5078#endif
5079 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
5080 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
5081 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5082 i = osst_write_trailer(STp, &SRpnt,
5083 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5084#if DEBUG
5085 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5086 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5087 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5088#endif
5089 if (i < 0) {
5090 retval = i;
5091 goto out;
5092 }
5093 }
5094 STps->rw = ST_IDLE;
5095 }
5096
5097 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5098 do_door_lock(STp, 0);
5099
5100 if (mtc.mt_op == MTSETDRVBUFFER &&
5101 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5102 retval = osst_set_options(STp, mtc.mt_count);
5103 goto out;
5104 }
5105
5106 if (mtc.mt_op == MTSETPART) {
5107 if (mtc.mt_count >= STp->nbr_partitions)
5108 retval = -EINVAL;
5109 else {
5110 STp->new_partition = mtc.mt_count;
5111 retval = 0;
5112 }
5113 goto out;
5114 }
5115
5116 if (mtc.mt_op == MTMKPART) {
5117 if (!STp->can_partitions) {
5118 retval = (-EINVAL);
5119 goto out;
5120 }
5121 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0
5122) {
5123 retval = i;
5124 goto out;
5125 }
5126 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5127 STp->ps[i].rw = ST_IDLE;
5128 STp->ps[i].at_sm = 0;
5129 STp->ps[i].last_block_valid = 0;
5130 }
5131 STp->partition = STp->new_partition = 0;
5132 STp->nbr_partitions = 1;
5133 STps->drv_block = STps->drv_file = 0;
5134 retval = 0;
5135 goto out;
5136 }
5137
5138 if (mtc.mt_op == MTSEEK) {
5139 if (STp->raw)
5140 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5141 else
5142 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5143 if (!STp->can_partitions)
5144 STp->ps[0].rw = ST_IDLE;
5145 retval = i;
5146 goto out;
5147 }
5148
5149 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5150 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5151 goto out;
5152 }
5153
5154 if (auto_weof)
5155 cross_eof(STp, &SRpnt, 0);
5156
5157 if (mtc.mt_op == MTCOMPRESSION)
5158 retval = -EINVAL;
5159 else
5160
5161
5162 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5163 goto out;
5164 }
5165
5166 if (!STm->defined) {
5167 retval = (-ENXIO);
5168 goto out;
5169 }
5170
5171 if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5172 retval = i;
5173 goto out;
5174 }
5175
5176 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5177 struct mtget mt_status;
5178
5179 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5180 retval = (-EINVAL);
5181 goto out;
5182 }
5183
5184 mt_status.mt_type = MT_ISONSTREAM_SC;
5185 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5186 mt_status.mt_dsreg =
5187 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5188 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5189 mt_status.mt_blkno = STps->drv_block;
5190 mt_status.mt_fileno = STps->drv_file;
5191 if (STp->block_size != 0) {
5192 if (STps->rw == ST_WRITING)
5193 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5194 else if (STps->rw == ST_READING)
5195 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5196 STp->block_size - 1) / STp->block_size;
5197 }
5198
5199 mt_status.mt_gstat = 0;
5200 if (STp->drv_write_prot)
5201 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5202 if (mt_status.mt_blkno == 0) {
5203 if (mt_status.mt_fileno == 0)
5204 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5205 else
5206 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5207 }
5208 mt_status.mt_resid = STp->partition;
5209 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5210 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5211 else if (STps->eof >= ST_EOM_OK)
5212 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5213 if (STp->density == 1)
5214 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5215 else if (STp->density == 2)
5216 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5217 else if (STp->density == 3)
5218 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5219 if (STp->ready == ST_READY)
5220 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5221 if (STp->ready == ST_NO_TAPE)
5222 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5223 if (STps->at_sm)
5224 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5225 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5226 STp->drv_buffer != 0)
5227 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5228
5229 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5230 if (i) {
5231 retval = (-EFAULT);
5232 goto out;
5233 }
5234
5235 STp->recover_erreg = 0;
5236 retval = 0;
5237 goto out;
5238 }
5239
5240 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5241 struct mtpos mt_pos;
5242
5243 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5244 retval = (-EINVAL);
5245 goto out;
5246 }
5247 if (STp->raw)
5248 blk = osst_get_frame_position(STp, &SRpnt);
5249 else
5250 blk = osst_get_sector(STp, &SRpnt);
5251 if (blk < 0) {
5252 retval = blk;
5253 goto out;
5254 }
5255 mt_pos.mt_blkno = blk;
5256 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5257 if (i)
5258 retval = -EFAULT;
5259 goto out;
5260 }
5261 if (SRpnt) osst_release_request(SRpnt);
5262
5263 mutex_unlock(&STp->lock);
5264
5265 retval = scsi_ioctl(STp->device, cmd_in, p);
5266 mutex_unlock(&osst_int_mutex);
5267 return retval;
5268
5269out:
5270 if (SRpnt) osst_release_request(SRpnt);
5271
5272 mutex_unlock(&STp->lock);
5273 mutex_unlock(&osst_int_mutex);
5274
5275 return retval;
5276}
5277
5278#ifdef CONFIG_COMPAT
5279static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5280{
5281 struct osst_tape *STp = file->private_data;
5282 struct scsi_device *sdev = STp->device;
5283 int ret = -ENOIOCTLCMD;
5284 if (sdev->host->hostt->compat_ioctl) {
5285
5286 ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5287
5288 }
5289 return ret;
5290}
5291#endif
5292
5293
5294
5295
5296
5297
5298static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5299{
5300 int i;
5301 gfp_t priority;
5302 struct osst_buffer *tb;
5303
5304 if (from_initialization)
5305 priority = GFP_ATOMIC;
5306 else
5307 priority = GFP_KERNEL;
5308
5309 i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5310 tb = kzalloc(i, priority);
5311 if (!tb) {
5312 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5313 return NULL;
5314 }
5315
5316 tb->sg_segs = tb->orig_sg_segs = 0;
5317 tb->use_sg = max_sg;
5318 tb->in_use = 1;
5319 tb->dma = need_dma;
5320 tb->buffer_size = 0;
5321#if DEBUG
5322 if (debugging)
5323 printk(OSST_DEB_MSG
5324 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5325 i, max_sg, need_dma);
5326#endif
5327 return tb;
5328}
5329
5330
5331static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5332{
5333 int segs, nbr, max_segs, b_size, order, got;
5334 gfp_t priority;
5335
5336 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5337 return 1;
5338
5339 if (STbuffer->sg_segs) {
5340 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5341 normalize_buffer(STbuffer);
5342 }
5343
5344 nbr = max_segs = STbuffer->use_sg;
5345 if (nbr <= 2)
5346 return 0;
5347
5348 priority = GFP_KERNEL ;
5349 if (need_dma)
5350 priority |= GFP_DMA;
5351
5352
5353
5354 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5355 struct page *page = alloc_pages(priority, order);
5356
5357 STbuffer->sg[0].offset = 0;
5358 if (page != NULL) {
5359 sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5360 STbuffer->b_data = page_address(page);
5361 break;
5362 }
5363 }
5364 if (sg_page(&STbuffer->sg[0]) == NULL) {
5365 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5366 return 0;
5367 }
5368
5369 for (segs=STbuffer->sg_segs=1, got=b_size;
5370 segs < max_segs && got < OS_FRAME_SIZE; ) {
5371 struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5372 STbuffer->sg[segs].offset = 0;
5373 if (page == NULL) {
5374 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5375 OS_FRAME_SIZE);
5376#if DEBUG
5377 STbuffer->buffer_size = got;
5378#endif
5379 normalize_buffer(STbuffer);
5380 return 0;
5381 }
5382 sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5383 got += STbuffer->sg[segs].length;
5384 STbuffer->buffer_size = got;
5385 STbuffer->sg_segs = ++segs;
5386 }
5387#if DEBUG
5388 if (debugging) {
5389 printk(OSST_DEB_MSG
5390 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5391 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5392 printk(OSST_DEB_MSG
5393 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5394 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5395 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5396 }
5397#endif
5398
5399 return 1;
5400}
5401
5402
5403
5404static void normalize_buffer(struct osst_buffer *STbuffer)
5405{
5406 int i, order, b_size;
5407
5408 for (i=0; i < STbuffer->sg_segs; i++) {
5409
5410 for (b_size = PAGE_SIZE, order = 0;
5411 b_size < STbuffer->sg[i].length;
5412 b_size *= 2, order++);
5413
5414 __free_pages(sg_page(&STbuffer->sg[i]), order);
5415 STbuffer->buffer_size -= STbuffer->sg[i].length;
5416 }
5417#if DEBUG
5418 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5419 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5420 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5421#endif
5422 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5423}
5424
5425
5426
5427
5428static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5429{
5430 int i, cnt, res, offset;
5431
5432 for (i=0, offset=st_bp->buffer_bytes;
5433 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5434 offset -= st_bp->sg[i].length;
5435 if (i == st_bp->sg_segs) {
5436 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5437 return (-EIO);
5438 }
5439 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5440 cnt = st_bp->sg[i].length - offset < do_count ?
5441 st_bp->sg[i].length - offset : do_count;
5442 res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5443 if (res)
5444 return (-EFAULT);
5445 do_count -= cnt;
5446 st_bp->buffer_bytes += cnt;
5447 ubp += cnt;
5448 offset = 0;
5449 }
5450 if (do_count) {
5451 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5452 do_count);
5453 return (-EIO);
5454 }
5455 return 0;
5456}
5457
5458
5459
5460
5461static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5462{
5463 int i, cnt, res, offset;
5464
5465 for (i=0, offset=st_bp->read_pointer;
5466 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5467 offset -= st_bp->sg[i].length;
5468 if (i == st_bp->sg_segs) {
5469 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5470 return (-EIO);
5471 }
5472 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5473 cnt = st_bp->sg[i].length - offset < do_count ?
5474 st_bp->sg[i].length - offset : do_count;
5475 res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5476 if (res)
5477 return (-EFAULT);
5478 do_count -= cnt;
5479 st_bp->buffer_bytes -= cnt;
5480 st_bp->read_pointer += cnt;
5481 ubp += cnt;
5482 offset = 0;
5483 }
5484 if (do_count) {
5485 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5486 return (-EIO);
5487 }
5488 return 0;
5489}
5490
5491
5492
5493static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5494{
5495 int i, offset, do_count, cnt;
5496
5497 for (i = 0, offset = st_bp->buffer_bytes;
5498 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5499 offset -= st_bp->sg[i].length;
5500 if (i == st_bp->sg_segs) {
5501 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5502 return (-EIO);
5503 }
5504 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5505 i < st_bp->sg_segs && do_count > 0; i++) {
5506 cnt = st_bp->sg[i].length - offset < do_count ?
5507 st_bp->sg[i].length - offset : do_count ;
5508 memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5509 do_count -= cnt;
5510 offset = 0;
5511 }
5512 if (do_count) {
5513 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5514 return (-EIO);
5515 }
5516 return 0;
5517}
5518
5519
5520
5521static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5522{
5523 int i, cnt, do_count = OS_DATA_SIZE;
5524
5525 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5526 cnt = st_bp->sg[i].length < do_count ?
5527 st_bp->sg[i].length : do_count ;
5528 memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5529 do_count -= cnt;
5530 ptr += cnt;
5531 }
5532 if (do_count || i != st_bp->sg_segs-1) {
5533 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5534 do_count, i);
5535 return (-EIO);
5536 }
5537 return 0;
5538}
5539
5540
5541
5542static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5543{
5544 int i, cnt, do_count = OS_DATA_SIZE;
5545
5546 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5547 cnt = st_bp->sg[i].length < do_count ?
5548 st_bp->sg[i].length : do_count ;
5549 memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5550 do_count -= cnt;
5551 ptr += cnt;
5552 }
5553 if (do_count || i != st_bp->sg_segs-1) {
5554 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5555 do_count, i);
5556 return (-EIO);
5557 }
5558 return 0;
5559}
5560
5561
5562
5563
5564static void validate_options (void)
5565{
5566 if (max_dev > 0)
5567 osst_max_dev = max_dev;
5568 if (write_threshold_kbs > 0)
5569 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5570 if (osst_write_threshold > osst_buffer_size)
5571 osst_write_threshold = osst_buffer_size;
5572 if (max_sg_segs >= OSST_FIRST_SG)
5573 osst_max_sg_segs = max_sg_segs;
5574#if DEBUG
5575 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5576 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5577#endif
5578}
5579
5580#ifndef MODULE
5581
5582
5583
5584static int __init osst_setup (char *str)
5585{
5586 int i, ints[5];
5587 char *stp;
5588
5589 stp = get_options(str, ARRAY_SIZE(ints), ints);
5590
5591 if (ints[0] > 0) {
5592 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5593 *parms[i].val = ints[i + 1];
5594 } else {
5595 while (stp != NULL) {
5596 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5597 int len = strlen(parms[i].name);
5598 if (!strncmp(stp, parms[i].name, len) &&
5599 (*(stp + len) == ':' || *(stp + len) == '=')) {
5600 *parms[i].val =
5601 simple_strtoul(stp + len + 1, NULL, 0);
5602 break;
5603 }
5604 }
5605 if (i >= ARRAY_SIZE(parms))
5606 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5607 stp);
5608 stp = strchr(stp, ',');
5609 if (stp)
5610 stp++;
5611 }
5612 }
5613
5614 return 1;
5615}
5616
5617__setup("osst=", osst_setup);
5618
5619#endif
5620
5621static const struct file_operations osst_fops = {
5622 .owner = THIS_MODULE,
5623 .read = osst_read,
5624 .write = osst_write,
5625 .unlocked_ioctl = osst_ioctl,
5626#ifdef CONFIG_COMPAT
5627 .compat_ioctl = osst_compat_ioctl,
5628#endif
5629 .open = os_scsi_tape_open,
5630 .flush = os_scsi_tape_flush,
5631 .release = os_scsi_tape_close,
5632 .llseek = noop_llseek,
5633};
5634
5635static int osst_supports(struct scsi_device * SDp)
5636{
5637 struct osst_support_data {
5638 char *vendor;
5639 char *model;
5640 char *rev;
5641 char *driver_hint;
5642 };
5643
5644static struct osst_support_data support_list[] = {
5645
5646 SIGS_FROM_OSST,
5647 {NULL, }};
5648
5649 struct osst_support_data *rp;
5650
5651
5652
5653
5654
5655 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5656 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5657 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5658 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5659 return 1;
5660 return 0;
5661}
5662
5663
5664
5665
5666
5667static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5668{
5669 return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5670}
5671
5672static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5673
5674static int osst_create_sysfs_files(struct device_driver *sysfs)
5675{
5676 return driver_create_file(sysfs, &driver_attr_version);
5677}
5678
5679static void osst_remove_sysfs_files(struct device_driver *sysfs)
5680{
5681 driver_remove_file(sysfs, &driver_attr_version);
5682}
5683
5684
5685
5686
5687
5688static ssize_t osst_adr_rev_show(struct device *dev,
5689 struct device_attribute *attr, char *buf)
5690{
5691 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5692 ssize_t l = 0;
5693
5694 if (STp && STp->header_ok && STp->linux_media)
5695 l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5696 return l;
5697}
5698
5699DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5700
5701static ssize_t osst_linux_media_version_show(struct device *dev,
5702 struct device_attribute *attr,
5703 char *buf)
5704{
5705 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5706 ssize_t l = 0;
5707
5708 if (STp && STp->header_ok && STp->linux_media)
5709 l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5710 return l;
5711}
5712
5713DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5714
5715static ssize_t osst_capacity_show(struct device *dev,
5716 struct device_attribute *attr, char *buf)
5717{
5718 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5719 ssize_t l = 0;
5720
5721 if (STp && STp->header_ok && STp->linux_media)
5722 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5723 return l;
5724}
5725
5726DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5727
5728static ssize_t osst_first_data_ppos_show(struct device *dev,
5729 struct device_attribute *attr,
5730 char *buf)
5731{
5732 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5733 ssize_t l = 0;
5734
5735 if (STp && STp->header_ok && STp->linux_media)
5736 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5737 return l;
5738}
5739
5740DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5741
5742static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5743 struct device_attribute *attr,
5744 char *buf)
5745{
5746 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5747 ssize_t l = 0;
5748
5749 if (STp && STp->header_ok && STp->linux_media)
5750 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5751 return l;
5752}
5753
5754DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5755
5756static ssize_t osst_filemark_cnt_show(struct device *dev,
5757 struct device_attribute *attr, char *buf)
5758{
5759 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5760 ssize_t l = 0;
5761
5762 if (STp && STp->header_ok && STp->linux_media)
5763 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5764 return l;
5765}
5766
5767DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5768
5769static struct class *osst_sysfs_class;
5770
5771static int osst_sysfs_init(void)
5772{
5773 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5774 if (IS_ERR(osst_sysfs_class)) {
5775 printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5776 return PTR_ERR(osst_sysfs_class);
5777 }
5778
5779 return 0;
5780}
5781
5782static void osst_sysfs_destroy(dev_t dev)
5783{
5784 device_destroy(osst_sysfs_class, dev);
5785}
5786
5787static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5788{
5789 struct device *osst_member;
5790 int err;
5791
5792 osst_member = device_create(osst_sysfs_class, device, dev, STp,
5793 "%s", name);
5794 if (IS_ERR(osst_member)) {
5795 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5796 return PTR_ERR(osst_member);
5797 }
5798
5799 err = device_create_file(osst_member, &dev_attr_ADR_rev);
5800 if (err)
5801 goto err_out;
5802 err = device_create_file(osst_member, &dev_attr_media_version);
5803 if (err)
5804 goto err_out;
5805 err = device_create_file(osst_member, &dev_attr_capacity);
5806 if (err)
5807 goto err_out;
5808 err = device_create_file(osst_member, &dev_attr_BOT_frame);
5809 if (err)
5810 goto err_out;
5811 err = device_create_file(osst_member, &dev_attr_EOD_frame);
5812 if (err)
5813 goto err_out;
5814 err = device_create_file(osst_member, &dev_attr_file_count);
5815 if (err)
5816 goto err_out;
5817
5818 return 0;
5819
5820err_out:
5821 osst_sysfs_destroy(dev);
5822 return err;
5823}
5824
5825static void osst_sysfs_cleanup(void)
5826{
5827 class_destroy(osst_sysfs_class);
5828}
5829
5830
5831
5832
5833
5834static int osst_probe(struct device *dev)
5835{
5836 struct scsi_device * SDp = to_scsi_device(dev);
5837 struct osst_tape * tpnt;
5838 struct st_modedef * STm;
5839 struct st_partstat * STps;
5840 struct osst_buffer * buffer;
5841 struct gendisk * drive;
5842 int i, dev_num, err = -ENODEV;
5843
5844 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5845 return -ENODEV;
5846
5847 drive = alloc_disk(1);
5848 if (!drive) {
5849 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5850 return -ENODEV;
5851 }
5852
5853
5854 write_lock(&os_scsi_tapes_lock);
5855 if (os_scsi_tapes == NULL) {
5856 os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), 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