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