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