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