1/*
2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
4
5 History:
6
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
10
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
15
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
17 email osst@riede.org
18
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
20
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
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/* The "failure to reconnect" firmware bug */
30#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
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/* The driver prints some debugging information on the console if DEBUG
59 is defined and non-zero. */
60#define DEBUG 0
61
62/* The message level for the debug messages is currently set to KERN_NOTICE
63 so that people can easily see the messages. Later when the debugging messages
64 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
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/* Some default definitions have been moved to osst_options.h */
114#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
115#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116
117/* The buffer size should fit into the 24 bits for length in the
118 6-byte SCSI read and write commands. */
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/* uncomment define below to test error recovery */
126// #define OSST_INJECT_ERRORS 1
127#endif
128
129/* Do not retry! The drive firmware already retries when appropriate,
130 and when it tries to tell us something, we had better listen... */
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)-1))
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/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
148 24 bits) */
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/* Routines that handle the interaction with mid-layer SCSI routines */
200
201
202/* Normalize Sense */
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/* Convert the result to success code */
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/* scode != UNIT_ATTENTION && */
273 scode != BLANK_CHECK &&
274 scode != VOLUME_OVERFLOW &&
275 SRpnt->cmd[0] != MODE_SENSE &&
276 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
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/* Wakeup from interrupt */
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);
345}
346
347/* osst_request memory management */
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, 0);
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 = kcalloc(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); /* ATAPI hates garbage after 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/* Do the scsi command. Waits until command performed if do_wait is true.
427 Otherwise osst_write_behind_check() is used to check that the command
428 has finished. */
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 /* if async, make sure there's no command outstanding */
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 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
466 which IO is outstanding. It's nulled out when the IO completes. */
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 /* could not allocate the buffer or request was too large */
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 /* or STp->read_error_frame to fail again on the block calculated above */ &&
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/* Handle the write-behind checking (downs the semaphore) */
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/* Onstream specific Routines */
551/*
552 * Initialize the OnStream AUX
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 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
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: ; /* probably FILL */
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 * Verify that we have the correct tape frame
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 /* See what block size was used to write file */
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 * Wait for the unit to become Ready
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 * Wait for a tape to be inserted in the unit
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); /* TODO - can this catch a write error? */
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 * Wait for write(s) to complete
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; /* successful recovery leaves drive ready for frame */
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 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
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 /* some failure - not just not-ready */
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 /* TODO - figure out which error conditions can be handled */
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 * Read the next OnStream tape frame at the current location
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) { /* Initialize read operation */
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 * Issue a read 0 command to get the OnStream drive
1123 * read frames into its buffer.
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 * If we want just any frame (-1) and there is a frame in the buffer, return it
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 * Search and wait for the next logical tape frame
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 /* positioning backwards did not bring us to the desired frame */
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 /* Do we know where we are? */
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 /* we've located the estimated frame, now does it have our block? */
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 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
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/* The values below are based on the OnStream frame payload size of 32K == 2**15,
1371 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1372 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1373 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
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 /* do we know where we are inside a file? */
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 * Read back the drive's internal buffer contents, as a part
1467 * of the write error recovery mechanism for old OnStream
1468 * firmware revisions.
1469 * Precondition for this function to work: all frames in the
1470 * drive's buffer must be of one type (DATA, MARK or EOD)!
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(array_size((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; /* Buffer Read */
1509 cmd[1] = 6; /* Retrieve Faulty Block */
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 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1536 /* In the header we don't actually re-write the frames that fail, just the ones after them */
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 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
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 /* if we just sent the last frame, wait till all successfully written */
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 /* in the process of becoming ready */
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); /* hit end of tape = fail */
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 /* error recovery did not successfully complete */
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); /* so buffer content == at entry in all cases */
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) { /* additional write error */
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) { /* additional write error */
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; /* hit end of tape = fail */
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 * Error recovery algorithm for the OnStream tape.
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 * direct lookup in header filemark list
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 * ADRL 1.1 compatible "slow" space filemarks fwd version
1948 *
1949 * Just scans for the filemark sequentially.
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 * Fast linux specific version of OnStream FSF
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 * direct lookup in header filemark list
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 * Find nearest (usually previous) marker, then jump from marker to marker
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 * In debug mode, we want to see as many errors as possible
2153 * to test the error recovery mechanism.
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; /* Medium Type - ignoring */
2169 (STp->buffer)->b_data[2] = 0; /* Reserved */
2170 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
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; /* warning: only first segment addressable */
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; /* further accesses from cached (full) copy */
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 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2578 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
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; /* usually - we don't really know */
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 /* prepare buffer for append and rewrite on top of original */
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/* Acc. to OnStream, the vers. numbering is the following:
2664 * X.XX for released versions (X=digit),
2665 * XXXY for unreleased versions (Y=letter)
2666 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2667 * This fn makes monoton numbers out of this scheme ...
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 * Configure the OnStream SCII tape drive for default operation
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 * Configure 32.5KB (data+aux) frame size.
2711 * Get the current frame size from the block size mode page
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 * Configure default auto columns mode, 32.5KB transfer mode
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 * In debug mode, we want to see as many errors as possible
2767 * to test the error recovery mechanism.
2768 */
2769 osst_set_retries(STp, aSRpnt, 0);
2770 SRpnt = * aSRpnt;
2771#endif
2772
2773 /*
2774 * Set vendor name to 'LIN4' for "Linux support version 4".
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; /* Medium Type - ignoring */
2784 header->dsp = 0; /* Reserved */
2785 header->bdl = 0; /* Block Descriptor Length */
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/* Step over EOF if it has been inadvertently crossed (ioctl not used because
2856 it messes up the block number). */
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 /* assumes that the filemark is already read by the drive, so this is low cost */
2870 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2871 }
2872 else
2873 /* assumes this is only called if we just read the filemark! */
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/* Get the tape position. */
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 /* KG: We want to be able to use it for checking Write Buffer availability
2894 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
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; /* 3: Write Error */
2915
2916 if (result == -EINVAL)
2917 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2918 else {
2919 if (result == -EIO) { /* re-read position - this needs to preserve media errors */
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/* Set the tape block */
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 /* true unless the user wrote the filemark for us */
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/* osst versions of st functions - augmented and stripped to suit OnStream only */
3053
3054/* Flush the write buffer (never need to write if variable blocksize). */
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: /* probably FILLER */
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) && /* FIXME - SC-30 drive doesn't assert EOM bit */
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); /* FIXME - even if write recovery succeeds? */
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/* Flush the tape buffer. The tape will be positioned correctly unless
3184 seek_next is true. */
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 * If there was a bus reset, block further access
3195 * to this device.
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) { /* Writing */
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; /* FIXME is this relevant w. OSST? */
3221 }
3222
3223 if (!seek_next) {
3224 if (STps->eof == ST_FM_HIT) {
3225 result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
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) /* TODO -- design and run a test case for this */
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)) { /* _must_ preserve buffer! */
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 /* error recovery may have bumped us past the header partition */
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// osst_build_stats(STp, &SRpnt);
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; /* one frame at a time... */
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/* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
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/* Set the internal state after reset */
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/* Entry points to osst */
3368
3369/* Write command */
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 * If we are in the middle of error recovery, don't let anyone
3389 * else try and use this device. Also, if error recovery fails, it
3390 * may try and take the device offline, in which case all further
3391 * access to the device is prohibited.
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 * If there was a bus reset, block further access
3415 * to this device.
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 /* Write must be integral number of blocks */
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 }