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