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