OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [osst.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.