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