1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27static const char * osst_version = "0.99.4";
28
29
30#define OSST_FW_NEED_POLL_MIN 10601
31#define OSST_FW_NEED_POLL_MAX 10704
32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
33
34#include <linux/module.h>
35
36#include <linux/fs.h>
37#include <linux/kernel.h>
38#include <linux/sched.h>
39#include <linux/proc_fs.h>
40#include <linux/mm.h>
41#include <linux/slab.h>
42#include <linux/init.h>
43#include <linux/string.h>
44#include <linux/errno.h>
45#include <linux/mtio.h>
46#include <linux/ioctl.h>
47#include <linux/fcntl.h>
48#include <linux/spinlock.h>
49#include <linux/vmalloc.h>
50#include <linux/blkdev.h>
51#include <linux/moduleparam.h>
52#include <linux/delay.h>
53#include <linux/jiffies.h>
54#include <linux/mutex.h>
55#include <asm/uaccess.h>
56#include <asm/dma.h>
57
58
59
60#define DEBUG 0
61
62
63
64
65#define OSST_DEB_MSG KERN_NOTICE
66
67#include <scsi/scsi.h>
68#include <scsi/scsi_dbg.h>
69#include <scsi/scsi_device.h>
70#include <scsi/scsi_driver.h>
71#include <scsi/scsi_eh.h>
72#include <scsi/scsi_host.h>
73#include <scsi/scsi_ioctl.h>
74
75#define ST_KILOBYTE 1024
76
77#include "st.h"
78#include "osst.h"
79#include "osst_options.h"
80#include "osst_detect.h"
81
82static DEFINE_MUTEX(osst_int_mutex);
83static int max_dev = 0;
84static int write_threshold_kbs = 0;
85static int max_sg_segs = 0;
86
87#ifdef MODULE
88MODULE_AUTHOR("Willem Riede");
89MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
90MODULE_LICENSE("GPL");
91MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
92MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
93
94module_param(max_dev, int, 0444);
95MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
96
97module_param(write_threshold_kbs, int, 0644);
98MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
99
100module_param(max_sg_segs, int, 0644);
101MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
102#else
103static struct osst_dev_parm {
104 char *name;
105 int *val;
106} parms[] __initdata = {
107 { "max_dev", &max_dev },
108 { "write_threshold_kbs", &write_threshold_kbs },
109 { "max_sg_segs", &max_sg_segs }
110};
111#endif
112
113
114#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
115#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116
117
118
119#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
120#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
121#endif
122
123#if DEBUG
124static int debugging = 1;
125
126
127#endif
128
129
130
131#define MAX_RETRIES 0
132
133#define NO_TAPE NOT_READY
134
135#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
136#define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
137#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
138
139#define OSST_TIMEOUT (200 * HZ)
140#define OSST_LONG_TIMEOUT (1800 * HZ)
141
142#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
143#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
144#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
145#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
146
147
148
149#define SET_DENS_AND_BLK 0x10001
150
151static int osst_buffer_size = OSST_BUFFER_SIZE;
152static int osst_write_threshold = OSST_WRITE_THRESHOLD;
153static int osst_max_sg_segs = OSST_MAX_SG;
154static int osst_max_dev = OSST_MAX_TAPES;
155static int osst_nr_dev;
156
157static struct osst_tape **os_scsi_tapes = NULL;
158static DEFINE_RWLOCK(os_scsi_tapes_lock);
159
160static int modes_defined = 0;
161
162static struct osst_buffer *new_tape_buffer(int, int, int);
163static int enlarge_buffer(struct osst_buffer *, int);
164static void normalize_buffer(struct osst_buffer *);
165static int append_to_buffer(const char __user *, struct osst_buffer *, int);
166static int from_buffer(struct osst_buffer *, char __user *, int);
167static int osst_zero_buffer_tail(struct osst_buffer *);
168static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
169static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
170
171static int osst_probe(struct device *);
172static int osst_remove(struct device *);
173
174static struct scsi_driver osst_template = {
175 .owner = THIS_MODULE,
176 .gendrv = {
177 .name = "osst",
178 .probe = osst_probe,
179 .remove = osst_remove,
180 }
181};
182
183static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
184 unsigned int cmd_in, unsigned long arg);
185
186static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
187
188static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
189
190static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
191
192static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
193
194static inline char *tape_name(struct osst_tape *tape)
195{
196 return tape->drive->disk_name;
197}
198
199
200
201
202
203static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
204{
205 const u8 *ucp;
206 const u8 *sense = SRpnt->sense;
207
208 s->have_sense = scsi_normalize_sense(SRpnt->sense,
209 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
210 s->flags = 0;
211
212 if (s->have_sense) {
213 s->deferred = 0;
214 s->remainder_valid =
215 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
216 switch (sense[0] & 0x7f) {
217 case 0x71:
218 s->deferred = 1;
219 case 0x70:
220 s->fixed_format = 1;
221 s->flags = sense[2] & 0xe0;
222 break;
223 case 0x73:
224 s->deferred = 1;
225 case 0x72:
226 s->fixed_format = 0;
227 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
228 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
229 break;
230 }
231 }
232}
233
234
235static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
236{
237 char *name = tape_name(STp);
238 int result = SRpnt->result;
239 u8 * sense = SRpnt->sense, scode;
240#if DEBUG
241 const char *stp;
242#endif
243 struct st_cmdstatus *cmdstatp;
244
245 if (!result)
246 return 0;
247
248 cmdstatp = &STp->buffer->cmdstat;
249 osst_analyze_sense(SRpnt, cmdstatp);
250
251 if (cmdstatp->have_sense)
252 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
253 else
254 scode = 0;
255#if DEBUG
256 if (debugging) {
257 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
258 name, result,
259 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
260 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
261 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
262 name, scode, sense[12], sense[13]);
263 if (cmdstatp->have_sense)
264 __scsi_print_sense(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, cmd;
3331
3332 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3333#if DEBUG
3334 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3335#endif
3336 retval = scsi_ioctl(STp->device, cmd, NULL);
3337 if (!retval) {
3338 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3339 }
3340 else {
3341 STp->door_locked = ST_LOCK_FAILS;
3342 }
3343 return retval;
3344}
3345
3346
3347static void reset_state(struct osst_tape *STp)
3348{
3349 int i;
3350 struct st_partstat *STps;
3351
3352 STp->pos_unknown = 0;
3353 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3354 STps = &(STp->ps[i]);
3355 STps->rw = ST_IDLE;
3356 STps->eof = ST_NOEOF;
3357 STps->at_sm = 0;
3358 STps->last_block_valid = 0;
3359 STps->drv_block = -1;
3360 STps->drv_file = -1;
3361 }
3362}
3363
3364
3365
3366
3367
3368static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3369{
3370 ssize_t total, retval = 0;
3371 ssize_t i, do_count, blks, transfer;
3372 int write_threshold;
3373 int doing_write = 0;
3374 const char __user * b_point;
3375 struct osst_request * SRpnt = NULL;
3376 struct st_modedef * STm;
3377 struct st_partstat * STps;
3378 struct osst_tape * STp = filp->private_data;
3379 char * name = tape_name(STp);
3380
3381
3382 if (mutex_lock_interruptible(&STp->lock))
3383 return (-ERESTARTSYS);
3384
3385
3386
3387
3388
3389
3390
3391 if( !scsi_block_when_processing_errors(STp->device) ) {
3392 retval = (-ENXIO);
3393 goto out;
3394 }
3395
3396 if (STp->ready != ST_READY) {
3397 if (STp->ready == ST_NO_TAPE)
3398 retval = (-ENOMEDIUM);
3399 else
3400 retval = (-EIO);
3401 goto out;
3402 }
3403 STm = &(STp->modes[STp->current_mode]);
3404 if (!STm->defined) {
3405 retval = (-ENXIO);
3406 goto out;
3407 }
3408 if (count == 0)
3409 goto out;
3410
3411
3412
3413
3414
3415 if (STp->pos_unknown) {
3416 retval = (-EIO);
3417 goto out;
3418 }
3419
3420#if DEBUG
3421 if (!STp->in_use) {
3422 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3423 retval = (-EIO);
3424 goto out;
3425 }
3426#endif
3427
3428 if (STp->write_prot) {
3429 retval = (-EACCES);
3430 goto out;
3431 }
3432
3433
3434 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3435 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3436 name, count, STp->block_size<1024?
3437 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3438 retval = (-EINVAL);
3439 goto out;
3440 }
3441
3442 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3443 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3444 name, STp->first_frame_position);
3445 retval = (-ENOSPC);
3446 goto out;
3447 }
3448
3449 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3450 STp->door_locked = ST_LOCKED_AUTO;
3451
3452 STps = &(STp->ps[STp->partition]);
3453
3454 if (STps->rw == ST_READING) {
3455#if DEBUG
3456 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3457 STps->drv_file, STps->drv_block);
3458#endif
3459 retval = osst_flush_buffer(STp, &SRpnt, 0);
3460 if (retval)
3461 goto out;
3462 STps->rw = ST_IDLE;
3463 }
3464 if (STps->rw != ST_WRITING) {
3465
3466 if (!STp->header_ok ||
3467 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3468 (STps->drv_file == 0 && STps->drv_block == 0)) {
3469 STp->wrt_pass_cntr++;
3470#if DEBUG
3471 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3472 name, STp->wrt_pass_cntr);
3473#endif
3474 osst_reset_header(STp, &SRpnt);
3475 STps->drv_file = STps->drv_block = 0;
3476 }
3477
3478 else {
3479 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3480 STps->drv_file < 0 || STps->drv_block < 0) {
3481 if (STp->first_frame_position == STp->eod_frame_ppos) {
3482 STps->drv_file = STp->filemark_cnt;
3483 STps->drv_block = 0;
3484 }
3485 else {
3486
3487#if DEBUG
3488 printk(OSST_DEB_MSG
3489 "%s:D: Cannot write at indeterminate position.\n", name);
3490#endif
3491 retval = (-EIO);
3492 goto out;
3493 }
3494 }
3495 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3496 gmb();
3497 STp->filemark_cnt = STps->drv_file;
3498 STp->last_mark_ppos =
3499 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3500 printk(KERN_WARNING
3501 "%s:W: Overwriting file %d with old write pass counter %d\n",
3502 name, STps->drv_file, STp->wrt_pass_cntr);
3503 printk(KERN_WARNING
3504 "%s:W: may lead to stale data being accepted on reading back!\n",
3505 name);
3506#if DEBUG
3507 printk(OSST_DEB_MSG
3508 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3509 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3510#endif
3511 }
3512 }
3513 STp->fast_open = 0;
3514 }
3515 if (!STp->header_ok) {
3516#if DEBUG
3517 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3518#endif
3519 retval = (-EIO);
3520 goto out;
3521 }
3522
3523 if ((STp->buffer)->writing) {
3524if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3525 osst_write_behind_check(STp);
3526 if ((STp->buffer)->syscall_result) {
3527#if DEBUG
3528 if (debugging)
3529 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3530 (STp->buffer)->midlevel_result);
3531#endif
3532 if ((STp->buffer)->midlevel_result == INT_MAX)
3533 STps->eof = ST_EOM_OK;
3534 else
3535 STps->eof = ST_EOM_ERROR;
3536 }
3537 }
3538 if (STps->eof == ST_EOM_OK) {
3539 retval = (-ENOSPC);
3540 goto out;
3541 }
3542 else if (STps->eof == ST_EOM_ERROR) {
3543 retval = (-EIO);
3544 goto out;
3545 }
3546
3547
3548
3549 if ((copy_from_user(&i, buf, 1) != 0 ||
3550 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3551 retval = (-EFAULT);
3552 goto out;
3553 }
3554
3555 if (!STm->do_buffer_writes) {
3556 write_threshold = 1;
3557 }
3558 else
3559 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3560 if (!STm->do_async_writes)
3561 write_threshold--;
3562
3563 total = count;
3564#if DEBUG
3565 if (debugging)
3566 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3567 name, (int) count, STps->drv_file, STps->drv_block,
3568 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3569#endif
3570 b_point = buf;
3571 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3572 {
3573 doing_write = 1;
3574 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3575 (STp->buffer)->buffer_bytes;
3576 if (do_count > count)
3577 do_count = count;
3578
3579 i = append_to_buffer(b_point, STp->buffer, do_count);
3580 if (i) {
3581 retval = i;
3582 goto out;
3583 }
3584
3585 blks = do_count / STp->block_size;
3586 STp->logical_blk_num += blks;
3587
3588 i = osst_write_frame(STp, &SRpnt, 1);
3589
3590 if (i == (-ENOSPC)) {
3591 transfer = STp->buffer->writing;
3592 if (transfer <= do_count) {
3593 *ppos += do_count - transfer;
3594 count -= do_count - transfer;
3595 if (STps->drv_block >= 0) {
3596 STps->drv_block += (do_count - transfer) / STp->block_size;
3597 }
3598 STps->eof = ST_EOM_OK;
3599 retval = (-ENOSPC);
3600#if DEBUG
3601 if (debugging)
3602 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3603 name, (int) transfer);
3604#endif
3605 }
3606 else {
3607 STps->eof = ST_EOM_ERROR;
3608 STps->drv_block = (-1);
3609 retval = (-EIO);
3610#if DEBUG
3611 if (debugging)
3612 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3613#endif
3614 }
3615 }
3616 else
3617 retval = i;
3618
3619 if (retval < 0) {
3620 if (SRpnt != NULL) {
3621 osst_release_request(SRpnt);
3622 SRpnt = NULL;
3623 }
3624 STp->buffer->buffer_bytes = 0;
3625 STp->dirty = 0;
3626 if (count < total)
3627 retval = total - count;
3628 goto out;
3629 }
3630
3631 *ppos += do_count;
3632 b_point += do_count;
3633 count -= do_count;
3634 if (STps->drv_block >= 0) {
3635 STps->drv_block += blks;
3636 }
3637 STp->buffer->buffer_bytes = 0;
3638 STp->dirty = 0;
3639 }
3640
3641 if (count != 0) {
3642 STp->dirty = 1;
3643 i = append_to_buffer(b_point, STp->buffer, count);
3644 if (i) {
3645 retval = i;
3646 goto out;
3647 }
3648 blks = count / STp->block_size;
3649 STp->logical_blk_num += blks;
3650 if (STps->drv_block >= 0) {
3651 STps->drv_block += blks;
3652 }
3653 *ppos += count;
3654 count = 0;
3655 }
3656
3657 if (doing_write && (STp->buffer)->syscall_result != 0) {
3658 retval = (STp->buffer)->syscall_result;
3659 goto out;
3660 }
3661
3662 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3663
3664 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3665 STp->block_size) * STp->block_size;
3666 STp->dirty = !((STp->buffer)->writing ==
3667 (STp->buffer)->buffer_bytes);
3668
3669 i = osst_write_frame(STp, &SRpnt, 0);
3670 if (i < 0) {
3671 retval = (-EIO);
3672 goto out;
3673 }
3674 SRpnt = NULL;
3675 }
3676 STps->at_sm &= (total == 0);
3677 if (total > 0)
3678 STps->eof = ST_NOEOF;
3679
3680 retval = total;
3681
3682out:
3683 if (SRpnt != NULL) osst_release_request(SRpnt);
3684
3685 mutex_unlock(&STp->lock);
3686
3687 return retval;
3688}
3689
3690
3691
3692static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3693{
3694 ssize_t total, retval = 0;
3695 ssize_t i, transfer;
3696 int special;
3697 struct st_modedef * STm;
3698 struct st_partstat * STps;
3699 struct osst_request * SRpnt = NULL;
3700 struct osst_tape * STp = filp->private_data;
3701 char * name = tape_name(STp);
3702
3703
3704 if (mutex_lock_interruptible(&STp->lock))
3705 return (-ERESTARTSYS);
3706
3707
3708
3709
3710
3711
3712
3713 if( !scsi_block_when_processing_errors(STp->device) ) {
3714 retval = (-ENXIO);
3715 goto out;
3716 }
3717
3718 if (STp->ready != ST_READY) {
3719 if (STp->ready == ST_NO_TAPE)
3720 retval = (-ENOMEDIUM);
3721 else
3722 retval = (-EIO);
3723 goto out;
3724 }
3725 STm = &(STp->modes[STp->current_mode]);
3726 if (!STm->defined) {
3727 retval = (-ENXIO);
3728 goto out;
3729 }
3730#if DEBUG
3731 if (!STp->in_use) {
3732 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3733 retval = (-EIO);
3734 goto out;
3735 }
3736#endif
3737
3738 if (!STp->header_ok) {
3739 retval = (-EIO);
3740 goto out;
3741 }
3742
3743 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3744 STp->door_locked = ST_LOCKED_AUTO;
3745
3746 STps = &(STp->ps[STp->partition]);
3747 if (STps->rw == ST_WRITING) {
3748 retval = osst_flush_buffer(STp, &SRpnt, 0);
3749 if (retval)
3750 goto out;
3751 STps->rw = ST_IDLE;
3752
3753 }
3754
3755 if ((count % STp->block_size) != 0) {
3756 printk(KERN_WARNING
3757 "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3758 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3759 }
3760
3761#if DEBUG
3762 if (debugging && STps->eof != ST_NOEOF)
3763 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3764 STps->eof, (STp->buffer)->buffer_bytes);
3765#endif
3766 if ((STp->buffer)->buffer_bytes == 0 &&
3767 STps->eof >= ST_EOD_1) {
3768 if (STps->eof < ST_EOD) {
3769 STps->eof += 1;
3770 retval = 0;
3771 goto out;
3772 }
3773 retval = (-EIO);
3774 goto out;
3775 }
3776
3777
3778
3779 if (copy_from_user(&i, buf, 1) != 0 ||
3780 copy_to_user (buf, &i, 1) != 0 ||
3781 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3782 copy_to_user (buf + count - 1, &i, 1) != 0) {
3783 retval = (-EFAULT);
3784 goto out;
3785 }
3786
3787
3788 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3789
3790
3791 if ((STp->buffer)->buffer_bytes == 0) {
3792 if (STps->eof == ST_FM_HIT)
3793 break;
3794 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3795 if (special < 0) {
3796 STp->frame_in_buffer = 0;
3797 retval = special;
3798 goto out;
3799 }
3800 }
3801
3802
3803 if ((STp->buffer)->buffer_bytes > 0) {
3804#if DEBUG
3805 if (debugging && STps->eof != ST_NOEOF)
3806 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3807 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3808#endif
3809
3810 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3811 (STp->buffer)->buffer_bytes : count - total)/
3812 STp->block_size) * STp->block_size;
3813
3814 if (transfer == 0) {
3815 printk(KERN_WARNING
3816 "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n",
3817 name, count, STp->block_size < 1024?
3818 STp->block_size:STp->block_size/1024,
3819 STp->block_size<1024?'b':'k');
3820 break;
3821 }
3822 i = from_buffer(STp->buffer, buf, transfer);
3823 if (i) {
3824 retval = i;
3825 goto out;
3826 }
3827 STp->logical_blk_num += transfer / STp->block_size;
3828 STps->drv_block += transfer / STp->block_size;
3829 *ppos += transfer;
3830 buf += transfer;
3831 total += transfer;
3832 }
3833
3834 if ((STp->buffer)->buffer_bytes == 0) {
3835#if DEBUG
3836 if (debugging)
3837 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3838 name, STp->frame_seq_number);
3839#endif
3840 STp->frame_in_buffer = 0;
3841 STp->frame_seq_number++;
3842 }
3843 }
3844
3845
3846 if (total == 0) {
3847 if (STps->eof == ST_FM_HIT) {
3848 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3849 STps->drv_block = 0;
3850 if (STps->drv_file >= 0)
3851 STps->drv_file++;
3852 }
3853 else if (STps->eof == ST_EOD_1) {
3854 STps->eof = ST_EOD_2;
3855 if (STps->drv_block > 0 && STps->drv_file >= 0)
3856 STps->drv_file++;
3857 STps->drv_block = 0;
3858 }
3859 else if (STps->eof == ST_EOD_2)
3860 STps->eof = ST_EOD;
3861 }
3862 else if (STps->eof == ST_FM)
3863 STps->eof = ST_NOEOF;
3864
3865 retval = total;
3866
3867out:
3868 if (SRpnt != NULL) osst_release_request(SRpnt);
3869
3870 mutex_unlock(&STp->lock);
3871
3872 return retval;
3873}
3874
3875
3876
3877static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3878{
3879 printk(KERN_INFO
3880"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3881 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3882 STm->do_read_ahead);
3883 printk(KERN_INFO
3884"%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3885 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3886 printk(KERN_INFO
3887"%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3888 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3889 STp->scsi2_logical);
3890 printk(KERN_INFO
3891"%s:I: sysv: %d\n", name, STm->sysv);
3892#if DEBUG
3893 printk(KERN_INFO
3894 "%s:D: debugging: %d\n",
3895 name, debugging);
3896#endif
3897}
3898
3899
3900static int osst_set_options(struct osst_tape *STp, long options)
3901{
3902 int value;
3903 long code;
3904 struct st_modedef * STm;
3905 char * name = tape_name(STp);
3906
3907 STm = &(STp->modes[STp->current_mode]);
3908 if (!STm->defined) {
3909 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3910 modes_defined = 1;
3911#if DEBUG
3912 if (debugging)
3913 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3914 name, STp->current_mode);
3915#endif
3916 }
3917
3918 code = options & MT_ST_OPTIONS;
3919 if (code == MT_ST_BOOLEANS) {
3920 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3921 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3922 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3923 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3924 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3925 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3926 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3927 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3928 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3929 if ((STp->device)->scsi_level >= SCSI_2)
3930 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3931 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3932 STm->sysv = (options & MT_ST_SYSV) != 0;
3933#if DEBUG
3934 debugging = (options & MT_ST_DEBUGGING) != 0;
3935#endif
3936 osst_log_options(STp, STm, name);
3937 }
3938 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3939 value = (code == MT_ST_SETBOOLEANS);
3940 if ((options & MT_ST_BUFFER_WRITES) != 0)
3941 STm->do_buffer_writes = value;
3942 if ((options & MT_ST_ASYNC_WRITES) != 0)
3943 STm->do_async_writes = value;
3944 if ((options & MT_ST_DEF_WRITES) != 0)
3945 STm->defaults_for_writes = value;
3946 if ((options & MT_ST_READ_AHEAD) != 0)
3947 STm->do_read_ahead = value;
3948 if ((options & MT_ST_TWO_FM) != 0)
3949 STp->two_fm = value;
3950 if ((options & MT_ST_FAST_MTEOM) != 0)
3951 STp->fast_mteom = value;
3952 if ((options & MT_ST_AUTO_LOCK) != 0)
3953 STp->do_auto_lock = value;
3954 if ((options & MT_ST_CAN_BSR) != 0)
3955 STp->can_bsr = value;
3956 if ((options & MT_ST_NO_BLKLIMS) != 0)
3957 STp->omit_blklims = value;
3958 if ((STp->device)->scsi_level >= SCSI_2 &&
3959 (options & MT_ST_CAN_PARTITIONS) != 0)
3960 STp->can_partitions = value;
3961 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3962 STp->scsi2_logical = value;
3963 if ((options & MT_ST_SYSV) != 0)
3964 STm->sysv = value;
3965#if DEBUG
3966 if ((options & MT_ST_DEBUGGING) != 0)
3967 debugging = value;
3968#endif
3969 osst_log_options(STp, STm, name);
3970 }
3971 else if (code == MT_ST_WRITE_THRESHOLD) {
3972 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3973 if (value < 1 || value > osst_buffer_size) {
3974 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3975 name, value);
3976 return (-EIO);
3977 }
3978 STp->write_threshold = value;
3979 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3980 name, value);
3981 }
3982 else if (code == MT_ST_DEF_BLKSIZE) {
3983 value = (options & ~MT_ST_OPTIONS);
3984 if (value == ~MT_ST_OPTIONS) {
3985 STm->default_blksize = (-1);
3986 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3987 }
3988 else {
3989 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3990 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3991 name, value);
3992 return (-EINVAL);
3993 }
3994 STm->default_blksize = value;
3995 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3996 name, STm->default_blksize);
3997 }
3998 }
3999 else if (code == MT_ST_TIMEOUTS) {
4000 value = (options & ~MT_ST_OPTIONS);
4001 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
4002 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
4003 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
4004 (value & ~MT_ST_SET_LONG_TIMEOUT));
4005 }
4006 else {
4007 STp->timeout = value * HZ;
4008 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
4009 }
4010 }
4011 else if (code == MT_ST_DEF_OPTIONS) {
4012 code = (options & ~MT_ST_CLEAR_DEFAULT);
4013 value = (options & MT_ST_CLEAR_DEFAULT);
4014 if (code == MT_ST_DEF_DENSITY) {
4015 if (value == MT_ST_CLEAR_DEFAULT) {
4016 STm->default_density = (-1);
4017 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
4018 }
4019 else {
4020 STm->default_density = value & 0xff;
4021 printk(KERN_INFO "%s:I: Density default set to %x\n",
4022 name, STm->default_density);
4023 }
4024 }
4025 else if (code == MT_ST_DEF_DRVBUFFER) {
4026 if (value == MT_ST_CLEAR_DEFAULT) {
4027 STp->default_drvbuffer = 0xff;
4028 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
4029 }
4030 else {
4031 STp->default_drvbuffer = value & 7;
4032 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
4033 name, STp->default_drvbuffer);
4034 }
4035 }
4036 else if (code == MT_ST_DEF_COMPRESSION) {
4037 if (value == MT_ST_CLEAR_DEFAULT) {
4038 STm->default_compression = ST_DONT_TOUCH;
4039 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
4040 }
4041 else {
4042 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
4043 printk(KERN_INFO "%s:I: Compression default set to %x\n",
4044 name, (value & 1));
4045 }
4046 }
4047 }
4048 else
4049 return (-EIO);
4050
4051 return 0;
4052}
4053
4054
4055
4056static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
4057 unsigned int cmd_in, unsigned long arg)
4058{
4059 int timeout;
4060 long ltmp;
4061 int i, ioctl_result;
4062 int chg_eof = 1;
4063 unsigned char cmd[MAX_COMMAND_SIZE];
4064 struct osst_request * SRpnt = * aSRpnt;
4065 struct st_partstat * STps;
4066 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
4067 int datalen = 0, direction = DMA_NONE;
4068 char * name = tape_name(STp);
4069
4070 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
4071 if (STp->ready == ST_NO_TAPE)
4072 return (-ENOMEDIUM);
4073 else
4074 return (-EIO);
4075 }
4076 timeout = STp->long_timeout;
4077 STps = &(STp->ps[STp->partition]);
4078 fileno = STps->drv_file;
4079 blkno = STps->drv_block;
4080 at_sm = STps->at_sm;
4081 frame_seq_numbr = STp->frame_seq_number;
4082 logical_blk_num = STp->logical_blk_num;
4083
4084 memset(cmd, 0, MAX_COMMAND_SIZE);
4085 switch (cmd_in) {
4086 case MTFSFM:
4087 chg_eof = 0;
4088 case MTFSF:
4089 if (STp->raw)
4090 return (-EIO);
4091 if (STp->linux_media)
4092 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4093 else
4094 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4095 if (fileno >= 0)
4096 fileno += arg;
4097 blkno = 0;
4098 at_sm &= (arg == 0);
4099 goto os_bypass;
4100
4101 case MTBSF:
4102 chg_eof = 0;
4103 case MTBSFM:
4104 if (STp->raw)
4105 return (-EIO);
4106 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4107 if (fileno >= 0)
4108 fileno -= arg;
4109 blkno = (-1);
4110 at_sm &= (arg == 0);
4111 goto os_bypass;
4112
4113 case MTFSR:
4114 case MTBSR:
4115#if DEBUG
4116 if (debugging)
4117 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4118 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4119#endif
4120 if (cmd_in == MTFSR) {
4121 logical_blk_num += arg;
4122 if (blkno >= 0) blkno += arg;
4123 }
4124 else {
4125 logical_blk_num -= arg;
4126 if (blkno >= 0) blkno -= arg;
4127 }
4128 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4129 fileno = STps->drv_file;
4130 blkno = STps->drv_block;
4131 at_sm &= (arg == 0);
4132 goto os_bypass;
4133
4134 case MTFSS:
4135 cmd[0] = SPACE;
4136 cmd[1] = 0x04;
4137 cmd[2] = (arg >> 16);
4138 cmd[3] = (arg >> 8);
4139 cmd[4] = arg;
4140#if DEBUG
4141 if (debugging)
4142 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4143 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4144#endif
4145 if (arg != 0) {
4146 blkno = fileno = (-1);
4147 at_sm = 1;
4148 }
4149 break;
4150 case MTBSS:
4151 cmd[0] = SPACE;
4152 cmd[1] = 0x04;
4153 ltmp = (-arg);
4154 cmd[2] = (ltmp >> 16);
4155 cmd[3] = (ltmp >> 8);
4156 cmd[4] = ltmp;
4157#if DEBUG
4158 if (debugging) {
4159 if (cmd[2] & 0x80)
4160 ltmp = 0xff000000;
4161 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4162 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4163 name, (-ltmp));
4164 }
4165#endif
4166 if (arg != 0) {
4167 blkno = fileno = (-1);
4168 at_sm = 1;
4169 }
4170 break;
4171 case MTWEOF:
4172 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4173 STp->write_type = OS_WRITE_DATA;
4174 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4175 } else
4176 ioctl_result = 0;
4177#if DEBUG
4178 if (debugging)
4179 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4180#endif
4181 for (i=0; i<arg; i++)
4182 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4183 if (fileno >= 0) fileno += arg;
4184 if (blkno >= 0) blkno = 0;
4185 goto os_bypass;
4186
4187 case MTWSM:
4188 if (STp->write_prot)
4189 return (-EACCES);
4190 if (!STp->raw)
4191 return 0;
4192 cmd[0] = WRITE_FILEMARKS;
4193 if (cmd_in == MTWSM)
4194 cmd[1] = 2;
4195 cmd[2] = (arg >> 16);
4196 cmd[3] = (arg >> 8);
4197 cmd[4] = arg;
4198 timeout = STp->timeout;
4199#if DEBUG
4200 if (debugging)
4201 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4202 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4203#endif
4204 if (fileno >= 0)
4205 fileno += arg;
4206 blkno = 0;
4207 at_sm = (cmd_in == MTWSM);
4208 break;
4209 case MTOFFL:
4210 case MTLOAD:
4211 case MTUNLOAD:
4212 case MTRETEN:
4213 cmd[0] = START_STOP;
4214 cmd[1] = 1;
4215 if (cmd_in == MTLOAD) {
4216 if (STp->ready == ST_NO_TAPE)
4217 cmd[4] = 4;
4218 else
4219 cmd[4] = 1;
4220 }
4221 if (cmd_in == MTRETEN)
4222 cmd[4] = 3;
4223 if (cmd_in == MTOFFL)
4224 cmd[4] = 4;
4225 timeout = STp->timeout;
4226#if DEBUG
4227 if (debugging) {
4228 switch (cmd_in) {
4229 case MTUNLOAD:
4230 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4231 break;
4232 case MTLOAD:
4233 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4234 break;
4235 case MTRETEN:
4236 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4237 break;
4238 case MTOFFL:
4239 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4240 break;
4241 }
4242 }
4243#endif
4244 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4245 break;
4246 case MTNOP:
4247#if DEBUG
4248 if (debugging)
4249 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4250#endif
4251 return 0;
4252 break;
4253 case MTEOM:
4254#if DEBUG
4255 if (debugging)
4256 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4257#endif
4258 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4259 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4260 ioctl_result = -EIO;
4261 goto os_bypass;
4262 }
4263 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4264#if DEBUG
4265 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4266#endif
4267 ioctl_result = -EIO;
4268 goto os_bypass;
4269 }
4270 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4271 fileno = STp->filemark_cnt;
4272 blkno = at_sm = 0;
4273 goto os_bypass;
4274
4275 case MTERASE:
4276 if (STp->write_prot)
4277 return (-EACCES);
4278 ioctl_result = osst_reset_header(STp, &SRpnt);
4279 i = osst_write_eod(STp, &SRpnt);
4280 if (i < ioctl_result) ioctl_result = i;
4281 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4282 if (i < ioctl_result) ioctl_result = i;
4283 fileno = blkno = at_sm = 0 ;
4284 goto os_bypass;
4285
4286 case MTREW:
4287 cmd[0] = REZERO_UNIT;
4288 cmd[1] = 1;
4289#if DEBUG
4290 if (debugging)
4291 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4292#endif
4293 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4294 break;
4295
4296 case MTSETBLK:
4297 if ((STps->drv_block == 0 ) &&
4298 !STp->dirty &&
4299 ((STp->buffer)->buffer_bytes == 0) &&
4300 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4301 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4302 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4303
4304
4305
4306
4307
4308
4309 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4310 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4311 name, STp->block_size);
4312 return 0;
4313 }
4314 case MTSETDENSITY:
4315 case MTSETDRVBUFFER:
4316 case SET_DENS_AND_BLK:
4317 chg_eof = 0;
4318 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4319 return (-EIO);
4320 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4321 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4322 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4323 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4324 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4325 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4326 return (-EINVAL);
4327 }
4328 return 0;
4329
4330 default:
4331 return (-ENOSYS);
4332 }
4333
4334 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4335
4336 ioctl_result = (STp->buffer)->syscall_result;
4337
4338 if (!SRpnt) {
4339#if DEBUG
4340 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4341#endif
4342 return ioctl_result;
4343 }
4344
4345 if (!ioctl_result) {
4346 STp->frame_seq_number = frame_seq_numbr;
4347 STp->logical_blk_num = logical_blk_num;
4348 }
4349
4350os_bypass:
4351#if DEBUG
4352 if (debugging)
4353 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4354#endif
4355
4356 if (!ioctl_result) {
4357
4358 if (cmd_in == MTFSFM) {
4359 fileno--;
4360 blkno--;
4361 }
4362 if (cmd_in == MTBSFM) {
4363 fileno++;
4364 blkno++;
4365 }
4366 STps->drv_block = blkno;
4367 STps->drv_file = fileno;
4368 STps->at_sm = at_sm;
4369
4370 if (cmd_in == MTEOM)
4371 STps->eof = ST_EOD;
4372 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4373 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4374 STps->drv_block++;
4375 STp->logical_blk_num++;
4376 STp->frame_seq_number++;
4377 STp->frame_in_buffer = 0;
4378 STp->buffer->read_pointer = 0;
4379 }
4380 else if (cmd_in == MTFSF)
4381 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4382 else if (chg_eof)
4383 STps->eof = ST_NOEOF;
4384
4385 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4386 STp->rew_at_close = 0;
4387 else if (cmd_in == MTLOAD) {
4388 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4389 STp->ps[i].rw = ST_IDLE;
4390 STp->ps[i].last_block_valid = 0;
4391 }
4392 STp->partition = 0;
4393 }
4394
4395 if (cmd_in == MTREW) {
4396 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4397 if (ioctl_result > 0)
4398 ioctl_result = 0;
4399 }
4400
4401 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4402 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4403 STps->drv_file = STps->drv_block = -1;
4404 else
4405 STps->drv_file = STps->drv_block = 0;
4406 STps->eof = ST_NOEOF;
4407 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4408 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4409 STps->drv_file = STps->drv_block = -1;
4410 else {
4411 STps->drv_file = STp->filemark_cnt;
4412 STps->drv_block = 0;
4413 }
4414 STps->eof = ST_EOD;
4415 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4416 STps->drv_file = STps->drv_block = (-1);
4417 STps->eof = ST_NOEOF;
4418 STp->header_ok = 0;
4419 } else if (cmd_in == MTERASE) {
4420 STp->header_ok = 0;
4421 } else if (SRpnt) {
4422 if (SRpnt->sense[2] & 0x40) {
4423 STps->eof = ST_EOM_OK;
4424 STps->drv_block = 0;
4425 }
4426 if (chg_eof)
4427 STps->eof = ST_NOEOF;
4428
4429 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4430 STps->eof = ST_EOD;
4431
4432 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4433 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4434 }
4435 *aSRpnt = SRpnt;
4436
4437 return ioctl_result;
4438}
4439
4440
4441
4442static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4443{
4444 unsigned short flags;
4445 int i, b_size, new_session = 0, retval = 0;
4446 unsigned char cmd[MAX_COMMAND_SIZE];
4447 struct osst_request * SRpnt = NULL;
4448 struct osst_tape * STp;
4449 struct st_modedef * STm;
4450 struct st_partstat * STps;
4451 char * name;
4452 int dev = TAPE_NR(inode);
4453 int mode = TAPE_MODE(inode);
4454
4455
4456
4457
4458
4459
4460 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4461
4462 write_lock(&os_scsi_tapes_lock);
4463 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4464 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4465 write_unlock(&os_scsi_tapes_lock);
4466 return (-ENXIO);
4467 }
4468
4469 name = tape_name(STp);
4470
4471 if (STp->in_use) {
4472 write_unlock(&os_scsi_tapes_lock);
4473#if DEBUG
4474 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4475#endif
4476 return (-EBUSY);
4477 }
4478 if (scsi_device_get(STp->device)) {
4479 write_unlock(&os_scsi_tapes_lock);
4480#if DEBUG
4481 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4482#endif
4483 return (-ENXIO);
4484 }
4485 filp->private_data = STp;
4486 STp->in_use = 1;
4487 write_unlock(&os_scsi_tapes_lock);
4488 STp->rew_at_close = TAPE_REWIND(inode);
4489
4490 if( !scsi_block_when_processing_errors(STp->device) ) {
4491 return -ENXIO;
4492 }
4493
4494 if (mode != STp->current_mode) {
4495#if DEBUG
4496 if (debugging)
4497 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4498 name, STp->current_mode, mode);
4499#endif
4500 new_session = 1;
4501 STp->current_mode = mode;
4502 }
4503 STm = &(STp->modes[STp->current_mode]);
4504
4505 flags = filp->f_flags;
4506 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4507
4508 STp->raw = TAPE_IS_RAW(inode);
4509 if (STp->raw)
4510 STp->header_ok = 0;
4511
4512
4513 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4514 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4515 retval = (-EOVERFLOW);
4516 goto err_out;
4517 }
4518 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4519 for (i = 0, b_size = 0;
4520 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4521 b_size += STp->buffer->sg[i++].length);
4522 STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4523#if DEBUG
4524 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4525 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4526 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4527 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4528#endif
4529 } else {
4530 STp->buffer->aux = NULL;
4531 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4532 retval = (-EIO);
4533 goto err_out;
4534 }
4535 STp->buffer->writing = 0;
4536 STp->buffer->syscall_result = 0;
4537 STp->dirty = 0;
4538 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4539 STps = &(STp->ps[i]);
4540 STps->rw = ST_IDLE;
4541 }
4542 STp->ready = ST_READY;
4543#if DEBUG
4544 STp->nbr_waits = STp->nbr_finished = 0;
4545#endif
4546
4547 memset (cmd, 0, MAX_COMMAND_SIZE);
4548 cmd[0] = TEST_UNIT_READY;
4549
4550 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4551 if (!SRpnt) {
4552 retval = (STp->buffer)->syscall_result;
4553 goto err_out;
4554 }
4555 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4556 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4557 SRpnt->sense[12] == 4 ) {
4558#if DEBUG
4559 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4560#endif
4561 if (filp->f_flags & O_NONBLOCK) {
4562 retval = -EAGAIN;
4563 goto err_out;
4564 }
4565 if (SRpnt->sense[13] == 2) {
4566 memset (cmd, 0, MAX_COMMAND_SIZE);
4567 cmd[0] = START_STOP;
4568 cmd[1] = 1;
4569 cmd[4] = 1;
4570 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4571 STp->timeout, MAX_RETRIES, 1);
4572 }
4573 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4574 }
4575 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4576 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4577#if DEBUG
4578 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4579#endif
4580 STp->header_ok = 0;
4581
4582 for (i=0; i < 10; i++) {
4583
4584 memset (cmd, 0, MAX_COMMAND_SIZE);
4585 cmd[0] = TEST_UNIT_READY;
4586
4587 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4588 STp->timeout, MAX_RETRIES, 1);
4589 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4590 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4591 break;
4592 }
4593
4594 STp->pos_unknown = 0;
4595 STp->partition = STp->new_partition = 0;
4596 if (STp->can_partitions)
4597 STp->nbr_partitions = 1;
4598 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4599 STps = &(STp->ps[i]);
4600 STps->rw = ST_IDLE;
4601 STps->eof = ST_NOEOF;
4602 STps->at_sm = 0;
4603 STps->last_block_valid = 0;
4604 STps->drv_block = 0;
4605 STps->drv_file = 0 ;
4606 }
4607 new_session = 1;
4608 STp->recover_count = 0;
4609 STp->abort_count = 0;
4610 }
4611
4612
4613
4614
4615 if (!STp->buffer->syscall_result && STp->header_ok &&
4616 !SRpnt->result && SRpnt->sense[0] == 0) {
4617
4618 memset(cmd, 0, MAX_COMMAND_SIZE);
4619 cmd[0] = MODE_SENSE;
4620 cmd[1] = 8;
4621 cmd[2] = VENDOR_IDENT_PAGE;
4622 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4623
4624 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4625
4626 if (STp->buffer->syscall_result ||
4627 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4628 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4629 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4630 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4631#if DEBUG
4632 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4633 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4634 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4635 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4636 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4637#endif
4638 STp->header_ok = 0;
4639 }
4640 i = STp->first_frame_position;
4641 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4642 if (STp->door_locked == ST_UNLOCKED) {
4643 if (do_door_lock(STp, 1))
4644 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4645 else
4646 STp->door_locked = ST_LOCKED_AUTO;
4647 }
4648 if (!STp->frame_in_buffer) {
4649 STp->block_size = (STm->default_blksize > 0) ?
4650 STm->default_blksize : OS_DATA_SIZE;
4651 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4652 }
4653 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4654 STp->fast_open = 1;
4655 osst_release_request(SRpnt);
4656 return 0;
4657 }
4658#if DEBUG
4659 if (i != STp->first_frame_position)
4660 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4661 name, i, STp->first_frame_position);
4662#endif
4663 STp->header_ok = 0;
4664 }
4665 STp->fast_open = 0;
4666
4667 if ((STp->buffer)->syscall_result != 0 &&
4668 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4669
4670 memset(cmd, 0, MAX_COMMAND_SIZE);
4671 cmd[0] = MODE_SELECT;
4672 cmd[1] = 0x10;
4673 cmd[4] = 4 + MODE_HEADER_LENGTH;
4674
4675 (STp->buffer)->b_data[0] = cmd[4] - 1;
4676 (STp->buffer)->b_data[1] = 0;
4677 (STp->buffer)->b_data[2] = 0;
4678 (STp->buffer)->b_data[3] = 0;
4679 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4680 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4681 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4682 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4683
4684#if DEBUG
4685 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4686#endif
4687 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4688
4689 STp->header_ok = 0;
4690
4691 for (i=0; i < 10; i++) {
4692
4693 memset (cmd, 0, MAX_COMMAND_SIZE);
4694 cmd[0] = TEST_UNIT_READY;
4695
4696 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4697 STp->timeout, MAX_RETRIES, 1);
4698 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4699 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4700 break;
4701
4702 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4703 int j;
4704
4705 STp->pos_unknown = 0;
4706 STp->partition = STp->new_partition = 0;
4707 if (STp->can_partitions)
4708 STp->nbr_partitions = 1;
4709 for (j = 0; j < ST_NBR_PARTITIONS; j++) {
4710 STps = &(STp->ps[j]);
4711 STps->rw = ST_IDLE;
4712 STps->eof = ST_NOEOF;
4713 STps->at_sm = 0;
4714 STps->last_block_valid = 0;
4715 STps->drv_block = 0;
4716 STps->drv_file = 0 ;
4717 }
4718 new_session = 1;
4719 }
4720 }
4721 }
4722
4723 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))
4724 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4725
4726 if ((STp->buffer)->syscall_result != 0) {
4727 if ((STp->device)->scsi_level >= SCSI_2 &&
4728 (SRpnt->sense[0] & 0x70) == 0x70 &&
4729 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4730 SRpnt->sense[12] == 0x3a) {
4731 STp->ready = ST_NO_TAPE;
4732 } else
4733 STp->ready = ST_NOT_READY;
4734 osst_release_request(SRpnt);
4735 SRpnt = NULL;
4736 STp->density = 0;
4737 STp->write_prot = 0;
4738 STp->block_size = 0;
4739 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4740 STp->partition = STp->new_partition = 0;
4741 STp->door_locked = ST_UNLOCKED;
4742 return 0;
4743 }
4744
4745 osst_configure_onstream(STp, &SRpnt);
4746
4747 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4748 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4749 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4750 STp->buffer->buffer_bytes =
4751 STp->buffer->read_pointer =
4752 STp->frame_in_buffer = 0;
4753
4754#if DEBUG
4755 if (debugging)
4756 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4757 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4758 (STp->buffer)->buffer_blocks);
4759#endif
4760
4761 if (STp->drv_write_prot) {
4762 STp->write_prot = 1;
4763#if DEBUG
4764 if (debugging)
4765 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4766#endif
4767 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4768 retval = (-EROFS);
4769 goto err_out;
4770 }
4771 }
4772
4773 if (new_session) {
4774#if DEBUG
4775 if (debugging)
4776 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4777#endif
4778 STp->density_changed = STp->blksize_changed = 0;
4779 STp->compression_changed = 0;
4780 }
4781
4782
4783
4784
4785 if (STp->door_locked == ST_UNLOCKED) {
4786 if (do_door_lock(STp, 1))
4787 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4788 else
4789 STp->door_locked = ST_LOCKED_AUTO;
4790 }
4791
4792 osst_analyze_headers(STp, &SRpnt);
4793
4794 osst_release_request(SRpnt);
4795 SRpnt = NULL;
4796
4797 return 0;
4798
4799err_out:
4800 if (SRpnt != NULL)
4801 osst_release_request(SRpnt);
4802 normalize_buffer(STp->buffer);
4803 STp->header_ok = 0;
4804 STp->in_use = 0;
4805 scsi_device_put(STp->device);
4806
4807 return retval;
4808}
4809
4810
4811static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4812{
4813 int ret;
4814
4815 mutex_lock(&osst_int_mutex);
4816 ret = __os_scsi_tape_open(inode, filp);
4817 mutex_unlock(&osst_int_mutex);
4818 return ret;
4819}
4820
4821
4822
4823
4824static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4825{
4826 int result = 0, result2;
4827 struct osst_tape * STp = filp->private_data;
4828 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4829 struct st_partstat * STps = &(STp->ps[STp->partition]);
4830 struct osst_request * SRpnt = NULL;
4831 char * name = tape_name(STp);
4832
4833 if (file_count(filp) > 1)
4834 return 0;
4835
4836 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4837 STp->write_type = OS_WRITE_DATA;
4838 result = osst_flush_write_buffer(STp, &SRpnt);
4839 if (result != 0 && result != (-ENOSPC))
4840 goto out;
4841 }
4842 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4843
4844#if DEBUG
4845 if (debugging) {
4846 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4847 name, (long)(filp->f_pos));
4848 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4849 name, STp->nbr_waits, STp->nbr_finished);
4850 }
4851#endif
4852 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4853#if DEBUG
4854 if (debugging)
4855 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4856 name, 1+STp->two_fm);
4857#endif
4858 }
4859 else if (!STp->rew_at_close) {
4860 STps = &(STp->ps[STp->partition]);
4861 if (!STm->sysv || STps->rw != ST_READING) {
4862 if (STp->can_bsr)
4863 result = osst_flush_buffer(STp, &SRpnt, 0);
4864 else if (STps->eof == ST_FM_HIT) {
4865 result = cross_eof(STp, &SRpnt, 0);
4866 if (result) {
4867 if (STps->drv_file >= 0)
4868 STps->drv_file++;
4869 STps->drv_block = 0;
4870 STps->eof = ST_FM;
4871 }
4872 else
4873 STps->eof = ST_NOEOF;
4874 }
4875 }
4876 else if ((STps->eof == ST_NOEOF &&
4877 !(result = cross_eof(STp, &SRpnt, 1))) ||
4878 STps->eof == ST_FM_HIT) {
4879 if (STps->drv_file >= 0)
4880 STps->drv_file++;
4881 STps->drv_block = 0;
4882 STps->eof = ST_FM;
4883 }
4884 }
4885
4886out:
4887 if (STp->rew_at_close) {
4888 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4889 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4890 if (result == 0 && result2 < 0)
4891 result = result2;
4892 }
4893 if (SRpnt) osst_release_request(SRpnt);
4894
4895 if (STp->abort_count || STp->recover_count) {
4896 printk(KERN_INFO "%s:I:", name);
4897 if (STp->abort_count)
4898 printk(" %d unrecovered errors", STp->abort_count);
4899 if (STp->recover_count)
4900 printk(" %d recovered errors", STp->recover_count);
4901 if (STp->write_count)
4902 printk(" in %d frames written", STp->write_count);
4903 if (STp->read_count)
4904 printk(" in %d frames read", STp->read_count);
4905 printk("\n");
4906 STp->recover_count = 0;
4907 STp->abort_count = 0;
4908 }
4909 STp->write_count = 0;
4910 STp->read_count = 0;
4911
4912 return result;
4913}
4914
4915
4916
4917static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4918{
4919 int result = 0;
4920 struct osst_tape * STp = filp->private_data;
4921
4922 if (STp->door_locked == ST_LOCKED_AUTO)
4923 do_door_lock(STp, 0);
4924
4925 if (STp->raw)
4926 STp->header_ok = 0;
4927
4928 normalize_buffer(STp->buffer);
4929 write_lock(&os_scsi_tapes_lock);
4930 STp->in_use = 0;
4931 write_unlock(&os_scsi_tapes_lock);
4932
4933 scsi_device_put(STp->device);
4934
4935 return result;
4936}
4937
4938
4939
4940static long osst_ioctl(struct file * file,
4941 unsigned int cmd_in, unsigned long arg)
4942{
4943 int i, cmd_nr, cmd_type, blk, retval = 0;
4944 struct st_modedef * STm;
4945 struct st_partstat * STps;
4946 struct osst_request * SRpnt = NULL;
4947 struct osst_tape * STp = file->private_data;
4948 char * name = tape_name(STp);
4949 void __user * p = (void __user *)arg;
4950
4951 mutex_lock(&osst_int_mutex);
4952 if (mutex_lock_interruptible(&STp->lock)) {
4953 mutex_unlock(&osst_int_mutex);
4954 return -ERESTARTSYS;
4955 }
4956
4957#if DEBUG
4958 if (debugging && !STp->in_use) {
4959 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4960 retval = (-EIO);
4961 goto out;
4962 }
4963#endif
4964 STm = &(STp->modes[STp->current_mode]);
4965 STps = &(STp->ps[STp->partition]);
4966
4967
4968
4969
4970
4971
4972
4973 if( !scsi_block_when_processing_errors(STp->device) ) {
4974 retval = (-ENXIO);
4975 goto out;
4976 }
4977
4978 cmd_type = _IOC_TYPE(cmd_in);
4979 cmd_nr = _IOC_NR(cmd_in);
4980#if DEBUG
4981 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4982 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4983#endif
4984 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4985 struct mtop mtc;
4986 int auto_weof = 0;
4987
4988 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4989 retval = (-EINVAL);
4990 goto out;
4991 }
4992
4993 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4994 if (i) {
4995 retval = (-EFAULT);
4996 goto out;
4997 }
4998
4999 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
5000 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
5001 retval = (-EPERM);
5002 goto out;
5003 }
5004
5005 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
5006 retval = (-ENXIO);
5007 goto out;
5008 }
5009
5010 if (!STp->pos_unknown) {
5011
5012 if (STps->eof == ST_FM_HIT) {
5013 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
5014 mtc.mt_count -= 1;
5015 if (STps->drv_file >= 0)
5016 STps->drv_file += 1;
5017 }
5018 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
5019 mtc.mt_count += 1;
5020 if (STps->drv_file >= 0)
5021 STps->drv_file += 1;
5022 }
5023 }
5024
5025 if (mtc.mt_op == MTSEEK) {
5026
5027 i = !STp->can_partitions || (STp->new_partition != STp->partition);
5028 }
5029 else {
5030 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
5031 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
5032 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
5033 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
5034 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
5035 mtc.mt_op == MTCOMPRESSION;
5036 }
5037 i = osst_flush_buffer(STp, &SRpnt, i);
5038 if (i < 0) {
5039 retval = i;
5040 goto out;
5041 }
5042 }
5043 else {
5044
5045
5046
5047
5048
5049 if(mtc.mt_op != MTREW &&
5050 mtc.mt_op != MTOFFL &&
5051 mtc.mt_op != MTRETEN &&
5052 mtc.mt_op != MTERASE &&
5053 mtc.mt_op != MTSEEK &&
5054 mtc.mt_op != MTEOM) {
5055 retval = (-EIO);
5056 goto out;
5057 }
5058 reset_state(STp);
5059
5060 STp->device->was_reset = 0;
5061 }
5062
5063 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
5064 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
5065 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
5066 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
5067 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
5068
5069
5070
5071
5072
5073
5074
5075#if DEBUG
5076 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
5077 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
5078 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
5079 STp->logical_blk_num, STps->drv_file, STps->drv_block );
5080#endif
5081 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
5082 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
5083 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5084 i = osst_write_trailer(STp, &SRpnt,
5085 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5086#if DEBUG
5087 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5088 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5089 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5090#endif
5091 if (i < 0) {
5092 retval = i;
5093 goto out;
5094 }
5095 }
5096 STps->rw = ST_IDLE;
5097 }
5098
5099 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5100 do_door_lock(STp, 0);
5101
5102 if (mtc.mt_op == MTSETDRVBUFFER &&
5103 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5104 retval = osst_set_options(STp, mtc.mt_count);
5105 goto out;
5106 }
5107
5108 if (mtc.mt_op == MTSETPART) {
5109 if (mtc.mt_count >= STp->nbr_partitions)
5110 retval = -EINVAL;
5111 else {
5112 STp->new_partition = mtc.mt_count;
5113 retval = 0;
5114 }
5115 goto out;
5116 }
5117
5118 if (mtc.mt_op == MTMKPART) {
5119 if (!STp->can_partitions) {
5120 retval = (-EINVAL);
5121 goto out;
5122 }
5123 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0
5124) {
5125 retval = i;
5126 goto out;
5127 }
5128 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5129 STp->ps[i].rw = ST_IDLE;
5130 STp->ps[i].at_sm = 0;
5131 STp->ps[i].last_block_valid = 0;
5132 }
5133 STp->partition = STp->new_partition = 0;
5134 STp->nbr_partitions = 1;
5135 STps->drv_block = STps->drv_file = 0;
5136 retval = 0;
5137 goto out;
5138 }
5139
5140 if (mtc.mt_op == MTSEEK) {
5141 if (STp->raw)
5142 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5143 else
5144 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5145 if (!STp->can_partitions)
5146 STp->ps[0].rw = ST_IDLE;
5147 retval = i;
5148 goto out;
5149 }
5150
5151 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5152 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5153 goto out;
5154 }
5155
5156 if (auto_weof)
5157 cross_eof(STp, &SRpnt, 0);
5158
5159 if (mtc.mt_op == MTCOMPRESSION)
5160 retval = -EINVAL;
5161 else
5162
5163
5164 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5165 goto out;
5166 }
5167
5168 if (!STm->defined) {
5169 retval = (-ENXIO);
5170 goto out;
5171 }
5172
5173 if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5174 retval = i;
5175 goto out;
5176 }
5177
5178 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5179 struct mtget mt_status;
5180
5181 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5182 retval = (-EINVAL);
5183 goto out;
5184 }
5185
5186 mt_status.mt_type = MT_ISONSTREAM_SC;
5187 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5188 mt_status.mt_dsreg =
5189 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5190 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5191 mt_status.mt_blkno = STps->drv_block;
5192 mt_status.mt_fileno = STps->drv_file;
5193 if (STp->block_size != 0) {
5194 if (STps->rw == ST_WRITING)
5195 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5196 else if (STps->rw == ST_READING)
5197 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5198 STp->block_size - 1) / STp->block_size;
5199 }
5200
5201 mt_status.mt_gstat = 0;
5202 if (STp->drv_write_prot)
5203 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5204 if (mt_status.mt_blkno == 0) {
5205 if (mt_status.mt_fileno == 0)
5206 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5207 else
5208 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5209 }
5210 mt_status.mt_resid = STp->partition;
5211 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5212 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5213 else if (STps->eof >= ST_EOM_OK)
5214 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5215 if (STp->density == 1)
5216 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5217 else if (STp->density == 2)
5218 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5219 else if (STp->density == 3)
5220 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5221 if (STp->ready == ST_READY)
5222 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5223 if (STp->ready == ST_NO_TAPE)
5224 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5225 if (STps->at_sm)
5226 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5227 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5228 STp->drv_buffer != 0)
5229 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5230
5231 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5232 if (i) {
5233 retval = (-EFAULT);
5234 goto out;
5235 }
5236
5237 STp->recover_erreg = 0;
5238 retval = 0;
5239 goto out;
5240 }
5241
5242 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5243 struct mtpos mt_pos;
5244
5245 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5246 retval = (-EINVAL);
5247 goto out;
5248 }
5249 if (STp->raw)
5250 blk = osst_get_frame_position(STp, &SRpnt);
5251 else
5252 blk = osst_get_sector(STp, &SRpnt);
5253 if (blk < 0) {
5254 retval = blk;
5255 goto out;
5256 }
5257 mt_pos.mt_blkno = blk;
5258 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5259 if (i)
5260 retval = -EFAULT;
5261 goto out;
5262 }
5263 if (SRpnt) osst_release_request(SRpnt);
5264
5265 mutex_unlock(&STp->lock);
5266
5267 retval = scsi_ioctl(STp->device, cmd_in, p);
5268 mutex_unlock(&osst_int_mutex);
5269 return retval;
5270
5271out:
5272 if (SRpnt) osst_release_request(SRpnt);
5273
5274 mutex_unlock(&STp->lock);
5275 mutex_unlock(&osst_int_mutex);
5276
5277 return retval;
5278}
5279
5280#ifdef CONFIG_COMPAT
5281static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5282{
5283 struct osst_tape *STp = file->private_data;
5284 struct scsi_device *sdev = STp->device;
5285 int ret = -ENOIOCTLCMD;
5286 if (sdev->host->hostt->compat_ioctl) {
5287
5288 ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5289
5290 }
5291 return ret;
5292}
5293#endif
5294
5295
5296
5297
5298
5299
5300static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5301{
5302 int i;
5303 gfp_t priority;
5304 struct osst_buffer *tb;
5305
5306 if (from_initialization)
5307 priority = GFP_ATOMIC;
5308 else
5309 priority = GFP_KERNEL;
5310
5311 i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5312 tb = kzalloc(i, priority);
5313 if (!tb) {
5314 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5315 return NULL;
5316 }
5317
5318 tb->sg_segs = tb->orig_sg_segs = 0;
5319 tb->use_sg = max_sg;
5320 tb->in_use = 1;
5321 tb->dma = need_dma;
5322 tb->buffer_size = 0;
5323#if DEBUG
5324 if (debugging)
5325 printk(OSST_DEB_MSG
5326 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5327 i, max_sg, need_dma);
5328#endif
5329 return tb;
5330}
5331
5332
5333static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5334{
5335 int segs, nbr, max_segs, b_size, order, got;
5336 gfp_t priority;
5337
5338 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5339 return 1;
5340
5341 if (STbuffer->sg_segs) {
5342 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5343 normalize_buffer(STbuffer);
5344 }
5345
5346 nbr = max_segs = STbuffer->use_sg;
5347 if (nbr <= 2)
5348 return 0;
5349
5350 priority = GFP_KERNEL ;
5351 if (need_dma)
5352 priority |= GFP_DMA;
5353
5354
5355
5356 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5357 struct page *page = alloc_pages(priority, order);
5358
5359 STbuffer->sg[0].offset = 0;
5360 if (page != NULL) {
5361 sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5362 STbuffer->b_data = page_address(page);
5363 break;
5364 }
5365 }
5366 if (sg_page(&STbuffer->sg[0]) == NULL) {
5367 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5368 return 0;
5369 }
5370
5371 for (segs=STbuffer->sg_segs=1, got=b_size;
5372 segs < max_segs && got < OS_FRAME_SIZE; ) {
5373 struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5374 STbuffer->sg[segs].offset = 0;
5375 if (page == NULL) {
5376 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5377 OS_FRAME_SIZE);
5378#if DEBUG
5379 STbuffer->buffer_size = got;
5380#endif
5381 normalize_buffer(STbuffer);
5382 return 0;
5383 }
5384 sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5385 got += STbuffer->sg[segs].length;
5386 STbuffer->buffer_size = got;
5387 STbuffer->sg_segs = ++segs;
5388 }
5389#if DEBUG
5390 if (debugging) {
5391 printk(OSST_DEB_MSG
5392 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5393 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5394 printk(OSST_DEB_MSG
5395 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5396 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5397 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5398 }
5399#endif
5400
5401 return 1;
5402}
5403
5404
5405
5406static void normalize_buffer(struct osst_buffer *STbuffer)
5407{
5408 int i, order, b_size;
5409
5410 for (i=0; i < STbuffer->sg_segs; i++) {
5411
5412 for (b_size = PAGE_SIZE, order = 0;
5413 b_size < STbuffer->sg[i].length;
5414 b_size *= 2, order++);
5415
5416 __free_pages(sg_page(&STbuffer->sg[i]), order);
5417 STbuffer->buffer_size -= STbuffer->sg[i].length;
5418 }
5419#if DEBUG
5420 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5421 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5422 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5423#endif
5424 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5425}
5426
5427
5428
5429
5430static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5431{
5432 int i, cnt, res, offset;
5433
5434 for (i=0, offset=st_bp->buffer_bytes;
5435 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5436 offset -= st_bp->sg[i].length;
5437 if (i == st_bp->sg_segs) {
5438 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5439 return (-EIO);
5440 }
5441 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5442 cnt = st_bp->sg[i].length - offset < do_count ?
5443 st_bp->sg[i].length - offset : do_count;
5444 res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5445 if (res)
5446 return (-EFAULT);
5447 do_count -= cnt;
5448 st_bp->buffer_bytes += cnt;
5449 ubp += cnt;
5450 offset = 0;
5451 }
5452 if (do_count) {
5453 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5454 do_count);
5455 return (-EIO);
5456 }
5457 return 0;
5458}
5459
5460
5461
5462
5463static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5464{
5465 int i, cnt, res, offset;
5466
5467 for (i=0, offset=st_bp->read_pointer;
5468 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5469 offset -= st_bp->sg[i].length;
5470 if (i == st_bp->sg_segs) {
5471 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5472 return (-EIO);
5473 }
5474 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5475 cnt = st_bp->sg[i].length - offset < do_count ?
5476 st_bp->sg[i].length - offset : do_count;
5477 res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5478 if (res)
5479 return (-EFAULT);
5480 do_count -= cnt;
5481 st_bp->buffer_bytes -= cnt;
5482 st_bp->read_pointer += cnt;
5483 ubp += cnt;
5484 offset = 0;
5485 }
5486 if (do_count) {
5487 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5488 return (-EIO);
5489 }
5490 return 0;
5491}
5492
5493
5494
5495static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5496{
5497 int i, offset, do_count, cnt;
5498
5499 for (i = 0, offset = st_bp->buffer_bytes;
5500 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5501 offset -= st_bp->sg[i].length;
5502 if (i == st_bp->sg_segs) {
5503 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5504 return (-EIO);
5505 }
5506 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5507 i < st_bp->sg_segs && do_count > 0; i++) {
5508 cnt = st_bp->sg[i].length - offset < do_count ?
5509 st_bp->sg[i].length - offset : do_count ;
5510 memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5511 do_count -= cnt;
5512 offset = 0;
5513 }
5514 if (do_count) {
5515 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5516 return (-EIO);
5517 }
5518 return 0;
5519}
5520
5521
5522
5523static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5524{
5525 int i, cnt, do_count = OS_DATA_SIZE;
5526
5527 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5528 cnt = st_bp->sg[i].length < do_count ?
5529 st_bp->sg[i].length : do_count ;
5530 memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5531 do_count -= cnt;
5532 ptr += cnt;
5533 }
5534 if (do_count || i != st_bp->sg_segs-1) {
5535 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5536 do_count, i);
5537 return (-EIO);
5538 }
5539 return 0;
5540}
5541
5542
5543
5544static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5545{
5546 int i, cnt, do_count = OS_DATA_SIZE;
5547
5548 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5549 cnt = st_bp->sg[i].length < do_count ?
5550 st_bp->sg[i].length : do_count ;
5551 memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5552 do_count -= cnt;
5553 ptr += cnt;
5554 }
5555 if (do_count || i != st_bp->sg_segs-1) {
5556 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5557 do_count, i);
5558 return (-EIO);
5559 }
5560 return 0;
5561}
5562
5563
5564
5565
5566static void validate_options (void)
5567{
5568 if (max_dev > 0)
5569 osst_max_dev = max_dev;
5570 if (write_threshold_kbs > 0)
5571 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5572 if (osst_write_threshold > osst_buffer_size)
5573 osst_write_threshold = osst_buffer_size;
5574 if (max_sg_segs >= OSST_FIRST_SG)
5575 osst_max_sg_segs = max_sg_segs;
5576#if DEBUG
5577 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5578 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5579#endif
5580}
5581
5582#ifndef MODULE
5583
5584
5585
5586static int __init osst_setup (char *str)
5587{
5588 int i, ints[5];
5589 char *stp;
5590
5591 stp = get_options(str, ARRAY_SIZE(ints), ints);
5592
5593 if (ints[0] > 0) {
5594 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5595 *parms[i].val = ints[i + 1];
5596 } else {
5597 while (stp != NULL) {
5598 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5599 int len = strlen(parms[i].name);
5600 if (!strncmp(stp, parms[i].name, len) &&
5601 (*(stp + len) == ':' || *(stp + len) == '=')) {
5602 *parms[i].val =
5603 simple_strtoul(stp + len + 1, NULL, 0);
5604 break;
5605 }
5606 }
5607 if (i >= ARRAY_SIZE(parms))
5608 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5609 stp);
5610 stp = strchr(stp, ',');
5611 if (stp)
5612 stp++;
5613 }
5614 }
5615
5616 return 1;
5617}
5618
5619__setup("osst=", osst_setup);
5620
5621#endif
5622
5623static const struct file_operations osst_fops = {
5624 .owner = THIS_MODULE,
5625 .read = osst_read,
5626 .write = osst_write,
5627 .unlocked_ioctl = osst_ioctl,
5628#ifdef CONFIG_COMPAT
5629 .compat_ioctl = osst_compat_ioctl,
5630#endif
5631 .open = os_scsi_tape_open,
5632 .flush = os_scsi_tape_flush,
5633 .release = os_scsi_tape_close,
5634 .llseek = noop_llseek,
5635};
5636
5637static int osst_supports(struct scsi_device * SDp)
5638{
5639 struct osst_support_data {
5640 char *vendor;
5641 char *model;
5642 char *rev;
5643 char *driver_hint;
5644 };
5645
5646static struct osst_support_data support_list[] = {
5647
5648 SIGS_FROM_OSST,
5649 {NULL, }};
5650
5651 struct osst_support_data *rp;
5652
5653
5654
5655
5656
5657 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5658 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5659 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5660 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5661 return 1;
5662 return 0;
5663}
5664
5665
5666
5667
5668
5669static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5670{
5671 return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5672}
5673
5674static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5675
5676static int osst_create_sysfs_files(struct device_driver *sysfs)
5677{
5678 return driver_create_file(sysfs, &driver_attr_version);
5679}
5680
5681static void osst_remove_sysfs_files(struct device_driver *sysfs)
5682{
5683 driver_remove_file(sysfs, &driver_attr_version);
5684}
5685
5686
5687
5688
5689
5690static ssize_t osst_adr_rev_show(struct device *dev,
5691 struct device_attribute *attr, char *buf)
5692{
5693 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5694 ssize_t l = 0;
5695
5696 if (STp && STp->header_ok && STp->linux_media)
5697 l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5698 return l;
5699}
5700
5701DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5702
5703static ssize_t osst_linux_media_version_show(struct device *dev,
5704 struct device_attribute *attr,
5705 char *buf)
5706{
5707 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5708 ssize_t l = 0;
5709
5710 if (STp && STp->header_ok && STp->linux_media)
5711 l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5712 return l;
5713}
5714
5715DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5716
5717static ssize_t osst_capacity_show(struct device *dev,
5718 struct device_attribute *attr, char *buf)
5719{
5720 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5721 ssize_t l = 0;
5722
5723 if (STp && STp->header_ok && STp->linux_media)
5724 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5725 return l;
5726}
5727
5728DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5729
5730static ssize_t osst_first_data_ppos_show(struct device *dev,
5731 struct device_attribute *attr,
5732 char *buf)
5733{
5734 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5735 ssize_t l = 0;
5736
5737 if (STp && STp->header_ok && STp->linux_media)
5738 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5739 return l;
5740}
5741
5742DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5743
5744static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5745 struct device_attribute *attr,
5746 char *buf)
5747{
5748 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5749 ssize_t l = 0;
5750
5751 if (STp && STp->header_ok && STp->linux_media)
5752 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5753 return l;
5754}
5755
5756DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5757
5758static ssize_t osst_filemark_cnt_show(struct device *dev,
5759 struct device_attribute *attr, char *buf)
5760{
5761 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5762 ssize_t l = 0;
5763
5764 if (STp && STp->header_ok && STp->linux_media)
5765 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5766 return l;
5767}
5768
5769DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5770
5771static struct class *osst_sysfs_class;
5772
5773static int osst_sysfs_init(void)
5774{
5775 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5776 if (IS_ERR(osst_sysfs_class)) {
5777 printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5778 return PTR_ERR(osst_sysfs_class);
5779 }
5780
5781 return 0;
5782}
5783
5784static void osst_sysfs_destroy(dev_t dev)
5785{
5786 device_destroy(osst_sysfs_class, dev);
5787}
5788
5789static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5790{
5791 struct device *osst_member;
5792 int err;
5793
5794 osst_member = device_create(osst_sysfs_class, device, dev, STp,
5795 "%s", name);
5796 if (IS_ERR(osst_member)) {
5797 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5798 return PTR_ERR(osst_member);
5799 }
5800
5801 err = device_create_file(osst_member, &dev_attr_ADR_rev);
5802 if (err)
5803 goto err_out;
5804 err = device_create_file(osst_member, &dev_attr_media_version);
5805 if (err)
5806 goto err_out;
5807 err = device_create_file(osst_member, &dev_attr_capacity);
5808 if (err)
5809 goto err_out;
5810 err = device_create_file(osst_member, &dev_attr_BOT_frame);
5811 if (err)
5812 goto err_out;
5813 err = device_create_file(osst_member, &dev_attr_EOD_frame);
5814 if (err)
5815 goto err_out;
5816 err = device_create_file(osst_member, &dev_attr_file_count);
5817 if (err)
5818 goto err_out;
5819
5820 return 0;
5821
5822err_out:
5823 osst_sysfs_destroy(dev);
5824 return err;
5825}
5826
5827static void osst_sysfs_cleanup(void)
5828{
5829 class_destroy(osst_sysfs_class);
5830}
5831
5832
5833
5834
5835
5836static int osst_probe(struct device *dev)
5837{
5838 struct scsi_device * SDp = to_scsi_device(dev);
5839 struct osst_tape * tpnt;
5840 struct st_modedef * STm;
5841 struct st_partstat * STps;
5842 struct osst_buffer * buffer;
5843 struct gendisk * drive;
5844 int i, dev_num, err = -ENODEV;
5845
5846 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5847 return -ENODEV;
5848
5849 drive = alloc_disk(1);
5850 if (!drive) {
5851 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5852 return -ENODEV;
5853 }
5854
5855
5856 write_lock(&os_scsi_tapes_lock);
5857 if (os_scsi_tapes == NULL) {
5858 os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC);
5859 if (os_scsi_tapes == NULL) {
5860 write_unlock(&os_scsi_tapes_lock);
5861 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5862 goto out_put_disk;
5863 }
5864 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5865 }
5866
5867 if (osst_nr_dev >= osst_max_dev) {
5868 write_unlock(&os_scsi_tapes_lock);
5869 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5870 goto out_put_disk;
5871 }
5872
5873
5874 for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++)
5875 ;
5876 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5877 dev_num = i;
5878
5879
5880 tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5881 if (!tpnt) {
5882 write_unlock(&os_scsi_tapes_lock);
5883 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5884 goto out_put_disk;
5885 }
5886
5887
5888 i = SDp->host->sg_tablesize;
5889 if (osst_max_sg_segs < i)
5890 i = osst_max_sg_segs;
5891 buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5892 if (buffer == NULL) {
5893 write_unlock(&os_scsi_tapes_lock);
5894 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5895 kfree(tpnt);
5896 goto out_put_disk;
5897 }
5898 os_scsi_tapes[dev_num] = tpnt;
5899 tpnt->buffer = buffer;
5900 tpnt->device = SDp;
5901 drive->private_data = &tpnt->driver;
5902 sprintf(drive->disk_name, "osst%d", dev_num);
5903 tpnt->driver = &osst_template;
5904 tpnt->drive = drive;
5905 tpnt->in_use = 0;
5906 tpnt->capacity = 0xfffff;
5907 tpnt->dirty = 0;
5908 tpnt->drv_buffer = 1;
5909 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5910 tpnt->density = 0;
5911 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5912 tpnt->can_bsr = OSST_IN_FILE_POS;
5913 tpnt->can_partitions = 0;
5914 tpnt->two_fm = OSST_TWO_FM;
5915 tpnt->fast_mteom = OSST_FAST_MTEOM;
5916 tpnt->scsi2_logical = OSST_SCSI2LOGICAL;
5917 tpnt->write_threshold = osst_write_threshold;
5918 tpnt->default_drvbuffer = 0xff;
5919 tpnt->partition = 0;
5920 tpnt->new_partition = 0;
5921 tpnt->nbr_partitions = 0;
5922 tpnt->min_block = 512;
5923 tpnt->max_block = OS_DATA_SIZE;
5924 tpnt->timeout = OSST_TIMEOUT;
5925 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5926
5927
5928
5929 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5930 tpnt->omit_blklims = 1;
5931
5932 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5933 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5934 tpnt->frame_in_buffer = 0;
5935 tpnt->header_ok = 0;
5936 tpnt->linux_media = 0;
5937 tpnt->header_cache = NULL;
5938
5939 for (i=0; i < ST_NBR_MODES; i++) {
5940 STm = &(tpnt->modes[i]);
5941 STm->defined = 0;
5942 STm->sysv = OSST_SYSV;
5943 STm->defaults_for_writes = 0;
5944 STm->do_async_writes = OSST_ASYNC_WRITES;
5945 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5946 STm->do_read_ahead = OSST_READ_AHEAD;
5947 STm->default_compression = ST_DONT_TOUCH;
5948 STm->default_blksize = 512;
5949 STm->default_density = (-1);
5950 }
5951
5952 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5953 STps = &(tpnt->ps[i]);
5954 STps->rw = ST_IDLE;
5955 STps->eof = ST_NOEOF;
5956 STps->at_sm = 0;
5957 STps->last_block_valid = 0;
5958 STps->drv_block = (-1);
5959 STps->drv_file = (-1);
5960 }
5961
5962 tpnt->current_mode = 0;
5963 tpnt->modes[0].defined = 1;
5964 tpnt->modes[2].defined = 1;
5965 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5966
5967 mutex_init(&tpnt->lock);
5968 osst_nr_dev++;
5969 write_unlock(&os_scsi_tapes_lock);
5970
5971 {
5972 char name[8];
5973
5974
5975 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5976 if (err)
5977 goto out_free_buffer;
5978
5979
5980 snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5981 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5982 if (err)
5983 goto out_free_sysfs1;
5984 }
5985
5986 sdev_printk(KERN_INFO, SDp,
5987 "osst :I: Attached OnStream %.5s tape as %s\n",
5988 SDp->model, tape_name(tpnt));
5989
5990 return 0;
5991
5992out_free_sysfs1:
5993 osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5994out_free_buffer:
5995 kfree(buffer);
5996out_put_disk:
5997 put_disk(drive);
5998 return err;
5999};
6000
6001static int osst_remove(struct device *dev)
6002{
6003 struct scsi_device * SDp = to_scsi_device(dev);
6004 struct osst_tape * tpnt;
6005 int i;
6006
6007 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
6008 return 0;
6009
6010 write_lock(&os_scsi_tapes_lock);
6011 for(i=0; i < osst_max_dev; i++) {
6012 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
6013 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
6014 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
6015 tpnt->device = NULL;
6016 put_disk(tpnt->drive);
6017 os_scsi_tapes[i] = NULL;
6018 osst_nr_dev--;
6019 write_unlock(&os_scsi_tapes_lock);
6020 vfree(tpnt->header_cache);
6021 if (tpnt->buffer) {
6022 normalize_buffer(tpnt->buffer);
6023 kfree(tpnt->buffer);
6024 }
6025 kfree(tpnt);
6026 return 0;
6027 }
6028 }
6029 write_unlock(&os_scsi_tapes_lock);
6030 return 0;
6031}
6032
6033static int __init init_osst(void)
6034{
6035 int err;
6036
6037 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
6038
6039 validate_options();
6040
6041 err = osst_sysfs_init();
6042 if (err)
6043 return err;
6044
6045 err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
6046 if (err < 0) {
6047 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
6048 goto err_out;
6049 }
6050
6051 err = scsi_register_driver(&osst_template.gendrv);
6052 if (err)
6053 goto err_out_chrdev;
6054
6055 err = osst_create_sysfs_files(&osst_template.gendrv);
6056 if (err)
6057 goto err_out_scsidrv;
6058
6059 return 0;
6060
6061err_out_scsidrv:
6062 scsi_unregister_driver(&osst_template.gendrv);
6063err_out_chrdev:
6064 unregister_chrdev(OSST_MAJOR, "osst");
6065err_out:
6066 osst_sysfs_cleanup();
6067 return err;
6068}
6069
6070static void __exit exit_osst (void)
6071{
6072 int i;
6073 struct osst_tape * STp;
6074
6075 osst_remove_sysfs_files(&osst_template.gendrv);
6076 scsi_unregister_driver(&osst_template.gendrv);
6077 unregister_chrdev(OSST_MAJOR, "osst");
6078 osst_sysfs_cleanup();
6079
6080 if (os_scsi_tapes) {
6081 for (i=0; i < osst_max_dev; ++i) {
6082 if (!(STp = os_scsi_tapes[i])) continue;
6083
6084 vfree(STp->header_cache);
6085 if (STp->buffer) {
6086 normalize_buffer(STp->buffer);
6087 kfree(STp->buffer);
6088 }
6089 put_disk(STp->drive);
6090 kfree(STp);
6091 }
6092 kfree(os_scsi_tapes);
6093 }
6094 printk(KERN_INFO "osst :I: Unloaded.\n");
6095}
6096
6097module_init(init_osst);
6098module_exit(exit_osst);
6099